summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gralloc4/Android.bp132
-rw-r--r--gralloc4/interfaces/aidl/Android.bp35
-rw-r--r--gralloc4/interfaces/aidl/aidl_api/arm.graphics/1/arm/graphics/ArmMetadataType.aidl23
-rw-r--r--gralloc4/interfaces/aidl/aidl_api/arm.graphics/1/arm/graphics/Compression.aidl22
-rw-r--r--gralloc4/interfaces/aidl/aidl_api/arm.graphics/current/arm/graphics/ArmMetadataType.aidl23
-rw-r--r--gralloc4/interfaces/aidl/aidl_api/arm.graphics/current/arm/graphics/Compression.aidl22
-rw-r--r--gralloc4/interfaces/aidl/arm/graphics/ArmMetadataType.aidl36
-rw-r--r--gralloc4/interfaces/aidl/arm/graphics/Compression.aidl31
-rw-r--r--gralloc4/interfaces/libs/drmutils/Android.bp49
-rw-r--r--gralloc4/interfaces/libs/drmutils/drmutils.h43
-rw-r--r--gralloc4/interfaces/libs/drmutils/src/drmutils.cpp165
-rw-r--r--gralloc4/service/4.x/Android.bp37
-rw-r--r--gralloc4/service/4.x/android.hardware.graphics.allocator@4.0-service.rc7
-rw-r--r--gralloc4/service/4.x/service.cpp28
-rw-r--r--gralloc4/src/4.x/Android.bp110
-rw-r--r--gralloc4/src/4.x/GrallocAllocator.cpp64
-rw-r--r--gralloc4/src/4.x/GrallocAllocator.h54
-rw-r--r--gralloc4/src/4.x/GrallocMapper.cpp178
-rw-r--r--gralloc4/src/4.x/GrallocMapper.h90
-rw-r--r--gralloc4/src/4.x/gralloc_allocator_hidl_header.h26
-rw-r--r--gralloc4/src/4.x/gralloc_mapper_hidl_header.h32
-rw-r--r--gralloc4/src/Android.bp32
-rw-r--r--gralloc4/src/allocator/Android.bp100
-rw-r--r--gralloc4/src/allocator/mali_gralloc_ion.cpp776
-rw-r--r--gralloc4/src/allocator/mali_gralloc_ion.h39
-rw-r--r--gralloc4/src/allocator/mali_gralloc_shared_memory.cpp37
-rw-r--r--gralloc4/src/allocator/mali_gralloc_shared_memory.h31
-rw-r--r--gralloc4/src/capabilities/Android.bp127
-rw-r--r--gralloc4/src/capabilities/gralloc_capabilities.h61
-rw-r--r--gralloc4/src/capabilities/src/gralloc_capabilities.cpp118
-rw-r--r--gralloc4/src/core/Android.bp94
-rw-r--r--gralloc4/src/core/exynos_format_allocation.h350
-rw-r--r--gralloc4/src/core/format_info.cpp1219
-rw-r--r--gralloc4/src/core/format_info.h115
-rw-r--r--gralloc4/src/core/mali_gralloc_bufferaccess.cpp285
-rw-r--r--gralloc4/src/core/mali_gralloc_bufferaccess.h34
-rw-r--r--gralloc4/src/core/mali_gralloc_bufferallocation.cpp1099
-rw-r--r--gralloc4/src/core/mali_gralloc_bufferallocation.h115
-rw-r--r--gralloc4/src/core/mali_gralloc_bufferdescriptor.h79
-rw-r--r--gralloc4/src/core/mali_gralloc_debug.cpp136
-rw-r--r--gralloc4/src/core/mali_gralloc_debug.h33
-rw-r--r--gralloc4/src/core/mali_gralloc_formats.cpp1562
-rw-r--r--gralloc4/src/core/mali_gralloc_reference.cpp118
-rw-r--r--gralloc4/src/core/mali_gralloc_reference.h27
-rw-r--r--gralloc4/src/gralloc_helper.h39
-rw-r--r--gralloc4/src/gralloc_priv.h49
-rw-r--r--gralloc4/src/hidl_common/Allocator.cpp150
-rw-r--r--gralloc4/src/hidl_common/Allocator.h61
-rw-r--r--gralloc4/src/hidl_common/Android.bp45
-rw-r--r--gralloc4/src/hidl_common/BufferDescriptor.h187
-rw-r--r--gralloc4/src/hidl_common/Mapper.cpp757
-rw-r--r--gralloc4/src/hidl_common/Mapper.h252
-rw-r--r--gralloc4/src/hidl_common/MapperMetadata.cpp931
-rw-r--r--gralloc4/src/hidl_common/MapperMetadata.h93
-rw-r--r--gralloc4/src/hidl_common/RegisteredHandlePool.cpp47
-rw-r--r--gralloc4/src/hidl_common/RegisteredHandlePool.h49
-rw-r--r--gralloc4/src/hidl_common/SharedMetadata.cpp171
-rw-r--r--gralloc4/src/hidl_common/SharedMetadata.h75
-rw-r--r--gralloc4/src/hidl_common/SharedMetadata_struct.h158
-rw-r--r--gralloc4/src/mali_fourcc.h142
-rw-r--r--gralloc4/src/mali_gralloc_buffer.h419
l---------gralloc4/src/mali_gralloc_buffer4.h1
-rw-r--r--gralloc4/src/mali_gralloc_formats.h371
-rw-r--r--gralloc4/src/mali_gralloc_log.h32
-rw-r--r--gralloc4/src/mali_gralloc_usages.h150
65 files changed, 11973 insertions, 0 deletions
diff --git a/gralloc4/Android.bp b/gralloc4/Android.bp
new file mode 100644
index 0000000..60750d4
--- /dev/null
+++ b/gralloc4/Android.bp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2020 Arm Limited.
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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.
+ */
+
+soong_config_module_type {
+ name: "arm_gralloc_cc_defaults",
+ module_type: "cc_defaults",
+ config_namespace: "arm_gralloc",
+ variables: [
+ "mali_display_version",
+ "gralloc_hwc_force_bgra_8888",
+ "gralloc_hwc_fb_disable_afbc",
+ "gralloc_camera_write_raw16",
+ ],
+ properties: [
+ "cflags",
+ ],
+}
+
+soong_config_string_variable {
+ name: "mali_display_version",
+ values: [
+ "v0",
+ "v500",
+ "v550",
+ "v650",
+ "v71",
+ ],
+}
+
+soong_config_bool_variable {
+ name: "gralloc_hwc_force_bgra_8888",
+}
+soong_config_bool_variable {
+ name: "gralloc_hwc_fb_disable_afbc",
+}
+soong_config_bool_variable {
+ name: "gralloc_camera_write_raw16",
+}
+
+arm_gralloc_cc_defaults {
+ name: "arm_gralloc_defaults",
+ owner: "arm",
+ vendor: true,
+ proprietary: true,
+ cflags: [
+ "-ldl",
+ "-Wundef",
+ "-Werror",
+ "-DGRALLOC_LIBRARY_BUILD=1",
+ "-DDISABLE_FRAMEBUFFER_HAL=1",
+ "-DGRALLOC_USE_LEGACY_CALCS=0",
+ "-DGRALLOC_USE_LEGACY_LOCK=0",
+ ],
+ product_variables: {
+ platform_sdk_version: {
+ cflags: ["-DPLATFORM_SDK_VERSION=%d"],
+ },
+ },
+ header_libs: [
+ "libgralloc_headers",
+ ],
+ target: {
+ android: {
+ cflags: [
+ "-DGRALLOC_HOST_BUILD=0",
+ ],
+ },
+ host: {
+ cflags: [
+ "-DGRALLOC_HOST_BUILD=1",
+ ],
+ },
+ },
+ soong_config_variables: {
+ mali_display_version: {
+ v0: {
+ cflags: [
+ "-DMALI_DISPLAY_VERSION=0",
+ ],
+ },
+ v500: {
+ cflags: [
+ "-DMALI_DISPLAY_VERSION=500",
+ ],
+ },
+ v550: {
+ cflags: [
+ "-DMALI_DISPLAY_VERSION=550",
+ ],
+ },
+ v650: {
+ cflags: [
+ "-DMALI_DISPLAY_VERSION=650",
+ ],
+ },
+ v71: {
+ cflags: [
+ "-DMALI_DISPLAY_VERSION=71",
+ ],
+ },
+ },
+ gralloc_hwc_force_bgra_8888: {
+ cflags: [
+ "-DGRALLOC_HWC_FORCE_BGRA_8888=1",
+ ],
+ },
+ gralloc_hwc_fb_disable_afbc: {
+ cflags: [
+ "-DGRALLOC_HWC_FB_DISABLE_AFBC=1",
+ ],
+ },
+ gralloc_camera_write_raw16: {
+ cflags: [
+ "-DGRALLOC_CAMERA_WRITE_RAW16=1",
+ ],
+ },
+ },
+}
diff --git a/gralloc4/interfaces/aidl/Android.bp b/gralloc4/interfaces/aidl/Android.bp
new file mode 100644
index 0000000..d05ea28
--- /dev/null
+++ b/gralloc4/interfaces/aidl/Android.bp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020 Arm Limited.
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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.
+ */
+
+aidl_interface {
+ name: "arm.graphics",
+ host_supported: true,
+ vendor: true,
+ srcs: [
+ "arm/graphics/*.aidl",
+ ],
+ stability: "vintf",
+ backend: {
+ java: {
+ enabled: false,
+ },
+ cpp: {
+ enabled: false,
+ },
+ },
+ versions: ["1"],
+} \ No newline at end of file
diff --git a/gralloc4/interfaces/aidl/aidl_api/arm.graphics/1/arm/graphics/ArmMetadataType.aidl b/gralloc4/interfaces/aidl/aidl_api/arm.graphics/1/arm/graphics/ArmMetadataType.aidl
new file mode 100644
index 0000000..14d77b4
--- /dev/null
+++ b/gralloc4/interfaces/aidl/aidl_api/arm.graphics/1/arm/graphics/ArmMetadataType.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package arm.graphics;
+@Backing(type="long") @VintfStability
+enum ArmMetadataType {
+ INVALID = 0,
+ PLANE_FDS = 1,
+}
diff --git a/gralloc4/interfaces/aidl/aidl_api/arm.graphics/1/arm/graphics/Compression.aidl b/gralloc4/interfaces/aidl/aidl_api/arm.graphics/1/arm/graphics/Compression.aidl
new file mode 100644
index 0000000..22510ca
--- /dev/null
+++ b/gralloc4/interfaces/aidl/aidl_api/arm.graphics/1/arm/graphics/Compression.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package arm.graphics;
+@Backing(type="long") @VintfStability
+enum Compression {
+ AFBC = 0,
+}
diff --git a/gralloc4/interfaces/aidl/aidl_api/arm.graphics/current/arm/graphics/ArmMetadataType.aidl b/gralloc4/interfaces/aidl/aidl_api/arm.graphics/current/arm/graphics/ArmMetadataType.aidl
new file mode 100644
index 0000000..14d77b4
--- /dev/null
+++ b/gralloc4/interfaces/aidl/aidl_api/arm.graphics/current/arm/graphics/ArmMetadataType.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package arm.graphics;
+@Backing(type="long") @VintfStability
+enum ArmMetadataType {
+ INVALID = 0,
+ PLANE_FDS = 1,
+}
diff --git a/gralloc4/interfaces/aidl/aidl_api/arm.graphics/current/arm/graphics/Compression.aidl b/gralloc4/interfaces/aidl/aidl_api/arm.graphics/current/arm/graphics/Compression.aidl
new file mode 100644
index 0000000..22510ca
--- /dev/null
+++ b/gralloc4/interfaces/aidl/aidl_api/arm.graphics/current/arm/graphics/Compression.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package arm.graphics;
+@Backing(type="long") @VintfStability
+enum Compression {
+ AFBC = 0,
+}
diff --git a/gralloc4/interfaces/aidl/arm/graphics/ArmMetadataType.aidl b/gralloc4/interfaces/aidl/arm/graphics/ArmMetadataType.aidl
new file mode 100644
index 0000000..cddefd8
--- /dev/null
+++ b/gralloc4/interfaces/aidl/arm/graphics/ArmMetadataType.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2020 Arm Limited.
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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.
+ */
+
+package arm.graphics;
+
+/**
+ * Used by IAllocator/IMapper (gralloc) to describe Arm private metadata types.
+ *
+ * This is an enum that defines Arm's types of gralloc 4 buffer metadata.
+ */
+@VintfStability
+@Backing(type="long")
+enum ArmMetadataType {
+ INVALID = 0,
+
+ /**
+ * Gives a list of FDs as int64_ts one for each plane of the buffer. These
+ * then correspond to the planeLayouts returned by
+ * android.hardware.graphics.common.StandardMetadataType::PLANE_LAYOUTS
+ */
+ PLANE_FDS = 1,
+}
diff --git a/gralloc4/interfaces/aidl/arm/graphics/Compression.aidl b/gralloc4/interfaces/aidl/arm/graphics/Compression.aidl
new file mode 100644
index 0000000..174e4c5
--- /dev/null
+++ b/gralloc4/interfaces/aidl/arm/graphics/Compression.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 Arm Limited.
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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.
+ */
+
+package arm.graphics;
+
+/**
+ * Used by IAllocator/IMapper (gralloc) to describe Arm compression strategies
+ */
+@VintfStability
+@Backing(type="long")
+enum Compression {
+ /**
+ * Arm Framebuffer Compression. For details query the buffer's DRM Modifier using the metadata type
+ * aidl::android::hardware::graphics::common::StandardMetadataType::PIXEL_FORMAT_MODIFIER
+ */
+ AFBC = 0,
+}
diff --git a/gralloc4/interfaces/libs/drmutils/Android.bp b/gralloc4/interfaces/libs/drmutils/Android.bp
new file mode 100644
index 0000000..97b50c3
--- /dev/null
+++ b/gralloc4/interfaces/libs/drmutils/Android.bp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2020 Arm Limited.
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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.
+ */
+
+cc_library_static {
+ name: "libgralloc_drmutils",
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ srcs: [
+ "src/drmutils.cpp",
+ ],
+ vendor: true,
+ shared_libs: [
+ "liblog",
+ "libdrm",
+ "libcutils",
+ ],
+ header_libs: [
+ "libgralloc_headers",
+ ],
+ include_dirs: [
+ ".",
+ "hardware/google/gchips/include",
+ ],
+ export_include_dirs: [
+ ".",
+ ],
+ export_shared_lib_headers: [
+ "libdrm",
+ ],
+ export_header_lib_headers: [
+ "libgralloc_headers",
+ ],
+}
diff --git a/gralloc4/interfaces/libs/drmutils/drmutils.h b/gralloc4/interfaces/libs/drmutils/drmutils.h
new file mode 100644
index 0000000..f0bbdc3
--- /dev/null
+++ b/gralloc4/interfaces/libs/drmutils/drmutils.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2020 Arm Limited.
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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_LIBS_DRMUTILS_H
+#define GRALLOC_LIBS_DRMUTILS_H
+
+#include "mali_fourcc.h"
+#include "mali_gralloc_buffer.h"
+
+/**
+ * @brief Obtain the FOURCC corresponding to the given Gralloc internal format.
+ *
+ * @param hnd Private handle where the format information is stored.
+ *
+ * @return The DRM FOURCC format or DRM_FORMAT_INVALID in case of errors.
+ */
+uint32_t drm_fourcc_from_handle(const private_handle_t *hnd);
+
+/**
+ * @brief Extract the part of the DRM modifier stored inside the given internal format and private handle.
+ *
+ * @param hnd Private handle where part of the modifier information is stored.
+ * @param internal_format The internal format, where part of the modifier information is stored.
+ *
+ * @return The information extracted from the argument, in the form of a DRM modifier.
+ */
+uint64_t drm_modifier_from_handle(const private_handle_t *hnd);
+
+#endif
diff --git a/gralloc4/interfaces/libs/drmutils/src/drmutils.cpp b/gralloc4/interfaces/libs/drmutils/src/drmutils.cpp
new file mode 100644
index 0000000..53c0827
--- /dev/null
+++ b/gralloc4/interfaces/libs/drmutils/src/drmutils.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2020 Arm Limited.
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 "drmutils.h"
+#include "mali_gralloc_formats.h"
+#include <exynos_format.h>
+
+uint32_t drm_fourcc_from_handle(const private_handle_t *hnd)
+{
+ /* Clean the modifier bits in the internal format. */
+ struct table_entry
+ {
+ uint64_t internal;
+ uint32_t fourcc;
+ };
+
+ static table_entry table[] = {
+ { MALI_GRALLOC_FORMAT_INTERNAL_RAW16, DRM_FORMAT_R16 },
+ { MALI_GRALLOC_FORMAT_INTERNAL_RGBA_8888, DRM_FORMAT_ABGR8888 },
+ { MALI_GRALLOC_FORMAT_INTERNAL_BGRA_8888, DRM_FORMAT_ARGB8888 },
+ { MALI_GRALLOC_FORMAT_INTERNAL_RGB_565, DRM_FORMAT_RGB565 },
+ { MALI_GRALLOC_FORMAT_INTERNAL_RGBX_8888, DRM_FORMAT_XBGR8888 },
+ { MALI_GRALLOC_FORMAT_INTERNAL_RGB_888, DRM_FORMAT_BGR888 },
+ { MALI_GRALLOC_FORMAT_INTERNAL_RGBA_1010102, DRM_FORMAT_ABGR2101010 },
+ { MALI_GRALLOC_FORMAT_INTERNAL_RGBA_16161616, DRM_FORMAT_ABGR16161616F },
+ { MALI_GRALLOC_FORMAT_INTERNAL_YV12, DRM_FORMAT_YVU420 },
+ { MALI_GRALLOC_FORMAT_INTERNAL_NV12, DRM_FORMAT_NV12 },
+ { MALI_GRALLOC_FORMAT_INTERNAL_NV16, DRM_FORMAT_NV16 },
+ { MALI_GRALLOC_FORMAT_INTERNAL_NV21, DRM_FORMAT_NV21 },
+ { MALI_GRALLOC_FORMAT_INTERNAL_Y0L2, DRM_FORMAT_Y0L2 },
+ { MALI_GRALLOC_FORMAT_INTERNAL_Y210, DRM_FORMAT_Y210 },
+ { MALI_GRALLOC_FORMAT_INTERNAL_P010, DRM_FORMAT_P010 },
+ { MALI_GRALLOC_FORMAT_INTERNAL_P210, DRM_FORMAT_P210 },
+ { MALI_GRALLOC_FORMAT_INTERNAL_Y410, DRM_FORMAT_Y410 },
+ { MALI_GRALLOC_FORMAT_INTERNAL_YUV422_8BIT, DRM_FORMAT_YUYV },
+ { MALI_GRALLOC_FORMAT_INTERNAL_YUV420_8BIT_I, DRM_FORMAT_YUV420_8BIT },
+ { MALI_GRALLOC_FORMAT_INTERNAL_YUV420_10BIT_I, DRM_FORMAT_YUV420_10BIT },
+
+ /* Deprecated legacy formats, mapped to MALI_GRALLOC_FORMAT_INTERNAL_YUV422_8BIT. */
+ { HAL_PIXEL_FORMAT_YCbCr_422_I, DRM_FORMAT_YUYV },
+ /* Deprecated legacy formats, mapped to MALI_GRALLOC_FORMAT_INTERNAL_NV21. */
+ { HAL_PIXEL_FORMAT_YCrCb_420_SP, DRM_FORMAT_NV21 },
+ /* Format introduced in Android P, mapped to MALI_GRALLOC_FORMAT_INTERNAL_P010. */
+ { HAL_PIXEL_FORMAT_YCBCR_P010, DRM_FORMAT_P010 },
+
+ /* Exynos Formats */
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP, DRM_FORMAT_NV12 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M, DRM_FORMAT_NV21 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL, DRM_FORMAT_NV21 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M, DRM_FORMAT_NV12 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YV12_M, DRM_FORMAT_YVU420 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M, DRM_FORMAT_NV12 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B, DRM_FORMAT_NV12 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED, DRM_FORMAT_NV12 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN, DRM_FORMAT_NV12 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B, DRM_FORMAT_NV12 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M, DRM_FORMAT_P010 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P, DRM_FORMAT_NV12 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC, DRM_FORMAT_NV12 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC, DRM_FORMAT_NV12 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC, DRM_FORMAT_P010 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC, DRM_FORMAT_P010 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_SBWC, DRM_FORMAT_NV21 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC, DRM_FORMAT_P010 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L50, DRM_FORMAT_NV12 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L75, DRM_FORMAT_NV12 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L50, DRM_FORMAT_NV12 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L75, DRM_FORMAT_NV12 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L40, DRM_FORMAT_P010 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L60, DRM_FORMAT_P010 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L80, DRM_FORMAT_P010 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L40, DRM_FORMAT_P010 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L60, DRM_FORMAT_P010 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L80, DRM_FORMAT_P010 },
+ };
+
+ const uint64_t unmasked_format = hnd->alloc_format;
+ const uint64_t internal_format = (unmasked_format & MALI_GRALLOC_INTFMT_FMT_MASK);
+ for (size_t i = 0; i < sizeof(table) / sizeof(table[0]); i++)
+ {
+ if (table[i].internal == internal_format)
+ {
+ bool afbc = (unmasked_format & MALI_GRALLOC_INTFMT_AFBCENABLE_MASK);
+ /* The internal RGB565 format describes two different component orderings depending on AFBC. */
+ if (afbc && internal_format == MALI_GRALLOC_FORMAT_INTERNAL_RGB_565)
+ {
+ return DRM_FORMAT_BGR565;
+ }
+ return table[i].fourcc;
+ }
+ }
+
+ return DRM_FORMAT_INVALID;
+}
+
+uint64_t drm_modifier_from_handle(const private_handle_t *hnd)
+{
+ const uint64_t internal_format = hnd->alloc_format;
+ if ((internal_format & MALI_GRALLOC_INTFMT_AFBCENABLE_MASK) == 0)
+ {
+ return 0;
+ }
+
+ uint64_t modifier = 0;
+
+ if (internal_format & MALI_GRALLOC_INTFMT_AFBC_SPLITBLK)
+ {
+ modifier |= AFBC_FORMAT_MOD_SPLIT;
+ }
+
+ if (internal_format & MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS)
+ {
+ modifier |= AFBC_FORMAT_MOD_TILED;
+ }
+
+ if (internal_format & MALI_GRALLOC_INTFMT_AFBC_DOUBLE_BODY)
+ {
+ modifier |= AFBC_FORMAT_MOD_DB;
+ }
+
+ if (internal_format & MALI_GRALLOC_INTFMT_AFBC_BCH)
+ {
+ modifier |= AFBC_FORMAT_MOD_BCH;
+ }
+
+ if (internal_format & MALI_GRALLOC_INTFMT_AFBC_YUV_TRANSFORM)
+ {
+ modifier |= AFBC_FORMAT_MOD_YTR;
+ }
+
+ if (internal_format & MALI_GRALLOC_INTFMT_AFBC_SPARSE)
+ {
+ modifier |= AFBC_FORMAT_MOD_SPARSE;
+ }
+
+ /* Extract the block-size modifiers. */
+ if (internal_format & MALI_GRALLOC_INTFMT_AFBC_WIDEBLK)
+ {
+ modifier |= (hnd->is_multi_plane() ? AFBC_FORMAT_MOD_BLOCK_SIZE_32x8_64x4 : AFBC_FORMAT_MOD_BLOCK_SIZE_32x8);
+ }
+ else if (internal_format & MALI_GRALLOC_INTFMT_AFBC_EXTRAWIDEBLK)
+ {
+ modifier |= AFBC_FORMAT_MOD_BLOCK_SIZE_64x4;
+ }
+ else
+ {
+ modifier |= AFBC_FORMAT_MOD_BLOCK_SIZE_16x16;
+ }
+
+ return DRM_FORMAT_MOD_ARM_AFBC(modifier);
+}
diff --git a/gralloc4/service/4.x/Android.bp b/gralloc4/service/4.x/Android.bp
new file mode 100644
index 0000000..b44f1a0
--- /dev/null
+++ b/gralloc4/service/4.x/Android.bp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 Arm Limited.
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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.
+ */
+
+cc_binary {
+ name: "android.hardware.graphics.allocator@4.0-service",
+ proprietary: true,
+ relative_install_path: "hw",
+ srcs: [
+ "service.cpp",
+ ],
+ init_rc: [
+ "android.hardware.graphics.allocator@4.0-service.rc",
+ ],
+ shared_libs: [
+ "android.hardware.graphics.allocator@4.0",
+ "libhidlbase",
+ "liblog",
+ "libutils",
+ ],
+ required: [
+ "android.hardware.graphics.allocator@4.0-impl",
+ ],
+}
diff --git a/gralloc4/service/4.x/android.hardware.graphics.allocator@4.0-service.rc b/gralloc4/service/4.x/android.hardware.graphics.allocator@4.0-service.rc
new file mode 100644
index 0000000..6523f4e
--- /dev/null
+++ b/gralloc4/service/4.x/android.hardware.graphics.allocator@4.0-service.rc
@@ -0,0 +1,7 @@
+service vendor.gralloc-4-0 /vendor/bin/hw/android.hardware.graphics.allocator@4.0-service
+ class hal animation
+ interface android.hardware.graphics.allocator@4.0::IAllocator default
+ user system
+ group graphics drmrpc
+ capabilities SYS_NICE
+ onrestart restart surfaceflinger
diff --git a/gralloc4/service/4.x/service.cpp b/gralloc4/service/4.x/service.cpp
new file mode 100644
index 0000000..bd28407
--- /dev/null
+++ b/gralloc4/service/4.x/service.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 Arm Limited.
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 "android.hardware.graphics.allocator@4.0-service"
+
+#include <android/hardware/graphics/allocator/4.0/IAllocator.h>
+
+#include <hidl/LegacySupport.h>
+
+using android::hardware::defaultPassthroughServiceImplementation;
+using android::hardware::graphics::allocator::V4_0::IAllocator;
+
+int main() {
+ return defaultPassthroughServiceImplementation<IAllocator>(/*maxThreads*/ 4);
+}
diff --git a/gralloc4/src/4.x/Android.bp b/gralloc4/src/4.x/Android.bp
new file mode 100644
index 0000000..86d7bee
--- /dev/null
+++ b/gralloc4/src/4.x/Android.bp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2020 Arm Limited.
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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.
+ */
+
+cc_defaults {
+ name: "arm_gralloc_version_defaults",
+ target: {
+ android: {
+ shared_libs: [
+ "android.hardware.graphics.common@1.2",
+ ],
+ },
+ },
+ cflags: [
+ "-DLOG_TAG=\"gralloc4\"",
+ "-DGRALLOC_VERSION_MAJOR=4",
+ "-DHIDL_ALLOCATOR_VERSION_SCALED=400",
+ "-DHIDL_MAPPER_VERSION_SCALED=400",
+ "-DHIDL_COMMON_VERSION_SCALED=120",
+ ],
+}
+
+cc_defaults {
+ name: "arm_gralloc_api_4x_defaults",
+ defaults: [
+ "arm_gralloc_defaults",
+ "arm_gralloc_version_defaults",
+ ],
+ compile_multilib: "both",
+ relative_install_path: "hw/",
+ shared_libs: [
+ "libhardware",
+ "liblog",
+ "libcutils",
+ "libion_google",
+ "libsync",
+ "libutils",
+ "libnativewindow",
+ "libhidlbase",
+ "libgralloctypes",
+ ],
+ static_libs: [
+ "libarect",
+ "libgralloc_core",
+ "libgralloc_allocator",
+ "libgralloc_capabilities",
+ "libdrm",
+ ],
+ header_libs: [
+ "libnativebase_headers",
+ ],
+ export_shared_lib_headers: [
+ "libhidlbase",
+ ],
+}
+
+cc_library_shared {
+ name: "android.hardware.graphics.allocator@4.0-impl",
+ defaults: [
+ "arm_gralloc_api_4x_defaults",
+ ],
+ shared_libs: [
+ "android.hardware.graphics.allocator@4.0",
+ "android.hardware.graphics.mapper@4.0",
+ ],
+ srcs: [
+ "GrallocAllocator.cpp",
+ ":libgralloc_hidl_common_allocator",
+ ":libgralloc_hidl_common_shared_metadata",
+ ],
+ include_dirs: [
+ "hardware/google/gchips/include",
+ ],
+}
+
+cc_library_shared {
+ name: "android.hardware.graphics.mapper@4.0-impl",
+ defaults: [
+ "arm_gralloc_api_4x_defaults",
+ ],
+ static_libs: [
+ "libgralloc_drmutils",
+ ],
+ shared_libs: [
+ "arm.graphics-ndk_platform",
+ "android.hardware.graphics.mapper@4.0",
+ ],
+ srcs: [
+ "GrallocMapper.cpp",
+ ":libgralloc_hidl_common_mapper",
+ ":libgralloc_hidl_common_mapper_metadata",
+ ":libgralloc_hidl_common_shared_metadata",
+ ],
+ include_dirs: [
+ "hardware/google/gchips/include",
+ ],
+}
diff --git a/gralloc4/src/4.x/GrallocAllocator.cpp b/gralloc4/src/4.x/GrallocAllocator.cpp
new file mode 100644
index 0000000..c3c0d4b
--- /dev/null
+++ b/gralloc4/src/4.x/GrallocAllocator.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2020 Arm Limited. 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 "GrallocAllocator.h"
+#include "hidl_common/BufferDescriptor.h"
+#include "hidl_common/Allocator.h"
+#include "allocator/mali_gralloc_ion.h"
+
+namespace arm
+{
+namespace allocator
+{
+using android::hardware::graphics::allocator::V4_0::IAllocator;
+using android::hardware::graphics::mapper::V4_0::Error;
+using android::hardware::Return;
+using android::hardware::hidl_handle;
+using android::hardware::hidl_vec;
+using android::hardware::Void;
+using android::hardware::hidl_string;
+
+GrallocAllocator::GrallocAllocator()
+{
+}
+
+GrallocAllocator::~GrallocAllocator()
+{
+ mali_gralloc_ion_close();
+}
+
+Return<void> GrallocAllocator::allocate(const BufferDescriptor &descriptor, uint32_t count, allocate_cb hidl_cb)
+{
+ buffer_descriptor_t bufferDescriptor;
+ if (!mapper::common::grallocDecodeBufferDescriptor(descriptor, bufferDescriptor))
+ {
+ hidl_cb(Error::BAD_DESCRIPTOR, 0, hidl_vec<hidl_handle>());
+ return Void();
+ }
+ common::allocate(bufferDescriptor, count, hidl_cb);
+ return Void();
+}
+
+} // namespace allocator
+} // namespace arm
+
+extern "C" IAllocator *HIDL_FETCH_IAllocator(const char * /* name */)
+{
+ MALI_GRALLOC_LOGV("Arm Module IAllocator %d.%d, pid = %d ppid = %d", GRALLOC_VERSION_MAJOR,
+ (HIDL_ALLOCATOR_VERSION_SCALED - (GRALLOC_VERSION_MAJOR * 100)) / 10, getpid(), getppid());
+
+ return new arm::allocator::GrallocAllocator();
+} \ No newline at end of file
diff --git a/gralloc4/src/4.x/GrallocAllocator.h b/gralloc4/src/4.x/GrallocAllocator.h
new file mode 100644
index 0000000..64de2ac
--- /dev/null
+++ b/gralloc4/src/4.x/GrallocAllocator.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2020 Arm Limited. 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 ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V4_x_GRALLOC_H
+#define ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V4_x_GRALLOC_H
+
+#include "gralloc_allocator_hidl_header.h"
+#include "core/mali_gralloc_bufferdescriptor.h"
+
+namespace arm
+{
+namespace allocator
+{
+using android::hardware::graphics::mapper::V4_0::BufferDescriptor;
+using android::hardware::Return;
+using android::hardware::hidl_handle;
+
+class GrallocAllocator : public IAllocator
+{
+public:
+ /**
+ * IAllocator constructor. All the state information required for the Gralloc
+ * private module is populated in its default constructor. Gralloc 4.0 specific
+ * state information can be populated here.
+ */
+ GrallocAllocator();
+
+ /**
+ * IAllocator destructor. All the resources acquired for Gralloc private module
+ * are released
+ */
+ virtual ~GrallocAllocator();
+
+ /* Override IAllocator 4.0 interface */
+ Return<void> allocate(const BufferDescriptor &descriptor, uint32_t count, allocate_cb hidl_cb) override;
+};
+
+} // namespace allocator
+} // namespace arm
+
+#endif // ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V4_x_GRALLOC_H
diff --git a/gralloc4/src/4.x/GrallocMapper.cpp b/gralloc4/src/4.x/GrallocMapper.cpp
new file mode 100644
index 0000000..d60a374
--- /dev/null
+++ b/gralloc4/src/4.x/GrallocMapper.cpp
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2020 Arm Limited. All rights reserved.
+ *
+ * Copyright 2016 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 "GrallocMapper.h"
+#include "hidl_common/BufferDescriptor.h"
+#include "hidl_common/MapperMetadata.h"
+
+#include "allocator/mali_gralloc_ion.h"
+
+namespace arm
+{
+namespace mapper
+{
+
+using android::hardware::graphics::mapper::V4_0::Error;
+using android::hardware::graphics::mapper::V4_0::BufferDescriptor;
+using android::hardware::graphics::mapper::V4_0::IMapper;
+using android::hardware::Return;
+using android::hardware::hidl_handle;
+using android::hardware::hidl_vec;
+using android::hardware::Void;
+
+
+GrallocMapper::GrallocMapper()
+{
+}
+
+GrallocMapper::~GrallocMapper()
+{
+ mali_gralloc_ion_close();
+}
+
+Return<void> GrallocMapper::createDescriptor(const BufferDescriptorInfo &descriptorInfo, createDescriptor_cb hidl_cb)
+{
+ if (common::validateDescriptorInfo(descriptorInfo))
+ {
+ hidl_cb(Error::NONE, common::grallocEncodeBufferDescriptor<uint8_t>(descriptorInfo));
+ }
+ else
+ {
+ MALI_GRALLOC_LOGE("Invalid attributes to create descriptor for Mapper 3.0");
+ hidl_cb(Error::BAD_VALUE, BufferDescriptor());
+ }
+
+ return Void();
+}
+
+Return<void> GrallocMapper::importBuffer(const hidl_handle &rawHandle, importBuffer_cb hidl_cb)
+{
+ common::importBuffer(rawHandle, hidl_cb);
+ return Void();
+}
+
+Return<Error> GrallocMapper::freeBuffer(void *buffer)
+{
+ return common::freeBuffer(buffer);
+}
+
+Return<Error> GrallocMapper::validateBufferSize(void *buffer, const BufferDescriptorInfo &descriptorInfo,
+ uint32_t in_stride)
+{
+ /* All Gralloc allocated buffers must be conform to local descriptor validation */
+ if (!common::validateDescriptorInfo<BufferDescriptorInfo>(descriptorInfo))
+ {
+ MALI_GRALLOC_LOGE("Invalid descriptor attributes for validating buffer size");
+ return Error::BAD_VALUE;
+ }
+ return common::validateBufferSize(buffer, descriptorInfo, in_stride);
+}
+
+Return<void> GrallocMapper::lock(void *buffer, uint64_t cpuUsage, const IMapper::Rect &accessRegion,
+ const hidl_handle &acquireFence, lock_cb hidl_cb)
+{
+ common::lock(buffer, cpuUsage, accessRegion, acquireFence, hidl_cb);
+ return Void();
+}
+
+Return<void> GrallocMapper::unlock(void *buffer, unlock_cb hidl_cb)
+{
+ common::unlock(buffer, hidl_cb);
+ return Void();
+}
+
+Return<void> GrallocMapper::flushLockedBuffer(void *buffer, flushLockedBuffer_cb hidl_cb)
+{
+ common::flushLockedBuffer(buffer, hidl_cb);
+ return Void();
+}
+
+Return<Error> GrallocMapper::rereadLockedBuffer(void *buffer)
+{
+ return common::rereadLockedBuffer(buffer);
+}
+
+Return<void> GrallocMapper::get(void *buffer, const MetadataType &metadataType, IMapper::get_cb hidl_cb)
+{
+ common::get(buffer, metadataType, hidl_cb);
+ return Void();
+}
+
+Return<Error> GrallocMapper::set(void *buffer, const MetadataType &metadataType, const hidl_vec<uint8_t> &metadata)
+{
+ return common::set(buffer, metadataType, metadata);
+}
+
+Return<void> GrallocMapper::getFromBufferDescriptorInfo(const BufferDescriptorInfo &description,
+ const MetadataType &metadataType,
+ getFromBufferDescriptorInfo_cb hidl_cb)
+{
+ common::getFromBufferDescriptorInfo(description, metadataType, hidl_cb);
+ return Void();
+}
+
+Return<void> GrallocMapper::getTransportSize(void *buffer, getTransportSize_cb hidl_cb)
+{
+ common::getTransportSize(buffer, hidl_cb);
+ return Void();
+}
+
+Return<void> GrallocMapper::isSupported(const IMapper::BufferDescriptorInfo &description, isSupported_cb hidl_cb)
+{
+ if (!common::validateDescriptorInfo<BufferDescriptorInfo>(description))
+ {
+ MALI_GRALLOC_LOGE("Invalid descriptor attributes for validating buffer size");
+ hidl_cb(Error::BAD_VALUE, false);
+ }
+ common::isSupported(description, hidl_cb);
+ return Void();
+}
+
+Return<void> GrallocMapper::listSupportedMetadataTypes(listSupportedMetadataTypes_cb hidl_cb)
+{
+ common::listSupportedMetadataTypes(hidl_cb);
+ return Void();
+}
+
+Return<void> GrallocMapper::dumpBuffer(void *buffer, dumpBuffer_cb hidl_cb)
+{
+ common::dumpBuffer(buffer, hidl_cb);
+ return Void();
+}
+
+Return<void> GrallocMapper::dumpBuffers(dumpBuffers_cb hidl_cb)
+{
+ common::dumpBuffers(hidl_cb);
+ return Void();
+}
+
+Return<void> GrallocMapper::getReservedRegion(void *buffer, getReservedRegion_cb hidl_cb)
+{
+ common::getReservedRegion(buffer, hidl_cb);
+ return Void();
+}
+
+} // namespace mapper
+} // namespace arm
+
+extern "C" IMapper *HIDL_FETCH_IMapper(const char * /* name */)
+{
+ MALI_GRALLOC_LOGV("Arm Module IMapper %d.%d , pid = %d ppid = %d ", GRALLOC_VERSION_MAJOR,
+ (HIDL_MAPPER_VERSION_SCALED - (GRALLOC_VERSION_MAJOR * 100)) / 10, getpid(), getppid());
+
+ return new arm::mapper::GrallocMapper();
+} \ No newline at end of file
diff --git a/gralloc4/src/4.x/GrallocMapper.h b/gralloc4/src/4.x/GrallocMapper.h
new file mode 100644
index 0000000..959efa5
--- /dev/null
+++ b/gralloc4/src/4.x/GrallocMapper.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2020 Arm Limited. All rights reserved.
+ *
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_HARDWARE_GRAPHICS_MAPPER_V4_x_GRALLOC_MAPPER_H
+#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V4_x_GRALLOC_MAPPER_H
+
+#include "hidl_common/Mapper.h"
+
+namespace arm
+{
+namespace mapper
+{
+
+using android::hardware::Return;
+using android::hardware::hidl_handle;
+using android::hardware::hidl_vec;
+
+class GrallocMapper : public IMapper
+{
+public:
+ /**
+ * IMapper constructor. All the state information required for the Gralloc
+ * private module is populated in its default constructor. Gralloc 4.x specific
+ * state information can be populated here.
+ */
+ GrallocMapper();
+
+ /**
+ * IMapper destructor. All the resources aquired for Gralloc private module
+ * (in the IMapper context) are released
+ */
+ ~GrallocMapper();
+
+ /* Override the public IMapper 4.0 interface */
+ Return<void> createDescriptor(const BufferDescriptorInfo &descriptorInfo, createDescriptor_cb hidl_cb) override;
+
+ Return<void> importBuffer(const hidl_handle &rawHandle, importBuffer_cb hidl_cb) override;
+
+ Return<Error> freeBuffer(void *buffer) override;
+
+ Return<Error> validateBufferSize(void *buffer, const IMapper::BufferDescriptorInfo &descriptorInfo,
+ uint32_t stride) override;
+
+ Return<void> getTransportSize(void *buffer, getTransportSize_cb _hidl_cb) override;
+
+ Return<void> lock(void *buffer, uint64_t cpuUsage, const IMapper::Rect &accessRegion,
+ const hidl_handle &acquireFence, lock_cb hidl_cb) override;
+
+ Return<void> unlock(void *buffer, unlock_cb hidl_cb) override;
+
+ Return<void> flushLockedBuffer(void *buffer, flushLockedBuffer_cb hidl_cb) override;
+
+ Return<Error> rereadLockedBuffer(void *buffer) override;
+
+ Return<void> isSupported(const IMapper::BufferDescriptorInfo &description, isSupported_cb hidl_cb) override;
+
+ Return<void> get(void *buffer, const MetadataType &metadataType, IMapper::get_cb hidl_cb) override;
+
+ Return<Error> set(void *buffer, const MetadataType &metadataType, const hidl_vec<uint8_t> &metadata) override;
+
+ Return<void> getFromBufferDescriptorInfo(BufferDescriptorInfo const &description, MetadataType const &metadataType,
+ getFromBufferDescriptorInfo_cb hidl_cb) override;
+
+ Return<void> listSupportedMetadataTypes(listSupportedMetadataTypes_cb _hidl_cb) override;
+
+ Return<void> dumpBuffer(void *buffer, dumpBuffer_cb _hidl_cb) override;
+
+ Return<void> dumpBuffers(dumpBuffers_cb _hidl_cb) override;
+
+ Return<void> getReservedRegion(void *buffer, getReservedRegion_cb _hidl_cb) override;
+};
+
+} // namespace mapper
+} // namespace arm
+
+#endif // ANDROID_HARDWARE_GRAPHICS_MAPPER_V4_x_GRALLOC_MAPPER_H
diff --git a/gralloc4/src/4.x/gralloc_allocator_hidl_header.h b/gralloc4/src/4.x/gralloc_allocator_hidl_header.h
new file mode 100644
index 0000000..586b07a
--- /dev/null
+++ b/gralloc4/src/4.x/gralloc_allocator_hidl_header.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2020 Arm Limited. All rights reserved.
+ *
+ * Copyright 2016 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_HIDL_HEADER_H
+#define GRALLOC_ALLOCATOR_HIDL_HEADER_H
+
+#include <android/hardware/graphics/allocator/4.0/IAllocator.h>
+using android::hardware::graphics::allocator::V4_0::IAllocator;
+using android::hardware::graphics::mapper::V4_0::Error;
+
+#endif
diff --git a/gralloc4/src/4.x/gralloc_mapper_hidl_header.h b/gralloc4/src/4.x/gralloc_mapper_hidl_header.h
new file mode 100644
index 0000000..6d3d549
--- /dev/null
+++ b/gralloc4/src/4.x/gralloc_mapper_hidl_header.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 Arm Limited. All rights reserved.
+ *
+ * Copyright 2016 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_MAPPER_HIDL_HEADER_H
+#define GRALLOC_MAPPER_HIDL_HEADER_H
+
+#include <android/hardware/graphics/mapper/4.0/IMapper.h>
+#include "mali_fourcc.h"
+#include <gralloctypes/Gralloc4.h>
+
+using android::hardware::graphics::mapper::V4_0::Error;
+using android::hardware::graphics::mapper::V4_0::BufferDescriptor;
+using android::hardware::graphics::common::V1_2::PixelFormat;
+using android::hardware::graphics::common::V1_2::BufferUsage;
+using android::hardware::graphics::mapper::V4_0::IMapper;
+
+#endif
diff --git a/gralloc4/src/Android.bp b/gralloc4/src/Android.bp
new file mode 100644
index 0000000..b7b800e
--- /dev/null
+++ b/gralloc4/src/Android.bp
@@ -0,0 +1,32 @@
+
+/*
+ * Copyright (C) 2020 Arm Limited.
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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.
+ */
+
+cc_library_headers {
+ name: "libgralloc_headers",
+ vendor: true,
+ host_supported: true,
+ export_include_dirs: [
+ ".",
+ ],
+ header_libs: [
+ "libsystem_headers",
+ ],
+ export_header_lib_headers: [
+ "libsystem_headers",
+ ],
+} \ No newline at end of file
diff --git a/gralloc4/src/allocator/Android.bp b/gralloc4/src/allocator/Android.bp
new file mode 100644
index 0000000..71e8e28
--- /dev/null
+++ b/gralloc4/src/allocator/Android.bp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2020 Arm Limited.
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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.
+ */
+
+soong_config_module_type {
+ name: "arm_gralloc_allocator_cc_defaults",
+ module_type: "cc_defaults",
+ config_namespace: "arm_gralloc",
+ variables: [
+ "gralloc_use_ion_dma_heap",
+ "gralloc_use_ion_compound_page_heap",
+ "gralloc_init_afbc",
+ "gralloc_use_ion_dmabuf_sync",
+ ],
+ properties: [
+ "cflags",
+ ],
+}
+
+soong_config_bool_variable {
+ name: "gralloc_use_ion_dma_heap",
+}
+soong_config_bool_variable {
+ name: "gralloc_use_ion_compound_page_heap",
+}
+soong_config_bool_variable {
+ name: "gralloc_init_afbc",
+}
+soong_config_bool_variable {
+ name: "gralloc_use_ion_dmabuf_sync",
+}
+
+arm_gralloc_allocator_cc_defaults {
+ name: "arm_gralloc_allocator_defaults",
+ defaults: [
+ "arm_gralloc_defaults",
+ ],
+ soong_config_variables: {
+ gralloc_use_ion_dma_heap: {
+ cflags: [
+ "-DGRALLOC_USE_ION_DMA_HEAP=1",
+ ],
+ },
+ gralloc_use_ion_compound_page_heap: {
+ cflags: [
+ "-DGRALLOC_USE_ION_COMPOUND_PAGE_HEAP=1",
+ ],
+ },
+ gralloc_init_afbc: {
+ cflags: [
+ "-DGRALLOC_INIT_AFBC=1",
+ ],
+ },
+ gralloc_use_ion_dmabuf_sync: {
+ cflags: [
+ "-DGRALLOC_USE_ION_DMABUF_SYNC=1",
+ ],
+ },
+ },
+ srcs: [
+ "mali_gralloc_ion.cpp",
+ "mali_gralloc_shared_memory.cpp",
+ ],
+ static_libs: [
+ "libarect",
+ ],
+ shared_libs: [
+ "libhardware",
+ "liblog",
+ "libcutils",
+ "libion_google",
+ "libsync",
+ "libutils",
+ "libnativewindow",
+ ],
+ header_libs: [
+ "libnativebase_headers",
+ ],
+}
+
+cc_library_static {
+ name: "libgralloc_allocator",
+ defaults: [
+ "arm_gralloc_allocator_defaults",
+ "arm_gralloc_version_defaults",
+ ],
+}
diff --git a/gralloc4/src/allocator/mali_gralloc_ion.cpp b/gralloc4/src/allocator/mali_gralloc_ion.cpp
new file mode 100644
index 0000000..d53664d
--- /dev/null
+++ b/gralloc4/src/allocator/mali_gralloc_ion.cpp
@@ -0,0 +1,776 @@
+/*
+ * Copyright (C) 2016-2020 ARM Limited. All rights reserved.
+ *
+ * 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 <string.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include <log/log.h>
+#include <cutils/atomic.h>
+
+#include <linux/dma-buf.h>
+#include <vector>
+#include <sys/ioctl.h>
+
+#include <hardware/hardware.h>
+#include <hardware/gralloc1.h>
+
+#include <hardware/exynos/ion.h>
+#include <hardware/exynos/dmabuf_container.h>
+
+#include "mali_gralloc_buffer.h"
+#include "gralloc_helper.h"
+#include "mali_gralloc_formats.h"
+#include "mali_gralloc_usages.h"
+#include "core/mali_gralloc_bufferdescriptor.h"
+#include "core/mali_gralloc_bufferallocation.h"
+
+#include "mali_gralloc_ion.h"
+
+#define INIT_ZERO(obj) (memset(&(obj), 0, sizeof((obj))))
+
+#define HEAP_MASK_FROM_ID(id) (1 << id)
+#define HEAP_MASK_FROM_TYPE(type) (1 << type)
+
+#if defined(ION_HEAP_SECURE_MASK)
+#if (HEAP_MASK_FROM_TYPE(ION_HEAP_TYPE_SECURE) != ION_HEAP_SECURE_MASK)
+#error "ION_HEAP_TYPE_SECURE value is not compatible with ION_HEAP_SECURE_MASK"
+#endif
+#endif
+
+struct ion_device
+{
+ int client()
+ {
+ return ion_client;
+ }
+
+ static void close()
+ {
+ ion_device &dev = get_inst();
+ if (dev.ion_client >= 0)
+ {
+ exynos_ion_close(dev.ion_client);
+ dev.ion_client = -1;
+ }
+ }
+
+ static ion_device *get()
+ {
+ ion_device &dev = get_inst();
+ if (dev.ion_client < 0)
+ {
+ if (dev.open_and_query_ion() != 0)
+ {
+ close();
+ }
+ }
+
+ if (dev.ion_client < 0)
+ {
+ return nullptr;
+ }
+ return &dev;
+ }
+
+ /*
+ * Identifies a heap and retrieves file descriptor from ION for allocation
+ *
+ * @param usage [in] Producer and consumer combined usage.
+ * @param size [in] Requested buffer size (in bytes).
+ * @param heap_type [in] Requested heap type.
+ * @param flags [in] ION allocation attributes defined by ION_FLAG_*.
+ * @param min_pgsz [out] Minimum page size (in bytes).
+ *
+ * @return File handle which can be used for allocation, on success
+ * -1, otherwise.
+ */
+ int alloc_from_ion_heap(uint64_t usage, size_t size, unsigned int flags, int *min_pgsz);
+
+private:
+ int ion_client;
+
+ ion_device()
+ : ion_client(-1)
+ {
+ }
+
+ static ion_device& get_inst()
+ {
+ static ion_device dev;
+ return dev;
+ }
+
+ /*
+ * Opens the ION module. Queries heap information and stores it for later use
+ *
+ * @return 0 in case of success
+ * -1 for all error cases
+ */
+ int open_and_query_ion();
+};
+
+static void set_ion_flags(uint64_t usage, unsigned int *ion_flags)
+{
+ if (ion_flags == nullptr)
+ return;
+
+ if ((usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN)
+ {
+ *ion_flags |= ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC;
+
+ if (usage & GRALLOC_USAGE_HW_RENDER)
+ {
+ *ion_flags |= ION_FLAG_SYNC_FORCE;
+ }
+ }
+
+ if (usage & (GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE))
+ {
+ *ion_flags |= ION_FLAG_MAY_HWRENDER;
+ }
+
+ if (usage & GRALLOC_USAGE_NOZEROED)
+ {
+ *ion_flags |= ION_FLAG_NOZEROED;
+ }
+
+ /* TODO: does not seem to be used anymore. But check again to make sure */
+#ifdef GRALLOC_PROTECTED_ION_FLAG_FOR_CAMERA_RESERVED
+ if (usage & GRALLOC_USAGE_CAMERA_RESERVED)
+ {
+ *ion_flags |= ION_FLAG_PROTECTED;
+ }
+#endif
+ // DRM or Secure Camera
+ if (usage & (GRALLOC_USAGE_PROTECTED | GRALLOC_USAGE_SECURE_CAMERA_RESERVED))
+ {
+ /* W/A to Android R Camera vts_r5. (W/A requested by Visual S/W group MCD) */
+ if(!(usage & GRALLOC_USAGE_CAMERA_RESERVED))
+ {
+ *ion_flags |= ION_FLAG_PROTECTED;
+ }
+ }
+
+ /* TODO: used for exynos3830. Add this as an option to Android.bp */
+#if defined(GRALLOC_SCALER_WFD) && GRALLOC_SCALER_WFD == 1
+ if (usage & GRALLOC_USAGE_PRIVATE_NONSECURE && usage & GRALLOC_USAGE_HW_COMPOSER)
+ {
+ *ion_flags |= ION_FLAG_PROTECTED;
+ }
+#endif
+}
+
+static unsigned int select_heap_mask(uint64_t usage)
+{
+ unsigned int heap_mask;
+ if (usage & GRALLOC_USAGE_PROTECTED)
+ {
+ if (usage & GRALLOC_USAGE_PRIVATE_NONSECURE)
+ {
+ heap_mask = EXYNOS_ION_HEAP_SYSTEM_MASK;
+ }
+ else if (usage & GRALLOC_USAGE_CAMERA_RESERVED)
+ {
+ /* W/A to Android R Camera vts_r5. (W/A requested by Visual S/W group MCD) */
+ heap_mask = EXYNOS_ION_HEAP_SYSTEM_MASK;
+ }
+ else if (usage & GRALLOC_USAGE_SECURE_CAMERA_RESERVED)
+ {
+ heap_mask = EXYNOS_ION_HEAP_SECURE_CAMERA_MASK;
+ }
+ else if (usage & GRALLOC_USAGE_VIDEO_EXT)
+ {
+ heap_mask = EXYNOS_ION_HEAP_VIDEO_STREAM_MASK;
+ }
+ else if ((usage & GRALLOC_USAGE_HW_COMPOSER) &&
+ !(usage & GRALLOC_USAGE_HW_TEXTURE) &&
+ !(usage & GRALLOC_USAGE_HW_RENDER))
+ {
+ heap_mask = EXYNOS_ION_HEAP_VIDEO_SCALER_MASK;
+ }
+ else
+ {
+ heap_mask = EXYNOS_ION_HEAP_VIDEO_FRAME_MASK;
+ }
+ }
+ /* TODO: used for exynos3830. Add this as a an option to Android.bp */
+#if defined(GRALLOC_SCALER_WFD) && GRALLOC_SCALER_WFD == 1
+ else if (usage & GRALLOC_USAGE_PRIVATE_NONSECURE && usage & GRALLOC_USAGE_HW_COMPOSER)
+ {
+ heap_mask = EXYNOS_ION_HEAP_EXT_UI_MASK;
+ }
+#endif
+ else if (usage & GRALLOC_USAGE_CAMERA_RESERVED)
+ {
+ heap_mask = EXYNOS_ION_HEAP_CAMERA_MASK;
+ }
+ else if (usage & GRALLOC_USAGE_SECURE_CAMERA_RESERVED)
+ {
+ heap_mask = EXYNOS_ION_HEAP_SECURE_CAMERA_MASK;
+ }
+ else
+ {
+ heap_mask = EXYNOS_ION_HEAP_SYSTEM_MASK;
+ }
+
+ return heap_mask;
+}
+
+int ion_device::alloc_from_ion_heap(uint64_t usage, size_t size, unsigned int flags, int *min_pgsz)
+{
+ int shared_fd = -1;
+ int ret = -1;
+
+ /* TODO: remove min_pgsz? I don't think this is useful on Exynos */
+ if (ion_client < 0 ||
+ size <= 0 ||
+ min_pgsz == NULL)
+ {
+ return -1;
+ }
+
+ unsigned int heap_mask = select_heap_mask(usage);
+
+ shared_fd = exynos_ion_alloc(ion_client, size, heap_mask, flags);
+
+ *min_pgsz = SZ_4K;
+
+ return shared_fd;
+}
+
+int ion_device::open_and_query_ion()
+{
+ int ret = -1;
+
+ if (ion_client >= 0)
+ {
+ MALI_GRALLOC_LOGW("ION device already open");
+ return 0;
+ }
+
+ ion_client = exynos_ion_open();
+ if (ion_client < 0)
+ {
+ MALI_GRALLOC_LOGE("ion_open failed with %s", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int mali_gralloc_ion_sync(const private_handle_t * const hnd,
+ const bool read,
+ const bool write,
+ const bool start)
+{
+ int ret = 0;
+
+ if (hnd == NULL)
+ {
+ return -EINVAL;
+ }
+
+ ion_device *dev = ion_device::get();
+ int direction = 0;
+
+ if (read)
+ {
+ direction |= ION_SYNC_READ;
+ }
+ if (write)
+ {
+ direction |= ION_SYNC_WRITE;
+ }
+
+ for (int idx = 0; idx < hnd->fd_count; idx++)
+ {
+ if (start)
+ {
+ ret |= exynos_ion_sync_start(dev->client(), hnd->fds[idx], direction);
+ }
+ else
+ {
+ ret |= exynos_ion_sync_end(dev->client(), hnd->fds[idx], direction);
+ }
+ }
+
+ return ret;
+}
+
+
+/*
+ * Signal start of CPU access to the DMABUF exported from ION.
+ *
+ * @param hnd [in] Buffer handle
+ * @param read [in] Flag indicating CPU read access to memory
+ * @param write [in] Flag indicating CPU write access to memory
+ *
+ * @return 0 in case of success
+ * errno for all error cases
+ */
+int mali_gralloc_ion_sync_start(const private_handle_t * const hnd,
+ const bool read,
+ const bool write)
+{
+ return mali_gralloc_ion_sync(hnd, read, write, true);
+}
+
+
+/*
+ * Signal end of CPU access to the DMABUF exported from ION.
+ *
+ * @param hnd [in] Buffer handle
+ * @param read [in] Flag indicating CPU read access to memory
+ * @param write [in] Flag indicating CPU write access to memory
+ *
+ * @return 0 in case of success
+ * errno for all error cases
+ */
+int mali_gralloc_ion_sync_end(const private_handle_t * const hnd,
+ const bool read,
+ const bool write)
+{
+ return mali_gralloc_ion_sync(hnd, read, write, false);
+}
+
+
+void mali_gralloc_ion_free(private_handle_t * const hnd)
+{
+ for (int i = 0; i < hnd->fd_count; i++)
+ {
+ void* mapped_addr = reinterpret_cast<void*>(hnd->bases[i]);
+
+ /* Buffer might be unregistered already so we need to assure we have a valid handle */
+ if (mapped_addr != nullptr)
+ {
+ if (munmap(mapped_addr, hnd->alloc_sizes[i]) != 0)
+ {
+ /* TODO: more detailed error logs */
+ MALI_GRALLOC_LOGE("Failed to munmap handle %p", hnd);
+ }
+ }
+ close(hnd->fds[i]);
+ hnd->fds[i] = -1;
+ hnd->bases[i] = 0;
+ }
+}
+
+static void mali_gralloc_ion_free_internal(buffer_handle_t * const pHandle,
+ const uint32_t num_hnds)
+{
+ for (uint32_t i = 0; i < num_hnds; i++)
+ {
+ if (pHandle[i] != NULL)
+ {
+ private_handle_t * const hnd = (private_handle_t * const)pHandle[i];
+ mali_gralloc_ion_free(hnd);
+ }
+ }
+}
+
+int mali_gralloc_ion_allocate_attr(private_handle_t *hnd)
+{
+ ion_device *dev = ion_device::get();
+ if (!dev)
+ {
+ return -1;
+ }
+
+ int idx = hnd->get_share_attr_fd_index();
+ int ion_flags = 0;
+ int min_pgsz;
+ uint64_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
+
+ ion_flags = ION_FLAG_CACHED;
+
+ hnd->fds[idx] = dev->alloc_from_ion_heap(usage, hnd->attr_size, ion_flags, &min_pgsz);
+ if (hnd->fds[idx] < 0)
+ {
+ MALI_GRALLOC_LOGE("ion_alloc failed from client ( %d )", dev->client());
+ return -1;
+ }
+
+ hnd->incr_numfds(1);
+
+ return 0;
+}
+
+static inline int createBufferContainer(int *fd, int size, int *containerFd)
+{
+ int bufferContainerFd = -1;
+
+ if (fd == NULL || size < 1 || containerFd == NULL)
+ {
+ MALI_GRALLOC_LOGE("invalid parameters. fd(%p), size(%d), containerFd(%p)",
+ fd, size, containerFd);
+ return -EINVAL;
+ }
+
+ bufferContainerFd = dma_buf_merge(fd[0], fd + 1, size - 1);
+ if (bufferContainerFd < 0)
+ {
+ MALI_GRALLOC_LOGE("fail to create Buffer Container. containerFd(%d), size(%d)",
+ bufferContainerFd, size);
+ return -EINVAL;
+ }
+
+ *containerFd = bufferContainerFd;
+
+ return 0;
+}
+
+static int allocate_to_container(buffer_descriptor_t *bufDescriptor, uint32_t ion_flags,
+ int *min_pgsz, int fd_arr[])
+{
+ /* TODO: make batch size as BoardConfig option */
+#define GRALLOC_HFR_BATCH_SIZE 8
+ const int layer_count = GRALLOC_HFR_BATCH_SIZE;
+ int hfr_fds[3][layer_count];
+ int err = 0;
+ int64_t usage = bufDescriptor->consumer_usage | bufDescriptor->producer_usage;
+
+ ion_device *dev = ion_device::get();
+ if (!dev)
+ {
+ return -1;
+ }
+
+ memset(hfr_fds, 0xff, sizeof(hfr_fds));
+
+ for (int layer = 0; layer < layer_count; layer++)
+ {
+ for (int fidx = 0; fidx < bufDescriptor->fd_count; fidx++)
+ {
+ hfr_fds[fidx][layer] =dev->alloc_from_ion_heap(usage,
+ bufDescriptor->alloc_sizes[fidx], ion_flags, min_pgsz);
+
+ if (hfr_fds[fidx][layer] < 0)
+ {
+ MALI_GRALLOC_LOGE("ion_alloc failed from client ( %d )", dev->client());
+ goto finish;
+ }
+ }
+ }
+
+
+ for (int fidx = 0; fidx < bufDescriptor->fd_count; fidx++)
+ {
+ err = createBufferContainer(hfr_fds[fidx], layer_count, &fd_arr[fidx]);
+ if (err)
+ {
+ for (int i = 0; i < fidx; i++)
+ {
+ if (fd_arr[i] >= 0)
+ {
+ close(fd_arr[i]);
+ fd_arr[i] = -1;
+ }
+ }
+
+ goto finish;
+ }
+ }
+
+finish:
+ /* free single fds to make ref count to 1 */
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < layer_count; j++)
+ if (hfr_fds[i][j] >= 0) close(hfr_fds[i][j]);
+
+ return err;
+}
+
+/*
+ * Allocates ION buffers
+ *
+ * @param descriptors [in] Buffer request descriptors
+ * @param numDescriptors [in] Number of descriptors
+ * @param pHandle [out] Handle for each allocated buffer
+ * @param shared_backend [out] Shared buffers flag
+ *
+ * @return File handle which can be used for allocation, on success
+ * -1, otherwise.
+ */
+int mali_gralloc_ion_allocate(const gralloc_buffer_descriptor_t *descriptors,
+ uint32_t numDescriptors, buffer_handle_t *pHandle,
+ bool *shared_backend)
+{
+ GRALLOC_UNUSED(shared_backend);
+
+ static int support_protected = 1;
+ unsigned int priv_heap_flag = 0;
+ unsigned char *cpu_ptr = NULL;
+ uint64_t usage;
+ uint32_t i, max_buffer_index = 0;
+ unsigned int ion_flags = 0;
+ int min_pgsz = 0;
+ int fds[5] = {-1, -1, -1, -1, -1};
+
+ ion_device *dev = ion_device::get();
+ if (!dev)
+ {
+ return -1;
+ }
+
+ for (i = 0; i < numDescriptors; i++)
+ {
+ buffer_descriptor_t *bufDescriptor = (buffer_descriptor_t *)(descriptors[i]);
+ usage = bufDescriptor->consumer_usage | bufDescriptor->producer_usage;
+
+ ion_flags = 0;
+ set_ion_flags(usage, &ion_flags);
+
+ if (usage & GRALLOC_USAGE_HFR_MODE)
+ {
+ priv_heap_flag |= private_handle_t::PRIV_FLAGS_USES_HFR_MODE;
+
+ if (0 > allocate_to_container(bufDescriptor, ion_flags, &min_pgsz, fds))
+ {
+ MALI_GRALLOC_LOGE("allocate to container failed");
+ mali_gralloc_ion_free_internal(pHandle, numDescriptors);
+ return -1;
+ }
+ }
+ else
+ {
+ for (int fidx = 0; fidx < bufDescriptor->fd_count; fidx++)
+ {
+ fds[fidx] = dev->alloc_from_ion_heap(usage, bufDescriptor->alloc_sizes[fidx], ion_flags, &min_pgsz);
+
+ if (fds[fidx] < 0)
+ {
+ MALI_GRALLOC_LOGE("ion_alloc failed from client ( %d )", dev->client());
+
+ for (int cidx = 0; cidx < fidx; cidx++)
+ {
+ close(fds[cidx]);
+ }
+
+ /* need to free already allocated memory. not just this one */
+ mali_gralloc_ion_free_internal(pHandle, numDescriptors);
+
+ return -1;
+ }
+ }
+ }
+
+ private_handle_t *hnd = new private_handle_t(
+ priv_heap_flag,
+ bufDescriptor->alloc_sizes,
+ bufDescriptor->consumer_usage, bufDescriptor->producer_usage,
+ fds, bufDescriptor->fd_count,
+ bufDescriptor->hal_format, bufDescriptor->alloc_format,
+ bufDescriptor->width, bufDescriptor->height, bufDescriptor->pixel_stride,
+ bufDescriptor->layer_count, bufDescriptor->plane_info);
+
+ if (NULL == hnd)
+ {
+ MALI_GRALLOC_LOGE("Private handle could not be created for descriptor:%d in non-shared usecase", i);
+
+ /* Close the obtained shared file descriptor for the current handle */
+ for (int j = 0; j < bufDescriptor->fd_count; j++)
+ {
+ close(fds[j]);
+ }
+
+ mali_gralloc_ion_free_internal(pHandle, numDescriptors);
+ return -1;
+ }
+
+ pHandle[i] = hnd;
+ }
+
+#if defined(GRALLOC_INIT_AFBC) && (GRALLOC_INIT_AFBC == 1)
+ for (i = 0; i < numDescriptors; i++)
+ {
+ buffer_descriptor_t *bufDescriptor = (buffer_descriptor_t *)(descriptors[i]);
+ private_handle_t *hnd = (private_handle_t *)(pHandle[i]);
+
+ usage = bufDescriptor->consumer_usage | bufDescriptor->producer_usage;
+
+ if ((bufDescriptor->alloc_format & MALI_GRALLOC_INTFMT_AFBCENABLE_MASK)
+ && !(usage & GRALLOC_USAGE_PROTECTED))
+ {
+ /* TODO: only map for AFBC buffers */
+ cpu_ptr =
+ (unsigned char *)mmap(NULL, bufDescriptor->alloc_sizes[0], PROT_READ | PROT_WRITE, MAP_SHARED, hnd->fds[0], 0);
+
+ if (MAP_FAILED == cpu_ptr)
+ {
+ MALI_GRALLOC_LOGE("mmap failed from client ( %d ), fd ( %d )", dev->client(), hnd->fds[0]);
+ mali_gralloc_ion_free_internal(pHandle, numDescriptors);
+ return -1;
+ }
+
+ mali_gralloc_ion_sync_start(hnd, true, true);
+
+ /* For separated plane YUV, there is a header to initialise per plane. */
+ const plane_info_t *plane_info = bufDescriptor->plane_info;
+ const bool is_multi_plane = hnd->is_multi_plane();
+ for (int i = 0; i < MAX_PLANES && (i == 0 || plane_info[i].byte_stride != 0); i++)
+ {
+ init_afbc(cpu_ptr + plane_info[i].offset,
+ bufDescriptor->alloc_format,
+ is_multi_plane,
+ plane_info[i].alloc_width,
+ plane_info[i].alloc_height);
+ }
+
+ mali_gralloc_ion_sync_end(hnd, true, true);
+
+ munmap(cpu_ptr, bufDescriptor->alloc_sizes[0]);
+ }
+ }
+#endif
+
+ return 0;
+}
+
+
+int mali_gralloc_ion_map(private_handle_t *hnd)
+{
+ uint64_t usage = hnd->producer_usage | hnd->consumer_usage;
+
+ /* Do not allow cpu access to secure buffers */
+ if (usage & (GRALLOC_USAGE_PROTECTED | GRALLOC_USAGE_NOZEROED | GRALLOC_USAGE_SECURE_CAMERA_RESERVED)
+ && !(usage & GRALLOC_USAGE_PRIVATE_NONSECURE))
+ {
+ return 0;
+ }
+
+ /* Do not allow cpu access to HFR buffers */
+ if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_HFR_MODE)
+ {
+ return 0;
+ }
+
+ for (int fidx = 0; fidx < hnd->fd_count; fidx++) {
+ unsigned char *mappedAddress =
+ (unsigned char *)mmap(NULL, hnd->alloc_sizes[fidx], PROT_READ | PROT_WRITE,
+ MAP_SHARED, hnd->fds[fidx], 0);
+
+ if (MAP_FAILED == mappedAddress)
+ {
+ int err = errno;
+ MALI_GRALLOC_LOGE("mmap( fds[%d]:%d size:%" PRIu64 " ) failed with %s",
+ fidx, hnd->fds[fidx], hnd->alloc_sizes[fidx], strerror(err));
+ hnd->dump("map fail");
+
+ for (int cidx = 0; cidx < fidx; fidx++)
+ {
+ munmap((void*)hnd->bases[cidx], hnd->alloc_sizes[cidx]);
+ }
+
+ return -err;
+ }
+
+ hnd->bases[fidx] = uintptr_t(mappedAddress);
+ }
+
+ return 0;
+}
+
+int import_exynos_ion_handles(private_handle_t *hnd)
+{
+ int retval = -1;
+
+ ion_device *dev = ion_device::get();
+
+ for (int idx = 0; idx < hnd->fd_count; idx++)
+ {
+ if (hnd->fds[idx] >= 0)
+ {
+ retval = exynos_ion_import_handle(dev->client(), hnd->fds[idx], &hnd->ion_handles[idx]);
+ if (retval)
+ {
+ MALI_GRALLOC_LOGE("error importing ion_handle. ion_client(%d), ion_handle[%d](%d) format(%#" PRIx64 ")",
+ dev->client(), idx, hnd->ion_handles[idx], hnd->alloc_format);
+ goto error;
+ }
+ }
+ }
+
+ return retval;
+
+error:
+ for (int idx = 0; idx < hnd->fd_count; idx++)
+ {
+ if (hnd->ion_handles[idx])
+ {
+ exynos_ion_free_handle(dev->client(), hnd->ion_handles[idx]);
+ }
+ }
+
+ return retval;
+}
+
+void free_exynos_ion_handles(private_handle_t *hnd)
+{
+ ion_device *dev = ion_device::get();
+
+ for (int idx = 0; idx < hnd->fd_count; idx++)
+ {
+ if (hnd->ion_handles[idx])
+ {
+ if (hnd->ion_handles[idx] &&
+ exynos_ion_free_handle(dev->client(), hnd->ion_handles[idx]))
+ {
+ MALI_GRALLOC_LOGE("error freeing ion_handle. ion_client(%d), ion_handle[%d](%d) format(%#" PRIx64 ")",
+ dev->client(), idx, hnd->ion_handles[idx], hnd->alloc_format);
+ }
+ }
+ }
+}
+
+
+void mali_gralloc_ion_unmap(private_handle_t *hnd)
+{
+ for (int i = 0; i < hnd->fd_count; i++)
+ {
+ int err = 0;
+ plane_info_t *plane = &hnd->plane_info[i];
+
+ if (hnd->bases[i])
+ {
+ err = munmap((void*)hnd->bases[i], hnd->alloc_sizes[i]);
+ }
+
+ if (err)
+ {
+ MALI_GRALLOC_LOGE("Could not munmap base:%p size:%" PRIu64 " '%s'",
+ (void*)hnd->bases[i], hnd->alloc_sizes[i], strerror(errno));
+ }
+ else
+ {
+ hnd->bases[i] = 0;
+ }
+ }
+
+ hnd->cpu_read = 0;
+ hnd->cpu_write = 0;
+}
+
+void mali_gralloc_ion_close(void)
+{
+ ion_device::close();
+}
+
diff --git a/gralloc4/src/allocator/mali_gralloc_ion.h b/gralloc4/src/allocator/mali_gralloc_ion.h
new file mode 100644
index 0000000..f46cc07
--- /dev/null
+++ b/gralloc4/src/allocator/mali_gralloc_ion.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2016, 2018-2020 ARM Limited. All rights reserved.
+ *
+ * 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 MALI_GRALLOC_ION_H_
+#define MALI_GRALLOC_ION_H_
+
+#include "core/mali_gralloc_bufferdescriptor.h"
+
+int mali_gralloc_ion_allocate_attr(private_handle_t *hnd);
+int mali_gralloc_ion_allocate(const gralloc_buffer_descriptor_t *descriptors,
+ uint32_t numDescriptors, buffer_handle_t *pHandle, bool *alloc_from_backing_store);
+void mali_gralloc_ion_free(private_handle_t * const hnd);
+int mali_gralloc_ion_sync_start(const private_handle_t * const hnd,
+ const bool read, const bool write);
+int mali_gralloc_ion_sync_end(const private_handle_t * const hnd,
+ const bool read, const bool write);
+int mali_gralloc_ion_map(private_handle_t *hnd);
+void mali_gralloc_ion_unmap(private_handle_t *hnd);
+void mali_gralloc_ion_close(void);
+int mali_gralloc_attr_allocate(void);
+int import_exynos_ion_handles(private_handle_t *hnd);
+void free_exynos_ion_handles(private_handle_t *hnd);
+
+#endif /* MALI_GRALLOC_ION_H_ */
diff --git a/gralloc4/src/allocator/mali_gralloc_shared_memory.cpp b/gralloc4/src/allocator/mali_gralloc_shared_memory.cpp
new file mode 100644
index 0000000..b681cd9
--- /dev/null
+++ b/gralloc4/src/allocator/mali_gralloc_shared_memory.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 Arm Limited. All rights reserved.
+ *
+ * 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 "mali_gralloc_shared_memory.h"
+#include "mali_gralloc_log.h"
+#include "mali_gralloc_buffer.h"
+#include "mali_gralloc_ion.h"
+#include "gralloc_helper.h"
+
+/* TODO: move shared attr memory allocation function here */
+
+void gralloc_shared_memory_free(private_handle_t *hnd)
+{
+ if (hnd->attr_base)
+ {
+ munmap(hnd->attr_base, hnd->attr_size);
+ hnd->attr_base = nullptr;
+ }
+
+ hnd->close_share_attr_fd();
+ hnd->set_share_attr_fd(-1);
+}
diff --git a/gralloc4/src/allocator/mali_gralloc_shared_memory.h b/gralloc4/src/allocator/mali_gralloc_shared_memory.h
new file mode 100644
index 0000000..28e0a62
--- /dev/null
+++ b/gralloc4/src/allocator/mali_gralloc_shared_memory.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 Arm Limited. All rights reserved.
+ *
+ * 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_SHARED_MEMORY_H_
+#define GRALLOC_SHARED_MEMORY_H_
+
+#include <stdint.h>
+#include <utility>
+#include "mali_gralloc_buffer.h"
+
+/*
+ * Frees resources acquired from gralloc_shared_memory_allocate.
+ */
+void gralloc_shared_memory_free(private_handle_t *hnd);
+
+#endif /* GRALLOC_SHARED_MEMORY_H_ */
diff --git a/gralloc4/src/capabilities/Android.bp b/gralloc4/src/capabilities/Android.bp
new file mode 100644
index 0000000..5bfb4f3
--- /dev/null
+++ b/gralloc4/src/capabilities/Android.bp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2020 Arm Limited.
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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.
+ */
+
+soong_config_module_type {
+ name: "arm_gralloc_capabilities_cc_defaults",
+ module_type: "cc_defaults",
+ config_namespace: "arm_gralloc",
+ variables: [
+ "mali_gpu_support_afbc_basic",
+ "mali_gpu_support_afbc_splitblk",
+ "mali_gpu_support_afbc_wideblk",
+ "mali_gpu_support_afbc_tiled_headers",
+ "mali_gpu_support_afbc_yuv_write",
+ "gralloc_arm_no_external_afbc",
+ "dpu_support_1010102_afbc",
+ "mali_gralloc_api_tests",
+ ],
+ properties: [
+ "cflags",
+ ],
+}
+
+soong_config_bool_variable {
+ name: "mali_gpu_support_afbc_basic",
+}
+soong_config_bool_variable {
+ name: "mali_gpu_support_afbc_splitblk",
+}
+soong_config_bool_variable {
+ name: "mali_gpu_support_afbc_wideblk",
+}
+soong_config_bool_variable {
+ name: "mali_gpu_support_afbc_tiled_headers",
+}
+soong_config_bool_variable {
+ name: "mali_gpu_support_afbc_yuv_write",
+}
+soong_config_bool_variable {
+ name: "gralloc_arm_no_external_afbc",
+}
+soong_config_bool_variable {
+ name: "dpu_support_1010102_afbc",
+}
+soong_config_bool_variable {
+ name: "mali_gralloc_api_tests",
+}
+
+arm_gralloc_capabilities_cc_defaults {
+ name: "arm_gralloc_capabilities_defaults",
+ defaults: [
+ "arm_gralloc_defaults",
+ ],
+ soong_config_variables: {
+ mali_gpu_support_afbc_basic: {
+ cflags: [
+ "-DMALI_GPU_SUPPORT_AFBC_BASIC=1",
+ ],
+ },
+ mali_gpu_support_afbc_splitblk: {
+ cflags: [
+ "-DMALI_GPU_SUPPORT_AFBC_SPLITBLK=1",
+ ],
+ },
+ mali_gpu_support_afbc_wideblk: {
+ cflags: [
+ "-DMALI_GPU_SUPPORT_AFBC_WIDEBLK=1",
+ ],
+ },
+ mali_gpu_support_afbc_tiled_headers: {
+ cflags: [
+ "-DMALI_GPU_SUPPORT_AFBC_TILED_HEADERS=1",
+ ],
+ },
+ mali_gpu_support_afbc_yuv_write: {
+ cflags: [
+ "-DMALI_GPU_SUPPORT_AFBC_YUV_WRITE=1",
+ ],
+ },
+ gralloc_arm_no_external_afbc: {
+ cflags: [
+ "-DGRALLOC_ARM_NO_EXTERNAL_AFBC=1",
+ ],
+ },
+ dpu_support_1010102_afbc: {
+ cflags: [
+ "-DGRALLOC_DPU_SUPPORT_1010102_AFBC=1",
+ ],
+ },
+ mali_gralloc_api_tests: {
+ cflags: [
+ "-DMALI_GRALLOC_VENDOR_VPU=1",
+ ],
+ },
+ },
+ srcs: [
+ "src/gralloc_capabilities.cpp",
+ ],
+ shared_libs: [
+ "libhardware",
+ "liblog",
+ "libcutils",
+ "libsync",
+ "libutils",
+ ],
+}
+
+cc_library_static {
+ name: "libgralloc_capabilities",
+ defaults: [
+ "arm_gralloc_capabilities_defaults",
+ "arm_gralloc_version_defaults",
+ ],
+}
diff --git a/gralloc4/src/capabilities/gralloc_capabilities.h b/gralloc4/src/capabilities/gralloc_capabilities.h
new file mode 100644
index 0000000..f8f21b1
--- /dev/null
+++ b/gralloc4/src/capabilities/gralloc_capabilities.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2020 ARM Limited. All rights reserved.
+ *
+ * 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.
+ */
+#pragma once
+
+#include "mali_gralloc_formats.h"
+
+extern mali_gralloc_format_caps cpu_runtime_caps;
+extern mali_gralloc_format_caps dpu_runtime_caps;
+extern mali_gralloc_format_caps vpu_runtime_caps;
+extern mali_gralloc_format_caps gpu_runtime_caps;
+extern mali_gralloc_format_caps cam_runtime_caps;
+
+/*
+ * Obtains the capabilities of each media system IP that form the producers
+ * and consumers. Default capabilities are assigned (within this function) for
+ * each IP, based on CFLAGS which specify the version of each IP (or, for GPU,
+ * explicit features):
+ * - GPU: MALI_GPU_SUPPORT_*
+ * - DPU: MALI_DISPLAY_VERSION
+ * - VPU: MALI_VIDEO_VERSION
+ *
+ * See src/Android.mk for default values.
+ *
+ * These defaults can be overridden by runtime capabilities defined in the
+ * userspace drivers (*.so) loaded for each IP. The drivers should define a
+ * symbol named MALI_GRALLOC_FORMATCAPS_SYM_NAME, which contains all
+ * capabilities from set MALI_GRALLOC_FORMAT_CAPABILITY_*
+ *
+ * @return none.
+ *
+ * NOTE: although no capabilities are returned, global variables global variables
+ * named '*_runtime_caps' are updated.
+ */
+void get_ip_capabilities(void);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void mali_gralloc_get_caps(struct mali_gralloc_format_caps *gpu_caps,
+ struct mali_gralloc_format_caps *vpu_caps,
+ struct mali_gralloc_format_caps *dpu_caps,
+ struct mali_gralloc_format_caps *cam_caps);
+#ifdef __cplusplus
+}
+#endif
diff --git a/gralloc4/src/capabilities/src/gralloc_capabilities.cpp b/gralloc4/src/capabilities/src/gralloc_capabilities.cpp
new file mode 100644
index 0000000..227bf33
--- /dev/null
+++ b/gralloc4/src/capabilities/src/gralloc_capabilities.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2020 ARM Limited. All rights reserved.
+ *
+ * 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 "gralloc_capabilities.h"
+
+#include <string.h>
+#include <dlfcn.h>
+#include <inttypes.h>
+#include <assert.h>
+#include <pthread.h>
+
+#include "core/format_info.h"
+
+/* Writing to runtime_caps_read is guarded by mutex caps_init_mutex. */
+static pthread_mutex_t caps_init_mutex = PTHREAD_MUTEX_INITIALIZER;
+static bool runtime_caps_read = false;
+
+mali_gralloc_format_caps cpu_runtime_caps;
+mali_gralloc_format_caps dpu_runtime_caps;
+mali_gralloc_format_caps vpu_runtime_caps;
+mali_gralloc_format_caps gpu_runtime_caps;
+mali_gralloc_format_caps cam_runtime_caps;
+
+void get_ip_capabilities(void)
+{
+ /* Ensure capability setting is not interrupted by other
+ * allocations during start-up.
+ */
+ pthread_mutex_lock(&caps_init_mutex);
+
+ if (runtime_caps_read)
+ {
+ goto already_init;
+ }
+
+ sanitize_formats();
+
+ memset((void *)&cpu_runtime_caps, 0, sizeof(cpu_runtime_caps));
+ memset((void *)&dpu_runtime_caps, 0, sizeof(dpu_runtime_caps));
+ memset((void *)&vpu_runtime_caps, 0, sizeof(vpu_runtime_caps));
+ memset((void *)&gpu_runtime_caps, 0, sizeof(gpu_runtime_caps));
+ memset((void *)&cam_runtime_caps, 0, sizeof(cam_runtime_caps));
+
+ /* Determine CPU IP capabilities */
+ cpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT;
+ cpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_PIXFMT_RGBA1010102;
+ cpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_PIXFMT_RGBA16161616;
+
+ /* Determine DPU IP capabilities */
+ dpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT;
+ dpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC;
+#if defined(GRALLOC_DPU_SUPPORT_1010102_AFBC) && (GRALLOC_DPU_SUPPORT_1010102_AFBC == 1)
+ dpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_PIXFMT_RGBA1010102;
+#endif
+
+#if defined(MALI_GPU_SUPPORT_AFBC_BASIC) && (MALI_GPU_SUPPORT_AFBC_BASIC == 1)
+ gpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT;
+ gpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC;
+ gpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_PIXFMT_RGBA1010102;
+ gpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_PIXFMT_RGBA16161616;
+
+#endif /* defined(MALI_GPU_SUPPORT_AFBC_BASIC) && (MALI_GPU_SUPPORT_AFBC_BASIC == 1) */
+
+ /* Determine VPU IP capabilities */
+ vpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT;
+
+/* Build specific capability changes */
+#if defined(GRALLOC_ARM_NO_EXTERNAL_AFBC) && (GRALLOC_ARM_NO_EXTERNAL_AFBC == 1)
+ dpu_runtime_caps.caps_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK;
+ gpu_runtime_caps.caps_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK;
+ vpu_runtime_caps.caps_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK;
+ cam_runtime_caps.caps_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK;
+#endif
+
+ cam_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT;
+
+ runtime_caps_read = true;
+
+already_init:
+ pthread_mutex_unlock(&caps_init_mutex);
+
+ MALI_GRALLOC_LOGV("GPU format capabilities 0x%" PRIx64, gpu_runtime_caps.caps_mask);
+ MALI_GRALLOC_LOGV("DPU format capabilities 0x%" PRIx64, dpu_runtime_caps.caps_mask);
+ MALI_GRALLOC_LOGV("VPU format capabilities 0x%" PRIx64, vpu_runtime_caps.caps_mask);
+ MALI_GRALLOC_LOGV("CAM format capabilities 0x%" PRIx64, cam_runtime_caps.caps_mask);
+}
+
+
+/* This is used by the unit tests to get the capabilities for each IP. */
+extern "C" {
+ void mali_gralloc_get_caps(struct mali_gralloc_format_caps *gpu_caps,
+ struct mali_gralloc_format_caps *vpu_caps,
+ struct mali_gralloc_format_caps *dpu_caps,
+ struct mali_gralloc_format_caps *cam_caps)
+ {
+ get_ip_capabilities();
+
+ memcpy(gpu_caps, (void *)&gpu_runtime_caps, sizeof(*gpu_caps));
+ memcpy(vpu_caps, (void *)&vpu_runtime_caps, sizeof(*vpu_caps));
+ memcpy(dpu_caps, (void *)&dpu_runtime_caps, sizeof(*dpu_caps));
+ memcpy(cam_caps, (void *)&cam_runtime_caps, sizeof(*cam_caps));
+ }
+}
diff --git a/gralloc4/src/core/Android.bp b/gralloc4/src/core/Android.bp
new file mode 100644
index 0000000..634764f
--- /dev/null
+++ b/gralloc4/src/core/Android.bp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2020 Arm Limited.
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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.
+ */
+
+soong_config_module_type {
+ name: "arm_gralloc_core_cc_defaults",
+ module_type: "cc_defaults",
+ config_namespace: "arm_gralloc",
+ variables: [
+ "gralloc_ion_sync_on_lock",
+ ],
+ properties: [
+ "cflags",
+ ],
+}
+
+soong_config_bool_variable {
+ name: "gralloc_ion_sync_on_lock",
+}
+
+arm_gralloc_core_cc_defaults {
+ name: "arm_gralloc_core_defaults",
+ defaults: [
+ "arm_gralloc_defaults",
+ ],
+ cflags: [
+ /* Minimum buffer dimensions in pixels when buffer will use AFBC */
+ /* TODO: set this via BoardConfig */
+ "-DGRALLOC_DISP_W=1920",
+ "-DGRALLOC_DISP_H=1080",
+ ],
+ soong_config_variables: {
+ gralloc_ion_sync_on_lock: {
+ cflags: [
+ "-DGRALLOC_ION_SYNC_ON_LOCK=1",
+ ],
+ },
+ },
+ srcs: [
+ "mali_gralloc_bufferaccess.cpp",
+ "mali_gralloc_bufferallocation.cpp",
+ "mali_gralloc_formats.cpp",
+ "mali_gralloc_reference.cpp",
+ "mali_gralloc_debug.cpp",
+ "format_info.cpp",
+ ],
+ include_dirs: [
+ "hardware/google/gchips/include",
+ ],
+ static_libs: [
+ "libarect",
+ ],
+ shared_libs: [
+ "liblog",
+ "libcutils",
+ "libutils",
+ "android.hardware.graphics.common@1.2",
+ ],
+ target: {
+ android: {
+ shared_libs: [
+ "libhardware",
+ ],
+ },
+ },
+}
+
+cc_library_static {
+ name: "libgralloc_core",
+ defaults: [
+ "arm_gralloc_core_defaults",
+ "arm_gralloc_version_defaults",
+ ],
+}
+
+cc_library_host_static {
+ name: "libgralloc_core_host",
+ defaults: [
+ "arm_gralloc_core_defaults",
+ ],
+}
diff --git a/gralloc4/src/core/exynos_format_allocation.h b/gralloc4/src/core/exynos_format_allocation.h
new file mode 100644
index 0000000..caefaa2
--- /dev/null
+++ b/gralloc4/src/core/exynos_format_allocation.h
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2020 Samsung Electronics Co. Ltd.
+ *
+ * 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.
+ */
+
+#pragma once
+
+#define PLANE_SIZE(w, h) ((w) * (h))
+#define S2B_PLANE_SIZE(w, h) (GRALLOC_ALIGN((w) / 4, 16) * (GRALLOC_ALIGN(h, 16)))
+
+/* helper macros */
+#ifndef __ALIGN_UP
+#define __ALIGN_UP(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
+#endif
+
+/* SBWC align macros */
+#define SBWC_8B_STRIDE(w) (128 * (((w) + 31) / 32))
+#define SBWC_10B_STRIDE(w) (160 * (((w) + 31) / 32))
+#define SBWC_HEADER_STRIDE(w) ((((((w) + 63) / 64) + 15) / 16) * 16)
+
+#define SBWC_Y_VSTRIDE_BLOCKS(h) ((__ALIGN_UP((h), 16) + 3) / 4)
+#define SBWC_CBCR_VSTRIDE_BLOCKS(h) (((__ALIGN_UP((h), 16) / 2) + 3) / 4)
+
+#define SBWC_8B_Y_SIZE(w, h) ((SBWC_8B_STRIDE(w) * ((__ALIGN_UP((h), 16) + 3) / 4)) + 64)
+#define SBWC_8B_Y_HEADER_SIZE(w, h) __ALIGN_UP(((SBWC_HEADER_STRIDE(w) * ((__ALIGN_UP((h), 16) + 3) / 4)) + 256), 32)
+#define SBWC_8B_CBCR_SIZE(w, h) ((SBWC_8B_STRIDE(w) * (((__ALIGN_UP((h), 16) / 2) + 3) / 4)) + 64)
+#define SBWC_8B_CBCR_HEADER_SIZE(w, h) ((SBWC_HEADER_STRIDE(w) * (((__ALIGN_UP((h), 16) / 2) + 3) / 4)) + 128)
+
+#define SBWC_10B_Y_SIZE(w, h) ((SBWC_10B_STRIDE(w) * ((__ALIGN_UP((h), 16) + 3) / 4)) + 64)
+#define SBWC_10B_Y_HEADER_SIZE(w, h) __ALIGN_UP((((__ALIGN_UP((w), 16) * __ALIGN_UP((h), 16) * 2) + 256) - SBWC_10B_Y_SIZE(w, h)), 32)
+#define SBWC_10B_CBCR_SIZE(w, h) ((SBWC_10B_STRIDE(w) * (((__ALIGN_UP((h), 16) / 2) + 3) / 4)) + 64)
+#define SBWC_10B_CBCR_HEADER_SIZE(w, h) (((__ALIGN_UP((w), 16) * __ALIGN_UP((h), 16)) + 256) - SBWC_10B_CBCR_SIZE(w, h))
+
+/* SBWC Lossy align macros */
+#define SBWCL_8B_STRIDE(w, r) (((128 * (r)) / 100) * (((w) + 31) / 32))
+#define SBWCL_10B_STRIDE(w, r) (((160 * (r)) / 100) * (((w) + 31) / 32))
+
+#define SBWCL_8B_Y_SIZE(w, h, r) ((SBWCL_8B_STRIDE(w, r) * ((__ALIGN_UP((h), 8) + 3) / 4)) + 64)
+#define SBWCL_8B_CBCR_SIZE(w, h, r) ((SBWCL_8B_STRIDE(w, r) * (((__ALIGN_UP((h), 8) / 2) + 3) / 4)) + 64)
+
+#define SBWCL_10B_Y_SIZE(w, h, r) ((SBWCL_10B_STRIDE(w, r) * ((__ALIGN_UP((h), 8) + 3) / 4)) + 64)
+#define SBWCL_10B_CBCR_SIZE(w, h, r) ((SBWCL_10B_STRIDE(w, r) * (((__ALIGN_UP((h), 8) / 2) + 3) / 4)) + 64)
+
+#define SBWCL_8B_CBCR_BASE(base, w, h, r) ((base) + SBWCL_8B_Y_SIZE(w, h, r))
+#define SBWCL_10B_CBCR_BASE(base, w, h, r) ((base) + SBWCL_10B_Y_SIZE(w, h, r))
+
+
+/*
+ * All setup_<format> function will returns the plane_count
+ */
+
+/* Sets up 8-bit SBWC semi planar and returns the plane count */
+int setup_sbwc_420_sp(int w, int h, int fd_count, plane_info_t *plane)
+{
+ plane[0].size = SBWC_8B_Y_SIZE(w, h) + SBWC_8B_Y_HEADER_SIZE(w, h);
+ plane[0].alloc_width = GRALLOC_ALIGN(w, 32);
+ plane[0].alloc_height = __ALIGN_UP(h, 16);
+ plane[0].byte_stride = SBWC_8B_STRIDE(w);
+ plane[0].fd_idx = 0;
+
+ plane[1].size = SBWC_8B_CBCR_SIZE(w, h) + SBWC_8B_CBCR_HEADER_SIZE(w, h);
+ plane[1].alloc_width = GRALLOC_ALIGN(w, 32);
+ plane[1].alloc_height = __ALIGN_UP(h, 16) / 2;
+ plane[1].byte_stride = SBWC_8B_STRIDE(w);
+
+ if (fd_count > 1)
+ {
+ plane[1].fd_idx = 1;
+ }
+ else
+ {
+ plane[1].fd_idx = 0;
+ plane[1].offset = plane[0].size;
+ }
+
+ return 2;
+}
+
+/* Sets up 10-bit SBWC semi planar and returns the plane count */
+int setup_sbwc_420_sp_10bit(int w, int h, int fd_count, plane_info_t *plane)
+{
+ plane[0].size = (SBWC_10B_Y_SIZE(w, h) + SBWC_10B_Y_HEADER_SIZE(w, h));
+ plane[0].alloc_width = GRALLOC_ALIGN(w, 32);
+ plane[0].alloc_height = __ALIGN_UP(h, 16);
+ plane[0].byte_stride = SBWC_10B_STRIDE(w);
+ plane[0].fd_idx = 0;
+
+ plane[1].size = (SBWC_10B_CBCR_SIZE(w, h) + SBWC_10B_CBCR_HEADER_SIZE(w, h));
+ plane[1].alloc_width = GRALLOC_ALIGN(w, 32);
+ plane[1].alloc_height = __ALIGN_UP(h, 16) / 2;
+ plane[1].byte_stride = SBWC_10B_STRIDE(w);
+
+ if (fd_count > 1)
+ {
+ plane[1].fd_idx = 1;
+ }
+ else
+ {
+ plane[1].fd_idx = 0;
+ plane[1].offset = plane[0].size;
+ }
+
+ return 2;
+}
+
+/* Sets up 8-bit Lossy SBWC semi planar and returns the plane count */
+int setup_sbwc_420_sp_lossy(int width, int height, int rate, int fd_count, plane_info_t *plane)
+{
+ plane[0].size = SBWCL_8B_Y_SIZE(width, height, rate);
+ plane[0].alloc_width = GRALLOC_ALIGN(width, 32);
+ plane[0].alloc_height = __ALIGN_UP(height, 8);
+ plane[0].byte_stride = SBWCL_8B_STRIDE(width, rate);
+ plane[0].fd_idx = 0;
+
+ plane[1].size = SBWCL_8B_CBCR_SIZE(width, height, rate);
+ plane[1].alloc_width = GRALLOC_ALIGN(width, 32);
+ plane[1].alloc_height = __ALIGN_UP(height, 8) / 2;
+ plane[1].byte_stride = SBWCL_8B_STRIDE(width, rate);
+
+ if (fd_count > 1)
+ {
+ plane[1].fd_idx = 1;
+ }
+ else
+ {
+ plane[1].fd_idx = 0;
+ plane[1].offset = plane[0].size;
+ }
+
+ return 2;
+}
+
+
+/* Sets up 10-bit Lossy SBWC semi planar and returns the plane count */
+int setup_sbwc_420_sp_10bit_lossy(int width, int height, int rate, int fd_count, plane_info_t *plane)
+{
+ plane[0].size = SBWCL_10B_Y_SIZE(width, height, rate);
+ plane[0].alloc_width = GRALLOC_ALIGN(width, 32);
+ plane[0].alloc_height = __ALIGN_UP(height, 8);
+ plane[0].byte_stride = SBWCL_10B_STRIDE(width, rate);
+ plane[0].fd_idx = 0;
+
+ plane[1].size = SBWCL_10B_CBCR_SIZE(width, height, rate);
+ plane[1].alloc_width = GRALLOC_ALIGN(width, 32);
+ plane[1].alloc_height = __ALIGN_UP(height, 8) / 2;
+ plane[1].byte_stride = SBWCL_10B_STRIDE(width, rate);
+
+ if (fd_count > 1)
+ {
+ plane[1].fd_idx = 1;
+ }
+ else
+ {
+ plane[1].fd_idx = 0;
+ plane[1].offset = plane[0].size;
+ }
+
+ return 2;
+}
+
+int setup_420_sp(int width, int height, int fd_count, plane_info_t *plane)
+{
+ /* TODO: make this into an assert instead ? */
+ height = GRALLOC_ALIGN(height, 2);
+
+ plane[0].size = PLANE_SIZE(width, height);
+ plane[0].alloc_width = width;
+ plane[0].alloc_height = height;
+ plane[0].byte_stride = width;
+ plane[0].fd_idx = 0;
+
+ int chroma_width = width;
+ int chroma_height = height / 2;
+
+ plane[1].size = PLANE_SIZE(chroma_width, chroma_height);
+ plane[1].alloc_width = chroma_width;
+ plane[1].alloc_height = chroma_height;
+ plane[1].byte_stride = chroma_width;
+
+ if (fd_count > 1)
+ {
+ plane[1].fd_idx = 1;
+ }
+ else
+ {
+ plane[1].fd_idx = 0;
+ plane[1].offset = plane[0].size;
+ }
+
+ return 2;
+}
+
+int setup_420_sp_s10b(int width, int height, int fd_count, plane_info_t *plane)
+{
+ /* TODO: make this into an assert instead ? */
+ /* TODO: assert height aligned to 16 ? */
+ height = GRALLOC_ALIGN(height, 2);
+
+ int mscl_ext = 256;
+
+ /* HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B have special padding requirement */
+ if (fd_count == 1)
+ {
+ mscl_ext = 64;
+ }
+
+ plane[0].size = PLANE_SIZE(width, height) + S2B_PLANE_SIZE(width, height) + mscl_ext;
+ plane[0].alloc_width = width;
+ plane[0].alloc_height = height;
+ plane[0].byte_stride = width;
+ plane[0].fd_idx = 0;
+
+ int chroma_width = width;
+ int chroma_height = height / 2;
+
+ plane[1].size = PLANE_SIZE(chroma_width, chroma_height)
+ + S2B_PLANE_SIZE(chroma_width, chroma_height) + mscl_ext;
+ plane[1].alloc_width = chroma_width;
+ plane[1].alloc_height = chroma_height;
+ plane[1].byte_stride = chroma_width;
+
+ if (fd_count > 1)
+ {
+ plane[1].fd_idx = 1;
+ }
+ else
+ {
+ plane[1].fd_idx = 0;
+ plane[1].offset = plane[0].size;
+ }
+
+ return 2;
+}
+
+int setup_p010_sp(int width, int height, int fd_count, plane_info_t *plane)
+{
+ /* TODO: make this into an assert instead ? */
+ height = GRALLOC_ALIGN(height, 2);
+
+ plane[0].size = PLANE_SIZE(width * 2, height);
+ plane[0].alloc_width = width;
+ plane[0].alloc_height = height;
+ plane[0].byte_stride = width * 2;
+ plane[0].fd_idx = 0;
+
+ int chroma_width = width;
+ int chroma_height = height / 2;
+
+ plane[1].size = PLANE_SIZE(chroma_width * 2, chroma_height);
+ plane[1].alloc_width = chroma_width;
+ plane[1].alloc_height = chroma_height;
+ plane[1].byte_stride = chroma_width * 2;
+
+ if (fd_count > 1)
+ {
+ plane[1].fd_idx = 1;
+ }
+ else
+ {
+ plane[1].fd_idx = 0;
+ plane[1].offset = plane[0].size;
+ }
+
+ return 2;
+}
+
+int setup_420_p(int width, int height, int fd_count, plane_info_t *plane)
+{
+ /* TODO: make this into an assert instead ? */
+ width = GRALLOC_ALIGN(width, 2);
+ height = GRALLOC_ALIGN(height, 2);
+
+ plane[0].size = PLANE_SIZE(width, height);
+ plane[0].alloc_width = width;
+ plane[0].alloc_height = height;
+ plane[0].byte_stride = width;
+ plane[0].fd_idx = 0;
+
+ int chroma_width = GRALLOC_ALIGN(width / 2, 16);
+ int chroma_height = height / 2;
+
+ plane[1].size = PLANE_SIZE(chroma_width, chroma_height);
+ plane[1].alloc_width = chroma_width;
+ plane[1].alloc_height = chroma_height;
+ plane[1].byte_stride = chroma_width;
+
+ plane[2].size = PLANE_SIZE(chroma_width, chroma_height);
+ plane[2].alloc_width = chroma_width;
+ plane[2].alloc_height = chroma_height;
+ plane[2].byte_stride = chroma_width;
+
+ if (fd_count > 1)
+ {
+ plane[1].fd_idx = 1;
+ plane[2].fd_idx = 2;
+ }
+ else
+ {
+ plane[1].fd_idx = 0;
+ plane[2].fd_idx = 0;
+ plane[1].offset = plane[0].size;
+ plane[2].offset = plane[0].size + plane[1].size;
+ }
+
+ return 3;
+}
+
+int setup_420_sp_tiled(int width, int height, int fd_count, plane_info_t *plane)
+{
+ /* TODO: make this into an assert instead ? */
+ width = GRALLOC_ALIGN(width, 2);
+ height = GRALLOC_ALIGN(height, 2);
+
+ plane[0].size = PLANE_SIZE(width, height);
+ plane[0].alloc_width = width;
+ plane[0].alloc_height = height;
+ plane[0].byte_stride = width * 16;
+ plane[0].fd_idx = 0;
+
+ int chroma_width = width;
+ int chroma_height = GRALLOC_ALIGN(height / 2, 32);
+
+ plane[1].size = PLANE_SIZE(chroma_width, chroma_height);
+ plane[1].alloc_width = chroma_width;
+ plane[1].alloc_height = chroma_height;
+ plane[1].byte_stride = chroma_width * 16;
+
+ if (fd_count > 1)
+ {
+ plane[1].fd_idx = 1;
+ }
+ else
+ {
+ plane[1].fd_idx = 0;
+ plane[1].offset = plane[0].size;
+ }
+
+ return 3;
+}
diff --git a/gralloc4/src/core/format_info.cpp b/gralloc4/src/core/format_info.cpp
new file mode 100644
index 0000000..c370528
--- /dev/null
+++ b/gralloc4/src/core/format_info.cpp
@@ -0,0 +1,1219 @@
+/*
+ * Copyright (C) 2018-2020 ARM Limited. All rights reserved.
+ *
+ * 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 <inttypes.h>
+#include "gralloc_helper.h"
+#include "mali_gralloc_formats.h"
+#include "format_info.h"
+#include "mali_gralloc_usages.h"
+#include <exynos_format.h>
+
+/* Default width aligned to whole pixel (CPU access). */
+#define ALIGN_W_CPU_DEFAULT .align_w_cpu = 1
+
+/*
+ * Format table, containing format properties.
+ *
+ * NOTE: This table should only be used within
+ * the gralloc library and not by clients directly.
+ */
+const format_info_t formats[] = {
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_RGB_565,
+ .npln = 1, .ncmp = { 3, 0, 0 }, .bps = 6, .bpp_afbc = { 16, 0, 0 }, .bpp = { 16, 0, 0 },
+ .hsub = 0, .vsub = 0, .align_w = 16, .align_h = 16, .align_w_cpu = 16,
+ .tile_size = 1, .has_alpha = false, .is_rgb = true, .is_yuv = false,
+ .afbc = true, .linear = true, .yuv_transform = true, .flex = false,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_RGB_888,
+ .npln = 1, .ncmp = { 3, 0, 0 }, .bps = 8, .bpp_afbc = { 24, 0, 0 }, .bpp = { 24, 0, 0 },
+ .hsub = 0, .vsub = 0, .align_w = 16, .align_h = 16, .align_w_cpu = 16,
+ .tile_size = 1, .has_alpha = false, .is_rgb = true, .is_yuv = false,
+ .afbc = true, .linear = true, .yuv_transform = true, .flex = true,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_RGBA_8888,
+ .npln = 1, .ncmp = { 4, 0, 0 }, .bps = 8, .bpp_afbc = { 32, 0, 0 }, .bpp = { 32, 0, 0 },
+ .hsub = 0, .vsub = 0, .align_w = 16, .align_h = 16, .align_w_cpu = 16,
+ .tile_size = 1, .has_alpha = true, .is_rgb = true, .is_yuv = false,
+ .afbc = true, .linear = true, .yuv_transform = true, .flex = true,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_BGRA_8888,
+ .npln = 1, .ncmp = { 4, 0, 0 }, .bps = 8, .bpp_afbc = { 32, 0, 0 }, .bpp = { 32, 0, 0 },
+ .hsub = 0, .vsub = 0, .align_w = 16, .align_h = 16, .align_w_cpu = 16,
+ .tile_size = 1, .has_alpha = true, .is_rgb = true, .is_yuv = false,
+ .afbc = true, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_RGBX_8888,
+ .npln = 1, .ncmp = { 3, 0, 0 }, .bps = 8, .bpp_afbc = { 32, 0, 0 }, .bpp = { 32, 0, 0 },
+ .hsub = 0, .vsub = 0, .align_w = 16, .align_h = 16, .align_w_cpu = 16,
+ .tile_size = 1, .has_alpha = false, .is_rgb = true, .is_yuv = false,
+ .afbc = true, .linear = true, .yuv_transform = true, .flex = true,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_RGBA_1010102,
+ .npln = 1, .ncmp = { 4, 0, 0 }, .bps = 10, .bpp_afbc = { 32, 0, 0 }, .bpp = { 32, 0, 0 },
+ .hsub = 0, .vsub = 0, .align_w = 16, .align_h = 16, .align_w_cpu = 16,
+ .tile_size = 1, .has_alpha = true, .is_rgb = true, .is_yuv = false,
+ .afbc = true, .linear = true, .yuv_transform = true, .flex = false,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_RGBA_16161616,
+ .npln = 1, .ncmp = { 4, 0, 0 }, .bps = 16, .bpp_afbc = { 64, 0, 0 }, .bpp = { 64, 0, 0 },
+ .hsub = 0, .vsub = 0, .align_w = 16, .align_h = 16, .align_w_cpu = 16,
+ .tile_size = 1, .has_alpha = true, .is_rgb = true, .is_yuv = false,
+ .afbc = true, .linear = true, .yuv_transform = true, .flex = true,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_Y8,
+ .npln = 1, .ncmp = { 1, 0, 0 }, .bps = 8, .bpp_afbc = { 8, 0, 0 }, .bpp = { 8, 0, 0 },
+ .hsub = 1, .vsub = 1, .align_w = 2, .align_h = 2, .align_w_cpu = 16,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = true, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_Y16,
+ .npln = 1, .ncmp = { 1, 0, 0 }, .bps = 16, .bpp_afbc = { 16, 0, 0 }, .bpp = { 16, 0, 0 },
+ .hsub = 1, .vsub = 1, .align_w = 2, .align_h = 2, .align_w_cpu = 16,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = true, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ /* 420 (8-bit) */
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_YUV420_8BIT_I,
+ .npln = 1, .ncmp = { 3, 0, 0 }, .bps = 8, .bpp_afbc = { 12, 0, 0 }, .bpp = { 0, 0, 0 },
+ .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = true, .linear = false, .yuv_transform = false, .flex = false,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_NV12,
+ .npln = 2, .ncmp = { 1, 2, 0 }, .bps = 8, .bpp_afbc = { 8, 16, 0 }, .bpp = { 8, 16, 0 },
+ .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = true, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_NV21,
+ .npln = 2, .ncmp = { 1, 2, 0 }, .bps = 8, .bpp_afbc = { 8, 16, 0 }, .bpp = { 8, 16, 0 },
+ .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = true, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_YV12,
+ .npln = 3, .ncmp = { 1, 1, 1 }, .bps = 8, .bpp_afbc = { 8, 8, 8 }, .bpp = { 8, 8, 8 },
+ .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, .align_w_cpu = 16,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = true, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ /* 422 (8-bit) */
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_YUV422_8BIT,
+ .npln = 1, .ncmp = { 3, 0, 0 }, .bps = 8, .bpp_afbc = { 16, 0, 0 }, .bpp = { 16, 0, 0 },
+ .hsub = 2, .vsub = 1, .align_w = 2, .align_h = 1, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = true, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_NV16,
+ .npln = 2, .ncmp = { 1, 2, 0 }, .bps = 8, .bpp_afbc = { 8, 16, 0 }, .bpp = { 8, 16, 0 },
+ .hsub = 2, .vsub = 1, .align_w = 2, .align_h = 1, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = true, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ /* 420 (10-bit) */
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_YUV420_10BIT_I,
+ .npln = 1, .ncmp = { 3, 0, 0 }, .bps = 10, .bpp_afbc = { 15, 0, 0 }, .bpp = { 0, 0, 0 },
+ .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = true, .linear = false, .yuv_transform = false, .flex = false,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_Y0L2,
+ .npln = 1, .ncmp = { 4, 0, 0 }, .bps = 10, .bpp_afbc = { 0, 0, 0 }, .bpp = { 16, 0, 0 },
+ .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 2, .has_alpha = true, .is_rgb = false, .is_yuv = true,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = false,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_P010,
+ .npln = 2, .ncmp = { 1, 2, 0 }, .bps = 10, .bpp_afbc = { 10, 20, 0 }, .bpp = { 16, 32, 0 },
+ .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = true, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ /* 422 (10-bit) */
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_Y210,
+ .npln = 1, .ncmp = { 3, 0, 0 }, .bps = 10, .bpp_afbc = { 20, 0, 0 }, .bpp = { 32, 0, 0 },
+ .hsub = 2, .vsub = 1, .align_w = 2, .align_h = 1, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = true, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_P210,
+ .npln = 2, .ncmp = { 1, 2, 0 }, .bps = 10, .bpp_afbc = { 10, 20, 0 }, .bpp = { 16, 32, 0 },
+ .hsub = 2, .vsub = 1, .align_w = 2, .align_h = 1, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = true, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ /* 444 (10-bit) */
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_YUV444_10BIT_I,
+ .npln = 1, .ncmp = { 3, 0, 0 }, .bps = 10, .bpp_afbc = { 30, 0, 0 }, .bpp = { 0, 0, 0 },
+ .hsub = 1, .vsub = 1, .align_w = 1, .align_h = 1, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = true, .linear = false, .yuv_transform = false, .flex = false,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_Y410,
+ .npln = 1, .ncmp = { 4, 0, 0 }, .bps = 10, .bpp_afbc = { 0, 0, 0 }, .bpp = { 32, 0, 0 },
+ .hsub = 1, .vsub = 1, .align_w = 1, .align_h = 1, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = true, .is_rgb = false, .is_yuv = true,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = false,
+ },
+ /* Other */
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_RAW16,
+ .npln = 1, .ncmp = { 1, 0, 0 }, .bps = 16, .bpp_afbc = { 0, 0, 0 }, .bpp = { 16, 0, 0 },
+ .hsub = 0, .vsub = 0, .align_w = 2, .align_h = 2, .align_w_cpu = 16,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = false,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = false,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_RAW12,
+ .npln = 1, .ncmp = { 1, 0, 0 }, .bps = 12, .bpp_afbc = { 0, 0, 0 }, .bpp = { 12, 0, 0 },
+ .hsub = 0, .vsub = 0, .align_w = 4, .align_h = 2, .align_w_cpu = 4,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = false,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = false,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_RAW10,
+ .npln = 1, .ncmp = { 1, 0, 0 }, .bps = 10, .bpp_afbc = { 0, 0, 0 }, .bpp = { 10, 0, 0 },
+ .hsub = 0, .vsub = 0, .align_w = 4, .align_h = 2, .align_w_cpu = 4,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = false,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = false,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_BLOB,
+ .npln = 1, .ncmp = { 1, 0, 0 }, .bps = 8, .bpp_afbc = { 0, 0, 0 }, .bpp = { 8, 0, 0 },
+ .hsub = 0, .vsub = 0, .align_w = 1, .align_h = 1, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = false,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = false,
+ },
+ /* Depth and Stencil */
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_DEPTH_16,
+ .npln = 1, .ncmp = { 1, 0, 0 }, .bps = 16, .bpp_afbc = { 0, 0, 0}, .bpp = { 16, 0, 0 },
+ .hsub = 0, .vsub = 0, .align_w = 1, .align_h = 1, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = false,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = false,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_DEPTH_24,
+ .npln = 1, .ncmp = { 1, 0, 0 }, .bps = 24, .bpp_afbc = { 0, 0, 0 }, .bpp = { 24, 0, 0 },
+ .hsub = 0, .vsub = 0, .align_w = 1, .align_h = 1, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = false,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = false,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_DEPTH_24_STENCIL_8,
+ .npln = 1, .ncmp = { 2, 0, 0 }, .bps = 24, .bpp_afbc = { 0, 0, 0 }, .bpp = { 32, 0, 0 },
+ .hsub = 0, .vsub = 0, .align_w = 1, .align_h = 1, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = false,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = false,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_DEPTH_32F,
+ .npln = 1, .ncmp = { 1, 0, 0 }, .bps = 32, .bpp_afbc = { 0, 0, 0 }, .bpp = { 32, 0, 0 },
+ .hsub = 0, .vsub = 0, .align_w = 1, .align_h = 1, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = false,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = false,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_DEPTH_32F_STENCIL_8,
+ .npln = 1, .ncmp = { 2, 0, 0 }, .bps = 32, .bpp_afbc = { 0, 0, 0 }, .bpp = { 40, 0, 0 },
+ .hsub = 0, .vsub = 0, .align_w = 1, .align_h = 1, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = false,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = false,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_STENCIL_8,
+ .npln = 1, .ncmp = { 1, 0, 0 }, .bps = 8, .bpp_afbc = { 0, 0, 0 }, .bpp = { 8, 0, 0 },
+ .hsub = 0, .vsub = 0, .align_w = 1, .align_h = 1, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = false,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = false,
+ },
+ /* Exynos Formats */
+ {
+ .id = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M,
+ .npln = 2, .ncmp = {1, 2, 0}, .bps = 8, .bpp_afbc = { 0, 0, 0 }, .bpp = { 8, 16, 0 },
+ .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ {
+ .id = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL,
+ .npln = 2, .ncmp = {1, 2, 0}, .bps = 8, .bpp_afbc = { 0, 0, 0 }, .bpp = { 8, 16, 0 },
+ .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ {
+ .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M,
+ .npln = 2, .ncmp = {1, 2, 0}, .bps = 8, .bpp_afbc = { 0, 0, 0 }, .bpp = { 8, 16, 0 },
+ .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ {
+ .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B,
+ .npln = 2, .ncmp = {1, 2, 0}, .bps = 10, .bpp_afbc = { 0, 0, 0 }, .bpp = { 16, 32, 0 },
+ .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ {
+ .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED,
+ .npln = 2, .ncmp = {1, 2, 0}, .bps = 8, .bpp_afbc = { 0, 0, 0 }, .bpp = { 8, 16, 0 },
+ .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 16,.has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ {
+ .id = HAL_PIXEL_FORMAT_EXYNOS_YV12_M,
+ .npln = 3, .ncmp = {1, 1, 1}, .bps = 8, .bpp_afbc = { 0, 0, 0 }, .bpp = { 8, 8, 8 },
+ .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ {
+ .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M,
+ .npln = 3, .ncmp = {1, 1, 1}, .bps = 8, .bpp_afbc = { 0, 0, 0 }, .bpp = { 8, 8, 8 },
+ .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ {
+ .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN,
+ .npln = 2, .ncmp = {1, 2, 0}, .bps = 8, .bpp_afbc = { 0, 0, 0 }, .bpp = { 8, 16, 0 },
+ .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ {
+ .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B,
+ .npln = 2, .ncmp = {1, 2, 0}, .bps = 10, .bpp_afbc = { 0, 0, 0 }, .bpp = { 16, 32, 0 },
+ .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ {
+ .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M,
+ .npln = 2, .ncmp = {1, 2, 0}, .bps = 10, .bpp_afbc = { 0, 0, 0 }, .bpp = { 16, 32, 0 },
+ .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ {
+ .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P,
+ .npln = 3, .ncmp = {1, 1, 1}, .bps = 8, .bpp_afbc = { 0, 0, 0 }, .bpp = { 8, 8, 8 },
+ .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, .align_w_cpu = 16,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ {
+ .id = HAL_PIXEL_FORMAT_YCrCb_420_SP,
+ .npln = 2, .ncmp = {1, 2, 0}, .bps = 8, .bpp_afbc = { 0, 0, 0 }, .bpp = { 8, 16, 0 },
+ .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = true,
+ },
+
+ /* SBWC Formats */
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC, .npln = 2, .ncmp = {1, 2, 0}, .bps = 8, .bpp_afbc = { 0, 0, 0 }, .bpp = { 8, 16, 0 }, .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT, .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true, .afbc = false, .linear = true, .yuv_transform = false, .flex = true, },
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC, .npln = 2, .ncmp = {1, 2, 0}, .bps = 10, .bpp_afbc = { 0, 0, 0 }, .bpp = { 16, 32, 0 }, .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT, .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true, .afbc = false, .linear = true, .yuv_transform = false, .flex = true, },
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC, .npln = 2, .ncmp = {1, 2, 0}, .bps = 8, .bpp_afbc = { 0, 0, 0 }, .bpp = { 8, 16, 0 }, .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT, .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true, .afbc = false, .linear = true, .yuv_transform = false, .flex = true, },
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC, .npln = 2, .ncmp = {1, 2, 0}, .bps = 10, .bpp_afbc = { 0, 0, 0 }, .bpp = { 16, 32, 0 }, .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT, .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true, .afbc = false, .linear = true, .yuv_transform = false, .flex = true, },
+ {
+ .id = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_SBWC,
+ .npln = 2, .ncmp = {1, 2, 0}, .bps = 8, .bpp_afbc = { 0, 0, 0 }, .bpp = { 8, 16, 0 },
+ .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = true,
+ },
+ {
+ .id = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC,
+ .npln = 2, .ncmp = {1, 2, 0}, .bps = 10, .bpp_afbc = { 0, 0, 0 }, .bpp = { 16, 32, 0 },
+ .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT,
+ .tile_size = 1,.has_alpha = false, .is_rgb = false, .is_yuv = true,
+ .afbc = false, .linear = true, .yuv_transform = false, .flex = true,
+ },
+
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L50, .npln = 2, .ncmp = {1, 2, 0}, .bps = 8, .bpp_afbc = { 0, 0, 0 }, .bpp = { 8, 16, 0 }, .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT, .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true, .afbc = false, .linear = true, .yuv_transform = false, .flex = true, },
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L75, .npln = 2, .ncmp = {1, 2, 0}, .bps = 8, .bpp_afbc = { 0, 0, 0 }, .bpp = { 8, 16, 0 }, .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT, .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true, .afbc = false, .linear = true, .yuv_transform = false, .flex = true, },
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L50, .npln = 2, .ncmp = {1, 2, 0}, .bps = 8, .bpp_afbc = { 0, 0, 0 }, .bpp = { 8, 16, 0 }, .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT, .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true, .afbc = false, .linear = true, .yuv_transform = false, .flex = true, },
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L75, .npln = 2, .ncmp = {1, 2, 0}, .bps = 8, .bpp_afbc = { 0, 0, 0 }, .bpp = { 8, 16, 0 }, .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT, .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true, .afbc = false, .linear = true, .yuv_transform = false, .flex = true, },
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L40, .npln = 2, .ncmp = {1, 2, 0}, .bps = 10, .bpp_afbc = { 0, 0, 0 }, .bpp = { 16, 32, 0 }, .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT, .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true, .afbc = false, .linear = true, .yuv_transform = false, .flex = true, },
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L60, .npln = 2, .ncmp = {1, 2, 0}, .bps = 10, .bpp_afbc = { 0, 0, 0 }, .bpp = { 16, 32, 0 }, .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT, .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true, .afbc = false, .linear = true, .yuv_transform = false, .flex = true, },
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L80, .npln = 2, .ncmp = {1, 2, 0}, .bps = 10, .bpp_afbc = { 0, 0, 0 }, .bpp = { 16, 32, 0 }, .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT, .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true, .afbc = false, .linear = true, .yuv_transform = false, .flex = true, },
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L40, .npln = 2, .ncmp = {1, 2, 0}, .bps = 10, .bpp_afbc = { 0, 0, 0 }, .bpp = { 16, 32, 0 }, .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT, .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true, .afbc = false, .linear = true, .yuv_transform = false, .flex = true, },
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L60, .npln = 2, .ncmp = {1, 2, 0}, .bps = 10, .bpp_afbc = { 0, 0, 0 }, .bpp = { 16, 32, 0 }, .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT, .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true, .afbc = false, .linear = true, .yuv_transform = false, .flex = true, },
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L80, .npln = 2, .ncmp = {1, 2, 0}, .bps = 10, .bpp_afbc = { 0, 0, 0 }, .bpp = { 16, 32, 0 }, .hsub = 2, .vsub = 2, .align_w = 2, .align_h = 2, ALIGN_W_CPU_DEFAULT, .tile_size = 1, .has_alpha = false, .is_rgb = false, .is_yuv = true, .afbc = false, .linear = true, .yuv_transform = false, .flex = true, },
+};
+const size_t num_formats = sizeof(formats)/sizeof(formats[0]);
+
+/*
+ * This table represents the superset of flags for each base format and producer/consumer.
+ * Where IP does not support a capability, it should be defined and not set.
+ */
+const format_ip_support_t formats_ip_support[] = {
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_RGB_565,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_LIN | F_AFBC,
+ .gpu_wr = F_LIN | F_AFBC,
+ .dpu_rd = F_LIN | F_AFBC,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_AFBC,
+ .vpu_rd = F_NONE,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_RGB_888,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_LIN | F_AFBC,
+ .gpu_wr = F_LIN | F_AFBC,
+ .dpu_rd = F_LIN | F_AFBC,
+ .dpu_wr = F_LIN,
+ .dpu_aeu_wr = F_AFBC,
+ .vpu_rd = F_NONE,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_RGBA_8888,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_LIN | F_AFBC,
+ .gpu_wr = F_LIN | F_AFBC,
+ .dpu_rd = F_LIN | F_AFBC,
+ .dpu_wr = F_LIN,
+ .dpu_aeu_wr = F_AFBC,
+ .vpu_rd = F_LIN,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_BGRA_8888,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_LIN,
+ .gpu_wr = F_LIN,
+ .dpu_rd = F_LIN,
+ .dpu_wr = F_LIN,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_LIN,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_RGBX_8888,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_LIN | F_AFBC,
+ .gpu_wr = F_LIN | F_AFBC,
+ .dpu_rd = F_LIN | F_AFBC,
+ .dpu_wr = F_LIN,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_NONE,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_RGBA_1010102,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_LIN | F_AFBC,
+ .gpu_wr = F_LIN | F_AFBC,
+ .dpu_rd = F_LIN | F_AFBC,
+ .dpu_wr = F_LIN,
+ .dpu_aeu_wr = F_AFBC,
+ .vpu_rd = F_NONE,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_RGBA_16161616,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_LIN | F_AFBC,
+ .gpu_wr = F_LIN | F_AFBC,
+ .dpu_rd = F_NONE,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_NONE,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_Y8,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_NONE,
+ .gpu_wr = F_NONE,
+ .dpu_rd = F_NONE,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_NONE,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_Y16,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_NONE,
+ .gpu_wr = F_NONE,
+ .dpu_rd = F_NONE,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_NONE,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ /* 420 (8-bit) */
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_YUV420_8BIT_I,
+ .cpu_rd = F_NONE,
+ .cpu_wr = F_NONE,
+ .gpu_rd = F_AFBC,
+ .gpu_wr = F_AFBC,
+ .dpu_rd = F_AFBC,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_AFBC,
+ .vpu_rd = F_AFBC,
+ .vpu_wr = F_AFBC,
+ .cam_wr = F_NONE,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_NV12,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_LIN | F_AFBC,
+ .gpu_wr = F_LIN,
+ .dpu_rd = F_LIN,
+ .dpu_wr = F_LIN,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_LIN,
+ .vpu_wr = F_LIN,
+ .cam_wr = F_NONE,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_NV21,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_LIN,
+ .gpu_wr = F_LIN,
+ .dpu_rd = F_NONE,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_LIN,
+ .vpu_wr = F_LIN,
+ .cam_wr = F_LIN,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_YV12,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_LIN,
+ .gpu_wr = F_LIN,
+ .dpu_rd = F_LIN,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_LIN,
+ .vpu_wr = F_LIN,
+ .cam_wr = F_NONE,
+ },
+ /* 422 (8-bit) */
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_YUV422_8BIT,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_LIN | F_AFBC,
+ .gpu_wr = F_LIN | F_AFBC,
+ .dpu_rd = F_LIN | F_AFBC,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_AFBC,
+ .vpu_rd = F_LIN,
+ .vpu_wr = F_LIN,
+ .cam_wr = F_LIN,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_NV16,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_LIN | F_AFBC,
+ .gpu_wr = F_LIN,
+ .dpu_rd = F_NONE,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_NONE,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ /* 420 (10-bit) */
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_YUV420_10BIT_I,
+ .cpu_rd = F_NONE,
+ .cpu_wr = F_NONE,
+ .gpu_rd = F_AFBC,
+ .gpu_wr = F_AFBC,
+ .dpu_rd = F_AFBC,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_AFBC,
+ .vpu_rd = F_AFBC,
+ .vpu_wr = F_AFBC,
+ .cam_wr = F_NONE,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_Y0L2,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_LIN,
+ .gpu_wr = F_LIN,
+ .dpu_rd = F_LIN,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_LIN,
+ .vpu_wr = F_LIN,
+ .cam_wr = F_NONE,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_P010,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_LIN,
+ .gpu_wr = F_LIN,
+ .dpu_rd = F_LIN,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_LIN,
+ .vpu_wr = F_LIN,
+ .cam_wr = F_NONE,
+ },
+ /* 422 (10-bit) */
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_Y210,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_LIN | F_AFBC,
+ .gpu_wr = F_LIN | F_AFBC,
+ .dpu_rd = F_NONE,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_NONE,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_P210,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_LIN,
+ .gpu_wr = F_LIN,
+ .dpu_rd = F_NONE,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_NONE,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ /* 444 (10-bit) */
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_YUV444_10BIT_I,
+ .cpu_rd = F_NONE,
+ .cpu_wr = F_NONE,
+ .gpu_rd = F_NONE,
+ .gpu_wr = F_NONE,
+ .dpu_rd = F_NONE,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_NONE,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_Y410,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_LIN,
+ .gpu_wr = F_LIN | F_AFBC,
+ .dpu_rd = F_NONE,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_NONE,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ /* Other */
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_RAW16,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_LIN,
+ .gpu_wr = F_NONE,
+ .dpu_rd = F_NONE,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_NONE,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_LIN,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_RAW12,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_NONE,
+ .gpu_wr = F_NONE,
+ .dpu_rd = F_NONE,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_NONE,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_RAW10,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_NONE,
+ .gpu_wr = F_NONE,
+ .dpu_rd = F_NONE,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_NONE,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_BLOB,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_LIN,
+ .gpu_wr = F_LIN,
+ .dpu_rd = F_NONE,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_NONE,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ /* Depth and Stencil */
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_DEPTH_16,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_NONE,
+ .gpu_wr = F_NONE,
+ .dpu_rd = F_NONE,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_NONE,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_DEPTH_24,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_NONE,
+ .gpu_wr = F_NONE,
+ .dpu_rd = F_NONE,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_NONE,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_DEPTH_24_STENCIL_8,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_NONE,
+ .gpu_wr = F_NONE,
+ .dpu_rd = F_NONE,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_NONE,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_DEPTH_32F,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_NONE,
+ .gpu_wr = F_NONE,
+ .dpu_rd = F_NONE,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_NONE,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_DEPTH_32F_STENCIL_8,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_NONE,
+ .gpu_wr = F_NONE,
+ .dpu_rd = F_NONE,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_NONE,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ {
+ .id = MALI_GRALLOC_FORMAT_INTERNAL_STENCIL_8,
+ .cpu_rd = F_LIN,
+ .cpu_wr = F_LIN,
+ .gpu_rd = F_NONE,
+ .gpu_wr = F_NONE,
+ .dpu_rd = F_NONE,
+ .dpu_wr = F_NONE,
+ .dpu_aeu_wr = F_NONE,
+ .vpu_rd = F_NONE,
+ .vpu_wr = F_NONE,
+ .cam_wr = F_NONE,
+ },
+ /* Exynos Formats */
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YV12_M, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN, .gpu_rd = F_LIN, .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_YCrCb_420_SP, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN, .gpu_rd = F_LIN, .dpu_wr = F_NONE, .dpu_rd = F_NONE, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+
+ /* SBWC Formats */
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_SBWC, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L50, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L75, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L50, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L75, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L40, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L60, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L80, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L40, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L60, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+ { .id = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L80, .cpu_wr = F_LIN, .cpu_rd = F_LIN, .gpu_wr = F_LIN , .gpu_rd = F_LIN , .dpu_wr = F_NONE, .dpu_rd = F_LIN, .dpu_aeu_wr = F_NONE, .vpu_wr = F_LIN, .vpu_rd = F_LIN},
+};
+
+const size_t num_ip_formats = sizeof(formats_ip_support)/sizeof(formats_ip_support[0]);
+
+typedef struct
+{
+ uint32_t hal_format;
+ bool is_flex;
+ uint32_t internal_format;
+} hal_int_fmt;
+
+
+static const hal_int_fmt hal_to_internal_format[] =
+{
+ { HAL_PIXEL_FORMAT_RGBA_8888, false, MALI_GRALLOC_FORMAT_INTERNAL_RGBA_8888 },
+ { HAL_PIXEL_FORMAT_RGBX_8888, false, MALI_GRALLOC_FORMAT_INTERNAL_RGBX_8888 },
+ { HAL_PIXEL_FORMAT_RGB_888, false, MALI_GRALLOC_FORMAT_INTERNAL_RGB_888 },
+ { HAL_PIXEL_FORMAT_RGB_565, false, MALI_GRALLOC_FORMAT_INTERNAL_RGB_565 },
+ { HAL_PIXEL_FORMAT_BGRA_8888, false, MALI_GRALLOC_FORMAT_INTERNAL_BGRA_8888 },
+ { HAL_PIXEL_FORMAT_YCbCr_422_SP, false, MALI_GRALLOC_FORMAT_INTERNAL_NV16 },
+ { HAL_PIXEL_FORMAT_YCrCb_420_SP, false, MALI_GRALLOC_FORMAT_INTERNAL_NV21 },
+ { HAL_PIXEL_FORMAT_YCbCr_422_I, false, MALI_GRALLOC_FORMAT_INTERNAL_YUV422_8BIT },
+ { HAL_PIXEL_FORMAT_RGBA_FP16, false, MALI_GRALLOC_FORMAT_INTERNAL_RGBA_16161616 },
+ { HAL_PIXEL_FORMAT_RAW16, false, MALI_GRALLOC_FORMAT_INTERNAL_RAW16 },
+ { HAL_PIXEL_FORMAT_BLOB, false, MALI_GRALLOC_FORMAT_INTERNAL_BLOB },
+ { HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, true, MALI_GRALLOC_FORMAT_INTERNAL_NV12 },
+ { HAL_PIXEL_FORMAT_YCbCr_420_888, true, MALI_GRALLOC_FORMAT_INTERNAL_NV12 },
+ { HAL_PIXEL_FORMAT_RAW_OPAQUE, false, MALI_GRALLOC_FORMAT_INTERNAL_UNDEFINED },
+ { HAL_PIXEL_FORMAT_RAW10, false, MALI_GRALLOC_FORMAT_INTERNAL_RAW10 },
+ { HAL_PIXEL_FORMAT_RAW12, false, MALI_GRALLOC_FORMAT_INTERNAL_RAW12 },
+ { HAL_PIXEL_FORMAT_YCbCr_422_888, true, MALI_GRALLOC_FORMAT_INTERNAL_YUV422_8BIT },
+ { HAL_PIXEL_FORMAT_YCbCr_444_888, true, MALI_GRALLOC_FORMAT_INTERNAL_UNDEFINED },
+ { HAL_PIXEL_FORMAT_FLEX_RGB_888, true, MALI_GRALLOC_FORMAT_INTERNAL_UNDEFINED },
+ { HAL_PIXEL_FORMAT_FLEX_RGBA_8888, true, MALI_GRALLOC_FORMAT_INTERNAL_UNDEFINED },
+ { HAL_PIXEL_FORMAT_RGBA_1010102, false, MALI_GRALLOC_FORMAT_INTERNAL_RGBA_1010102 },
+ { HAL_PIXEL_FORMAT_DEPTH_16, false, MALI_GRALLOC_FORMAT_INTERNAL_DEPTH_16 },
+ { HAL_PIXEL_FORMAT_DEPTH_24, false, MALI_GRALLOC_FORMAT_INTERNAL_DEPTH_24 },
+ { HAL_PIXEL_FORMAT_DEPTH_24_STENCIL_8, false, MALI_GRALLOC_FORMAT_INTERNAL_DEPTH_24_STENCIL_8 },
+ { HAL_PIXEL_FORMAT_DEPTH_32F, false, MALI_GRALLOC_FORMAT_INTERNAL_DEPTH_32F },
+ { HAL_PIXEL_FORMAT_DEPTH_32F_STENCIL_8, false, MALI_GRALLOC_FORMAT_INTERNAL_DEPTH_32F_STENCIL_8 },
+ { HAL_PIXEL_FORMAT_STENCIL_8, false, MALI_GRALLOC_FORMAT_INTERNAL_STENCIL_8 },
+ { HAL_PIXEL_FORMAT_YCBCR_P010, false, MALI_GRALLOC_FORMAT_INTERNAL_P010 },
+ { HAL_PIXEL_FORMAT_Y8, false, MALI_GRALLOC_FORMAT_INTERNAL_Y8 },
+ { HAL_PIXEL_FORMAT_Y16, false, MALI_GRALLOC_FORMAT_INTERNAL_Y16 },
+ { HAL_PIXEL_FORMAT_YV12, false, MALI_GRALLOC_FORMAT_INTERNAL_YV12 },
+ /* Exynos Formats */
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP, true, MALI_GRALLOC_FORMAT_INTERNAL_NV12 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M, false, HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL, false, HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M, false, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M },
+ { HAL_PIXEL_FORMAT_EXYNOS_YV12_M, false, HAL_PIXEL_FORMAT_EXYNOS_YV12_M },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M, false, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B, false, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED, false, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED},
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN, false, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B, false, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M, false, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P, false, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P },
+ /* SBWC Formats */
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC, false, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC, false, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC, false, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC, false, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_SBWC, false, HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_SBWC },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC, false, HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC },
+
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L50, false, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L50 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L75, false, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L75 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L50, false, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L50 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L75, false, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L75 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L40, false, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L40 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L60, false, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L60 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L80, false, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L80 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L40, false, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L40 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L60, false, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L60 },
+ { HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L80, false, HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L80 },
+};
+
+const size_t num_hal_formats = sizeof(hal_to_internal_format)/sizeof(hal_to_internal_format[0]);
+
+
+/*
+ * Finds "Look-up Table" index for the given format
+ *
+ * @param base_format [in] Format for which index is required.
+ *
+ * @return index, when the format is found in the look up table
+ * -1, otherwise
+ *
+ */
+int32_t get_format_index(const uint32_t base_format)
+{
+ int32_t format_idx;
+ for (format_idx = 0; format_idx < (int32_t)num_formats; format_idx++)
+ {
+ if (formats[format_idx].id == base_format)
+ {
+ break;
+ }
+ }
+ if (format_idx >= (int32_t)num_formats)
+ {
+ MALI_GRALLOC_LOGE("ERROR: Format allocation info not found for format: %" PRIx32, base_format);
+ return -1;
+ }
+
+ return format_idx;
+}
+
+
+int32_t get_ip_format_index(const uint32_t base_format)
+{
+ int32_t format_idx;
+ for (format_idx = 0; format_idx < (int32_t)num_ip_formats; format_idx++)
+ {
+ if (formats_ip_support[format_idx].id == base_format)
+ {
+ break;
+ }
+ }
+ if (format_idx >= (int32_t)num_ip_formats)
+ {
+ MALI_GRALLOC_LOGE("ERROR: IP support not found for format: %" PRIx32, base_format);
+ return -1;
+ }
+
+ return format_idx;
+}
+
+
+/*
+ * Attempt to map base HAL format to an internal format and
+ * validate format is supported for allocation.
+ *
+ * @param map_to_internal [in] 1: Forces mapping to (and validation of) internal format
+ * 0: Only maps flex HAL formats to internal
+ *
+ * @return internal_format, where internal format is found
+ * HAL format, where map_to_internal == 0 and base_format is not flex
+ * MALI_GRALLOC_FORMAT_INTERNAL_UNDEFINED, otherwise
+ *
+ * NOTE: Base format might be either a HAL format or (already) an internal format.
+ *
+ */
+uint32_t get_internal_format(const uint32_t base_format, const bool map_to_internal)
+{
+ uint32_t internal_format = base_format;
+
+ for (int idx = 0; idx < (int)num_hal_formats; idx++)
+ {
+ if (hal_to_internal_format[idx].hal_format == base_format)
+ {
+ if (hal_to_internal_format[idx].is_flex || map_to_internal)
+ {
+ internal_format = hal_to_internal_format[idx].internal_format;
+ }
+ break;
+ }
+ }
+
+ /* Ensure internal format is valid when expected. */
+ if (map_to_internal && get_format_index(internal_format) < 0)
+ {
+ internal_format = MALI_GRALLOC_FORMAT_INTERNAL_UNDEFINED;
+ }
+
+ return internal_format;
+}
+
+
+/* Get the dataspace to use based on private usage and format. */
+void get_format_dataspace(uint32_t base_format,
+ uint64_t usage,
+ int width,
+ int height,
+ android_dataspace_t *dataspace)
+{
+ GRALLOC_UNUSED(usage);
+
+ uint64_t color_space = HAL_DATASPACE_STANDARD_UNSPECIFIED;
+ uint64_t range = HAL_DATASPACE_RANGE_UNSPECIFIED;
+ *dataspace = HAL_DATASPACE_UNKNOWN;
+
+ const int32_t format_idx = get_format_index(base_format);
+ if (format_idx < 0)
+ {
+ return;
+ }
+
+ /* This resolution is the cut-off point at which BT709 is used (as default)
+ * instead of BT601 for YUV formats < 10 bits.
+ */
+ constexpr int yuv_bt601_max_width = 1280;
+ constexpr int yuv_bt601_max_height = 720;
+
+ if (formats[format_idx].is_yuv)
+ {
+ /* Default YUV dataspace. */
+ color_space = HAL_DATASPACE_STANDARD_BT709;
+ range = HAL_DATASPACE_RANGE_LIMITED;
+
+ /* 10-bit YUV is assumed to be wide BT2020.
+ */
+ if (formats[format_idx].bps >= 10)
+ {
+ color_space = HAL_DATASPACE_STANDARD_BT2020;
+ range = HAL_DATASPACE_RANGE_FULL;
+ }
+ else if (width < yuv_bt601_max_width || height < yuv_bt601_max_height)
+ {
+ color_space = HAL_DATASPACE_STANDARD_BT601_625;
+ range = HAL_DATASPACE_RANGE_LIMITED;
+ }
+
+ *dataspace = static_cast<android_dataspace_t>(color_space | range);
+ }
+ else if (formats[format_idx].is_rgb)
+ {
+ /* Default RGB dataspace. Expected by Mapper VTS. */
+ *dataspace = static_cast<android_dataspace_t>(HAL_DATASPACE_UNKNOWN);
+ }
+}
+
+
+bool is_power2(uint8_t n)
+{
+ return ((n & (n-1)) == 0);
+}
+
+
+bool sanitize_formats(void)
+{
+ bool fail = false;
+
+ for (int i = 0; i < (int)num_formats; i++)
+ {
+ const format_info_t * format = &formats[i];
+
+ /* Identify invalid values. */
+ if (format->id == 0 ||
+ format->npln == 0 || format->npln > 3 ||
+ format->total_components() == 0 ||
+ format->bps == 0 ||
+ format->align_w == 0 ||
+ format->align_h == 0 ||
+ format->align_w_cpu == 0 ||
+ format->tile_size == 0)
+ {
+ MALI_GRALLOC_LOGE("Format [id:0x%" PRIx32 "] property zero/out of range (unexpected)", format->id);
+ fail = true;
+ }
+
+ if (format->is_rgb && format->is_yuv)
+ {
+ MALI_GRALLOC_LOGE("Format [id:0x%" PRIx32 "] cannot be both RGB and YUV", format->id);
+ fail = true;
+ }
+
+ if (format->npln > format->total_components())
+ {
+ MALI_GRALLOC_LOGE("Format [id:0x%" PRIx32 "] planes cannot exceed components", format->id);
+ fail = true;
+ }
+
+ if (format->linear && (format->bps > format->bpp[0]))
+ {
+ MALI_GRALLOC_LOGE("Format [id:0x%" PRIx32 "] bpp should be greater than/equal to bps", format->id);
+ fail = true;
+ }
+
+ if (format->afbc && (format->bps > format->bpp_afbc[0]))
+ {
+ MALI_GRALLOC_LOGE("Format [id:0x%" PRIx32 "] bpp_afbc should be greater than/equal to bps", format->id);
+ fail = true;
+ }
+
+ if (!format->linear && format->tile_size > 1)
+ {
+ MALI_GRALLOC_LOGE("Format [id:0x%" PRIx32 "] tile_size must be set to 1 for formats without linear support", format->id);
+ fail = true;
+ }
+
+ for (int pln = 0; pln < 3; pln++)
+ {
+ if (format->linear && (pln < format->npln) && (format->bpp[pln] == 0))
+ {
+ MALI_GRALLOC_LOGE("Format [id:0x%" PRIx32 "] does not have bpp defined for plane: %d", format->id, pln);
+ fail = true;
+ }
+ else if (format->linear && (pln >= format->npln) && (format->bpp[pln] != 0))
+ {
+ MALI_GRALLOC_LOGE("Format [id:0x%" PRIx32 "] should not have bpp defined for plane: %d", format->id, pln);
+ fail = true;
+ }
+ else if (!format->linear && (format->bpp[pln] != 0))
+ {
+ MALI_GRALLOC_LOGE("Format [id:0x%" PRIx32 "] which doesn't support linear should not have bpp defined", format->id);
+ fail = true;
+ }
+
+ if (format->afbc && (pln < format->npln) && (format->bpp_afbc[pln] == 0))
+ {
+ MALI_GRALLOC_LOGE("Format [id:0x%" PRIx32 "] does not have bpp_afbc defined for plane: %d", format->id, pln);
+ fail = true;
+ }
+ else if (format->afbc && (pln >= format->npln) && (format->bpp_afbc[pln] != 0))
+ {
+ MALI_GRALLOC_LOGE("Format [id:0x%" PRIx32 "] should not have bpp_afbc defined for plane: %d", format->id, pln);
+ fail = true;
+ }
+ else if (!format->afbc && (format->bpp_afbc[pln] != 0))
+ {
+ MALI_GRALLOC_LOGE("Format [id:0x%" PRIx32 "] which doesn't support afbc should not have bpp defined", format->id);
+ fail = true;
+ }
+ }
+
+ if (format->is_yuv)
+ {
+ if (format->hsub == 0 || format->vsub == 0)
+ {
+ MALI_GRALLOC_LOGE("Format [id:0x%" PRIx32 "] hsub and vsub should be non-zero (YUV)", format->id);
+ fail = true;
+ }
+
+ if (!is_power2(format->hsub) || !is_power2(format->vsub))
+ {
+ MALI_GRALLOC_LOGE("Format [id:0x%" PRIx32 "] hsub and vsub should be powers of 2", format->id);
+ fail = true;
+ }
+
+ if ((format->align_w % format->hsub) != 0)
+ {
+ MALI_GRALLOC_LOGE("Format [id:0x%" PRIx32 "] align_w should be a multiple of hsub", format->id);
+ fail = true;
+ }
+
+ if ((format->align_h % format->vsub) != 0)
+ {
+ MALI_GRALLOC_LOGE("Format [id:0x%" PRIx32 "] align_h should be a multiple of vsub", format->id);
+ fail = true;
+ }
+ }
+ else
+ {
+ if (format->hsub != 0 || format->vsub != 0)
+ {
+ MALI_GRALLOC_LOGE("Format [id:0x%" PRIx32 "] hsub and vsub should be zero (non-YUV)", format->id);
+ fail = true;
+ }
+ }
+
+ if (format->align_w == 0 || format->align_h == 0)
+ {
+ MALI_GRALLOC_LOGE("Format [id:0x%" PRIx32 "] align_w and align_h should be non-zero", format->id);
+ fail = true;
+ }
+ else
+ {
+ if (!is_power2(format->align_w) || !is_power2(format->align_h))
+ {
+ MALI_GRALLOC_LOGE("Format [id:0x%" PRIx32 "] align_w and align_h should be powers of 2", format->id);
+ fail = true;
+ }
+
+ if (!is_power2(format->align_w_cpu))
+ {
+ MALI_GRALLOC_LOGE("Format [id:0x%" PRIx32 "] align_w_cpu should be a power of 2", format->id);
+ fail = true;
+ }
+ }
+ }
+
+ return fail;
+}
diff --git a/gralloc4/src/core/format_info.h b/gralloc4/src/core/format_info.h
new file mode 100644
index 0000000..e569a8f
--- /dev/null
+++ b/gralloc4/src/core/format_info.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2018-2020 ARM Limited. All rights reserved.
+ *
+ * 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 FORMAT_INFO_H_
+#define FORMAT_INFO_H_
+
+#include "mali_gralloc_buffer.h"
+
+typedef uint8_t format_support_flags;
+
+/* Base format unsupported */
+#define F_NONE 0
+/* Base format supports uncompressed */
+#define F_LIN ((uint8_t)1 << 0)
+/* Base format supports AFBC */
+#define F_AFBC ((uint8_t)1 << 1)
+/* Base format supports AFBC with different swizzle */
+#define F_AFBC_SWIZ ((uint8_t)1 << 2)
+
+
+typedef struct
+{
+ uint16_t width;
+ uint16_t height;
+} rect_t;
+
+
+/*
+ * Pixel format information.
+ *
+ * These properties are used by gralloc for buffer allocation.
+ * Each format is uniquely identified with 'id'.
+ */
+typedef struct
+{
+ uint32_t id; /* Format ID. */
+ uint8_t npln; /* Number of planes. */
+ uint8_t ncmp[MAX_PLANES]; /* Number of components in each plane. */
+ uint8_t bps; /* Bits per sample (primary/largest). */
+ uint8_t bpp_afbc[MAX_PLANES]; /* Bits per pixel (AFBC), without implicit padding. 'X' in RGBX is still included. */
+ uint8_t bpp[MAX_PLANES]; /* Bits per pixel (linear/uncompressed), including any implicit sample padding defined by format (e.g. 10-bit Y210 padded to 16-bits).
+ * NOTE: bpp[n] and/or (bpp[n] * align_w_cpu) must be multiples of 8. */
+ uint8_t hsub; /* Horizontal sub-sampling (YUV formats). Pixel rounding in width (all formats). Must be a power of 2. */
+ uint8_t vsub; /* Vertical sub-sampling (YUV formats). Pixel rounding in height (all formats). Must be a power of 2. */
+ uint8_t align_w; /* Alignment of width (per plane, in pixels). Must be a power of 2. NOTE: where 'is_yuv == true', this must be a multiple of 'hsub'. */
+ uint8_t align_h; /* Alignment of height (per plane, in pixels). Must be a power of 2. NOTE: where 'is_yuv == true', this must be a multiple of 'vsub'. */
+ uint8_t align_w_cpu; /* Alignment of width for CPU access (per plane, in pixels). ALIGN_W_CPU_DEFAULT: 1. Must be a power of 2. */
+ uint16_t tile_size; /* Tile size (in pixels), assumed square. Uncompressed only. */
+ bool has_alpha; /* Alpha channel present. */
+ bool is_rgb; /* RGB format. */
+ bool is_yuv; /* YUV format. */
+ bool afbc; /* AFBC supported (per specification and by gralloc). IP support not considered. */
+ bool linear; /* Linear/uncompressed supported. */
+ bool yuv_transform; /* Supports AFBC YUV transform: 3+ channel RGB (strict R-G-B-? order) with less than 12-bit per sample. */
+ bool flex; /* Linear version of format can be represented as flex. */
+ /* Computes the total number of components in the format. */
+ int total_components() const
+ {
+ int sum = 0;
+ for (auto n: ncmp)
+ {
+ sum += n;
+ }
+ return sum;
+ }
+} format_info_t;
+
+typedef struct
+{
+ uint32_t id; /* Format ID. */
+ format_support_flags cpu_wr; /* CPU producer. */
+ format_support_flags cpu_rd; /* CPU consumer. */
+ format_support_flags gpu_wr; /* GPU producer. */
+ format_support_flags gpu_rd; /* GPU consumer. */
+ format_support_flags dpu_wr; /* DPU producer. */
+ format_support_flags dpu_rd; /* DPU consumer. */
+ format_support_flags dpu_aeu_wr; /* DPU AEU producer. (UNUSED IN EXYNOS) */
+ format_support_flags vpu_wr; /* VPU producer. */
+ format_support_flags vpu_rd; /* VPU consumer. */
+ format_support_flags cam_wr; /* Camera producer. */
+
+} format_ip_support_t;
+
+
+extern const format_info_t formats[];
+extern const format_ip_support_t formats_ip_support[];
+extern const size_t num_formats;
+extern const size_t num_ip_formats;
+
+extern int32_t get_format_index(const uint32_t base_format);
+extern int32_t get_ip_format_index(const uint32_t base_format);
+extern uint32_t get_internal_format(const uint32_t base_format, const bool map_to_internal);
+void get_format_dataspace(uint32_t base_format,
+ uint64_t usage,
+ int width,
+ int height,
+ android_dataspace_t *dataspace);
+extern bool sanitize_formats(void);
+
+#endif
diff --git a/gralloc4/src/core/mali_gralloc_bufferaccess.cpp b/gralloc4/src/core/mali_gralloc_bufferaccess.cpp
new file mode 100644
index 0000000..154ad25
--- /dev/null
+++ b/gralloc4/src/core/mali_gralloc_bufferaccess.cpp
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2016-2020 ARM Limited. All rights reserved.
+ *
+ * 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 <errno.h>
+#include <inttypes.h>
+#include <inttypes.h>
+/* For error codes. */
+#include <hardware/gralloc1.h>
+
+#include "mali_gralloc_buffer.h"
+#include "mali_gralloc_formats.h"
+#include "mali_gralloc_usages.h"
+#include "allocator/mali_gralloc_ion.h"
+#include "gralloc_helper.h"
+#include "format_info.h"
+
+
+enum tx_direction
+{
+ TX_NONE = 0,
+ TX_TO_DEVICE,
+ TX_FROM_DEVICE,
+ TX_BOTH,
+};
+
+
+static enum tx_direction get_tx_direction(const uint64_t usage)
+{
+ const bool read = (usage & GRALLOC_USAGE_SW_READ_MASK) ? true : false;
+ const bool write = (usage & GRALLOC_USAGE_SW_WRITE_MASK) ? true : false;
+ enum tx_direction dir = TX_NONE;
+
+ if (read && write)
+ {
+ dir = TX_BOTH;
+ }
+ else if (write)
+ {
+ dir = TX_TO_DEVICE;
+ }
+ else if (read)
+ {
+ dir = TX_FROM_DEVICE;
+ }
+
+ return dir;
+}
+
+static void buffer_sync(private_handle_t * const hnd,
+ const enum tx_direction direction)
+{
+ if (direction != TX_NONE)
+ {
+ hnd->cpu_read = (direction == TX_FROM_DEVICE || direction == TX_BOTH) ? 1 : 0;
+ hnd->cpu_write = (direction == TX_TO_DEVICE || direction == TX_BOTH) ? 1 : 0;
+
+#if defined(GRALLOC_ION_SYNC_ON_LOCK) && GRALLOC_ION_SYNC_ON_LOCK == 1
+ const int status = mali_gralloc_ion_sync_start(hnd,
+ hnd->cpu_read ? true : false,
+ hnd->cpu_write ? true : false);
+ if (status < 0)
+ {
+ return;
+ }
+#endif
+ }
+ else if (hnd->cpu_read || hnd->cpu_write)
+ {
+#if defined(GRALLOC_ION_SYNC_ON_LOCK) && GRALLOC_ION_SYNC_ON_LOCK == 1
+ const int status = mali_gralloc_ion_sync_end(hnd,
+ hnd->cpu_read ? true : false,
+ hnd->cpu_write ? true : false);
+ if (status < 0)
+ {
+ return;
+ }
+#endif
+ hnd->cpu_read = 0;
+ hnd->cpu_write = 0;
+ }
+}
+
+
+/*
+ * Validates input parameters of lock request.
+ *
+ * @param buffer [in] The buffer to lock.
+ * @param l [in] Access region left offset (in pixels).
+ * @param t [in] Access region top offset (in pixels).
+ * @param w [in] Access region requested width (in pixels).
+ * @param h [in] Access region requested height (in pixels).
+ * @param usage [in] Lock request (producer and consumer combined) usage.
+ *
+ * @return 0,for valid input parameters;
+ * -EINVAL, for erroneous input parameters
+ */
+int validate_lock_input_parameters(const buffer_handle_t buffer, const int l,
+ const int t, const int w, const int h,
+ uint64_t usage)
+{
+ bool is_registered_process = false;
+ const int lock_pid = getpid();
+ const private_handle_t * const hnd = (private_handle_t *)buffer;
+
+ /* TODO: do not check access region for blob formats.
+ * This is because codec2 attempts to lock with wrong access region.
+ * Ask Google to fix codec2
+ */
+ if (hnd->get_alloc_format() != HAL_PIXEL_FORMAT_BLOB)
+ {
+ if ((l < 0) || (t < 0) || (w < 0) || (h < 0))
+ {
+ MALI_GRALLOC_LOGW("Negative values for access region (l = %d t = %d w = %d and "
+ "h = %d) in buffer lock request are invalid. Locking PID:%d",
+ l, t, w, h, lock_pid);
+ return -EINVAL;
+ }
+
+ /* Test overflow conditions on access region parameters */
+ if (((l + w) < 0) || ((t + h) < 0))
+ {
+ MALI_GRALLOC_LOGW("Encountered overflow with access region (l = %d t = %d w = %d and"
+ " h = %d) in buffer lock request. Locking PID:%d",
+ l, t, w, h, lock_pid);
+ return -EINVAL;
+ }
+
+ /* Region of interest shall be inside the allocated buffer */
+ if (((t + h) > hnd->height) || ((l + w) > hnd->width))
+ {
+ MALI_GRALLOC_LOGW("Buffer lock access region (l = %d t = %d w = %d "
+ "and h = %d) is outside allocated buffer (width = %d and height = %d)"
+ " Locking PID:%d", l, t, w, h, hnd->width, hnd->height, lock_pid);
+ return -EINVAL;
+ }
+ }
+
+ /* Locking process should have a valid buffer virtual address. A process
+ * will have a valid buffer virtual address if it is the allocating
+ * process or it retained / registered a cloned buffer handle
+ */
+ if ((hnd->allocating_pid == lock_pid) || (hnd->remote_pid == lock_pid))
+ {
+ is_registered_process = true;
+ }
+
+ /* TODO: differentiate between mappable and unmappable(secure, hfr etc) buffers */
+ if (is_registered_process == false)
+ {
+ MALI_GRALLOC_LOGE("The buffer must be retained before lock request");
+ return -EINVAL;
+ }
+
+ /* Reject lock requests for AFBC (compressed format) enabled buffers */
+ if ((hnd->alloc_format & MALI_GRALLOC_INTFMT_EXT_MASK) != 0)
+ {
+ MALI_GRALLOC_LOGE("Lock is not supported for AFBC enabled buffers."
+ "Internal Format:0x%" PRIx64, hnd->alloc_format);
+
+ return GRALLOC1_ERROR_UNSUPPORTED;
+ }
+
+ /* Producer and consumer usage is verified in gralloc1 specific code. */
+ GRALLOC_UNUSED(usage);
+
+ return 0;
+}
+
+
+/*
+ * Locks the given buffer for the specified CPU usage.
+ *
+ * @param m [in] Gralloc module.
+ * @param buffer [in] The buffer to lock.
+ * @param usage [in] Producer and consumer combined usage.
+ * @param l [in] Access region left offset (in pixels).
+ * @param t [in] Access region top offset (in pixels).
+ * @param w [in] Access region requested width (in pixels).
+ * @param h [in] Access region requested height (in pixels).
+ * @param vaddr [out] To be filled with a CPU-accessible pointer to
+ * the buffer data for CPU usage.
+ *
+ * @return 0, when the locking is successful;
+ * Appropriate error, otherwise
+ *
+ * @Note: There is no way to ascertain whether buffer data is valid or not (for
+ * example, establishing if the h/w needs to finish rendering or if CPU
+ * caches need to be synchronized).
+ *
+ * @Note: Locking a buffer simultaneously for write or read/write leaves the
+ * buffer's content in an indeterminate state.
+ */
+int mali_gralloc_lock(buffer_handle_t buffer,
+ uint64_t usage, int l, int t, int w, int h, void **vaddr)
+{
+ int status;
+
+ if (private_handle_t::validate(buffer) < 0)
+ {
+ MALI_GRALLOC_LOGE("Locking invalid buffer %p, returning error", buffer);
+ return -EINVAL;
+ }
+
+ /* Validate input parameters for lock request */
+ status = validate_lock_input_parameters(buffer, l, t, w, h, usage);
+ if (status != 0)
+ {
+ return status;
+ }
+
+ private_handle_t *hnd = (private_handle_t *)buffer;
+
+ const int32_t format_idx = get_format_index(hnd->alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK);
+ if (format_idx == -1)
+ {
+ MALI_GRALLOC_LOGE("Corrupted buffer format 0x%" PRIx64 " of buffer %p", hnd->alloc_format, hnd);
+ return -EINVAL;
+ }
+
+ /* Populate CPU-accessible pointer when requested for CPU usage */
+ if ((usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) != 0)
+ {
+ if (vaddr == NULL)
+ {
+ return -EINVAL;
+ }
+
+ /* Mapping is done during reference retain instead of lock */
+#if 0
+ if (ion_map_for_lock(hnd) < 0)
+ {
+ return -EINVAL;
+ }
+#endif
+
+ *vaddr = (void *)hnd->bases[0];
+
+ buffer_sync(hnd, get_tx_direction(usage));
+ }
+
+ return 0;
+}
+
+
+/*
+ * Unlocks the given buffer.
+ *
+ * @param m [in] Gralloc module.
+ * @param buffer [in] The buffer to unlock.
+ *
+ * @return 0, when the locking is successful;
+ * Appropriate error, otherwise
+ *
+ * Note: unlocking a buffer which is not locked results in an unexpected behaviour.
+ * Though it is possible to create a state machine to track the buffer state to
+ * recognize erroneous conditions, it is expected of client to adhere to API
+ * call sequence
+ */
+int mali_gralloc_unlock(buffer_handle_t buffer)
+{
+ if (private_handle_t::validate(buffer) < 0)
+ {
+ MALI_GRALLOC_LOGE("Unlocking invalid buffer %p, returning error", buffer);
+ return -EINVAL;
+ }
+
+ private_handle_t *hnd = (private_handle_t *)buffer;
+ buffer_sync(hnd, TX_NONE);
+
+ return 0;
+}
diff --git a/gralloc4/src/core/mali_gralloc_bufferaccess.h b/gralloc4/src/core/mali_gralloc_bufferaccess.h
new file mode 100644
index 0000000..a6f9f0c
--- /dev/null
+++ b/gralloc4/src/core/mali_gralloc_bufferaccess.h
@@ -0,0 +1,34 @@
+
+/*
+ * Copyright (C) 2016-2017, 2020 ARM Limited. All rights reserved.
+ *
+ * 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 MALI_GRALLOC_BUFFERACCESS_H_
+#define MALI_GRALLOC_BUFFERACCESS_H_
+
+#include "gralloc_priv.h"
+
+int mali_gralloc_lock(buffer_handle_t buffer, uint64_t usage, int l, int t, int w, int h,
+ void **vaddr);
+int mali_gralloc_lock_ycbcr(buffer_handle_t buffer, uint64_t usage, int l, int t, int w,
+ int h, android_ycbcr *ycbcr);
+int mali_gralloc_unlock(buffer_handle_t buffer);
+
+int mali_gralloc_get_num_flex_planes(buffer_handle_t buffer, uint32_t *num_planes);
+int mali_gralloc_lock_flex(buffer_handle_t buffer, uint64_t usage, int l, int t,
+ int w, int h, struct android_flex_layout *flex_layout);
+
+#endif /* MALI_GRALLOC_BUFFERACCESS_H_ */
diff --git a/gralloc4/src/core/mali_gralloc_bufferallocation.cpp b/gralloc4/src/core/mali_gralloc_bufferallocation.cpp
new file mode 100644
index 0000000..8ddc8fa
--- /dev/null
+++ b/gralloc4/src/core/mali_gralloc_bufferallocation.cpp
@@ -0,0 +1,1099 @@
+/*
+ * Copyright (C) 2016-2020 ARM Limited. All rights reserved.
+ *
+ * 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 <inttypes.h>
+#include <assert.h>
+#include <atomic>
+#include <algorithm>
+
+#include <hardware/hardware.h>
+#include <hardware/gralloc1.h>
+
+#include "mali_gralloc_bufferallocation.h"
+#include "allocator/mali_gralloc_ion.h"
+#include "allocator/mali_gralloc_shared_memory.h"
+#include "mali_gralloc_buffer.h"
+#include "mali_gralloc_bufferdescriptor.h"
+#include "mali_gralloc_debug.h"
+#include "mali_gralloc_log.h"
+#include "format_info.h"
+#include <exynos_format.h>
+#include "exynos_format_allocation.h"
+
+/* MSCL Padding */
+#define MSCL_ALIGN 128
+#define MSCL_EXT_SIZE 512
+#define EXT_SIZE 256
+
+/* Default align values for Exynos */
+#define YUV_BYTE_ALIGN_DEFAULT 16
+#define RGB_BYTE_ALIGN_DEFAULT 64
+
+/* Always CPU align for Exynos */
+#define CAN_SKIP_CPU_ALIGN 0
+
+/* Do not realign YV12 formats for Exynos */
+#define REALIGN_YV12 0
+
+/* TODO: set S10B format align in BoardConfig.mk */
+#define BOARD_EXYNOS_S10B_FORMAT_ALIGN 64
+#if 0
+ifeq ($(BOARD_EXYNOS_S10B_FORMAT_ALIGN), 64)
+LOCAL_CFLAGS += -DBOARD_EXYNOS_S10B_FORMAT_ALIGN=$(BOARD_EXYNOS_S10B_FORMAT_ALIGN)
+else
+LOCAL_CFLAGS += -DBOARD_EXYNOS_S10B_FORMAT_ALIGN=16
+endif
+#endif
+
+/* Exynos W/A for BLOB DRM Contents.
+ * Assigning additional usage to allocate buffer would be better...
+ */
+#define BLOB_DRM_WA 1
+
+#define AFBC_PIXELS_PER_BLOCK 256
+#define AFBC_HEADER_BUFFER_BYTES_PER_BLOCKENTRY 16
+
+static int mali_gralloc_buffer_free_internal(buffer_handle_t *pHandle, uint32_t num_hnds);
+bool afbc_format_fallback(uint32_t * const format_idx, const uint64_t usage, bool force);
+
+
+/*
+ * Get a global unique ID
+ */
+static uint64_t getUniqueId()
+{
+ static std::atomic<uint32_t> counter(0);
+ uint64_t id = static_cast<uint64_t>(getpid()) << 32;
+ return id | counter++;
+}
+
+static void afbc_buffer_align(const bool is_tiled, int *size)
+{
+ const uint16_t AFBC_BODY_BUFFER_BYTE_ALIGNMENT = 1024;
+
+ int buffer_byte_alignment = AFBC_BODY_BUFFER_BYTE_ALIGNMENT;
+
+ if (is_tiled)
+ {
+ buffer_byte_alignment = 4 * AFBC_BODY_BUFFER_BYTE_ALIGNMENT;
+ }
+
+ *size = GRALLOC_ALIGN(*size, buffer_byte_alignment);
+}
+
+/*
+ * Obtain AFBC superblock dimensions from type.
+ */
+static rect_t get_afbc_sb_size(AllocBaseType alloc_base_type)
+{
+ const uint16_t AFBC_BASIC_BLOCK_WIDTH = 16;
+ const uint16_t AFBC_BASIC_BLOCK_HEIGHT = 16;
+ const uint16_t AFBC_WIDE_BLOCK_WIDTH = 32;
+ const uint16_t AFBC_WIDE_BLOCK_HEIGHT = 8;
+ const uint16_t AFBC_EXTRAWIDE_BLOCK_WIDTH = 64;
+ const uint16_t AFBC_EXTRAWIDE_BLOCK_HEIGHT = 4;
+
+ rect_t sb = {0, 0};
+
+ switch(alloc_base_type)
+ {
+ case AllocBaseType::AFBC:
+ sb.width = AFBC_BASIC_BLOCK_WIDTH;
+ sb.height = AFBC_BASIC_BLOCK_HEIGHT;
+ break;
+ case AllocBaseType::AFBC_WIDEBLK:
+ sb.width = AFBC_WIDE_BLOCK_WIDTH;
+ sb.height = AFBC_WIDE_BLOCK_HEIGHT;
+ break;
+ case AllocBaseType::AFBC_EXTRAWIDEBLK:
+ sb.width = AFBC_EXTRAWIDE_BLOCK_WIDTH;
+ sb.height = AFBC_EXTRAWIDE_BLOCK_HEIGHT;
+ break;
+ default:
+ break;
+ }
+ return sb;
+}
+
+/*
+ * Obtain AFBC superblock dimensions for specific plane.
+ *
+ * See alloc_type_t for more information.
+ */
+static rect_t get_afbc_sb_size(alloc_type_t alloc_type, const uint8_t plane)
+{
+ if (plane > 0 && alloc_type.is_afbc() && alloc_type.is_multi_plane)
+ {
+ return get_afbc_sb_size(AllocBaseType::AFBC_EXTRAWIDEBLK);
+ }
+ else
+ {
+ return get_afbc_sb_size(alloc_type.primary_type);
+ }
+}
+
+bool get_alloc_type(const uint64_t format_ext,
+ const uint32_t format_idx,
+ const uint64_t usage,
+ alloc_type_t * const alloc_type)
+{
+ alloc_type->primary_type = AllocBaseType::UNCOMPRESSED;
+ alloc_type->is_multi_plane = formats[format_idx].npln > 1;
+ alloc_type->is_tiled = false;
+ alloc_type->is_padded = false;
+ alloc_type->is_frontbuffer_safe = false;
+
+ /* Determine AFBC type for this format. This is used to decide alignment.
+ Split block does not affect alignment, and therefore doesn't affect the allocation type. */
+ if (format_ext & MALI_GRALLOC_INTFMT_AFBCENABLE_MASK)
+ {
+ /* YUV transform shall not be enabled for a YUV format */
+ if ((formats[format_idx].is_yuv == true) && (format_ext & MALI_GRALLOC_INTFMT_AFBC_YUV_TRANSFORM))
+ {
+ MALI_GRALLOC_LOGW("YUV Transform is incorrectly enabled for format = 0x%x. Extended internal format = 0x%" PRIx64 "\n",
+ formats[format_idx].id, format_ext);
+ }
+
+ /* Determine primary AFBC (superblock) type. */
+ alloc_type->primary_type = AllocBaseType::AFBC;
+ if (format_ext & MALI_GRALLOC_INTFMT_AFBC_WIDEBLK)
+ {
+ alloc_type->primary_type = AllocBaseType::AFBC_WIDEBLK;
+ }
+ else if (format_ext & MALI_GRALLOC_INTFMT_AFBC_EXTRAWIDEBLK)
+ {
+ alloc_type->primary_type = AllocBaseType::AFBC_EXTRAWIDEBLK;
+ }
+
+ if (format_ext & MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS)
+ {
+ alloc_type->is_tiled = true;
+
+ if (formats[format_idx].npln > 1 &&
+ (format_ext & MALI_GRALLOC_INTFMT_AFBC_EXTRAWIDEBLK) == 0)
+ {
+ MALI_GRALLOC_LOGW("Extra-wide AFBC must be signalled for multi-plane formats. "
+ "Falling back to single plane AFBC.");
+ alloc_type->is_multi_plane = false;
+ }
+
+ if (format_ext & MALI_GRALLOC_INTFMT_AFBC_DOUBLE_BODY)
+ {
+ alloc_type->is_frontbuffer_safe = true;
+ }
+ }
+ else
+ {
+ if (formats[format_idx].npln > 1)
+ {
+ MALI_GRALLOC_LOGW("Multi-plane AFBC is not supported without tiling. "
+ "Falling back to single plane AFBC.");
+ }
+ alloc_type->is_multi_plane = false;
+ }
+
+ if (format_ext & MALI_GRALLOC_INTFMT_AFBC_EXTRAWIDEBLK &&
+ !alloc_type->is_tiled)
+ {
+ /* Headers must be tiled for extra-wide. */
+ MALI_GRALLOC_LOGE("ERROR: Invalid to specify extra-wide block without tiled headers.");
+ return false;
+ }
+
+ if (alloc_type->is_frontbuffer_safe &&
+ (format_ext & (MALI_GRALLOC_INTFMT_AFBC_WIDEBLK | MALI_GRALLOC_INTFMT_AFBC_EXTRAWIDEBLK)))
+ {
+ MALI_GRALLOC_LOGE("ERROR: Front-buffer safe not supported with wide/extra-wide block.");
+ }
+
+ if (formats[format_idx].npln == 1 &&
+ format_ext & MALI_GRALLOC_INTFMT_AFBC_WIDEBLK &&
+ format_ext & MALI_GRALLOC_INTFMT_AFBC_EXTRAWIDEBLK)
+ {
+ /* "Wide + Extra-wide" implicitly means "multi-plane". */
+ MALI_GRALLOC_LOGE("ERROR: Invalid to specify multiplane AFBC with single plane format.");
+ return false;
+ }
+
+ if (usage & MALI_GRALLOC_USAGE_AFBC_PADDING)
+ {
+ alloc_type->is_padded = true;
+ }
+ }
+ return true;
+}
+
+/*
+ * Initialise AFBC header based on superblock layout.
+ * Width and height should already be AFBC aligned.
+ */
+void init_afbc(uint8_t *buf, const uint64_t alloc_format,
+ const bool is_multi_plane,
+ const int w, const int h)
+{
+ const bool is_tiled = ((alloc_format & MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS)
+ == MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS);
+ const uint32_t n_headers = (w * h) / AFBC_PIXELS_PER_BLOCK;
+ int body_offset = n_headers * AFBC_HEADER_BUFFER_BYTES_PER_BLOCKENTRY;
+
+ afbc_buffer_align(is_tiled, &body_offset);
+
+ /*
+ * Declare the AFBC header initialisation values for each superblock layout.
+ * Tiled headers (AFBC 1.2) can be initialised to zero for non-subsampled formats
+ * (SB layouts: 0, 3, 4, 7).
+ */
+ uint32_t headers[][4] = {
+ { (uint32_t)body_offset, 0x1, 0x10000, 0x0 }, /* Layouts 0, 3, 4, 7 */
+ { ((uint32_t)body_offset + (1 << 28)), 0x80200040, 0x1004000, 0x20080 } /* Layouts 1, 5 */
+ };
+ if ((alloc_format & MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS))
+ {
+ /* Zero out body_offset for non-subsampled formats. */
+ memset(headers[0], 0, sizeof(uint32_t) * 4);
+ }
+
+ /* Map base format to AFBC header layout */
+ const uint32_t base_format = alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK;
+
+ /* Sub-sampled formats use layouts 1 and 5 which is index 1 in the headers array.
+ * 1 = 4:2:0 16x16, 5 = 4:2:0 32x8.
+ *
+ * Non-subsampled use layouts 0, 3, 4 and 7, which is index 0.
+ * 0 = 16x16, 3 = 32x8 + split, 4 = 32x8, 7 = 64x4.
+ *
+ * When using separated planes for YUV formats, the header layout is the non-subsampled one
+ * as there is a header per-plane and there is no sub-sampling within the plane.
+ * Separated plane only supports 32x8 or 64x4 for the luma plane, so the first plane must be 4 or 7.
+ * Seperated plane only supports 64x4 for subsequent planes, so these must be header layout 7.
+ */
+ const uint32_t layout = is_subsampled_yuv(base_format) && !is_multi_plane ? 1 : 0;
+
+ MALI_GRALLOC_LOGV("Writing AFBC header layout %d for format %" PRIx32, layout, base_format);
+
+ for (uint32_t i = 0; i < n_headers; i++)
+ {
+ memcpy(buf, headers[layout], sizeof(headers[layout]));
+ buf += sizeof(headers[layout]);
+ }
+}
+
+static int max(int a, int b)
+{
+ return a > b ? a : b;
+}
+
+static int max(int a, int b, int c)
+{
+ return c > max(a, b) ? c : max(a, b);
+}
+
+static int max(int a, int b, int c, int d)
+{
+ return d > max(a, b, c) ? d : max(a, b, c);
+}
+
+/*
+ * Obtain plane allocation dimensions (in pixels).
+ *
+ * NOTE: pixel stride, where defined for format, is
+ * incorporated into allocation dimensions.
+ */
+static void get_pixel_w_h(uint32_t * const width,
+ uint32_t * const height,
+ const format_info_t format,
+ const alloc_type_t alloc_type,
+ const uint8_t plane,
+ bool has_cpu_usage)
+{
+ const rect_t sb = get_afbc_sb_size(alloc_type, plane);
+
+ /*
+ * Round-up plane dimensions, to multiple of:
+ * - Samples for all channels (sub-sampled formats)
+ * - Memory bytes/words (some packed formats)
+ */
+ *width = GRALLOC_ALIGN(*width, format.align_w);
+ *height = GRALLOC_ALIGN(*height, format.align_h);
+
+ /*
+ * Sub-sample (sub-sampled) planes.
+ */
+ if (plane > 0)
+ {
+ *width /= format.hsub;
+ *height /= format.vsub;
+ }
+
+ /*
+ * Pixel alignment (width),
+ * where format stride is stated in pixels.
+ */
+ int pixel_align_w = 1, pixel_align_h = 1;
+ if (has_cpu_usage)
+ {
+ pixel_align_w = format.align_w_cpu;
+ }
+ else if (alloc_type.is_afbc())
+ {
+#define HEADER_STRIDE_ALIGN_IN_SUPER_BLOCKS (0)
+ uint32_t num_sb_align = 0;
+ if (alloc_type.is_padded && !format.is_yuv)
+ {
+ /* Align to 4 superblocks in width --> 64-byte,
+ * assuming 16-byte header per superblock.
+ */
+ num_sb_align = 4;
+ }
+ pixel_align_w = max(HEADER_STRIDE_ALIGN_IN_SUPER_BLOCKS, num_sb_align) * sb.width;
+
+ /*
+ * Determine AFBC tile size when allocating tiled headers.
+ */
+ rect_t afbc_tile = sb;
+ if (alloc_type.is_tiled)
+ {
+ afbc_tile.width = format.bpp_afbc[plane] > 32 ? 4 * afbc_tile.width : 8 * afbc_tile.width;
+ afbc_tile.height = format.bpp_afbc[plane] > 32 ? 4 * afbc_tile.height : 8 * afbc_tile.height;
+ }
+
+ MALI_GRALLOC_LOGV("Plane[%hhu]: [SUB-SAMPLE] w:%d, h:%d\n", plane, *width, *height);
+ MALI_GRALLOC_LOGV("Plane[%hhu]: [PIXEL_ALIGN] w:%d\n", plane, pixel_align_w);
+ MALI_GRALLOC_LOGV("Plane[%hhu]: [LINEAR_TILE] w:%" PRIu16 "\n", plane, format.tile_size);
+ MALI_GRALLOC_LOGV("Plane[%hhu]: [AFBC_TILE] w:%" PRIu16 ", h:%" PRIu16 "\n", plane, afbc_tile.width, afbc_tile.height);
+
+ pixel_align_w = max(pixel_align_w, afbc_tile.width);
+ pixel_align_h = max(pixel_align_h, afbc_tile.height);
+
+ if (AllocBaseType::AFBC_WIDEBLK == alloc_type.primary_type && !alloc_type.is_tiled)
+ {
+ /*
+ * Special case for wide block (32x8) AFBC with linear (non-tiled)
+ * headers: hardware reads and writes 32x16 blocks so we need to
+ * pad the body buffer accordingly.
+ *
+ * Note that this branch will not be taken for multi-plane AFBC
+ * since that requires tiled headers.
+ */
+ pixel_align_h = max(pixel_align_h, 16);
+ }
+ }
+ *width = GRALLOC_ALIGN(*width, max(1, pixel_align_w, format.tile_size));
+ *height = GRALLOC_ALIGN(*height, max(1, pixel_align_h, format.tile_size));
+}
+
+
+
+static uint32_t gcd(uint32_t a, uint32_t b)
+{
+ uint32_t r, t;
+
+ if (a == b)
+ {
+ return a;
+ }
+ else if (a < b)
+ {
+ t = a;
+ a = b;
+ b = t;
+ }
+
+ while (b != 0)
+ {
+ r = a % b;
+ a = b;
+ b = r;
+ }
+
+ return a;
+}
+
+uint32_t lcm(uint32_t a, uint32_t b)
+{
+ if (a != 0 && b != 0)
+ {
+ return (a * b) / gcd(a, b);
+ }
+
+ return max(a, b);
+}
+
+
+/*
+ * YV12 stride has additional complexity since chroma stride
+ * must conform to the following:
+ *
+ * c_stride = ALIGN(stride/2, 16)
+ *
+ * Since the stride alignment must satisfy both CPU and HW
+ * constraints, the luma stride must be doubled.
+ */
+static void update_yv12_stride(int8_t plane,
+ uint32_t luma_stride,
+ uint32_t stride_align,
+ uint32_t * byte_stride)
+{
+ if (plane == 0)
+ {
+ /*
+ * Ensure luma stride is aligned to "2*lcm(hw_align, cpu_align)" so
+ * that chroma stride can satisfy both CPU and HW alignment
+ * constraints when only half luma stride (as mandated for format).
+ */
+ *byte_stride = GRALLOC_ALIGN(luma_stride, 2 * stride_align);
+ }
+ else
+ {
+ /*
+ * Derive chroma stride from luma and verify it is:
+ * 1. Aligned to lcm(hw_align, cpu_align)
+ * 2. Multiple of 16px (16 bytes)
+ */
+ *byte_stride = luma_stride / 2;
+ assert(*byte_stride == GRALLOC_ALIGN(*byte_stride, stride_align));
+ assert(*byte_stride & 15 == 0);
+ }
+}
+
+
+
+/*
+ * Calculate allocation size.
+ *
+ * Determine the width and height of each plane based on pixel alignment for
+ * both uncompressed and AFBC allocations.
+ *
+ * @param width [in] Buffer width.
+ * @param height [in] Buffer height.
+ * @param alloc_type [in] Allocation type inc. whether tiled and/or multi-plane.
+ * @param format [in] Pixel format.
+ * @param has_cpu_usage [in] CPU usage requested (in addition to any other).
+ * @param pixel_stride [out] Calculated pixel stride.
+ * @param size [out] Total calculated buffer size including all planes.
+ * @param plane_info [out] Array of calculated information for each plane. Includes
+ * offset, byte stride and allocation width and height.
+ */
+static void calc_allocation_size(const int width,
+ const int height,
+ const alloc_type_t alloc_type,
+ const format_info_t format,
+ const bool has_cpu_usage,
+ const bool has_hw_usage,
+ int * const pixel_stride,
+ uint64_t * const size,
+ plane_info_t plane_info[MAX_PLANES])
+{
+ /* pixel_stride is set outside this function after this function is called */
+ GRALLOC_UNUSED(pixel_stride);
+
+ plane_info[0].offset = 0;
+
+ *size = 0;
+ for (uint8_t plane = 0; plane < format.npln; plane++)
+ {
+ plane_info[plane].alloc_width = width;
+ plane_info[plane].alloc_height = height;
+ get_pixel_w_h(&plane_info[plane].alloc_width,
+ &plane_info[plane].alloc_height,
+ format,
+ alloc_type,
+ plane,
+ has_cpu_usage);
+ MALI_GRALLOC_LOGV("Aligned w=%d, h=%d (in pixels)",
+ plane_info[plane].alloc_width, plane_info[plane].alloc_height);
+
+ /*
+ * Calculate byte stride (per plane).
+ */
+ if (alloc_type.is_afbc())
+ {
+ assert((plane_info[plane].alloc_width * format.bpp_afbc[plane]) % 8 == 0);
+ plane_info[plane].byte_stride = (plane_info[plane].alloc_width * format.bpp_afbc[plane]) / 8;
+ }
+ else
+ {
+ assert((plane_info[plane].alloc_width * format.bpp[plane]) % 8 == 0);
+ plane_info[plane].byte_stride = (plane_info[plane].alloc_width * format.bpp[plane]) / 8;
+
+ /*
+ * Align byte stride (uncompressed allocations only).
+ *
+ * Find the lowest-common-multiple of:
+ * 1. hw_align: Minimum byte stride alignment for HW IP (has_hw_usage == true)
+ * 2. cpu_align: Byte equivalent of 'align_w_cpu' (has_cpu_usage == true)
+ *
+ * NOTE: Pixel stride is defined as multiple of 'align_w_cpu'.
+ */
+ uint16_t hw_align = 0;
+ if (has_hw_usage)
+ {
+ hw_align = format.is_yuv ?
+ YUV_BYTE_ALIGN_DEFAULT :
+ (format.is_rgb ? RGB_BYTE_ALIGN_DEFAULT : 0);
+ }
+
+ uint32_t cpu_align = 0;
+
+#if CAN_SKIP_CPU_ALIGN == 1
+ if (has_cpu_usage)
+#endif
+ {
+ assert((format.bpp[plane] * format.align_w_cpu) % 8 == 0);
+ cpu_align = (format.bpp[plane] * format.align_w_cpu) / 8;
+ }
+
+ uint32_t stride_align = lcm(hw_align, cpu_align);
+ if (stride_align)
+ {
+ plane_info[plane].byte_stride = GRALLOC_ALIGN(plane_info[plane].byte_stride * format.tile_size, stride_align) / format.tile_size;
+ plane_info[plane].alloc_width = plane_info[plane].byte_stride * 8 / format.bpp[plane];
+ }
+
+#if REALIGN_YV12 == 1
+ /*
+ * Update YV12 stride with both CPU & HW usage due to constraint of chroma stride.
+ * Width is anyway aligned to 16px for luma and chroma (has_cpu_usage).
+ */
+ if (format.id == MALI_GRALLOC_FORMAT_INTERNAL_YV12 && has_hw_usage && has_cpu_usage)
+ {
+ update_yv12_stride(plane,
+ plane_info[0].byte_stride,
+ stride_align,
+ &plane_info[plane].byte_stride);
+ }
+#endif
+ }
+ MALI_GRALLOC_LOGV("Byte stride: %d", plane_info[plane].byte_stride);
+
+ const uint32_t sb_num = (plane_info[plane].alloc_width * plane_info[plane].alloc_height)
+ / AFBC_PIXELS_PER_BLOCK;
+
+ /*
+ * Calculate body size (per plane).
+ */
+ int body_size = 0;
+ if (alloc_type.is_afbc())
+ {
+ const rect_t sb = get_afbc_sb_size(alloc_type, plane);
+ const int sb_bytes = GRALLOC_ALIGN((format.bpp_afbc[plane] * sb.width * sb.height) / 8, 128);
+ body_size = sb_num * sb_bytes;
+
+ /* When AFBC planes are stored in separate buffers and this is not the last plane,
+ also align the body buffer to make the subsequent header aligned. */
+ if (format.npln > 1 && plane < 2)
+ {
+ afbc_buffer_align(alloc_type.is_tiled, &body_size);
+ }
+
+ if (alloc_type.is_frontbuffer_safe)
+ {
+ int back_buffer_size = body_size;
+ afbc_buffer_align(alloc_type.is_tiled, &back_buffer_size);
+ body_size += back_buffer_size;
+ }
+ }
+ else
+ {
+ body_size = plane_info[plane].byte_stride * plane_info[plane].alloc_height;
+ }
+ MALI_GRALLOC_LOGV("Body size: %d", body_size);
+
+
+ /*
+ * Calculate header size (per plane).
+ */
+ int header_size = 0;
+ if (alloc_type.is_afbc())
+ {
+ /* As this is AFBC, calculate header size for this plane.
+ * Always align the header, which will make the body buffer aligned.
+ */
+ header_size = sb_num * AFBC_HEADER_BUFFER_BYTES_PER_BLOCKENTRY;
+ afbc_buffer_align(alloc_type.is_tiled, &header_size);
+ }
+ MALI_GRALLOC_LOGV("AFBC Header size: %d", header_size);
+
+ /*
+ * Set offset for separate chroma planes.
+ */
+ if (plane > 0)
+ {
+ plane_info[plane].offset = *size;
+ }
+
+ /*
+ * Set overall size.
+ * Size must be updated after offset.
+ */
+ *size += body_size + header_size;
+ MALI_GRALLOC_LOGV("size=%" PRIu64, *size);
+ }
+}
+
+
+
+/*
+ * Validate selected format against requested.
+ * Return true if valid, false otherwise.
+ */
+static bool validate_format(const format_info_t * const format,
+ const alloc_type_t alloc_type,
+ const buffer_descriptor_t * const bufDescriptor)
+{
+ if (alloc_type.is_afbc())
+ {
+ /*
+ * Validate format is supported by AFBC specification and gralloc.
+ */
+ if (format->afbc == false)
+ {
+ MALI_GRALLOC_LOGE("ERROR: AFBC selected but not supported for base format: 0x%" PRIx32, format->id);
+ return false;
+ }
+
+ /*
+ * Enforce consistency between number of format planes and
+ * request for single/multi-plane AFBC.
+ */
+ if (((format->npln == 1 && alloc_type.is_multi_plane) ||
+ (format->npln > 1 && !alloc_type.is_multi_plane)))
+ {
+ MALI_GRALLOC_LOGE("ERROR: Format (%" PRIx32 ", num planes: %u) is incompatible with %s-plane AFBC request",
+ format->id, format->npln, (alloc_type.is_multi_plane) ? "multi" : "single");
+ return false;
+ }
+ }
+ else
+ {
+ if (format->linear == false)
+ {
+ MALI_GRALLOC_LOGE("ERROR: Uncompressed format requested but not supported for base format: %" PRIx32, format->id);
+ return false;
+ }
+ }
+
+ if (format->id == MALI_GRALLOC_FORMAT_INTERNAL_BLOB &&
+ bufDescriptor->height != 1)
+ {
+ MALI_GRALLOC_LOGE("ERROR: Height for format BLOB must be 1.");
+ return false;
+ }
+
+ return true;
+}
+
+static int prepare_descriptor_exynos_formats(
+ buffer_descriptor_t *bufDescriptor)
+{
+ size_t sizes[3] = {0, 0, 0};
+
+ int fd_count = 1;
+ int w = bufDescriptor->width;
+ int h = bufDescriptor->height;
+ uint64_t usage = bufDescriptor->producer_usage | bufDescriptor->consumer_usage;
+ int plane_count = 2;
+ int format = MALI_GRALLOC_INTFMT_FMT_MASK & bufDescriptor->alloc_format;
+
+ if (usage & (GRALLOC_USAGE_HW_VIDEO_ENCODER | GRALLOC_USAGE_HW_VIDEO_DECODER))
+ {
+ usage |= GRALLOC_USAGE_VIDEO_PRIVATE_DATA;
+ bufDescriptor->producer_usage |= GRALLOC_USAGE_VIDEO_PRIVATE_DATA;
+ bufDescriptor->consumer_usage |= GRALLOC_USAGE_VIDEO_PRIVATE_DATA;
+ }
+
+ /* set SBWC format fd_count */
+ fd_count = 1;
+ switch (format)
+ {
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_SBWC:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L50:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L75:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L40:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L60:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L80:
+ fd_count = 2;
+ break;
+ }
+
+ /* SWBC Formats have special size requirements */
+ switch (format)
+ {
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_SBWC:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC:
+ plane_count = setup_sbwc_420_sp(w, h, fd_count, bufDescriptor->plane_info);
+ break;
+
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC:
+ plane_count = setup_sbwc_420_sp_10bit(w, h, fd_count, bufDescriptor->plane_info);
+ break;
+
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L50:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L50:
+ plane_count = setup_sbwc_420_sp_lossy(w, h, 50, fd_count, bufDescriptor->plane_info);
+ break;
+
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L75:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L75:
+ plane_count = setup_sbwc_420_sp_lossy(w, h, 75, fd_count, bufDescriptor->plane_info);
+ break;
+
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L40:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L40:
+ plane_count = setup_sbwc_420_sp_10bit_lossy(w, h, 40, fd_count, bufDescriptor->plane_info);
+ break;
+
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L60:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L60:
+ plane_count = setup_sbwc_420_sp_10bit_lossy(w, h, 60, fd_count, bufDescriptor->plane_info);
+ break;
+
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L80:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L80:
+ plane_count = setup_sbwc_420_sp_10bit_lossy(w, h, 80, fd_count, bufDescriptor->plane_info);
+ break;
+
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ fd_count = 1;
+ h = GRALLOC_ALIGN(h, 2);
+ plane_count = setup_420_sp(w, h, fd_count, bufDescriptor->plane_info);
+ break;
+
+ case HAL_PIXEL_FORMAT_EXYNOS_YV12_M:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M:
+ w = GRALLOC_ALIGN(w, 32);
+ h = GRALLOC_ALIGN(h, 16);
+ fd_count = 3;
+ plane_count = setup_420_p(w, h, fd_count, bufDescriptor->plane_info);
+ break;
+
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED:
+ w = GRALLOC_ALIGN(w, 16);
+ h = GRALLOC_ALIGN(h, 32);
+ fd_count = 2;
+ plane_count = setup_420_sp_tiled(w, h, fd_count, bufDescriptor->plane_info);
+ break;
+
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P:
+ w = GRALLOC_ALIGN(w, 16);
+ fd_count = 1;
+ plane_count = setup_420_p(w, h, fd_count, bufDescriptor->plane_info);
+ break;
+
+ case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M:
+ w = GRALLOC_ALIGN(w, 16);
+ h = GRALLOC_ALIGN(h, 32);
+ fd_count = 2;
+ plane_count = setup_420_sp(w, h, fd_count, bufDescriptor->plane_info);
+ break;
+
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN:
+ w = GRALLOC_ALIGN(w, 16);
+ h = GRALLOC_ALIGN(h, 16);
+ fd_count = 1;
+ plane_count = setup_420_sp(w, h, fd_count, bufDescriptor->plane_info);
+ break;
+
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B:
+ /* This is 64 pixel align for now */
+ w = GRALLOC_ALIGN(w, BOARD_EXYNOS_S10B_FORMAT_ALIGN);
+ h = GRALLOC_ALIGN(h, 16);
+ fd_count = 2;
+ plane_count = setup_420_sp_s10b(w, h, fd_count, bufDescriptor->plane_info);
+ break;
+
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B:
+ w = GRALLOC_ALIGN(w, BOARD_EXYNOS_S10B_FORMAT_ALIGN);
+ h = GRALLOC_ALIGN(h, 16);
+ fd_count = 1;
+ plane_count = setup_420_sp_s10b(w, h, fd_count, bufDescriptor->plane_info);
+ break;
+
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M:
+ w = GRALLOC_ALIGN(w, 16);
+ h = GRALLOC_ALIGN(h, 16);
+ fd_count = 2;
+ plane_count = setup_p010_sp(w, h, fd_count, bufDescriptor->plane_info);
+ break;
+
+ default:
+ MALI_GRALLOC_LOGE("invalid yuv format %" PRIx64, bufDescriptor->alloc_format);
+ return -1;
+ }
+
+ plane_info_t *plane = bufDescriptor->plane_info;
+
+ for (int fidx = 0; fidx < fd_count; fidx++)
+ {
+ uint64_t size = 0;
+
+ for (int pidx = 0; pidx < plane_count; pidx++)
+ {
+ if (plane[pidx].fd_idx == fidx)
+ {
+ size += plane[pidx].size;
+ }
+ }
+
+ /* TODO: is there a need to check the condition for padding like in older gralloc? */
+ /* Add MSCL_EXT_SIZE */
+ /* MSCL_EXT_SIZE + MSCL_EXT_SIZE/2 + ext_size */
+ size += 1024;
+
+ size = size < SZ_4K ? SZ_4K : size;
+
+ bufDescriptor->alloc_sizes[fidx] = size;
+ }
+
+
+ bufDescriptor->fd_count = fd_count;
+ bufDescriptor->plane_count = plane_count;
+
+ return 0;
+}
+
+int mali_gralloc_derive_format_and_size(buffer_descriptor_t * const bufDescriptor)
+{
+ alloc_type_t alloc_type{};
+ int err;
+
+ int alloc_width = bufDescriptor->width;
+ int alloc_height = bufDescriptor->height;
+ uint64_t usage = bufDescriptor->producer_usage | bufDescriptor->consumer_usage;
+
+ /*
+ * Select optimal internal pixel format based upon
+ * usage and requested format.
+ */
+ bufDescriptor->alloc_format = mali_gralloc_select_format(bufDescriptor->hal_format,
+ bufDescriptor->format_type,
+ usage,
+ bufDescriptor->width * bufDescriptor->height);
+ if (bufDescriptor->alloc_format == MALI_GRALLOC_FORMAT_INTERNAL_UNDEFINED)
+ {
+ MALI_GRALLOC_LOGE("ERROR: Unrecognized and/or unsupported format 0x%" PRIx64 " and usage 0x%" PRIx64,
+ bufDescriptor->hal_format, usage);
+ return -EINVAL;
+ }
+
+ int32_t format_idx = get_format_index(bufDescriptor->alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK);
+ if (format_idx == -1)
+ {
+ return -EINVAL;
+ }
+ MALI_GRALLOC_LOGV("alloc_format: 0x%" PRIx64 " format_idx: %d", bufDescriptor->alloc_format, format_idx);
+
+ /*
+ * Obtain allocation type (uncompressed, AFBC basic, etc...)
+ */
+ if (!get_alloc_type(bufDescriptor->alloc_format & MALI_GRALLOC_INTFMT_EXT_MASK,
+ format_idx, usage, &alloc_type))
+ {
+ return -EINVAL;
+ }
+
+ if (!validate_format(&formats[format_idx], alloc_type, bufDescriptor))
+ {
+ return -EINVAL;
+ }
+
+ if (is_exynos_format(bufDescriptor->alloc_format))
+ {
+ prepare_descriptor_exynos_formats(bufDescriptor);
+ }
+ else
+ {
+ /*
+ * Resolution of frame (allocation width and height) might require adjustment.
+ * This adjustment is only based upon specific usage and pixel format.
+ * If using AFBC, further adjustments to the allocation width and height will be made later
+ * based on AFBC alignment requirements and, for YUV, the plane properties.
+ */
+ mali_gralloc_adjust_dimensions(bufDescriptor->alloc_format,
+ usage,
+ &alloc_width,
+ &alloc_height);
+
+ /* Obtain buffer size and plane information. */
+ calc_allocation_size(alloc_width,
+ alloc_height,
+ alloc_type,
+ formats[format_idx],
+ usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK),
+ usage & ~(GRALLOC_USAGE_PRIVATE_MASK | GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK),
+ &bufDescriptor->pixel_stride,
+ &bufDescriptor->alloc_sizes[0],
+ bufDescriptor->plane_info);
+ }
+
+ /* Set pixel stride differently for RAW formats */
+ switch (MALI_GRALLOC_INTFMT_FMT_MASK & bufDescriptor->alloc_format)
+ {
+ case MALI_GRALLOC_FORMAT_INTERNAL_RAW12:
+ case MALI_GRALLOC_FORMAT_INTERNAL_RAW10:
+ bufDescriptor->pixel_stride = bufDescriptor->plane_info[0].byte_stride;
+ break;
+ default:
+ bufDescriptor->pixel_stride = bufDescriptor->plane_info[0].alloc_width;
+ }
+
+ /*
+ * Each layer of a multi-layer buffer must be aligned so that
+ * it is accessible by both producer and consumer. In most cases,
+ * the stride alignment is also sufficient for each layer, however
+ * for AFBC the header buffer alignment is more constrained (see
+ * AFBC specification v3.4, section 2.15: "Alignment requirements").
+ * Also update the buffer size to accommodate all layers.
+ */
+ if (bufDescriptor->layer_count > 1 && ~usage & GRALLOC_USAGE_HFR_MODE)
+ {
+ if (bufDescriptor->alloc_format & MALI_GRALLOC_INTFMT_AFBCENABLE_MASK)
+ {
+ if (bufDescriptor->alloc_format & MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS)
+ {
+ bufDescriptor->alloc_sizes[0] = GRALLOC_ALIGN(bufDescriptor->alloc_sizes[0], 4096);
+ }
+ else
+ {
+ bufDescriptor->alloc_sizes[0] = GRALLOC_ALIGN(bufDescriptor->alloc_sizes[0], 128);
+ }
+ }
+
+ bufDescriptor->alloc_sizes[0] *= bufDescriptor->layer_count;
+ }
+
+ /* MFC requires EXT_SIZE padding */
+ bufDescriptor->alloc_sizes[0] += EXT_SIZE;
+
+ if (bufDescriptor->width % MSCL_ALIGN)
+ {
+ bufDescriptor->alloc_sizes[0] += MSCL_EXT_SIZE;
+ }
+
+ return 0;
+}
+
+
+int mali_gralloc_buffer_allocate(const gralloc_buffer_descriptor_t *descriptors,
+ uint32_t numDescriptors, buffer_handle_t *pHandle, bool *shared_backend)
+{
+ bool shared = false;
+ uint64_t backing_store_id = 0x0;
+ int err;
+
+ for (uint32_t i = 0; i < numDescriptors; i++)
+ {
+ buffer_descriptor_t * const bufDescriptor = (buffer_descriptor_t *)(descriptors[i]);
+
+#if BLOB_DRM_WA == 1
+ // W/A for BLOB DRM Contents. we should add additional usages to allocate buffer
+ if(bufDescriptor->hal_format == HAL_PIXEL_FORMAT_BLOB)
+ {
+ uint64_t usage = bufDescriptor->producer_usage | bufDescriptor->consumer_usage;
+ if(usage == GRALLOC_USAGE_PROTECTED)
+ {
+ bufDescriptor->producer_usage |= GRALLOC_USAGE_DECODER;
+ bufDescriptor->consumer_usage |= GRALLOC_USAGE_VIDEO_EXT;
+ }
+ }
+#endif
+
+ /* Derive the buffer size from descriptor parameters */
+ err = mali_gralloc_derive_format_and_size(bufDescriptor);
+ if (err != 0)
+ {
+ return err;
+ }
+ }
+
+ /* Allocate ION backing store memory */
+ err = mali_gralloc_ion_allocate(descriptors, numDescriptors, pHandle, &shared);
+ if (err < 0)
+ {
+ return err;
+ }
+
+ if (shared)
+ {
+ backing_store_id = getUniqueId();
+ }
+
+ for (uint32_t i = 0; i < numDescriptors; i++)
+ {
+ buffer_descriptor_t * const bufDescriptor = (buffer_descriptor_t *)descriptors[i];
+ private_handle_t *hnd = (private_handle_t *)pHandle[i];
+ uint64_t usage = bufDescriptor->consumer_usage | bufDescriptor->producer_usage;
+
+ mali_gralloc_dump_buffer_add(hnd);
+
+ if (shared)
+ {
+ /*each buffer will share the same backing store id.*/
+ hnd->backing_store_id = backing_store_id;
+ }
+ else
+ {
+ /* each buffer will have an unique backing store id.*/
+ hnd->backing_store_id = getUniqueId();
+ }
+ }
+
+ if (NULL != shared_backend)
+ {
+ *shared_backend = shared;
+ }
+
+ return 0;
+}
+
+int mali_gralloc_buffer_free(buffer_handle_t pHandle)
+{
+ auto *hnd = const_cast<private_handle_t *>(
+ reinterpret_cast<const private_handle_t *>(pHandle));
+
+ if (hnd == nullptr)
+ {
+ return -1;
+ }
+
+ mali_gralloc_ion_free(hnd);
+ gralloc_shared_memory_free(hnd);
+
+ return 0;
+}
+
+static int mali_gralloc_buffer_free_internal(buffer_handle_t *pHandle, uint32_t num_hnds)
+{
+ int err = -1;
+ uint32_t i = 0;
+
+ for (i = 0; i < num_hnds; i++)
+ {
+ err = mali_gralloc_buffer_free(pHandle[i]);
+ }
+
+ return err;
+}
diff --git a/gralloc4/src/core/mali_gralloc_bufferallocation.h b/gralloc4/src/core/mali_gralloc_bufferallocation.h
new file mode 100644
index 0000000..bcc927f
--- /dev/null
+++ b/gralloc4/src/core/mali_gralloc_bufferallocation.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2016-2020 ARM Limited. All rights reserved.
+ *
+ * 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 MALI_GRALLOC_BUFFERALLOCATION_H_
+#define MALI_GRALLOC_BUFFERALLOCATION_H_
+
+#include <hardware/hardware.h>
+#include "mali_gralloc_buffer.h"
+#include "core/mali_gralloc_bufferdescriptor.h"
+
+/* Compression scheme */
+enum class AllocBaseType
+{
+ /*
+ * No compression scheme
+ */
+ UNCOMPRESSED,
+
+ /*
+ * Arm Framebuffer Compression
+ */
+ AFBC, /* 16 x 16 block size */
+ AFBC_WIDEBLK, /* 32 x 8 block size */
+ AFBC_EXTRAWIDEBLK, /* 64 x 4 block size */
+
+};
+
+/*
+ * Allocation type.
+ *
+ * Allocation-specific properties of format modifiers
+ * described by MALI_GRALLOC_INTFMT_*.
+ */
+struct AllocType
+{
+ /*
+ * The compression scheme in use
+ *
+ * For AFBC formats, this describes:
+ * - the block size for single plane base formats, or
+ * - the block size of the first/luma plane for multi-plane base formats.
+ */
+ AllocBaseType primary_type{AllocBaseType::UNCOMPRESSED};
+
+ /*
+ * Multi-plane AFBC format. AFBC chroma-only plane(s) are
+ * always compressed with superblock type 'AFBC_EXTRAWIDEBLK'.
+ */
+ bool is_multi_plane{};
+
+ /*
+ * Allocate tiled AFBC headers.
+ */
+ bool is_tiled{};
+
+ /*
+ * Pad AFBC header stride to 64-byte alignment
+ * (multiple of 4x16B headers).
+ */
+ bool is_padded{};
+
+ /*
+ * Front-buffer rendering safe AFBC allocations include an
+ * additional 4kB-aligned body buffer.
+ */
+ bool is_frontbuffer_safe{};
+
+ bool is_afbc() const
+ {
+ switch (primary_type)
+ {
+ case AllocBaseType::AFBC:
+ case AllocBaseType::AFBC_WIDEBLK:
+ case AllocBaseType::AFBC_EXTRAWIDEBLK:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+};
+
+using alloc_type_t = AllocType;
+
+int mali_gralloc_derive_format_and_size(buffer_descriptor_t * const bufDescriptor);
+
+int mali_gralloc_buffer_allocate(const gralloc_buffer_descriptor_t *descriptors,
+ uint32_t numDescriptors, buffer_handle_t *pHandle, bool *shared_backend);
+
+int mali_gralloc_buffer_free(buffer_handle_t pHandle);
+
+void init_afbc(uint8_t *buf, uint64_t internal_format, const bool is_multi_plane, int w, int h);
+
+uint32_t lcm(uint32_t a, uint32_t b);
+
+bool get_alloc_type(const uint64_t format_ext,
+ const uint32_t format_idx,
+ const uint64_t usage,
+ alloc_type_t * const alloc_type);
+
+#endif /* MALI_GRALLOC_BUFFERALLOCATION_H_ */
diff --git a/gralloc4/src/core/mali_gralloc_bufferdescriptor.h b/gralloc4/src/core/mali_gralloc_bufferdescriptor.h
new file mode 100644
index 0000000..8624b29
--- /dev/null
+++ b/gralloc4/src/core/mali_gralloc_bufferdescriptor.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2016-2020 Arm Limited. All rights reserved.
+ *
+ * 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 MALI_GRALLOC_BUFFERDESCRIPTOR_H_
+#define MALI_GRALLOC_BUFFERDESCRIPTOR_H_
+
+#include "mali_gralloc_buffer.h"
+#include "mali_gralloc_formats.h"
+#include <string>
+
+typedef uint64_t gralloc_buffer_descriptor_t;
+
+/* A buffer_descriptor contains the requested parameters for the buffer
+ * as well as the calculated parameters that are passed to the allocator.
+ */
+struct buffer_descriptor_t
+{
+ /* For validation. */
+ uint32_t signature;
+
+ /* Requested parameters from IAllocator. */
+ uint32_t width;
+ uint32_t height;
+ uint64_t producer_usage;
+ uint64_t consumer_usage;
+ uint64_t hal_format;
+ uint32_t layer_count;
+ mali_gralloc_format_type format_type;
+ std::string name;
+ uint64_t reserved_size;
+
+ /*
+ * Calculated values that will be passed to the allocator in order to
+ * allocate the buffer.
+ */
+ uint64_t alloc_sizes[MAX_PLANES];
+ int pixel_stride;
+ uint64_t alloc_format;
+ uint32_t fd_count;
+ uint32_t plane_count;
+ plane_info_t plane_info[MAX_PLANES];
+
+ buffer_descriptor_t() :
+ signature(0),
+ width(0),
+ height(0),
+ producer_usage(0),
+ consumer_usage(0),
+ hal_format(0),
+ layer_count(0),
+ format_type(MALI_GRALLOC_FORMAT_TYPE_USAGE),
+ name("Unnamed"),
+ reserved_size(0),
+ pixel_stride(0),
+ alloc_format(0),
+ fd_count(1),
+ plane_count(1)
+ {
+ memset(plane_info, 0, sizeof(plane_info_t) * MAX_PLANES);
+ memset(alloc_sizes, 0, sizeof(alloc_sizes));
+ }
+};
+
+#endif /* MALI_GRALLOC_BUFFERDESCRIPTOR_H_ */
diff --git a/gralloc4/src/core/mali_gralloc_debug.cpp b/gralloc4/src/core/mali_gralloc_debug.cpp
new file mode 100644
index 0000000..cc3bc7f
--- /dev/null
+++ b/gralloc4/src/core/mali_gralloc_debug.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2016, 2018 ARM Limited. All rights reserved.
+ *
+ * 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 <inttypes.h>
+#include <stdlib.h>
+#include <vector>
+#include <algorithm>
+
+#include <hardware/hardware.h>
+
+#include "mali_gralloc_debug.h"
+
+static pthread_mutex_t dump_lock = PTHREAD_MUTEX_INITIALIZER;
+static std::vector<private_handle_t *> dump_buffers;
+static android::String8 dumpStrings;
+
+void mali_gralloc_dump_buffer_add(private_handle_t *handle)
+{
+ if (NULL == handle)
+ {
+ MALI_GRALLOC_LOGE("Invalid handle %p and return", handle);
+ return;
+ }
+
+ pthread_mutex_lock(&dump_lock);
+ dump_buffers.push_back(handle);
+ pthread_mutex_unlock(&dump_lock);
+}
+
+void mali_gralloc_dump_buffer_erase(private_handle_t *handle)
+{
+ if (NULL == handle)
+ {
+ MALI_GRALLOC_LOGE("Invalid handle %p and return", handle);
+ return;
+ }
+
+ pthread_mutex_lock(&dump_lock);
+ dump_buffers.erase(std::remove(dump_buffers.begin(), dump_buffers.end(), handle), dump_buffers.end());
+ pthread_mutex_unlock(&dump_lock);
+}
+
+void mali_gralloc_dump_string(android::String8 &buf, const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ buf.appendFormatV(fmt, args);
+ va_end(args);
+}
+
+void mali_gralloc_dump_buffers(android::String8 &dumpStrings, uint32_t *outSize)
+{
+ if (NULL == outSize)
+ {
+ MALI_GRALLOC_LOGE("Invalid pointer to dump buffer size and return");
+ return;
+ }
+
+ dumpStrings.clear();
+ mali_gralloc_dump_string(dumpStrings,
+ "-------------------------Start to dump Gralloc buffers info------------------------\n");
+ private_handle_t *hnd;
+ size_t num;
+
+ mali_gralloc_dump_string(dumpStrings, " handle | width | height | stride | req format |alloc "
+ "format|consumer usage|producer usage| shared fd | AFBC "
+ "|\n");
+ mali_gralloc_dump_string(dumpStrings, "------------+-------+--------+--------+----------------+---------------+----"
+ "----------+--------------+-----------+------+\n");
+ pthread_mutex_lock(&dump_lock);
+
+ for (num = 0; num < dump_buffers.size(); num++)
+ {
+ hnd = dump_buffers[num];
+ mali_gralloc_dump_string(dumpStrings, " %08" PRIxPTR " | %5d | %5d | %5d | %08x | %09" PRIx64
+ " | %09" PRIx64 " | %09" PRIx64 " | %08x | %4d |\n",
+ hnd, hnd->width, hnd->height, hnd->stride, hnd->req_format, hnd->alloc_format,
+ hnd->consumer_usage, hnd->producer_usage, hnd->fds[0],
+ (hnd->alloc_format & MALI_GRALLOC_INTFMT_AFBCENABLE_MASK) ? true : false);
+ }
+
+ pthread_mutex_unlock(&dump_lock);
+ mali_gralloc_dump_string(
+ dumpStrings, "---------------------End dump Gralloc buffers info with num %zu----------------------\n", num);
+
+ *outSize = dumpStrings.size();
+}
+
+void mali_gralloc_dump_internal(uint32_t *outSize, char *outBuffer)
+{
+ uint32_t dumpSize;
+
+ if (NULL == outSize)
+ {
+ MALI_GRALLOC_LOGE("Invalid pointer to dump buffer size and return");
+ return;
+ }
+
+ if (NULL == outBuffer)
+ {
+ if (!dumpStrings.isEmpty())
+ {
+ dumpStrings.clear();
+ }
+
+ mali_gralloc_dump_buffers(dumpStrings, outSize);
+ }
+ else
+ {
+ if (dumpStrings.isEmpty())
+ {
+ *outSize = 0;
+ }
+ else
+ {
+ dumpSize = dumpStrings.size();
+ *outSize = (dumpSize < *outSize) ? dumpSize : *outSize;
+ memcpy(outBuffer, dumpStrings.string(), *outSize);
+ }
+ }
+}
diff --git a/gralloc4/src/core/mali_gralloc_debug.h b/gralloc4/src/core/mali_gralloc_debug.h
new file mode 100644
index 0000000..9f99f0e
--- /dev/null
+++ b/gralloc4/src/core/mali_gralloc_debug.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016, 2018 ARM Limited. All rights reserved.
+ *
+ * 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 MALI_GRALLOC_DEBUG_H_
+#define MALI_GRALLOC_DEBUG_H_
+
+#include <utils/String8.h>
+#include "gralloc_priv.h"
+
+#include <hardware/gralloc1.h>
+
+void mali_gralloc_dump_buffer_add(private_handle_t *handle);
+void mali_gralloc_dump_buffer_erase(private_handle_t *handle);
+
+void mali_gralloc_dump_string(android::String8 &buf, const char *fmt, ...);
+void mali_gralloc_dump_buffers(android::String8 &dumpBuffer, uint32_t *outSize);
+void mali_gralloc_dump_internal(uint32_t *outSize, char *outBuffer);
+#endif
diff --git a/gralloc4/src/core/mali_gralloc_formats.cpp b/gralloc4/src/core/mali_gralloc_formats.cpp
new file mode 100644
index 0000000..62e40e5
--- /dev/null
+++ b/gralloc4/src/core/mali_gralloc_formats.cpp
@@ -0,0 +1,1562 @@
+/*
+ * Copyright (C) 2016-2020 ARM Limited. All rights reserved.
+ *
+ * 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 <string.h>
+#include <dlfcn.h>
+#include <inttypes.h>
+#include <log/log.h>
+#include <assert.h>
+#include <vector>
+
+#include "gralloc_priv.h"
+#include "mali_gralloc_bufferallocation.h"
+#include "format_info.h"
+#include "capabilities/gralloc_capabilities.h"
+#include "exynos_format.h"
+
+/* Producer/consumer definitions.
+ * CPU: Software access
+ * GPU: Graphics processor
+ * DPU: Display processor
+ * VPU: Video processor
+ * CAM: Camera ISP
+ */
+#define MALI_GRALLOC_PRODUCER_CPU ((uint16_t)1 << 0)
+#define MALI_GRALLOC_PRODUCER_GPU ((uint16_t)1 << 1)
+#define MALI_GRALLOC_PRODUCER_DPU ((uint16_t)1 << 2)
+#define MALI_GRALLOC_PRODUCER_VPU ((uint16_t)1 << 4)
+#define MALI_GRALLOC_PRODUCER_CAM ((uint16_t)1 << 5)
+
+#define MALI_GRALLOC_CONSUMER_CPU ((uint16_t)1 << 0)
+#define MALI_GRALLOC_CONSUMER_GPU ((uint16_t)1 << 1)
+#define MALI_GRALLOC_CONSUMER_DPU ((uint16_t)1 << 2)
+#define MALI_GRALLOC_CONSUMER_VPU ((uint16_t)1 << 3)
+
+typedef struct
+{
+ uint32_t base_format;
+ uint64_t format_ext;
+ format_support_flags f_flags;
+} fmt_props;
+
+/*
+ * Determines all IP consumers included by the requested buffer usage.
+ * Private usage flags are excluded from this process.
+ *
+ * @param usage [in] Buffer usage.
+ *
+ * @return flags word of all enabled consumers;
+ * 0, if no consumers are enabled
+ */
+static uint16_t get_consumers(uint64_t usage)
+{
+ uint16_t consumers = 0;
+
+ /* Private usage is not applicable to consumer derivation */
+ usage &= ~GRALLOC_USAGE_PRIVATE_MASK;
+ /* Exclude usages also not applicable to consumer derivation */
+ usage &= ~GRALLOC_USAGE_PROTECTED;
+
+ get_ip_capabilities();
+
+ if (usage == GRALLOC_USAGE_HW_COMPOSER)
+ {
+ consumers = MALI_GRALLOC_CONSUMER_DPU;
+ }
+ else
+ {
+ if (usage & GRALLOC_USAGE_SW_READ_MASK)
+ {
+ consumers |= MALI_GRALLOC_CONSUMER_CPU;
+ }
+
+ /* GRALLOC_USAGE_HW_FB describes a framebuffer which contains a
+ * pre-composited scene that is scanned-out to a display. This buffer
+ * can be consumed by even the most basic display processor which does
+ * not support multi-layer composition.
+ */
+ if (usage & GRALLOC_USAGE_HW_FB)
+ {
+ consumers |= MALI_GRALLOC_CONSUMER_DPU;
+ }
+
+ if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER)
+ {
+ consumers |= MALI_GRALLOC_CONSUMER_VPU;
+ }
+
+ /* GRALLOC_USAGE_HW_COMPOSER does not explicitly define whether the
+ * display processor is producer or consumer. When used in combination
+ * with GRALLOC_USAGE_HW_TEXTURE, it is assumed to be consumer since the
+ * GPU and DPU both act as compositors.
+ */
+ if ((usage & (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER)) ==
+ (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER))
+ {
+ consumers |= MALI_GRALLOC_CONSUMER_DPU;
+ }
+
+ if (usage & (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_GPU_DATA_BUFFER))
+ {
+ consumers |= MALI_GRALLOC_CONSUMER_GPU;
+ }
+ }
+
+ return consumers;
+}
+
+
+/*
+ * Determines all IP producers included by the requested buffer usage.
+ * Private usage flags are excluded from this process.
+ *
+ * @param usage [in] Buffer usage.
+ *
+ * @return flags word of all enabled producers;
+ * 0, if no producers are enabled
+ */
+static uint16_t get_producers(uint64_t usage)
+{
+ uint16_t producers = 0;
+
+ /* Private usage is not applicable to producer derivation */
+ usage &= ~GRALLOC_USAGE_PRIVATE_MASK;
+ /* Exclude usages also not applicable to producer derivation */
+ usage &= ~GRALLOC_USAGE_PROTECTED;
+
+ get_ip_capabilities();
+
+ if (usage & GRALLOC_USAGE_SW_WRITE_MASK)
+ {
+ producers |= MALI_GRALLOC_PRODUCER_CPU;
+ }
+
+ /* DPU is normally consumer however, when there is an alternative
+ * consumer (VPU) and no other producer (e.g. VPU), it acts as a producer.
+ */
+ if ((usage & GRALLOC_USAGE_DECODER) != GRALLOC_USAGE_DECODER &&
+ (usage & (GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_VIDEO_ENCODER)) ==
+ (GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_VIDEO_ENCODER))
+ {
+ producers |= MALI_GRALLOC_PRODUCER_DPU;
+ }
+
+ if (usage & (GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_GPU_DATA_BUFFER))
+ {
+ producers |= MALI_GRALLOC_PRODUCER_GPU;
+ }
+
+ if (usage & GRALLOC_USAGE_HW_CAMERA_WRITE)
+ {
+ producers |= MALI_GRALLOC_PRODUCER_CAM;
+ }
+
+ /* Video decoder producer is signalled by a combination of usage flags
+ * (see definition of GRALLOC_USAGE_DECODER).
+ */
+ if ((usage & GRALLOC_USAGE_DECODER) == GRALLOC_USAGE_DECODER)
+ {
+ producers |= MALI_GRALLOC_PRODUCER_VPU;
+ }
+
+ return producers;
+}
+
+
+/*
+ * Determines the intersection of all IP consumers capability sets. Since all
+ * capabiltiies are positive, the intersection can be expressed via a logical
+ * AND operation. Capabilities must be defined (OPTIONS_PRESENT) to indicate
+ * that an IP is part of the media system (otherwise it will be ignored).
+ * See definition of MALI_GRALLOC_FORMAT_CAPABILITY_* for more information.
+ *
+ * @param consumers [in] Buffer consumers.
+ *
+ * @return flags word of common capabilities shared by *all* consumers;
+ * 0, if no capabilities are shared
+ */
+static uint64_t get_consumer_caps(const uint16_t consumers)
+{
+ uint64_t consumer_caps = ~0;
+
+ get_ip_capabilities();
+
+ /* Consumers can't write */
+ consumer_caps &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_YUV_WRITE;
+
+ if (consumers & MALI_GRALLOC_CONSUMER_CPU)
+ {
+ consumer_caps &= cpu_runtime_caps.caps_mask;
+ }
+
+ if (consumers & MALI_GRALLOC_CONSUMER_GPU &&
+ gpu_runtime_caps.caps_mask & MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT)
+ {
+ consumer_caps &= gpu_runtime_caps.caps_mask;
+ }
+
+ if (consumers & MALI_GRALLOC_CONSUMER_DPU &&
+ dpu_runtime_caps.caps_mask & MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT)
+ {
+ consumer_caps &= dpu_runtime_caps.caps_mask;
+ }
+
+ if (consumers & MALI_GRALLOC_CONSUMER_VPU &&
+ vpu_runtime_caps.caps_mask & MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT)
+ {
+ consumer_caps &= vpu_runtime_caps.caps_mask;
+ }
+
+ /* TODO: if consumers is 0, set consumer_caps to 0 as well */
+
+ return consumer_caps;
+}
+
+
+/*
+ * Determines the intersection of all IP producers capability sets. Since all
+ * capabiltiies are positive, the intersection can be expressed via a logical
+ * AND operation. Capabilities must be defined (OPTIONS_PRESENT) to indicate
+ * that an IP is part of the media system (otherwise it will be ignored).
+ * See definition of MALI_GRALLOC_FORMAT_CAPABILITY_* for more information.
+ *
+ * @param producers [in] Buffer producers.
+ *
+ * @return flags word of common capabilities shared by *all* producers;
+ * 0, if no capabilities are shared
+ */
+static uint64_t get_producer_caps(const uint16_t producers)
+{
+ uint64_t producer_caps = ~0;
+
+ if (producers == 0)
+ {
+ /* When no producer is specified assume no capabilities. */
+ return 0;
+ }
+
+ get_ip_capabilities();
+
+ /* Producers can't read */
+ producer_caps &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_YUV_READ;
+
+ if (producers & MALI_GRALLOC_PRODUCER_CPU)
+ {
+ producer_caps &= cpu_runtime_caps.caps_mask;
+ }
+
+ if (producers & MALI_GRALLOC_PRODUCER_GPU &&
+ gpu_runtime_caps.caps_mask & MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT)
+ {
+ producer_caps &= gpu_runtime_caps.caps_mask;
+ }
+
+ if (producers & MALI_GRALLOC_PRODUCER_DPU &&
+ dpu_runtime_caps.caps_mask & MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT)
+ {
+ producer_caps &= dpu_runtime_caps.caps_mask;
+ }
+
+ if (producers & MALI_GRALLOC_PRODUCER_CAM &&
+ cam_runtime_caps.caps_mask & MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT)
+ {
+ producer_caps &= cam_runtime_caps.caps_mask;
+ }
+
+ if (producers & MALI_GRALLOC_PRODUCER_VPU &&
+ vpu_runtime_caps.caps_mask & MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT)
+ {
+ producer_caps &= vpu_runtime_caps.caps_mask;
+ }
+
+ return producer_caps;
+}
+
+
+/*
+ * Update buffer dimensions for producer/consumer constraints. This process is
+ * not valid with CPU producer/consumer since the new resolution cannot be
+ * communicated to generic clients through the public APIs. Adjustments are
+ * likely to be related to AFBC.
+ *
+ * @param alloc_format [in] Format (inc. modifiers) to be allocated.
+ * @param usage [in] Buffer usage.
+ * @param width [inout] Buffer width (in pixels).
+ * @param height [inout] Buffer height (in pixels).
+ *
+ * @return none.
+ */
+void mali_gralloc_adjust_dimensions(const uint64_t alloc_format,
+ const uint64_t usage,
+ int* const width,
+ int* const height)
+{
+ /* Determine producers and consumers. */
+ const uint16_t producers = get_producers(usage);
+ const uint16_t consumers = get_consumers(usage);
+
+ /*
+ * Video producer requires additional height padding of AFBC buffers (whole
+ * rows of 16x16 superblocks). Cropping will be applied to internal
+ * dimensions to fit the public size.
+ */
+ if ((producers & MALI_GRALLOC_PRODUCER_VPU) &&
+ (alloc_format & MALI_GRALLOC_INTFMT_AFBC_BASIC))
+ {
+ const int32_t idx = get_format_index(alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK);
+ if (idx != -1)
+ {
+ /* 8-bit/10-bit YUV420 formats. */
+ if (formats[idx].is_yuv && formats[idx].hsub == 2 && formats[idx].vsub == 2)
+ {
+ *height += (alloc_format & MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS) ? 16 : 32;
+ }
+ }
+ }
+
+ if (producers & MALI_GRALLOC_PRODUCER_GPU)
+ {
+ /* Pad all AFBC allocations to multiple of GPU tile size. */
+ if (alloc_format & MALI_GRALLOC_INTFMT_AFBC_BASIC)
+ {
+ *width = GRALLOC_ALIGN(*width, 16);
+ *height = GRALLOC_ALIGN(*height, 16);
+ }
+ }
+
+out:
+ MALI_GRALLOC_LOGV("%s: alloc_format=0x%" PRIx64 " usage=0x%" PRIx64
+ " alloc_width=%u, alloc_height=%u",
+ __FUNCTION__, alloc_format, usage, *width, *height);
+}
+
+
+/*
+ * Obtain level of support for base format across all producers and consumers as
+ * defined by IP support table. This support is defined for the most capable IP -
+ * specific IP might have reduced support based on specific capabilities.
+ *
+ * @param producers [in] Producers (flags).
+ * @param consumers [in] Consumers (flags).
+ * @param format [in] Format entry in IP support table.
+ *
+ * @return format support flags.
+ */
+static format_support_flags ip_supports_base_format(const uint16_t producers,
+ const uint16_t consumers,
+ const format_ip_support_t * const format)
+{
+ format_support_flags support = ~0;
+
+ /* Determine producer support for base format. */
+ if (producers & MALI_GRALLOC_PRODUCER_CPU)
+ {
+ support &= format->cpu_wr;
+ }
+ if (producers & MALI_GRALLOC_PRODUCER_GPU)
+ {
+ support &= format->gpu_wr;
+ }
+ if (producers & MALI_GRALLOC_PRODUCER_DPU)
+ {
+ support &= format->dpu_wr;
+ }
+ if (producers & MALI_GRALLOC_PRODUCER_CAM)
+ {
+ support &= format->cam_wr;
+ }
+ if (producers & MALI_GRALLOC_PRODUCER_VPU)
+ {
+ support &= format->vpu_wr;
+ }
+
+ /* Determine producer support for base format. */
+ if (consumers & MALI_GRALLOC_CONSUMER_CPU)
+ {
+ support &= format->cpu_rd;
+ }
+ if (consumers & MALI_GRALLOC_CONSUMER_GPU)
+ {
+ support &= format->gpu_rd;
+ }
+ if (consumers & MALI_GRALLOC_CONSUMER_DPU)
+ {
+ support &= format->dpu_rd;
+ }
+ if (consumers & MALI_GRALLOC_CONSUMER_VPU)
+ {
+ support &= format->vpu_rd;
+ }
+
+ return support;
+}
+
+
+/*
+ * Determines whether a base format is subsampled YUV, where each
+ * chroma channel has fewer samples than the luma channel. The
+ * sub-sampling is always a power of 2.
+ *
+ * @param base_format [in] Base format (internal).
+ *
+ * @return 1, where format is subsampled YUV;
+ * 0, otherwise
+ */
+bool is_subsampled_yuv(const uint32_t base_format)
+{
+ unsigned long i;
+
+ for (i = 0; i < num_formats; i++)
+ {
+ if (formats[i].id == (base_format & MALI_GRALLOC_INTFMT_FMT_MASK))
+ {
+ if (formats[i].is_yuv == true &&
+ (formats[i].hsub > 1 || formats[i].vsub > 1))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+
+/*
+ * Determines whether multi-plane AFBC (requires specific IP capabiltiies) is
+ * supported across all producers and consumers.
+ *
+ * @param producers [in] Producers (flags).
+ * @param consumers [in] Consumers (flags).
+ * @param producer_caps [in] Producer capabilities (flags).
+ * @param consumer_caps [in] Consumer capabilities (flags).
+ *
+ * @return 1, multiplane AFBC is supported
+ * 0, otherwise
+ */
+static inline bool is_afbc_multiplane_supported(const uint16_t producers,
+ const uint16_t consumers,
+ const uint64_t producer_caps,
+ const uint64_t consumer_caps)
+{
+ GRALLOC_UNUSED(consumers);
+
+ return (producer_caps & consumer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC &&
+ producer_caps & consumer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_TILED_HEADERS &&
+ producer_caps & consumer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_EXTRAWIDEBLK &&
+ /*no_producer*/ consumer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_MULTIPLANE_READ &&
+ producers == 0) ? true : false;
+}
+
+
+/*
+ * Determines whether a given base format is supported by all producers and
+ * consumers. After checking broad support across producer/consumer IP, this
+ * function uses capabilities to disable features (base formats and AFBC
+ * modifiers) that are not supported by specific versions of each IP.
+ *
+ * @param fmt_idx [in] Index into format properties table (base format).
+ * @param ip_fmt_idx [in] Index into format IP support table (base format).
+ * @param usage [in] Buffer usage.
+ * @param producers [in] Producers (flags).
+ * @param consumers [in] Consumers (flags).
+ * @param producer_caps [in] Producer capabilities (flags).
+ * @param consumer_caps [in] Consumer capabilities (flags).
+ *
+ * @return format support flags.
+ */
+static format_support_flags is_format_supported(const int32_t fmt_idx,
+ const int32_t ip_fmt_idx,
+ const uint64_t usage,
+ const uint16_t producers,
+ const uint16_t consumers,
+ const uint64_t producer_caps,
+ const uint64_t consumer_caps)
+{
+ /* Determine format support from table. */
+ format_support_flags f_flags = ip_supports_base_format(producers, consumers,
+ &formats_ip_support[ip_fmt_idx]);
+
+ /* Determine whether producers/consumers support required AFBC features. */
+ if (f_flags & F_AFBC)
+ {
+ if (!formats[fmt_idx].afbc ||
+ (producer_caps & consumer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC) == 0)
+ {
+ f_flags &= ~F_AFBC;
+ }
+
+ /* Check that multi-plane format supported by producers/consumers. */
+ if (formats[fmt_idx].npln > 1 &&
+ !is_afbc_multiplane_supported(producers, consumers, producer_caps, consumer_caps))
+ {
+ f_flags &= ~F_AFBC;
+ }
+
+ /* Apply some additional restrictions from producer_caps and consumer_caps */
+ /* Some modifiers affect base format support */
+ if (formats[fmt_idx].is_yuv)
+ {
+ if ((producer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_YUV_WRITE) == 0)
+ {
+ f_flags &= ~F_AFBC;
+ }
+
+ if ((consumer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_YUV_READ) == 0)
+ {
+ f_flags &= ~F_AFBC;
+ }
+ }
+
+ if (usage & MALI_GRALLOC_USAGE_FRONTBUFFER)
+ {
+ if ((producer_caps & consumer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_DOUBLE_BODY) == 0)
+ {
+ f_flags &= ~F_AFBC;
+ }
+ }
+ }
+ if (f_flags != F_NONE)
+ {
+ if (formats[fmt_idx].id == MALI_GRALLOC_FORMAT_INTERNAL_RGBA_1010102 &&
+ (producer_caps & consumer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_PIXFMT_RGBA1010102) == 0)
+ {
+ /* TODO: forcing F_LIN is a W/A. Make a proper solution */
+ f_flags = F_NONE;
+ f_flags = F_LIN;
+ }
+ else if (formats[fmt_idx].id == MALI_GRALLOC_FORMAT_INTERNAL_RGBA_16161616)
+ {
+ if ((producer_caps & consumer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_PIXFMT_RGBA16161616) == 0)
+ {
+ /* TODO: forcing F_LIN is a W/A. Make a proper solution */
+ //f_flags = F_NONE;
+ f_flags = F_LIN;
+ }
+ else if ((producer_caps & consumer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_RGBA16161616) == 0)
+ {
+ f_flags = F_LIN;
+ }
+ }
+ }
+
+ return f_flags;
+}
+
+
+/*
+ * Ensures that the allocation format conforms to the AFBC specification and is
+ * supported by producers and consumers. Format modifiers are (in most cases)
+ * disabled as required to make valid. It is important to first resolve invalid
+ * combinations which are not dependent upon others to reduce the possibility of
+ * circular dependency.
+ *
+ * @param alloc_format [in] Allocation format (base + modifiers).
+ * @param producer_active_caps [in] Producer capabilities (flags).
+ * @param consumer_active_caps [in] Consumer capabilities (flags).
+ *
+ * @return valid alloc_format with AFBC possibly disabled (if required)
+ */
+static uint64_t validate_afbc_format(uint64_t alloc_format,
+ const uint64_t producer_active_caps,
+ const uint64_t consumer_active_caps)
+{
+ const uint32_t base_format = alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK;
+
+ /*
+ * AFBC with tiled-headers must be enabled for AFBC front-buffer-safe allocations.
+ * NOTE: format selection algorithm will always try and enable AFBC with
+ * tiled-headers where supported by producer(s) and consumer(s).
+ */
+ if (alloc_format & MALI_GRALLOC_INTFMT_AFBC_DOUBLE_BODY)
+ {
+ /*
+ * Disable (extra-) wide-block which is unsupported with front-buffer safe AFBC.
+ */
+ alloc_format &= ~MALI_GRALLOC_INTFMT_AFBC_WIDEBLK;
+ alloc_format &= ~MALI_GRALLOC_INTFMT_AFBC_EXTRAWIDEBLK;
+ }
+
+ /*
+ * AFBC specification: Split-block is not supported for
+ * subsampled formats (YUV) when wide-block is enabled.
+ */
+ if (alloc_format & MALI_GRALLOC_INTFMT_AFBC_WIDEBLK &&
+ alloc_format & MALI_GRALLOC_INTFMT_AFBC_SPLITBLK &&
+ is_subsampled_yuv(base_format))
+ {
+ /* Disable split-block instead of wide-block because because
+ * wide-block has greater impact on display performance.
+ */
+ alloc_format &= ~MALI_GRALLOC_INTFMT_AFBC_SPLITBLK;
+ }
+
+ /* AFBC specification: Split-block must be enabled for
+ * non-subsampled formats > 16 bpp, where wide-block is enabled.
+ */
+ if (alloc_format & MALI_GRALLOC_INTFMT_AFBC_WIDEBLK &&
+ (alloc_format & MALI_GRALLOC_INTFMT_AFBC_SPLITBLK) == 0 &&
+ !is_subsampled_yuv(base_format) &&
+ base_format != MALI_GRALLOC_FORMAT_INTERNAL_RGB_565)
+ {
+ /* Enable split-block if supported by producer(s) & consumer(s),
+ * otherwise disable wide-block.
+ */
+ if (producer_active_caps & consumer_active_caps &
+ MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_SPLITBLK)
+ {
+ alloc_format |= MALI_GRALLOC_INTFMT_AFBC_SPLITBLK;
+ }
+ else
+ {
+ alloc_format &= ~MALI_GRALLOC_INTFMT_AFBC_WIDEBLK;
+ }
+ }
+
+ /* Some RGB formats don't support split block. */
+ if (base_format == MALI_GRALLOC_FORMAT_INTERNAL_RGB_565)
+ {
+ alloc_format &= ~MALI_GRALLOC_INTFMT_AFBC_SPLITBLK;
+ }
+
+ /* Ensure that AFBC features are supported by producers/consumers. */
+ if ((alloc_format & MALI_GRALLOC_INTFMT_AFBC_BASIC) &&
+ (producer_active_caps & consumer_active_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC) == 0)
+ {
+ MALI_GRALLOC_LOGE("AFBC basic selected but not supported by producer/consumer. Disabling "
+ "MALI_GRALLOC_INTFMT_AFBC_BASIC");
+ alloc_format &= ~MALI_GRALLOC_INTFMT_AFBC_BASIC;
+ }
+
+ if ((alloc_format & MALI_GRALLOC_INTFMT_AFBC_SPLITBLK) &&
+ (producer_active_caps & consumer_active_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_SPLITBLK) == 0)
+ {
+ MALI_GRALLOC_LOGE("AFBC split-block selected but not supported by producer/consumer. Disabling "
+ "MALI_GRALLOC_INTFMT_AFBC_SPLITBLK");
+ alloc_format &= ~MALI_GRALLOC_INTFMT_AFBC_SPLITBLK;
+ }
+
+ if ((alloc_format & MALI_GRALLOC_INTFMT_AFBC_WIDEBLK) &&
+ (producer_active_caps & consumer_active_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_WIDEBLK) == 0)
+ {
+ MALI_GRALLOC_LOGE("AFBC wide-block selected but not supported by producer/consumer. Disabling "
+ "MALI_GRALLOC_INTFMT_AFBC_WIDEBLK");
+ alloc_format &= ~MALI_GRALLOC_INTFMT_AFBC_WIDEBLK;
+ }
+
+ if ((alloc_format & MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS) &&
+ (producer_active_caps & consumer_active_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_TILED_HEADERS) == 0)
+ {
+ MALI_GRALLOC_LOGE("AFBC tiled-headers selected but not supported by producer/consumer. Disabling "
+ "MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS");
+ alloc_format &= ~MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS;
+ }
+
+ if (!((alloc_format & MALI_GRALLOC_INTFMT_AFBC_SPARSE) ||
+ (producer_active_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_WRITE_NON_SPARSE)))
+ {
+ MALI_GRALLOC_LOGE("AFBC sparse not selected while producer cannot write non-sparse. Enabling "
+ "MALI_GRALLOC_INTFMT_AFBC_SPARSE");
+ alloc_format |= MALI_GRALLOC_INTFMT_AFBC_SPARSE;
+ }
+
+ return alloc_format;
+}
+
+
+/*
+ * Derives a valid AFBC format (via modifiers) for all producers and consumers.
+ * Formats are validated after enabling the largest feature set supported (and
+ * desirable) for the IP usage. Some format modifier combinations are not
+ * compatible. See MALI_GRALLOC_INTFMT_* modifiers for more information.
+ *
+ * @param base_format [in] Base format (internal).
+ * @param usage [in] Buffer usage.
+ * @param producer [in] Buffer producers (write).
+ * @param consumer [in] Buffer consumers (read).
+ * @param producer_caps [in] Buffer producer capabilities (intersection).
+ * @param consumer_caps [in] Buffer consumer capabilities (intersection).
+ *
+ * @return valid AFBC format, where modifiers are enabled (supported/preferred);
+ * base format without modifers, otherwise
+ */
+static uint64_t get_afbc_format(const uint32_t base_format,
+ const uint64_t usage,
+ const uint16_t producer,
+ const uint16_t consumer,
+ const uint64_t producer_caps,
+ const uint64_t consumer_caps)
+{
+ uint64_t alloc_format = base_format;
+
+ /*
+ * Determine AFBC modifiers where capabilities are defined for all producers
+ * and consumers. NOTE: AFBC is not supported for video transcode (VPU --> VPU).
+ */
+ if (producer_caps & consumer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT &&
+ ((producer & MALI_GRALLOC_PRODUCER_VPU) == 0 || (consumer & MALI_GRALLOC_CONSUMER_VPU) == 0))
+ {
+ if (producer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC &&
+ consumer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC)
+ {
+ alloc_format |= MALI_GRALLOC_INTFMT_AFBC_BASIC;
+
+ const int format_idx = get_format_index(base_format);
+
+ /* TODO: AFBC YUV TRANSFORM corrupts screen when enabled. find out why */
+#if 0
+ if (format_idx != -1)
+ {
+ if (formats[format_idx].yuv_transform == true)
+ {
+ alloc_format |= MALI_GRALLOC_INTFMT_AFBC_YUV_TRANSFORM;
+ }
+ }
+#endif
+
+ if (!(producer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_WRITE_NON_SPARSE))
+ {
+ alloc_format |= MALI_GRALLOC_INTFMT_AFBC_SPARSE;
+ }
+
+ if (producer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_TILED_HEADERS &&
+ consumer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_TILED_HEADERS)
+ {
+ alloc_format |= MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS;
+
+ if (usage & MALI_GRALLOC_USAGE_FRONTBUFFER &&
+ producer_caps & consumer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_DOUBLE_BODY)
+ {
+ alloc_format |= MALI_GRALLOC_INTFMT_AFBC_DOUBLE_BODY;
+ }
+ }
+
+ /*
+ * Specific producer/consumer combinations benefit from additional
+ * AFBC features (e.g. GPU --> DPU).
+ */
+ if (producer & MALI_GRALLOC_PRODUCER_GPU && consumer & MALI_GRALLOC_CONSUMER_DPU &&
+ dpu_runtime_caps.caps_mask & MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT)
+ {
+ if (producer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_SPLITBLK &&
+ consumer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_SPLITBLK)
+ {
+ alloc_format |= MALI_GRALLOC_INTFMT_AFBC_SPLITBLK;
+ }
+
+ /*
+ * NOTE: assume that all AFBC layers are pre-rotated. 16x16 SB
+ * must be used with DPU consumer when rotation is required.
+ */
+ if (producer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_WIDEBLK &&
+ consumer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_WIDEBLK)
+ {
+ alloc_format |= MALI_GRALLOC_INTFMT_AFBC_WIDEBLK;
+ }
+ }
+ }
+ }
+
+ alloc_format = validate_afbc_format(alloc_format, producer_caps, consumer_caps);
+
+ return alloc_format;
+}
+
+/*
+ * Obtains the 'active' capabilities (for producers/consumers) by applying
+ * additional constraints to the capabilities declared for each IP. Some rules
+ * are based on format, others specific to producer/consumer. This function must
+ * be careful not to make any assumptions about the base format properties since
+ * fallback might still occur. It is safe to use any properties which are common
+ * across all compatible formats as defined by is_format_compatible().
+ *
+ * @param format [in] Base format requested.
+ * @param producers [in] Producers (flags).
+ * @param consumers [in] Consumers (flags).
+ * @param producer_active_caps [out] Active producer capabilities (flags).
+ * @param consumer_active_caps [out] Active consumer capabilities (flags).
+ * @param buffer_size [in] Buffer resolution (w x h, in pixels).
+ *
+ * @return none.
+ */
+static void get_active_caps(const format_info_t format,
+ const uint16_t producers,
+ const uint16_t consumers,
+ uint64_t * const producer_active_caps,
+ uint64_t * const consumer_active_caps,
+ const int buffer_size)
+{
+ const uint64_t producer_caps = (producer_active_caps) ? *producer_active_caps : 0;
+ const uint64_t consumer_caps = (consumer_active_caps) ? *consumer_active_caps : 0;
+ uint64_t producer_mask = ~0;
+ uint64_t consumer_mask = ~0;
+
+ if (format.is_yuv)
+ {
+ /* AFBC wide-block is not supported across IP for YUV formats. */
+ producer_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_WIDEBLK;
+ consumer_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_WIDEBLK;
+
+ if ((producer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_YUV_WRITE) == 0)
+ {
+ producer_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK;
+ }
+ else if (producers & MALI_GRALLOC_PRODUCER_GPU)
+ {
+ /* All GPUs that can write YUV AFBC can only do it in 16x16,
+ * optionally with tiled headers.
+ */
+ producer_mask &=
+ ~(MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_SPLITBLK |
+ MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_WIDEBLK);
+ }
+
+ if ((consumer_caps & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_YUV_READ) == 0)
+ {
+ consumer_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK;
+ }
+ }
+
+ if (consumers & MALI_GRALLOC_CONSUMER_DPU)
+ {
+ /* DPU does not support split-block other than RGB(A) 24/32-bit */
+ if (!format.is_rgb || format.bpp[0] < 24)
+ {
+ if (consumers & MALI_GRALLOC_CONSUMER_DPU)
+ {
+ consumer_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_SPLITBLK;
+ }
+ }
+ }
+
+ bool afbc_allowed = false;
+ afbc_allowed = buffer_size > (192 * 192);
+
+ if (consumers & MALI_GRALLOC_CONSUMER_DPU)
+ {
+ /* TODO: make this into an option in BoardConfig */
+#if GRALLOC_DISP_W != 0 && GRALLOC_DISP_H != 0
+#define GRALLOC_AFBC_MIN_SIZE 40
+ /* Disable AFBC based on buffer dimensions */
+ afbc_allowed = ((buffer_size * 100) / (GRALLOC_DISP_W * GRALLOC_DISP_H)) >= GRALLOC_AFBC_MIN_SIZE;
+#endif
+ }
+
+ if (!afbc_allowed)
+ {
+ consumer_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK;
+ }
+
+ if (producer_active_caps)
+ {
+ *producer_active_caps &= producer_mask;
+ }
+ if (consumer_active_caps)
+ {
+ *consumer_active_caps &= consumer_mask;
+ }
+}
+
+
+/*
+ * Obtains support flags and modifiers for base format.
+ *
+ * @param base_format [in] Base format for which to deduce support.
+ * @param usage [in] Buffer usage.
+ * @param producers [in] Producers (flags).
+ * @param consumers [in] Consumers (flags).
+ * @param producer_active_caps [in] Producer capabilities (flags).
+ * @param consumer_active_caps [in] Consumer capabilities (flags).
+ * @param fmt_supported [out] Format (base + modifiers) and support (flags).
+ *
+ * @return 1, base format supported
+ * 0, otherwise
+ */
+bool get_supported_format(const uint32_t base_format,
+ const uint64_t usage,
+ const uint16_t producers,
+ const uint16_t consumers,
+ const uint64_t producer_active_caps,
+ const uint64_t consumer_active_caps,
+ fmt_props * const fmt_supported)
+{
+ const int32_t fmt_idx = get_format_index(base_format);
+ const int32_t ip_fmt_idx = get_ip_format_index(base_format);
+ assert(fmt_idx >= 0);
+ if (ip_fmt_idx == -1)
+ {
+ /* Return undefined base format. */
+ MALI_GRALLOC_LOGE("Failed to find IP support info for format id: 0x%" PRIx32,
+ base_format);
+ return false;
+ }
+
+ fmt_supported->f_flags = is_format_supported(fmt_idx,
+ ip_fmt_idx,
+ usage,
+ producers,
+ consumers,
+ producer_active_caps,
+ consumer_active_caps);
+ MALI_GRALLOC_LOGV("IP support: 0x%" PRIx16, fmt_supported->f_flags);
+ if (fmt_supported->f_flags == F_NONE &&
+ consumers & MALI_GRALLOC_CONSUMER_GPU &&
+ consumers & MALI_GRALLOC_CONSUMER_DPU)
+ {
+ /* Determine alternative caps for formats when GPU/DPU consumer.
+ * Although we normally combine capabilities for multiple consumers with "AND",
+ * in some situations (e.g. formats) we make best effort and say that fallback
+ * to GPU is acceptable and perferred over rejecting allocation. GPU composition
+ * must always be supported in case of fallback from DPU.
+ */
+ const uint16_t consumers_nodpu = consumers & ~MALI_GRALLOC_CONSUMER_DPU;
+ uint64_t consumer_nodpu_caps = consumer_active_caps;
+
+ /* Set consumer caps to GPU-only (assume superset of DPU). */
+ consumer_nodpu_caps = get_consumer_caps(consumers_nodpu);
+ get_active_caps(formats[fmt_idx],
+ producers, consumers_nodpu,
+ NULL, &consumer_nodpu_caps,
+ 0 /* N/A without DPU consumer */);
+
+ fmt_supported->f_flags = is_format_supported(fmt_idx,
+ ip_fmt_idx,
+ usage,
+ producers,
+ consumers_nodpu,
+ producer_active_caps,
+ consumer_nodpu_caps);
+ }
+
+ fmt_supported->base_format = base_format;
+ if (fmt_supported->f_flags & F_AFBC)
+ {
+ const uint64_t afbc_format = get_afbc_format(base_format,
+ usage,
+ producers,
+ consumers,
+ producer_active_caps,
+ consumer_active_caps);
+
+ MALI_GRALLOC_LOGV("AFBC format: 0x%" PRIx64, afbc_format);
+
+ /* Disable AFBC when forced by usage or no format modifiers selected. */
+ if ((usage & MALI_GRALLOC_USAGE_NO_AFBC) == MALI_GRALLOC_USAGE_NO_AFBC ||
+ afbc_format == fmt_supported->base_format)
+ {
+ fmt_supported->f_flags &= ~F_AFBC;
+ }
+
+ /* Check that AFBC features are correct for multiplane format. */
+ alloc_type_t alloc_type{};
+ get_alloc_type(afbc_format & MALI_GRALLOC_INTFMT_EXT_MASK,
+ fmt_idx,
+ usage,
+ &alloc_type);
+ if (formats[fmt_idx].npln > 1 && alloc_type.is_multi_plane == false)
+ {
+ fmt_supported->f_flags &= ~F_AFBC;
+ }
+
+ /* Store any format modifiers */
+ fmt_supported->format_ext = afbc_format & MALI_GRALLOC_INTFMT_EXT_MASK;
+ }
+ if ((fmt_supported->f_flags & F_AFBC) == 0)
+ {
+ fmt_supported->format_ext = 0;
+ }
+
+ MALI_GRALLOC_LOGV("Ext format: 0x%" PRIx64, fmt_supported->format_ext);
+
+ return (fmt_supported->f_flags == F_NONE) ? false : true;
+}
+
+
+/*
+ * Determines whether two base formats have comparable 'color' components. Alpha
+ * is considered unimportant for YUV formats.
+ *
+ * @param f_old [in] Format properties (old format).
+ * @param f_new [in] Format properties (new format).
+ *
+ * @return 1, format components are equivalent
+ * 0, otherwise
+ */
+static bool comparable_components(const format_info_t * const f_old,
+ const format_info_t * const f_new)
+{
+ if (f_old->is_yuv && f_new->bps == f_old->bps)
+ {
+ /* Formats have the same number of components. */
+ if (f_new->total_components() == f_old->total_components())
+ {
+ return true;
+ }
+
+ /* Alpha component can be dropped for yuv formats.
+ * This assumption is required for mapping Y0L2 to
+ * single plane 10-bit YUV420 AFBC.
+ */
+ if (f_old->has_alpha)
+ {
+ if (f_new->total_components() == 3 &&
+ f_new->is_yuv &&
+ !f_new->has_alpha)
+ {
+ return true;
+ }
+ }
+ }
+ else if (f_old->is_rgb)
+ {
+ if (f_new->total_components() == f_old->total_components())
+ {
+ if (f_new->bpp[0] == f_old->bpp[0] && f_new->bps == f_old->bps)
+ {
+ return true;
+ }
+ }
+ }
+ else
+ {
+ if (f_new->id == f_old->id)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+/*
+ * Determines whether two base formats are compatible such that data from one
+ * format could be accurately represented/interpreted in the other format.
+ *
+ * @param f_old [in] Format properties (old format).
+ * @param f_new [in] Format properties (new format).
+ *
+ * @return 1, formats are equivalent
+ * 0, otherwise
+ */
+static bool is_format_compatible(const format_info_t * const f_old,
+ const format_info_t * const f_new)
+{
+ if (f_new->hsub == f_old->hsub &&
+ f_new->vsub == f_old->vsub &&
+ f_new->is_rgb == f_old->is_rgb &&
+ f_new->is_yuv == f_old->is_yuv &&
+ comparable_components(f_old, f_new))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+/**
+ * Provide a grade for the compatible format with respect to the requested format. Used to find the best compatible
+ * format.
+ *
+ * @param fmt[in] Compatible format properties.
+ * @param req_format Requested base format.
+ *
+ * @return The grade of the compatible format. Higher is better. Returns 0 if format extensions are incompatible with
+ * requested format.
+ */
+uint64_t grade_format(const fmt_props &fmt, uint32_t req_format)
+{
+ uint64_t grade = 1;
+
+ GRALLOC_UNUSED(req_format);
+
+ static const struct {
+ uint64_t fmt_ext;
+ uint64_t value;
+ } fmt_ext_values[] {
+ { MALI_GRALLOC_INTFMT_AFBC_BASIC, 1 },
+ { MALI_GRALLOC_INTFMT_AFBC_SPLITBLK, 1 },
+ { MALI_GRALLOC_INTFMT_AFBC_WIDEBLK, 1 },
+ { MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS, 1 },
+ { MALI_GRALLOC_INTFMT_AFBC_EXTRAWIDEBLK, 1 },
+ { MALI_GRALLOC_INTFMT_AFBC_DOUBLE_BODY, 1 },
+ { MALI_GRALLOC_INTFMT_AFBC_BCH, 1 },
+ { MALI_GRALLOC_INTFMT_AFBC_YUV_TRANSFORM, 1 },
+ { MALI_GRALLOC_INTFMT_AFBC_SPARSE, 1 },
+ };
+ for (auto& ext : fmt_ext_values)
+ {
+ if (fmt.format_ext & ext.fmt_ext)
+ {
+ grade += ext.value;
+ }
+ }
+
+ return grade;
+}
+
+/*
+ * Obtains the 'best' allocation format for requested format and usage:
+ * 1. Find compatible base formats (based on format properties alone)
+ * 2. Find base formats supported by producers/consumers
+ * 3. Find best modifiers from supported base formats
+ * 4. Select allocation format from "best" base format with "best" modifiers
+ *
+ * NOTE: Base format re-mapping should not take place when CPU usage is
+ * requested.
+ *
+ * @param req_base_format [in] Base format requested by client.
+ * @param usage [in] Buffer usage.
+ * @param producers [in] Producers (flags).
+ * @param consumers [in] Consumers (flags).
+ * @param producer_active_caps [in] Producer capabilities (flags).
+ * @param consumer_active_caps [in] Consumer capabilities (flags).
+ *
+ * @return alloc_format, supported for usage;
+ * MALI_GRALLOC_FORMAT_INTERNAL_UNDEFINED, otherwise
+ */
+static uint64_t get_best_format(const uint32_t req_base_format,
+ const uint64_t usage,
+ const uint16_t producers,
+ const uint16_t consumers,
+ const uint64_t producer_active_caps,
+ const uint64_t consumer_active_caps)
+{
+ uint64_t alloc_format = MALI_GRALLOC_FORMAT_INTERNAL_UNDEFINED;
+
+ assert(req_base_format != MALI_GRALLOC_FORMAT_INTERNAL_UNDEFINED);
+ const int32_t req_fmt_idx = get_format_index(req_base_format);
+ MALI_GRALLOC_LOGV("req_base_format: 0x%" PRIx32, req_base_format);
+ MALI_GRALLOC_LOGV("req_fmt_idx: %d", req_fmt_idx);
+ assert(req_fmt_idx >= 0);
+
+ /* 1. Find compatible base formats. */
+ std::vector<fmt_props> f_compat;
+ for (uint16_t i = 0; i < num_formats; i++)
+ {
+ if (is_format_compatible(&formats[req_fmt_idx], &formats[i]))
+ {
+ fmt_props fmt = {0, 0, 0};
+ fmt.base_format = formats[i].id;
+ MALI_GRALLOC_LOGV("Compatible: Base-format: 0x%" PRIx32, fmt.base_format);
+ f_compat.push_back(fmt);
+ }
+ }
+ assert(f_compat.size() > 0);
+
+ /* 2. Find base formats supported by IP and among them, find the highest
+ * number of modifier enabled format and check if requested format is present
+ */
+
+ int32_t num_supported_formats = 0;
+ uint64_t req_format_grade = 0;
+ uint64_t best_fmt_grade = 0;
+ uint64_t first_of_best_formats = MALI_GRALLOC_FORMAT_INTERNAL_UNDEFINED;
+ uint64_t req_format = MALI_GRALLOC_FORMAT_INTERNAL_UNDEFINED;
+
+ for (uint16_t i = 0; i < f_compat.size(); i++)
+ {
+ MALI_GRALLOC_LOGV("Compatible: Base-format: 0x%" PRIx32, f_compat[i].base_format);
+ fmt_props fmt = {0, 0, 0};
+ bool supported = get_supported_format(f_compat[i].base_format,
+ usage,
+ producers,
+ consumers,
+ producer_active_caps,
+ consumer_active_caps,
+ &fmt);
+ if (supported)
+ {
+ const uint64_t sup_fmt_grade = grade_format(fmt, req_base_format);
+ if (sup_fmt_grade)
+ {
+ num_supported_formats++;
+ MALI_GRALLOC_LOGV("Supported: Base-format: 0x%" PRIx32 ", Modifiers: 0x%" PRIx64 ", Flags: 0x%" PRIx16,
+ fmt.base_format, fmt.format_ext, fmt.f_flags);
+
+ /* 3. Find best modifiers from supported base formats */
+ if (sup_fmt_grade > best_fmt_grade)
+ {
+ best_fmt_grade = sup_fmt_grade;
+ first_of_best_formats = fmt.base_format | fmt.format_ext;
+ }
+
+ /* Check if current supported format is same as requested format */
+ if (fmt.base_format == req_base_format)
+ {
+ req_format_grade = sup_fmt_grade;
+ req_format = fmt.base_format | fmt.format_ext;
+ }
+ }
+ }
+ }
+
+ /* 4. Select allocation format from "best" base format with "best" modifiers */
+ if (num_supported_formats > 0)
+ {
+ /* Select first/one of best format when requested format is either not
+ * supported or requested format is not the best format.
+ */
+ if ((req_format_grade != best_fmt_grade) &&
+ (((producers & MALI_GRALLOC_PRODUCER_CPU) == 0) &&
+ ((consumers & MALI_GRALLOC_CONSUMER_CPU) == 0)))
+ {
+ alloc_format = first_of_best_formats;
+ }
+ else if (req_format_grade != 0)
+ {
+ alloc_format = req_format;
+ }
+ }
+
+ MALI_GRALLOC_LOGV("Selected format: 0x%" PRIx64, alloc_format);
+ return alloc_format;
+}
+
+/* Returns true if the format modifier specifies no compression scheme. */
+static bool is_uncompressed(uint64_t format_ext)
+{
+ return format_ext == 0;
+}
+
+
+/* Returns true if the format modifier specifies AFBC. */
+static bool is_afbc(uint64_t format_ext)
+{
+ return format_ext & MALI_GRALLOC_INTFMT_AFBC_BASIC;
+}
+
+/* Returns true if the format modifier specifies multiplane AFBC. */
+static bool is_multiplane_afbc(uint64_t format_ext)
+{
+ return is_afbc(format_ext) &&
+ (format_ext & MALI_GRALLOC_INTFMT_AFBC_EXTRAWIDEBLK) &&
+ (format_ext & MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS);
+}
+
+/* Returns true if the format modifier specifies single plane AFBC. */
+static bool is_single_plane_afbc(uint64_t format_ext)
+{
+ return is_afbc(format_ext) && !is_multiplane_afbc(format_ext);
+}
+
+/*
+ * Determines the base format suitable for requested allocation format (base +
+ * modifiers). Going forward, the base format requested MUST be compatible with
+ * the format modifiers.
+ *
+ * @param fmt_idx [in] Index into format properties table (base format).
+ * @param format_ext [in] Format modifiers (extension bits).
+ *
+ * @return base_format, suitable for modifiers;
+ * MALI_GRALLOC_FORMAT_INTERNAL_UNDEFINED, otherwise
+ */
+static uint32_t get_base_format_for_modifiers(const int32_t fmt_idx,
+ const uint64_t format_ext)
+{
+ uint32_t base_format = MALI_GRALLOC_FORMAT_INTERNAL_UNDEFINED;
+ if (is_uncompressed(format_ext))
+ {
+ /* Uncompressed formats have no forced fallback. */
+ base_format = formats[fmt_idx].id;
+ }
+ else if (is_afbc(format_ext))
+ {
+ if (formats[fmt_idx].afbc &&
+ (formats[fmt_idx].npln == 1 || is_multiplane_afbc(format_ext)))
+ {
+ /* Requested format modifiers are suitable for base format. */
+ base_format = formats[fmt_idx].id;
+ }
+ }
+
+ return base_format;
+}
+
+
+/*
+ * Obtain format modifiers from requested format.
+ *
+ * @param req_format [in] Requested format (base + optional modifiers).
+ * @param usage [in] Buffer usage.
+ *
+ * @return format modifiers, where extracted from requested format;
+ * 0, otherwise
+ */
+uint64_t get_format_ext(const uint64_t req_format, const uint64_t usage)
+{
+ /* TODO: clean up this function. Or remove it */
+ GRALLOC_UNUSED(usage);
+ return req_format & MALI_GRALLOC_INTFMT_EXT_MASK;
+}
+
+
+/*
+ * Obtain base format from requested format. There are two primary ways in which
+ * the client can specify requested format:
+ * - Public API:
+ * - Normal usage, with HAL_PIXEL_FORMAT_* / MALI_GRALLOC_FORMAT_INTERNAL_*
+ * - Private usage, (as normal usage) with additional format modifiers (MALI_GRALLOC_INTFMT_*)
+ * - Private API: allows private usage to be provided explicitly
+ * (type == MALI_GRALLOC_FORMAT_TYPE_INTERNAL)
+ *
+ * @param req_format [in] Requested format (base + optional modifiers).
+ * @param usage [in] Buffer usage.
+ * @param type [in] Format type (public usage or internal).
+ * @param map_to_internal [in] Base format (if public HAL_PIXEL_FORMAT_*)
+ * should be mapped to internal representation.
+ *
+ * @return base format, where identified/translated from requested format;
+ * MALI_GRALLOC_FORMAT_INTERNAL_UNDEFINED, otherwise
+ */
+uint32_t get_base_format(const uint64_t req_format,
+ const uint64_t usage,
+ const mali_gralloc_format_type type,
+ const bool map_to_internal)
+{
+ GRALLOC_UNUSED(type);
+
+ uint32_t base_format = MALI_GRALLOC_FORMAT_INTERNAL_UNDEFINED;
+
+ /* Mask out extension bits which could be present with type 'internal'. */
+ base_format = req_format & MALI_GRALLOC_INTFMT_FMT_MASK;
+
+ /* Map Android flexible formats to internal base formats */
+ if (req_format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)
+ {
+ if ((usage & GRALLOC_USAGE_HW_TEXTURE) || (usage & GRALLOC_USAGE_HW_COMPOSER))
+ {
+ if(usage & GRALLOC_USAGE_YUV_RANGE_FULL)
+ {
+ base_format = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL; // NV21M Full
+ }
+ else
+ {
+ base_format = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M; //NV21M narrow
+ }
+ }
+ else if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER)
+ {
+ base_format = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M; //NV21M narrow
+ }
+ else if (usage & GRALLOC_USAGE_VIDEO_PRIVATE_DATA)
+ {
+ base_format = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M;
+ }
+ else if ((usage & GRALLOC_USAGE_HW_CAMERA_READ) && (usage & GRALLOC_USAGE_HW_CAMERA_WRITE))
+ {
+ base_format = HAL_PIXEL_FORMAT_YCbCr_422_I; // YUYV
+ }
+ else
+ {
+ base_format = HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M; //NV21M narrow
+ }
+ }
+ else if (req_format == HAL_PIXEL_FORMAT_YCbCr_420_888)
+ {
+ if (usage & (GRALLOC_USAGE_HW_VIDEO_ENCODER | GRALLOC_USAGE_HW_VIDEO_DECODER))
+ {
+ base_format = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M;
+ if (usage & (GRALLOC_USAGE_SBWC_REQUEST_10BIT))
+ {
+ base_format = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M;
+ }
+ }
+ else if (usage & (GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE))
+ {
+ base_format = HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M;
+ }
+ else
+ {
+ // Flexible framework-accessible YUV format; map to NV21 for now
+ base_format = HAL_PIXEL_FORMAT_YCrCb_420_SP;
+ }
+ }
+
+ /* Obtain a valid base format, optionally mapped to internal. Flex formats
+ * are always mapped to internal base format.
+ * NOTE: Overlap between HAL_PIXEL_FORMAT_* and MALI_GRALLOC_FORMAT_INTERNAL_*
+ * is intentional. See enumerations for more information.
+ */
+ return get_internal_format(base_format, map_to_internal);
+}
+
+
+/*
+ * Select pixel format (base + modifier) for allocation.
+ *
+ * @param req_format [in] Format (base + optional modifiers) requested by client.
+ * @param type [in] Format type (public usage or internal).
+ * @param usage [in] Buffer usage.
+ * @param buffer_size [in] Buffer resolution (w x h, in pixels).
+ *
+ * @return alloc_format, format to be used in allocation;
+ * MALI_GRALLOC_FORMAT_INTERNAL_UNDEFINED, where no suitable
+ * format could be found.
+ */
+uint64_t mali_gralloc_select_format(const uint64_t req_format,
+ const mali_gralloc_format_type type,
+ const uint64_t usage,
+ const int buffer_size)
+{
+ uint64_t alloc_format = MALI_GRALLOC_FORMAT_INTERNAL_UNDEFINED;
+
+ /*
+ * Obtain base_format (no extension bits) and indexes into format tables.
+ */
+ const uint32_t req_base_format = get_base_format(req_format, usage, type, true);
+ const int32_t req_fmt_idx = get_format_index(req_base_format);
+ if (req_base_format == MALI_GRALLOC_FORMAT_INTERNAL_UNDEFINED ||
+ req_fmt_idx == -1)
+ {
+ MALI_GRALLOC_LOGE("Invalid base format! req_base_format = 0x%" PRIx32
+ ", req_format = 0x%" PRIx64 ", type = 0x%" PRIx32,
+ req_base_format, req_format, type);
+ goto out;
+ }
+
+ /* Reject if usage specified is outside white list of valid usages. */
+ if (type != MALI_GRALLOC_FORMAT_TYPE_INTERNAL && (usage & (~VALID_USAGE)) != 0)
+ {
+ MALI_GRALLOC_LOGE("Invalid usage specified: 0x%" PRIx64, usage);
+ goto out;
+ }
+
+ /* TODO: Make a function for finding formats that should be allocated as the request format */
+ if (is_exynos_format(req_base_format) || req_base_format == HAL_PIXEL_FORMAT_BLOB)
+ {
+ alloc_format = req_base_format;
+ }
+ else if (usage == 0)
+ {
+ /* Allocate format as-is when no usage is specified */
+ alloc_format = req_base_format;
+ }
+ else
+ {
+ /* Determine producers and consumers. */
+ const uint16_t producers = get_producers(usage);
+ const uint16_t consumers = get_consumers(usage);
+
+ MALI_GRALLOC_LOGV("Producers: 0x%" PRIx16 ", Consumers: 0x%" PRIx16,
+ producers, consumers);
+
+ /* Obtain producer and consumer capabilities. */
+ const uint64_t producer_caps = get_producer_caps(producers);
+
+ uint64_t consumer_caps = 0;
+#ifdef GRALLOC_HWC_FB_DISABLE_AFBC
+ if (GRALLOC_HWC_FB_DISABLE_AFBC && DISABLE_FRAMEBUFFER_HAL && (usage & GRALLOC_USAGE_HW_FB))
+ {
+ /* Override capabilities to disable AFBC for DRM HWC framebuffer surfaces. */
+ consumer_caps = MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT;
+ }
+ else
+#endif
+ {
+ consumer_caps = get_consumer_caps(consumers);
+ }
+
+ MALI_GRALLOC_LOGV("Producer caps: 0x%" PRIx64 ", Consumer caps: 0x%" PRIx64,
+ producer_caps, consumer_caps);
+
+ if (producers == 0 && consumers == 0)
+ {
+ MALI_GRALLOC_LOGE("Producer and consumer not identified.");
+ goto out;
+ }
+ else if (producers == 0 || consumers == 0)
+ {
+ MALI_GRALLOC_LOGV("Producer or consumer not identified.");
+ }
+
+ if ((usage & MALI_GRALLOC_USAGE_NO_AFBC) == MALI_GRALLOC_USAGE_NO_AFBC &&
+ formats[req_fmt_idx].is_yuv)
+ {
+ MALI_GRALLOC_LOGE("ERROR: Invalid usage 'MALI_GRALLOC_USAGE_NO_AFBC' when allocating YUV formats");
+ goto out;
+ }
+
+ uint64_t producer_active_caps = producer_caps;
+ uint64_t consumer_active_caps = consumer_caps;
+ uint64_t consumer_caps_mask;
+
+ get_active_caps(formats[req_fmt_idx],
+ producers, consumers,
+ &producer_active_caps, &consumer_active_caps,
+ buffer_size);
+
+ MALI_GRALLOC_LOGV("Producer caps (active): 0x%" PRIx64 ", Consumer caps (active): 0x%" PRIx64,
+ producer_active_caps, consumer_active_caps);
+
+ /* TODO: reimplment get_best_format */
+ alloc_format = get_best_format(formats[req_fmt_idx].id,
+ usage,
+ producers,
+ consumers,
+ producer_active_caps,
+ consumer_active_caps);
+ }
+
+out:
+ MALI_GRALLOC_LOGV("mali_gralloc_select_format: req_format=0x%08" PRIx64 ", usage=0x%" PRIx64
+ ", req_base_format=0x%" PRIx32 ", alloc_format=0x%" PRIx64,
+ req_format, usage, req_base_format, alloc_format);
+
+ return alloc_format;
+}
+
+bool is_exynos_format(uint32_t base_format)
+{
+ switch (base_format)
+ {
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_EXYNOS_YV12_M:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_SBWC:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L50:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L75:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L50:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L75:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L40:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L60:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L80:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L40:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L60:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L80:
+ return true;
+ }
+
+ return false;
+}
+
diff --git a/gralloc4/src/core/mali_gralloc_reference.cpp b/gralloc4/src/core/mali_gralloc_reference.cpp
new file mode 100644
index 0000000..22d8aa0
--- /dev/null
+++ b/gralloc4/src/core/mali_gralloc_reference.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2016, 2018-2020 ARM Limited. All rights reserved.
+ *
+ * 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 <hardware/gralloc1.h>
+
+#include "mali_gralloc_buffer.h"
+#include "allocator/mali_gralloc_ion.h"
+#include "allocator/mali_gralloc_shared_memory.h"
+#include "mali_gralloc_bufferallocation.h"
+#include "mali_gralloc_debug.h"
+
+static pthread_mutex_t s_map_lock = PTHREAD_MUTEX_INITIALIZER;
+
+int mali_gralloc_reference_retain(buffer_handle_t handle)
+{
+ if (private_handle_t::validate(handle) < 0)
+ {
+ MALI_GRALLOC_LOGE("Registering/Retaining invalid buffer %p, returning error", handle);
+ return -EINVAL;
+ }
+
+ private_handle_t *hnd = (private_handle_t *)handle;
+ pthread_mutex_lock(&s_map_lock);
+
+ if (hnd->allocating_pid == getpid() || hnd->remote_pid == getpid())
+ {
+ hnd->ref_count++;
+ pthread_mutex_unlock(&s_map_lock);
+ return 0;
+ }
+ else
+ {
+ hnd->remote_pid = getpid();
+ hnd->ref_count = 1;
+ }
+
+ int retval= mali_gralloc_ion_map(hnd);
+
+ /* Import ION handle to let ION driver know who's using the buffer */
+ import_exynos_ion_handles(hnd);
+
+ pthread_mutex_unlock(&s_map_lock);
+
+ return retval;
+}
+
+int mali_gralloc_reference_release(buffer_handle_t handle, bool canFree)
+{
+ if (private_handle_t::validate(handle) < 0)
+ {
+ MALI_GRALLOC_LOGE("unregistering/releasing invalid buffer %p, returning error", handle);
+ return -EINVAL;
+ }
+
+ private_handle_t *hnd = (private_handle_t *)handle;
+ pthread_mutex_lock(&s_map_lock);
+
+ if (hnd->ref_count == 0)
+ {
+ MALI_GRALLOC_LOGE("Buffer %p should have already been released", handle);
+ pthread_mutex_unlock(&s_map_lock);
+ return -EINVAL;
+ }
+
+ if (hnd->allocating_pid == getpid())
+ {
+ hnd->ref_count--;
+
+ if (hnd->ref_count == 0 && canFree)
+ {
+ free_exynos_ion_handles(hnd);
+ mali_gralloc_dump_buffer_erase(hnd);
+ mali_gralloc_buffer_free(handle);
+ delete handle;
+
+ }
+ }
+ else if (hnd->remote_pid == getpid()) // never unmap buffers that were not imported into this process
+ {
+ hnd->ref_count--;
+
+ if (hnd->ref_count == 0)
+ {
+ mali_gralloc_ion_unmap(hnd);
+ free_exynos_ion_handles(hnd);
+
+ /* TODO: Make this unmapping of shared meta fd into a function? */
+ if (hnd->attr_base)
+ {
+ munmap(hnd->attr_base, hnd->attr_size);
+ hnd->attr_base = nullptr;
+ }
+ }
+ }
+ else
+ {
+ MALI_GRALLOC_LOGE("Trying to unregister buffer %p from process %d that was not imported into current process: %d", hnd,
+ hnd->remote_pid, getpid());
+ }
+
+ pthread_mutex_unlock(&s_map_lock);
+ return 0;
+}
diff --git a/gralloc4/src/core/mali_gralloc_reference.h b/gralloc4/src/core/mali_gralloc_reference.h
new file mode 100644
index 0000000..f2afc61
--- /dev/null
+++ b/gralloc4/src/core/mali_gralloc_reference.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2016 ARM Limited. All rights reserved.
+ *
+ * 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 MALI_GRALLOC_REFERENCE_H_
+#define MALI_GRALLOC_REFERENCE_H_
+
+#include "gralloc_priv.h"
+
+int mali_gralloc_reference_retain(buffer_handle_t handle);
+int mali_gralloc_reference_release(buffer_handle_t handle, bool canFree);
+
+#endif /* MALI_GRALLOC_REFERENCE_H_ */
diff --git a/gralloc4/src/gralloc_helper.h b/gralloc4/src/gralloc_helper.h
new file mode 100644
index 0000000..ba31333
--- /dev/null
+++ b/gralloc4/src/gralloc_helper.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2010-2020 ARM Limited. All rights reserved.
+ *
+ * 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_HELPER_H_
+#define GRALLOC_HELPER_H_
+
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/user.h>
+
+#include "mali_gralloc_log.h"
+
+#define GRALLOC_ALIGN(value, base) ((((value) + (base) -1) / (base)) * (base))
+
+#define GRALLOC_MAX(a, b) (((a)>(b))?(a):(b))
+
+#define GRALLOC_UNUSED(x) ((void)x)
+
+static inline size_t round_up_to_page_size(size_t x)
+{
+ return (x + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
+}
+
+#endif /* GRALLOC_HELPER_H_ */
diff --git a/gralloc4/src/gralloc_priv.h b/gralloc4/src/gralloc_priv.h
new file mode 100644
index 0000000..bbef1b6
--- /dev/null
+++ b/gralloc4/src/gralloc_priv.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017, 2019-2020 Arm Limited. All rights reserved.
+ *
+ * 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_PRIV_H_
+#define GRALLOC_PRIV_H_
+
+#include <stdint.h>
+#include <pthread.h>
+#include <errno.h>
+#include <linux/fb.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <cutils/native_handle.h>
+
+/* Allocator = 4.0, Mapper = 4.0 and Common = 1.2 */
+#define HIDL_ALLOCATOR_VERSION_SCALED 400
+#define HIDL_MAPPER_VERSION_SCALED 400
+#define HIDL_COMMON_VERSION_SCALED 120
+
+#include "mali_gralloc_formats.h"
+#include "mali_gralloc_usages.h"
+#include "gralloc_helper.h"
+
+/*
+ * This header file contains the private buffer definition. For gralloc 0.3 it will
+ * always be exposed, but for gralloc 1.0 it will be removed at some point in the future.
+ *
+ * GRALLOC_DISABLE_PRIVATE_BUFFER_DEF is intended for DDKs to test while implementing
+ * the new private API.
+ */
+#include "mali_gralloc_buffer.h"
+
+#endif /* GRALLOC_PRIV_H_ */
diff --git a/gralloc4/src/hidl_common/Allocator.cpp b/gralloc4/src/hidl_common/Allocator.cpp
new file mode 100644
index 0000000..8174f05
--- /dev/null
+++ b/gralloc4/src/hidl_common/Allocator.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2020 ARM Limited. All rights reserved.
+ *
+ * Copyright 2016 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 "SharedMetadata.h"
+#include "Allocator.h"
+#include "core/mali_gralloc_bufferallocation.h"
+#include "core/mali_gralloc_bufferdescriptor.h"
+#include "core/format_info.h"
+#include "allocator/mali_gralloc_ion.h"
+#include "allocator/mali_gralloc_shared_memory.h"
+#include "gralloc_priv.h"
+
+namespace arm
+{
+namespace allocator
+{
+namespace common
+{
+
+void allocate(const buffer_descriptor_t &bufferDescriptor, uint32_t count, IAllocator::allocate_cb hidl_cb,
+ std::function<int(const buffer_descriptor_t *, buffer_handle_t *)> fb_allocator)
+{
+#if DISABLE_FRAMEBUFFER_HAL
+ GRALLOC_UNUSED(fb_allocator);
+#endif
+
+ Error error = Error::NONE;
+ int stride = 0;
+ std::vector<hidl_handle> grallocBuffers;
+ gralloc_buffer_descriptor_t grallocBufferDescriptor[1];
+
+ grallocBufferDescriptor[0] = (gralloc_buffer_descriptor_t)(&bufferDescriptor);
+ grallocBuffers.reserve(count);
+
+ for (uint32_t i = 0; i < count; i++)
+ {
+ buffer_handle_t tmpBuffer = nullptr;
+
+ int allocResult;
+#if (DISABLE_FRAMEBUFFER_HAL != 1)
+ if (((bufferDescriptor.producer_usage & GRALLOC_USAGE_HW_FB) ||
+ (bufferDescriptor.consumer_usage & GRALLOC_USAGE_HW_FB)) &&
+ fb_allocator)
+ {
+ allocResult = fb_allocator(&bufferDescriptor, &tmpBuffer);
+ }
+ else
+#endif
+ {
+ allocResult = mali_gralloc_buffer_allocate(grallocBufferDescriptor, 1, &tmpBuffer, nullptr);
+ if (allocResult != 0)
+ {
+ MALI_GRALLOC_LOGE("%s, buffer allocation failed with %d", __func__, allocResult);
+ error = Error::NO_RESOURCES;
+ break;
+ }
+ auto hnd = const_cast<private_handle_t *>(reinterpret_cast<const private_handle_t *>(tmpBuffer));
+ hnd->imapper_version = HIDL_MAPPER_VERSION_SCALED;
+
+ hnd->reserved_region_size = bufferDescriptor.reserved_size;
+ hnd->attr_size = mapper::common::shared_metadata_size() + hnd->reserved_region_size;
+
+ if (hnd->get_usage() & GRALLOC_USAGE_ROIINFO)
+ {
+ hnd->attr_size += 32768;
+ }
+
+ /* TODO: must do error checking */
+ mali_gralloc_ion_allocate_attr(hnd);
+
+ /* TODO: error check for failure */
+ hnd->attr_base = mmap(nullptr, hnd->attr_size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, hnd->get_share_attr_fd(), 0);
+
+ memset(hnd->attr_base, 0, hnd->attr_size);
+
+ mapper::common::shared_metadata_init(hnd->attr_base, bufferDescriptor.name);
+
+ const uint32_t base_format = bufferDescriptor.alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK;
+ const uint64_t usage = bufferDescriptor.consumer_usage | bufferDescriptor.producer_usage;
+ android_dataspace_t dataspace;
+ get_format_dataspace(base_format, usage, hnd->width, hnd->height, &dataspace);
+
+ mapper::common::set_dataspace(hnd, static_cast<mapper::common::Dataspace>(dataspace));
+
+ /*
+ * We need to set attr_base to MAP_FAILED before the HIDL callback
+ * to avoid sending an invalid pointer to the client process.
+ *
+ * hnd->attr_base = mmap(...);
+ * hidl_callback(hnd); // client receives hnd->attr_base = <dangling pointer>
+ */
+ munmap(hnd->attr_base, hnd->attr_size);
+ hnd->attr_base = 0;
+ }
+
+ int tmpStride = 0;
+ tmpStride = bufferDescriptor.pixel_stride;
+
+ if (stride == 0)
+ {
+ stride = tmpStride;
+ }
+ else if (stride != tmpStride)
+ {
+ /* Stride must be the same for all allocations */
+ mali_gralloc_buffer_free(tmpBuffer);
+ stride = 0;
+ error = Error::UNSUPPORTED;
+ break;
+ }
+
+ grallocBuffers.emplace_back(hidl_handle(tmpBuffer));
+ }
+
+ /* Populate the array of buffers for application consumption */
+ hidl_vec<hidl_handle> hidlBuffers;
+ if (error == Error::NONE)
+ {
+ hidlBuffers.setToExternal(grallocBuffers.data(), grallocBuffers.size());
+ }
+ hidl_cb(error, stride, hidlBuffers);
+
+ /* The application should import the Gralloc buffers using IMapper for
+ * further usage. Free the allocated buffers in IAllocator context
+ */
+ for (const auto &buffer : grallocBuffers)
+ {
+ mali_gralloc_buffer_free(buffer.getNativeHandle());
+ }
+}
+
+} // namespace common
+} // namespace allocator
+} // namespace arm
diff --git a/gralloc4/src/hidl_common/Allocator.h b/gralloc4/src/hidl_common/Allocator.h
new file mode 100644
index 0000000..8fdd5ba
--- /dev/null
+++ b/gralloc4/src/hidl_common/Allocator.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2020 ARM Limited. All rights reserved.
+ *
+ * Copyright 2016 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_COMMON_ALLOCATOR_H
+#define GRALLOC_COMMON_ALLOCATOR_H
+
+#include "4.x/gralloc_allocator_hidl_header.h"
+
+#include <functional>
+
+#include "core/mali_gralloc_bufferdescriptor.h"
+#include "BufferDescriptor.h"
+
+namespace arm
+{
+namespace allocator
+{
+namespace common
+{
+
+using android::hardware::hidl_handle;
+using android::hardware::hidl_vec;
+
+/*
+ * Allocates buffers with the properties specified by the descriptor
+ *
+ * @param bufferDescriptor: Specifies the properties of the buffers to allocate.
+ * @param count: Number of buffers to allocate.
+ * @param hidl_cb [in] HIDL callback function generating -
+ * error : NONE upon success. Otherwise,
+ * BAD_DESCRIPTOR when the descriptor is invalid.
+ * NO_RESOURCES when the allocation cannot be fulfilled
+ * UNSUPPORTED when any of the property encoded in the descriptor
+ * is not supported
+ * stride: Number of pixels between two consecutive rows of the
+ * buffers, when the concept of consecutive rows is defined.
+ * buffers: An array of raw handles to the newly allocated buffers
+ * @param fb_allocator [in] function to use for allocation of buffers with GRALLOC_USAGE_HW_FB
+ */
+void allocate(const buffer_descriptor_t &bufferDescriptor, uint32_t count, IAllocator::allocate_cb hidl_cb,
+ std::function<int(const buffer_descriptor_t *, buffer_handle_t *)> fb_allocator = nullptr);
+
+} // namespace common
+} // namespace allocator
+} // namespace arm
+
+#endif /* GRALLOC_COMMON_ALLOCATOR_H */
diff --git a/gralloc4/src/hidl_common/Android.bp b/gralloc4/src/hidl_common/Android.bp
new file mode 100644
index 0000000..7c09bfc
--- /dev/null
+++ b/gralloc4/src/hidl_common/Android.bp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 Arm Limited.
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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.
+ */
+
+filegroup {
+ name: "libgralloc_hidl_common_allocator",
+ srcs: [
+ "Allocator.cpp",
+ ],
+}
+
+filegroup {
+ name: "libgralloc_hidl_common_mapper",
+ srcs: [
+ "Mapper.cpp",
+ "RegisteredHandlePool.cpp",
+ ],
+}
+
+filegroup {
+ name: "libgralloc_hidl_common_mapper_metadata",
+ srcs: [
+ "MapperMetadata.cpp",
+ ],
+}
+
+filegroup {
+ name: "libgralloc_hidl_common_shared_metadata",
+ srcs: [
+ "SharedMetadata.cpp",
+ ],
+} \ No newline at end of file
diff --git a/gralloc4/src/hidl_common/BufferDescriptor.h b/gralloc4/src/hidl_common/BufferDescriptor.h
new file mode 100644
index 0000000..abaac62
--- /dev/null
+++ b/gralloc4/src/hidl_common/BufferDescriptor.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2020 ARM Limited. All rights reserved.
+ *
+ * Copyright 2016 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_BUFFER_DESCRIPTOR_H_
+#define _GRALLOC_BUFFER_DESCRIPTOR_H_
+
+#include "core/mali_gralloc_bufferdescriptor.h"
+
+#include "4.x/gralloc_mapper_hidl_header.h"
+
+#include <assert.h>
+#include <inttypes.h>
+#include <string.h>
+
+namespace arm {
+namespace mapper {
+namespace common {
+
+using android::hardware::hidl_vec;
+
+const size_t DESCRIPTOR_32BIT_FIELDS = 5;
+const size_t DESCRIPTOR_64BIT_FIELDS = 2;
+
+const uint64_t validUsageBits =
+ BufferUsage::GPU_CUBE_MAP |
+ BufferUsage::GPU_MIPMAP_COMPLETE |
+ BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
+ BufferUsage::GPU_TEXTURE | BufferUsage::GPU_RENDER_TARGET |
+ BufferUsage::COMPOSER_OVERLAY | BufferUsage::COMPOSER_CLIENT_TARGET |
+ BufferUsage::CAMERA_INPUT | BufferUsage::CAMERA_OUTPUT |
+ BufferUsage::PROTECTED |
+ BufferUsage::COMPOSER_CURSOR |
+ BufferUsage::VIDEO_ENCODER |
+ BufferUsage::RENDERSCRIPT |
+ BufferUsage::VIDEO_DECODER |
+ BufferUsage::SENSOR_DIRECT_DATA |
+ BufferUsage::GPU_DATA_BUFFER |
+ BufferUsage::VENDOR_MASK |
+ BufferUsage::VENDOR_MASK_HI;
+
+template<typename BufferDescriptorInfoT>
+static bool validateDescriptorInfo(const BufferDescriptorInfoT &descriptorInfo)
+{
+ if (descriptorInfo.width == 0 || descriptorInfo.height == 0 || descriptorInfo.layerCount == 0)
+ {
+ return false;
+ }
+
+ if (static_cast<int32_t>(descriptorInfo.format) == 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+template <typename vecT>
+static void push_descriptor_uint32(hidl_vec<vecT> *vec, size_t *pos, uint32_t val)
+{
+ static_assert(sizeof(val) % sizeof(vecT) == 0, "Unsupported vector type");
+ memcpy(vec->data() + *pos, &val, sizeof(val));
+ *pos += sizeof(val) / sizeof(vecT);
+}
+
+template <typename vecT>
+static uint32_t pop_descriptor_uint32(const hidl_vec<vecT> &vec, size_t *pos)
+{
+ uint32_t val;
+ static_assert(sizeof(val) % sizeof(vecT) == 0, "Unsupported vector type");
+ memcpy(&val, vec.data() + *pos, sizeof(val));
+ *pos += sizeof(val) / sizeof(vecT);
+ return val;
+}
+
+template <typename vecT>
+static void push_descriptor_uint64(hidl_vec<vecT> *vec, size_t *pos, uint64_t val)
+{
+ static_assert(sizeof(val) % sizeof(vecT) == 0, "Unsupported vector type");
+ memcpy(vec->data() + *pos, &val, sizeof(val));
+ *pos += sizeof(val) / sizeof(vecT);
+}
+
+template <typename vecT>
+static uint64_t pop_descriptor_uint64(const hidl_vec<vecT> &vec, size_t *pos)
+{
+ uint64_t val;
+ static_assert(sizeof(val) % sizeof(vecT) == 0, "Unsupported vector type");
+ memcpy(&val, vec.data() + *pos, sizeof(val));
+ *pos += sizeof(val) / sizeof(vecT);
+ return val;
+}
+
+static void push_descriptor_string(hidl_vec<uint8_t> *vec, size_t *pos, const std::string &str)
+{
+ strcpy(reinterpret_cast<char *>(vec->data() + *pos), str.c_str());
+ *pos += strlen(str.c_str()) + 1;
+}
+
+static std::string pop_descriptor_string(const hidl_vec<uint8_t> &vec, size_t *pos)
+{
+ std::string str(reinterpret_cast<const char *>(vec.data() + *pos));
+ *pos += str.size() + 1;
+ return str;
+}
+
+template <typename vecT, typename BufferDescriptorInfoT>
+static const hidl_vec<vecT> grallocEncodeBufferDescriptor(const BufferDescriptorInfoT &descriptorInfo)
+{
+ hidl_vec<vecT> descriptor;
+
+ static_assert(sizeof(uint32_t) % sizeof(vecT) == 0, "Unsupported vector type");
+ size_t dynamic_size = 0;
+ constexpr size_t static_size = (DESCRIPTOR_32BIT_FIELDS * sizeof(uint32_t) / sizeof(vecT)) +
+ (DESCRIPTOR_64BIT_FIELDS * sizeof(uint64_t) / sizeof(vecT));
+
+ /* Include the name and '\0' in the descriptor. */
+ dynamic_size += strlen(descriptorInfo.name.c_str()) + 1;
+
+ size_t pos = 0;
+ descriptor.resize(dynamic_size + static_size);
+ push_descriptor_uint32(&descriptor, &pos, HIDL_MAPPER_VERSION_SCALED / 10);
+ push_descriptor_uint32(&descriptor, &pos, descriptorInfo.width);
+ push_descriptor_uint32(&descriptor, &pos, descriptorInfo.height);
+ push_descriptor_uint32(&descriptor, &pos, descriptorInfo.layerCount);
+ push_descriptor_uint32(&descriptor, &pos, static_cast<uint32_t>(descriptorInfo.format));
+ push_descriptor_uint64(&descriptor, &pos, static_cast<uint64_t>(descriptorInfo.usage));
+
+ push_descriptor_uint64(&descriptor, &pos, descriptorInfo.reservedSize);
+
+ assert(pos == static_size);
+
+ push_descriptor_string(&descriptor, &pos, descriptorInfo.name);
+
+ return descriptor;
+}
+
+template <typename vecT>
+static bool grallocDecodeBufferDescriptor(const hidl_vec<vecT> &androidDescriptor, buffer_descriptor_t &grallocDescriptor)
+{
+ static_assert(sizeof(uint32_t) % sizeof(vecT) == 0, "Unsupported vector type");
+ size_t pos = 0;
+
+ if (((DESCRIPTOR_32BIT_FIELDS * sizeof(uint32_t) / sizeof(vecT)) +
+ (DESCRIPTOR_64BIT_FIELDS * sizeof(uint64_t) / sizeof(vecT))) > androidDescriptor.size())
+ {
+ MALI_GRALLOC_LOGE("Descriptor is too small");
+ return false;
+ }
+
+ if (pop_descriptor_uint32(androidDescriptor, &pos) != HIDL_MAPPER_VERSION_SCALED / 10)
+ {
+ MALI_GRALLOC_LOGE("Corrupted buffer version in descriptor = %p, pid = %d ", &androidDescriptor, getpid());
+ return false;
+ }
+
+ grallocDescriptor.width = pop_descriptor_uint32(androidDescriptor, &pos);
+ grallocDescriptor.height = pop_descriptor_uint32(androidDescriptor, &pos);
+ grallocDescriptor.layer_count = pop_descriptor_uint32(androidDescriptor, &pos);
+ grallocDescriptor.hal_format = static_cast<uint64_t>(pop_descriptor_uint32(androidDescriptor, &pos));
+ grallocDescriptor.producer_usage = pop_descriptor_uint64(androidDescriptor, &pos);
+ grallocDescriptor.consumer_usage = grallocDescriptor.producer_usage;
+ grallocDescriptor.format_type = MALI_GRALLOC_FORMAT_TYPE_USAGE;
+ grallocDescriptor.signature = sizeof(buffer_descriptor_t);
+ grallocDescriptor.reserved_size = pop_descriptor_uint64(androidDescriptor, &pos);
+ grallocDescriptor.name = pop_descriptor_string(androidDescriptor, &pos);
+
+ return true;
+}
+
+} // namespace common
+} // namespace mapper
+} // namespace arm
+#endif
diff --git a/gralloc4/src/hidl_common/Mapper.cpp b/gralloc4/src/hidl_common/Mapper.cpp
new file mode 100644
index 0000000..700484e
--- /dev/null
+++ b/gralloc4/src/hidl_common/Mapper.cpp
@@ -0,0 +1,757 @@
+/*
+ * Copyright (C) 2020 ARM Limited. All rights reserved.
+ *
+ * Copyright 2016 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 <inttypes.h>
+#include <sync/sync.h>
+#include "RegisteredHandlePool.h"
+#include "Mapper.h"
+#include "BufferDescriptor.h"
+#include "mali_gralloc_log.h"
+#include "core/mali_gralloc_bufferallocation.h"
+#include "core/mali_gralloc_bufferdescriptor.h"
+#include "core/mali_gralloc_bufferaccess.h"
+#include "core/mali_gralloc_reference.h"
+#include "core/format_info.h"
+#include "allocator/mali_gralloc_ion.h"
+#include "mali_gralloc_buffer.h"
+#include "mali_gralloc_log.h"
+
+#include "MapperMetadata.h"
+#include "SharedMetadata.h"
+
+/* GraphicBufferMapper is expected to be valid (and leaked) during process
+ * termination. IMapper, and in turn, gRegisteredHandles must be valid as
+ * well. Create the registered handle pool on the heap, and let
+ * it leak for simplicity.
+ *
+ * However, there is no way to make sure gralloc0/gralloc1 are valid. Any use
+ * of static/global object in gralloc0/gralloc1 that may have been destructed
+ * is potentially broken.
+ */
+RegisteredHandlePool* gRegisteredHandles = new RegisteredHandlePool;
+
+namespace arm {
+namespace mapper {
+namespace common {
+
+/*
+ * Translates the register buffer API into existing gralloc implementation
+ *
+ * @param bufferHandle [in] Private handle for the buffer to be imported
+ *
+ * @return Error::BAD_BUFFER for an invalid buffer
+ * Error::NO_RESOURCES when unable to import the given buffer
+ * Error::NONE on successful import
+ */
+static Error registerBuffer(buffer_handle_t bufferHandle)
+{
+ if (private_handle_t::validate(bufferHandle) < 0)
+ {
+ MALI_GRALLOC_LOGE("Buffer: %p is corrupted", bufferHandle);
+ return Error::BAD_BUFFER;
+ }
+
+ if (mali_gralloc_reference_retain(bufferHandle) < 0)
+ {
+ return Error::NO_RESOURCES;
+ }
+
+ return Error::NONE;
+}
+
+/*
+ * Translates the unregister buffer API into existing gralloc implementation
+ *
+ * @param bufferHandle [in] Private handle for the buffer to be released
+ *
+ * @return Error::BAD_BUFFER for an invalid buffer / buffers which can't be released
+ * Error::NONE on successful release of the buffer
+ */
+static Error unregisterBuffer(buffer_handle_t bufferHandle)
+{
+ if (private_handle_t::validate(bufferHandle) < 0)
+ {
+ MALI_GRALLOC_LOGE("Buffer: %p is corrupted", bufferHandle);
+ return Error::BAD_BUFFER;
+ }
+
+ const int status = mali_gralloc_reference_release(bufferHandle, true);
+ if (status != 0)
+ {
+ MALI_GRALLOC_LOGE("Unable to release buffer:%p", bufferHandle);
+ return Error::BAD_BUFFER;
+ }
+
+ return Error::NONE;
+}
+
+/*
+ * Retrieves the file descriptor referring to a sync fence object
+ *
+ * @param fenceHandle [in] HIDL fence handle
+ * @param outFenceFd [out] Fence file descriptor. '-1' indicates no fence
+ *
+ * @return false, for an invalid HIDL fence handle
+ * true, otherwise
+ */
+static bool getFenceFd(const hidl_handle& fenceHandle, int* outFenceFd)
+{
+ auto const handle = fenceHandle.getNativeHandle();
+ if (handle && handle->numFds > 1)
+ {
+ MALI_GRALLOC_LOGE("Invalid fence handle with %d fds", handle->numFds);
+ return false;
+ }
+
+ *outFenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1;
+ return true;
+}
+
+/*
+ * Populates the HIDL fence handle for the given fence object
+ *
+ * @param fenceFd [in] Fence file descriptor
+ * @param handleStorage [in] HIDL handle storage for fence
+ *
+ * @return HIDL fence handle
+ */
+static hidl_handle getFenceHandle(int fenceFd, char* handleStorage)
+{
+ native_handle_t* handle = nullptr;
+ if (fenceFd >= 0)
+ {
+ handle = native_handle_init(handleStorage, 1, 0);
+ handle->data[0] = fenceFd;
+ }
+
+ return hidl_handle(handle);
+}
+
+/*
+ * Locks the given buffer for the specified CPU usage.
+ *
+ * @param bufferHandle [in] Buffer to lock.
+ * @param cpuUsage [in] Specifies one or more CPU usage flags to request
+ * @param accessRegion [in] Portion of the buffer that the client intends to access.
+ * @param fenceFd [in] Fence file descriptor
+ * @param outData [out] CPU accessible buffer address
+ *
+ * @return Error::BAD_BUFFER for an invalid buffer
+ * Error::NO_RESOURCES when unable to duplicate fence
+ * Error::BAD_VALUE when locking fails
+ * Error::NONE on successful buffer lock
+ */
+static Error lockBuffer(buffer_handle_t bufferHandle,
+ uint64_t cpuUsage,
+ const IMapper::Rect& accessRegion, int fenceFd,
+ void** outData)
+{
+ /* dup fenceFd as it is going to be owned by gralloc. Note that it is
+ * gralloc's responsibility to close it, even on locking errors.
+ */
+ if (fenceFd >= 0)
+ {
+ fenceFd = dup(fenceFd);
+ if (fenceFd < 0)
+ {
+ MALI_GRALLOC_LOGE("Error encountered while duplicating fence file descriptor");
+ return Error::NO_RESOURCES;
+ }
+ }
+
+ if (private_handle_t::validate(bufferHandle) < 0)
+ {
+ if (fenceFd >= 0)
+ {
+ close(fenceFd);
+ }
+ MALI_GRALLOC_LOGE("Buffer: %p is corrupted", bufferHandle);
+ return Error::BAD_BUFFER;
+ }
+
+ auto private_handle = private_handle_t::dynamicCast(bufferHandle);
+ if (private_handle->cpu_write != 0 && (cpuUsage & BufferUsage::CPU_WRITE_MASK))
+ {
+ if (fenceFd >= 0)
+ {
+ close(fenceFd);
+ }
+#if 0
+ MALI_GRALLOC_LOGW("Attempt to call lock*() for writing on an already locked buffer (%p)", bufferHandle);
+#endif
+
+ /* TODO: handle simulatneous locks differently. May be keep a global lock count per buffer? */
+ }
+ else if (fenceFd >= 0)
+ {
+ sync_wait(fenceFd, -1);
+ close(fenceFd);
+ }
+
+ void* data = nullptr;
+ if (mali_gralloc_lock(bufferHandle, cpuUsage, accessRegion.left, accessRegion.top, accessRegion.width,
+ accessRegion.height, &data) < 0)
+ {
+ return Error::BAD_VALUE;
+ }
+
+ *outData = data;
+
+ return Error::NONE;
+}
+
+/*
+ * Unlocks a buffer to indicate all CPU accesses to the buffer have completed
+ *
+ * @param bufferHandle [in] Buffer to lock.
+ * @param outFenceFd [out] Fence file descriptor
+ *
+ * @return Error::BAD_BUFFER for an invalid buffer
+ * Error::BAD_VALUE when unlocking failed
+ * Error::NONE on successful buffer unlock
+ */
+static Error unlockBuffer(buffer_handle_t bufferHandle,
+ int* outFenceFd)
+{
+ if (private_handle_t::validate(bufferHandle) < 0)
+ {
+ MALI_GRALLOC_LOGE("Buffer: %p is corrupted", bufferHandle);
+ return Error::BAD_BUFFER;
+ }
+
+ auto private_handle = private_handle_t::dynamicCast(bufferHandle);
+#if 0
+ if (!private_handle->cpu_write && !private_handle->cpu_read)
+ {
+ MALI_GRALLOC_LOGW("Attempt to call unlock*() on an unlocked buffer (%p)", bufferHandle);
+
+ /* TODO: handle simulatneous locks differently. May be keep a global lock count per buffer? */
+ }
+#endif
+
+ const int result = mali_gralloc_unlock(bufferHandle);
+ if (result)
+ {
+ MALI_GRALLOC_LOGE("Unlocking failed with error: %d", result);
+ return Error::BAD_VALUE;
+ }
+
+ *outFenceFd = -1;
+
+ return Error::NONE;
+}
+
+void importBuffer(const hidl_handle& rawHandle, IMapper::importBuffer_cb hidl_cb)
+{
+ if (!rawHandle.getNativeHandle())
+ {
+ MALI_GRALLOC_LOGE("Invalid buffer handle to import");
+ hidl_cb(Error::BAD_BUFFER, nullptr);
+ return;
+ }
+
+ native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle());
+ if (!bufferHandle)
+ {
+ MALI_GRALLOC_LOGE("Failed to clone buffer handle");
+ hidl_cb(Error::NO_RESOURCES, nullptr);
+ return;
+ }
+
+ const Error error = registerBuffer(bufferHandle);
+ if (error != Error::NONE)
+ {
+ native_handle_close(bufferHandle);
+ native_handle_delete(bufferHandle);
+
+ hidl_cb(error, nullptr);
+ return;
+ }
+
+ auto *private_handle = static_cast<private_handle_t *>(bufferHandle);
+ private_handle->attr_base = mmap(nullptr, private_handle->attr_size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, private_handle->get_share_attr_fd(), 0);
+ if (private_handle->attr_base == MAP_FAILED)
+ {
+ native_handle_close(bufferHandle);
+ native_handle_delete(bufferHandle);
+ hidl_cb(Error::NO_RESOURCES, nullptr);
+ return;
+ }
+
+ if (gRegisteredHandles->add(bufferHandle) == false)
+ {
+ /* The newly cloned handle is already registered. This can only happen
+ * when a handle previously registered was native_handle_delete'd instead
+ * of freeBuffer'd.
+ */
+ MALI_GRALLOC_LOGE("Handle %p has already been imported; potential fd leaking",
+ bufferHandle);
+ unregisterBuffer(bufferHandle);
+ native_handle_close(bufferHandle);
+ native_handle_delete(bufferHandle);
+
+ hidl_cb(Error::NO_RESOURCES, nullptr);
+ return;
+ }
+
+ hidl_cb(Error::NONE, bufferHandle);
+}
+
+Error freeBuffer(void* buffer)
+{
+ native_handle_t * const bufferHandle = gRegisteredHandles->remove(buffer);
+ if (!bufferHandle)
+ {
+ MALI_GRALLOC_LOGE("Invalid buffer handle %p to freeBuffer", buffer);
+ return Error::BAD_BUFFER;
+ }
+
+ {
+ auto *private_handle = static_cast<private_handle_t *>(bufferHandle);
+ int ret = munmap(private_handle->attr_base, private_handle->attr_size);
+ if (ret < 0)
+ {
+ MALI_GRALLOC_LOGW("munmap: %s", strerror(errno));
+ }
+ private_handle->attr_base = MAP_FAILED;
+ }
+
+ const Error status = unregisterBuffer(bufferHandle);
+ if (status != Error::NONE)
+ {
+ return status;
+ }
+
+ native_handle_close(bufferHandle);
+ native_handle_delete(bufferHandle);
+
+ return Error::NONE;
+}
+
+void lock(void* buffer, uint64_t cpuUsage, const IMapper::Rect& accessRegion,
+ const hidl_handle& acquireFence, IMapper::lock_cb hidl_cb)
+{
+ buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer);
+ if (!bufferHandle || private_handle_t::validate(bufferHandle) < 0)
+ {
+ MALI_GRALLOC_LOGE("Buffer to lock: %p is not valid", buffer);
+ hidl_cb(Error::BAD_BUFFER, nullptr);
+ return;
+ }
+
+ int fenceFd;
+ if (!getFenceFd(acquireFence, &fenceFd))
+ {
+ hidl_cb(Error::BAD_VALUE, nullptr);
+ return;
+ }
+
+ void* data = nullptr;
+ const Error error = lockBuffer(bufferHandle, cpuUsage, accessRegion, fenceFd, &data);
+
+ hidl_cb(error, data);
+}
+
+void unlock(void* buffer, IMapper::unlock_cb hidl_cb)
+{
+ buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer);
+ if (!bufferHandle)
+ {
+ MALI_GRALLOC_LOGE("Buffer to unlock: %p has not been registered with Gralloc", buffer);
+ hidl_cb(Error::BAD_BUFFER, nullptr);
+ return;
+ }
+
+ int fenceFd;
+ const Error error = unlockBuffer(bufferHandle, &fenceFd);
+ if (error == Error::NONE)
+ {
+ NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);
+ hidl_cb(error, getFenceHandle(fenceFd, fenceStorage));
+
+ if (fenceFd >= 0)
+ {
+ close(fenceFd);
+ }
+ }
+ else
+ {
+ hidl_cb(error, nullptr);
+ }
+}
+
+Error validateBufferSize(void* buffer,
+ const IMapper::BufferDescriptorInfo& descriptorInfo,
+ uint32_t in_stride)
+{
+ /* The buffer must have been allocated by Gralloc */
+ buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer);
+ if (!bufferHandle)
+ {
+ MALI_GRALLOC_LOGE("Buffer: %p has not been registered with Gralloc", buffer);
+ return Error::BAD_BUFFER;
+ }
+
+ if (private_handle_t::validate(bufferHandle) < 0)
+ {
+ MALI_GRALLOC_LOGE("Buffer: %p is corrupted", bufferHandle);
+ return Error::BAD_BUFFER;
+ }
+
+ buffer_descriptor_t grallocDescriptor;
+ grallocDescriptor.width = descriptorInfo.width;
+ grallocDescriptor.height = descriptorInfo.height;
+ grallocDescriptor.layer_count = descriptorInfo.layerCount;
+ grallocDescriptor.hal_format = static_cast<uint64_t>(descriptorInfo.format);
+ grallocDescriptor.producer_usage = static_cast<uint64_t>(descriptorInfo.usage);
+ grallocDescriptor.consumer_usage = grallocDescriptor.producer_usage;
+ grallocDescriptor.format_type = MALI_GRALLOC_FORMAT_TYPE_USAGE;
+
+ /* Derive the buffer size for the given descriptor */
+ const int result = mali_gralloc_derive_format_and_size(&grallocDescriptor);
+ if (result)
+ {
+ MALI_GRALLOC_LOGV("Unable to derive format and size for the given descriptor information. error: %d", result);
+ return Error::BAD_VALUE;
+ }
+
+ /* Validate the buffer parameters against descriptor info */
+ private_handle_t *gralloc_buffer = (private_handle_t *)bufferHandle;
+
+ /* The buffer size must be greater than (or equal to) what would have been allocated with descriptor */
+ for (int i = 0; i < gralloc_buffer->fd_count; i++)
+ {
+ if (gralloc_buffer->alloc_sizes[i] < grallocDescriptor.alloc_sizes[i])
+ {
+ MALI_GRALLOC_LOGW("Buf size mismatch. fd_idx(%d) Buffer size = %" PRIu64 ", Descriptor (derived) size = %" PRIu64,
+ i, gralloc_buffer->alloc_sizes[i], grallocDescriptor.alloc_sizes[i]);
+ return Error::BAD_VALUE;
+ }
+ }
+
+ if (in_stride != 0 && (uint32_t)gralloc_buffer->stride != in_stride)
+ {
+ MALI_GRALLOC_LOGE("Stride mismatch. Expected stride = %d, Buffer stride = %d",
+ in_stride, gralloc_buffer->stride);
+ return Error::BAD_VALUE;
+ }
+
+ if (gralloc_buffer->alloc_format != grallocDescriptor.alloc_format)
+ {
+ MALI_GRALLOC_LOGE("Buffer alloc format :0x%" PRIx64" does not match descriptor (derived) alloc format :0x%"
+ PRIx64, gralloc_buffer->alloc_format, grallocDescriptor.alloc_format);
+ return Error::BAD_VALUE;
+ }
+
+ const int format_idx = get_format_index(gralloc_buffer->alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK);
+ if (format_idx == -1)
+ {
+ MALI_GRALLOC_LOGE("Invalid format to validate buffer descriptor");
+ return Error::BAD_VALUE;
+ }
+ else
+ {
+ for (int i = 0; i < formats[format_idx].npln; i++)
+ {
+ if (gralloc_buffer->plane_info[i].byte_stride != grallocDescriptor.plane_info[i].byte_stride)
+ {
+ MALI_GRALLOC_LOGE("Buffer byte stride 0x%x mismatch with desc byte stride 0x%x in plane %d ",
+ gralloc_buffer->plane_info[i].byte_stride, grallocDescriptor.plane_info[i].byte_stride, i);
+ return Error::BAD_VALUE;
+ }
+
+ if (gralloc_buffer->plane_info[i].alloc_width != grallocDescriptor.plane_info[i].alloc_width)
+ {
+ MALI_GRALLOC_LOGE("Buffer alloc width 0x%x mismatch with desc alloc width 0x%x in plane %d ",
+ gralloc_buffer->plane_info[i].alloc_width, grallocDescriptor.plane_info[i].alloc_width, i);
+ return Error::BAD_VALUE;
+ }
+
+ if (gralloc_buffer->plane_info[i].alloc_height != grallocDescriptor.plane_info[i].alloc_height)
+ {
+ MALI_GRALLOC_LOGE("Buffer alloc height 0x%x mismatch with desc alloc height 0x%x in plane %d ",
+ gralloc_buffer->plane_info[i].alloc_height, grallocDescriptor.plane_info[i].alloc_height, i);
+ return Error::BAD_VALUE;
+ }
+ }
+ }
+
+ if ((uint32_t)gralloc_buffer->width != grallocDescriptor.width)
+ {
+ MALI_GRALLOC_LOGE("Width mismatch. Buffer width = %u, Descriptor width = %u",
+ gralloc_buffer->width, grallocDescriptor.width);
+ return Error::BAD_VALUE;
+ }
+
+ if ((uint32_t)gralloc_buffer->height != grallocDescriptor.height)
+ {
+ MALI_GRALLOC_LOGE("Height mismatch. Buffer height = %u, Descriptor height = %u",
+ gralloc_buffer->height, grallocDescriptor.height);
+ return Error::BAD_VALUE;
+ }
+
+ if (gralloc_buffer->layer_count != grallocDescriptor.layer_count)
+ {
+ MALI_GRALLOC_LOGE("Layer Count mismatch. Buffer layer_count = %u, Descriptor layer_count width = %u",
+ gralloc_buffer->layer_count, grallocDescriptor.layer_count);
+ return Error::BAD_VALUE;
+ }
+
+ return Error::NONE;
+}
+
+void getTransportSize(void* buffer, IMapper::getTransportSize_cb hidl_cb)
+{
+ /* The buffer must have been allocated by Gralloc */
+ buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer);
+ if (!bufferHandle)
+ {
+ MALI_GRALLOC_LOGE("Buffer %p is not registered with Gralloc", bufferHandle);
+ hidl_cb(Error::BAD_BUFFER, -1, -1);
+ return;
+ }
+
+ if (private_handle_t::validate(bufferHandle) < 0)
+ {
+ MALI_GRALLOC_LOGE("Buffer %p is corrupted", buffer);
+ hidl_cb(Error::BAD_BUFFER, -1, -1);
+ return;
+ }
+ hidl_cb(Error::NONE, bufferHandle->numFds, bufferHandle->numInts);
+}
+
+void isSupported(const IMapper::BufferDescriptorInfo& description, IMapper::isSupported_cb hidl_cb)
+{
+ buffer_descriptor_t grallocDescriptor;
+ grallocDescriptor.width = description.width;
+ grallocDescriptor.height = description.height;
+ grallocDescriptor.layer_count = description.layerCount;
+ grallocDescriptor.hal_format = static_cast<uint64_t>(description.format);
+ grallocDescriptor.producer_usage = static_cast<uint64_t>(description.usage);
+ grallocDescriptor.consumer_usage = grallocDescriptor.producer_usage;
+ grallocDescriptor.format_type = MALI_GRALLOC_FORMAT_TYPE_USAGE;
+
+ /* Check if it is possible to allocate a buffer for the given description */
+ const int result = mali_gralloc_derive_format_and_size(&grallocDescriptor);
+ if (result != 0)
+ {
+ MALI_GRALLOC_LOGV("Allocation for the given description will not succeed. error: %d", result);
+ hidl_cb(Error::NO_RESOURCES, false);
+ }
+ else
+ {
+ hidl_cb(Error::NONE, true);
+ }
+}
+
+void flushLockedBuffer(void *buffer, IMapper::flushLockedBuffer_cb hidl_cb)
+{
+ buffer_handle_t handle = gRegisteredHandles->get(buffer);
+ if (private_handle_t::validate(handle) < 0)
+ {
+ MALI_GRALLOC_LOGE("Bandle: %p is corrupted", handle);
+ hidl_cb(Error::BAD_BUFFER, hidl_handle{});
+ return;
+ }
+
+ auto private_handle = static_cast<const private_handle_t *>(handle);
+ if (!private_handle->cpu_write && !private_handle->cpu_read)
+ {
+ MALI_GRALLOC_LOGE("Attempt to call flushLockedBuffer() on an unlocked buffer (%p)", handle);
+ hidl_cb(Error::BAD_BUFFER, hidl_handle{});
+ return;
+ }
+
+ mali_gralloc_ion_sync_end(private_handle, false, true);
+ hidl_cb(Error::NONE, hidl_handle{});
+}
+
+Error rereadLockedBuffer(void *buffer)
+{
+ buffer_handle_t handle = gRegisteredHandles->get(buffer);
+ if (private_handle_t::validate(handle) < 0)
+ {
+ MALI_GRALLOC_LOGE("Buffer: %p is corrupted", handle);
+ return Error::BAD_BUFFER;
+ }
+
+ auto private_handle = static_cast<const private_handle_t *>(handle);
+ if (!private_handle->cpu_write && !private_handle->cpu_read)
+ {
+ MALI_GRALLOC_LOGE("Attempt to call rereadLockedBuffer() on an unlocked buffer (%p)", handle);
+ return Error::BAD_BUFFER;
+ }
+
+ mali_gralloc_ion_sync_start(private_handle, true, false);
+ return Error::NONE;
+}
+
+void get(void *buffer, const IMapper::MetadataType &metadataType, IMapper::get_cb hidl_cb)
+{
+ /* The buffer must have been allocated by Gralloc */
+ const private_handle_t *handle = static_cast<const private_handle_t *>(gRegisteredHandles->get(buffer));
+ if (handle == nullptr)
+ {
+ MALI_GRALLOC_LOGE("Buffer: %p has not been registered with Gralloc", buffer);
+ hidl_cb(Error::BAD_BUFFER, hidl_vec<uint8_t>());
+ return;
+ }
+ get_metadata(handle, metadataType, hidl_cb);
+}
+
+Error set(void *buffer, const IMapper::MetadataType &metadataType, const hidl_vec<uint8_t> &metadata)
+{
+ /* The buffer must have been allocated by Gralloc */
+ const private_handle_t *handle = static_cast<const private_handle_t *>(gRegisteredHandles->get(buffer));
+ if (handle == nullptr)
+ {
+ MALI_GRALLOC_LOGE("Buffer: %p has not been registered with Gralloc", buffer);
+ return Error::BAD_BUFFER;
+ }
+ return set_metadata(handle, metadataType, metadata);
+}
+
+void listSupportedMetadataTypes(IMapper::listSupportedMetadataTypes_cb hidl_cb)
+{
+ /* Returns a vector of {metadata type, description, isGettable, isSettable}
+ * Only non-standardMetadataTypes require a description.
+ */
+ hidl_vec<IMapper::MetadataTypeDescription> descriptions = {
+ { android::gralloc4::MetadataType_BufferId, "", true, false },
+ { android::gralloc4::MetadataType_Name, "", true, false },
+ { android::gralloc4::MetadataType_Width, "", true, false },
+ { android::gralloc4::MetadataType_Height, "", true, false },
+ { android::gralloc4::MetadataType_LayerCount, "", true, false },
+ { android::gralloc4::MetadataType_PixelFormatRequested, "", true, false },
+ { android::gralloc4::MetadataType_PixelFormatFourCC, "", true, false },
+ { android::gralloc4::MetadataType_PixelFormatModifier, "", true, false },
+ { android::gralloc4::MetadataType_Usage, "", true, false },
+ { android::gralloc4::MetadataType_AllocationSize, "", true, false },
+ { android::gralloc4::MetadataType_ProtectedContent, "", true, false },
+ { android::gralloc4::MetadataType_Compression, "", true, false },
+ { android::gralloc4::MetadataType_Interlaced, "", true, false },
+ { android::gralloc4::MetadataType_ChromaSiting, "", true, false },
+ { android::gralloc4::MetadataType_PlaneLayouts, "", true, false },
+ { android::gralloc4::MetadataType_Dataspace, "", true, true },
+ { android::gralloc4::MetadataType_BlendMode, "", true, true },
+ { android::gralloc4::MetadataType_Smpte2086, "", true, true },
+ { android::gralloc4::MetadataType_Cta861_3, "", true, true },
+ { android::gralloc4::MetadataType_Smpte2094_40, "", true, true },
+ { android::gralloc4::MetadataType_Crop, "", true, true },
+ /* Arm vendor metadata */
+ { ArmMetadataType_PLANE_FDS,
+ "Vector of file descriptors of each plane", true, false },
+ };
+ hidl_cb(Error::NONE, descriptions);
+ return;
+}
+
+
+static hidl_vec<IMapper::MetadataDump> dumpBufferHelper(const private_handle_t* handle)
+{
+ hidl_vec<IMapper::MetadataType> standardMetadataTypes = {
+ android::gralloc4::MetadataType_BufferId,
+ android::gralloc4::MetadataType_Name,
+ android::gralloc4::MetadataType_Width,
+ android::gralloc4::MetadataType_Height,
+ android::gralloc4::MetadataType_LayerCount,
+ android::gralloc4::MetadataType_PixelFormatRequested,
+ android::gralloc4::MetadataType_PixelFormatFourCC,
+ android::gralloc4::MetadataType_PixelFormatModifier,
+ android::gralloc4::MetadataType_Usage,
+ android::gralloc4::MetadataType_AllocationSize,
+ android::gralloc4::MetadataType_ProtectedContent,
+ android::gralloc4::MetadataType_Compression,
+ android::gralloc4::MetadataType_Interlaced,
+ android::gralloc4::MetadataType_ChromaSiting,
+ android::gralloc4::MetadataType_PlaneLayouts,
+ android::gralloc4::MetadataType_Dataspace,
+ android::gralloc4::MetadataType_BlendMode,
+ android::gralloc4::MetadataType_Smpte2086,
+ android::gralloc4::MetadataType_Cta861_3,
+ android::gralloc4::MetadataType_Smpte2094_40,
+ android::gralloc4::MetadataType_Crop,
+ };
+
+ std::vector<IMapper::MetadataDump> metadataDumps;
+ for (const auto& metadataType: standardMetadataTypes)
+ {
+ get_metadata(handle, metadataType, [&metadataDumps, &metadataType](Error error, hidl_vec<uint8_t> metadata) {
+ switch(error)
+ {
+ case Error::NONE:
+ metadataDumps.push_back({metadataType, metadata});
+ break;
+ case Error::UNSUPPORTED:
+ default:
+ return;
+ }
+ });
+ }
+ return hidl_vec<IMapper::MetadataDump>(metadataDumps);
+}
+
+void dumpBuffer(void *buffer, IMapper::dumpBuffer_cb hidl_cb)
+{
+ IMapper::BufferDump bufferDump{};
+ auto handle = static_cast<const private_handle_t *>(gRegisteredHandles->get(buffer));
+ if (handle == nullptr)
+ {
+ MALI_GRALLOC_LOGE("Buffer: %p has not been registered with Gralloc", buffer);
+ hidl_cb(Error::BAD_BUFFER, bufferDump);
+ return;
+ }
+
+ bufferDump.metadataDump = dumpBufferHelper(handle);
+ hidl_cb(Error::NONE, bufferDump);
+}
+
+void dumpBuffers(IMapper::dumpBuffers_cb hidl_cb)
+{
+ std::vector<IMapper::BufferDump> bufferDumps;
+ gRegisteredHandles->for_each([&bufferDumps](buffer_handle_t buffer) {
+ IMapper::BufferDump bufferDump { dumpBufferHelper(static_cast<const private_handle_t *>(buffer)) };
+ bufferDumps.push_back(bufferDump);
+ });
+ hidl_cb(Error::NONE, hidl_vec<IMapper::BufferDump>(bufferDumps));
+}
+
+void getReservedRegion(void *buffer, IMapper::getReservedRegion_cb hidl_cb)
+{
+ auto handle = static_cast<const private_handle_t *>(gRegisteredHandles->get(buffer));
+ if (handle == nullptr)
+ {
+ MALI_GRALLOC_LOGE("Buffer: %p has not been registered with Gralloc", buffer);
+ hidl_cb(Error::BAD_BUFFER, 0, 0);
+ return;
+ }
+ else if (handle->reserved_region_size == 0)
+ {
+ MALI_GRALLOC_LOGE("Buffer: %p has no reserved region", buffer);
+ hidl_cb(Error::BAD_BUFFER, 0, 0);
+ return;
+ }
+ void *reserved_region = static_cast<std::byte *>(handle->attr_base)
+ + mapper::common::shared_metadata_size();
+ hidl_cb(Error::NONE, reserved_region, handle->reserved_region_size);
+}
+
+} // namespace common
+} // namespace mapper
+} // namespace arm
diff --git a/gralloc4/src/hidl_common/Mapper.h b/gralloc4/src/hidl_common/Mapper.h
new file mode 100644
index 0000000..6d114cc
--- /dev/null
+++ b/gralloc4/src/hidl_common/Mapper.h
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2020 ARM Limited. All rights reserved.
+ *
+ * Copyright 2016 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_COMMON_MAPPER_H
+#define GRALLOC_COMMON_MAPPER_H
+
+#include <inttypes.h>
+#include "mali_gralloc_log.h"
+#include "core/mali_gralloc_bufferdescriptor.h"
+
+#include "4.x/gralloc_mapper_hidl_header.h"
+
+namespace arm
+{
+namespace mapper
+{
+namespace common
+{
+
+using android::hardware::hidl_handle;
+using android::hardware::hidl_vec;
+using android::hardware::Void;
+
+/**
+ * Imports a raw buffer handle to create an imported buffer handle for use with
+ * the rest of the mapper or with other in-process libraries.
+ *
+ * @param rawHandle [in] Raw buffer handle to import.
+ * @param hidl_cb [in] HIDL Callback function to export output information
+ * @param hidl_cb [in] HIDL callback function generating -
+ * error : NONE upon success. Otherwise,
+ * BAD_BUFFER for an invalid buffer
+ * NO_RESOURCES when the raw handle cannot be imported
+ * BAD_VALUE when any of the specified attributes are invalid
+ * buffer : Imported buffer handle
+ */
+void importBuffer(const hidl_handle &rawHandle, IMapper::importBuffer_cb hidl_cb);
+
+/**
+ * Frees a buffer handle and releases all the resources associated with it
+ *
+ * @param buffer [in] Imported buffer to free
+ *
+ * @return Error::BAD_BUFFER for an invalid buffer / when failed to free the buffer
+ * Error::NONE on successful free
+ */
+Error freeBuffer(void *buffer);
+
+/**
+ * Locks the given buffer for the specified CPU usage.
+ *
+ * @param buffer [in] Buffer to lock
+ * @param cpuUsage [in] Specifies one or more CPU usage flags to request
+ * @param accessRegion [in] Portion of the buffer that the client intends to access
+ * @param acquireFence [in] Handle for aquire fence object
+ * @param hidl_cb [in] HIDL callback function generating -
+ * error: NONE upon success. Otherwise,
+ * BAD_BUFFER for an invalid buffer
+ * BAD_VALUE for an invalid input parameters
+ * data: CPU-accessible pointer to the buffer data
+ * bytesPerPixel: v3.X Only. Number of bytes per pixel in the buffer
+ * bytesPerStride: v3.X Only. Bytes per stride of the buffer
+ */
+void lock(void *buffer, uint64_t cpuUsage, const IMapper::Rect &accessRegion, const hidl_handle &acquireFence,
+ IMapper::lock_cb hidl_cb);
+
+/**
+ * Unlocks a buffer to indicate all CPU accesses to the buffer have completed
+ *
+ * @param buffer [in] Buffer to lock.
+ * @param hidl_cb [in] HIDL callback function generating -
+ * error: NONE upon success. Otherwise,
+ * BAD_BUFFER for an invalid buffer
+ * releaseFence: Referrs to a sync fence object
+ */
+void unlock(void *buffer, IMapper::unlock_cb hidl_cb);
+
+/**
+ * Validates the buffer against specified descriptor attributes
+ *
+ * @param buffer [in] Buffer which needs to be validated.
+ * @param descriptorInfo [in] Required attributes of the buffer
+ * @param in_stride [in] Buffer stride returned by IAllocator::allocate,
+ * or zero if unknown.
+ *
+ * @return Error::NONE upon success. Otherwise,
+ * Error::BAD_BUFFER upon bad buffer input
+ * Error::BAD_VALUE when any of the specified attributes are invalid
+ */
+Error validateBufferSize(void *buffer, const IMapper::BufferDescriptorInfo &descriptorInfo, uint32_t stride);
+
+/**
+ * Get the transport size of a buffer
+ *
+ * @param buffer [in] Buffer for computing transport size
+ * @param hidl_cb [in] HIDL callback function generating -
+ * error: NONE upon success. Otherwise,
+ * BAD_BUFFER for an invalid buffer
+ * numFds: Number of file descriptors needed for transport
+ * numInts: Number of integers needed for transport
+ */
+void getTransportSize(void *buffer, IMapper::getTransportSize_cb hidl_cb);
+
+/**
+ * Test whether the given BufferDescriptorInfo is allocatable.
+ *
+ * @param description [in] Description for the buffer
+ * @param hidl_cb [in] HIDL callback function generating -
+ * error: NONE, for supported description
+ * BAD_VALUE, Otherwise,
+ * supported: Whether the description can be allocated
+ */
+void isSupported(const IMapper::BufferDescriptorInfo &description, IMapper::isSupported_cb hidl_cb);
+
+/* TODO: implement this feature for exynos */
+/**
+ * Flushes the CPU caches of a mapped buffer.
+ *
+ * @param buffer [in] Locked buffer which needs to have CPU caches flushed.
+ * @param hidl_cb [in] HIDL callback function generating -
+ * error: NONE upon success. Otherwise, BAD_BUFFER for an invalid buffer or a buffer that
+ * has not been locked.
+ * releaseFence: Empty fence signaling completion as all work is completed within the call.
+ */
+void flushLockedBuffer(void *buffer, IMapper::flushLockedBuffer_cb hidl_cb);
+
+/* TODO: implement this feature for exynos */
+/**
+ * Invalidates the CPU caches of a mapped buffer.
+ *
+ * @param buffer [in] Locked buffer which needs to have CPU caches invalidated.
+ *
+ * @return Error::NONE upon success.
+ * Error::BAD_BUFFER for an invalid buffer or a buffer that has not been locked.
+ */
+Error rereadLockedBuffer(void *buffer);
+
+/**
+ * Retrieves a Buffer's metadata value.
+ *
+ * @param buffer [in] The buffer to query for metadata.
+ * @param metadataType [in] The type of metadata queried.
+ * @param hidl_cb [in] HIDL callback function generating -
+ * error: NONE on success.
+ * BAD_BUFFER on invalid buffer argument.
+ * UNSUPPORTED on error when reading or unsupported metadata type.
+ * metadata: Vector of bytes representing the metadata value.
+ */
+void get(void *buffer, const IMapper::MetadataType &metadataType, IMapper::get_cb hidl_cb);
+
+/**
+ * Sets a Buffer's metadata value.
+ *
+ * @param buffer [in] The buffer for which to modify metadata.
+ * @param metadataType [in] The type of metadata to modify.
+ * @param metadata [in] Vector of bytes representing the new value for the metadata associated with the buffer.
+ *
+ * @return Error::NONE on success.
+ * Error::BAD_BUFFER on invalid buffer argument.
+ * Error::UNSUPPORTED on error when writing or unsupported metadata type.
+ */
+Error set(void *buffer, const IMapper::MetadataType &metadataType, const hidl_vec<uint8_t> &metadata);
+
+/**
+ * Lists all the MetadataTypes supported by IMapper as well as a description
+ * of each supported MetadataType. For StandardMetadataTypes, the description
+ * string can be left empty.
+ *
+ * @param hidl_cb [in] HIDL callback function generating -
+ * error: Error status of the call, which may be
+ * - NONE upon success.
+ * - NO_RESOURCES if the get cannot be fullfilled due to unavailability of
+ * resources.
+ * descriptions: vector of MetadataTypeDescriptions that represent the
+ * MetadataTypes supported by the device.
+ */
+void listSupportedMetadataTypes(IMapper::listSupportedMetadataTypes_cb hidl_cb);
+
+/**
+ * Dumps a buffer's metadata.
+ *
+ * @param buffer [in] Buffer that is being dumped
+ * @param hidl_cb [in] HIDL callback function generating -
+ * error: Error status of the call, which may be
+ * - NONE upon success.
+ * - BAD_BUFFER if the raw handle is invalid.
+ * - NO_RESOURCES if the get cannot be fullfilled due to unavailability of
+ * resources.
+ * bufferDump: Struct representing the metadata being dumped
+ */
+void dumpBuffer(void *buffer, IMapper::dumpBuffer_cb hidl_cb);
+
+/**
+ * Dumps the metadata for all the buffers in the current process.
+ *
+ * @param hidl_cb [in] HIDL callback function generating -
+ * error: Error status of the call, which may be
+ * - NONE upon success.
+ * - NO_RESOURCES if the get cannot be fullfilled due to unavailability of
+ * resources.
+ * bufferDumps: Vector of structs representing the buffers being dumped
+ */
+void dumpBuffers(IMapper::dumpBuffers_cb hidl_cb);
+
+/**
+ * Returns the region of shared memory associated with the buffer that is
+ * reserved for client use.
+ *
+ * The shared memory may be allocated from any shared memory allocator.
+ * The shared memory must be CPU-accessible and virtually contiguous. The
+ * starting address must be word-aligned.
+ *
+ * This function may only be called after importBuffer() has been called by the
+ * client. The reserved region must remain accessible until freeBuffer() has
+ * been called. After freeBuffer() has been called, the client must not access
+ * the reserved region.
+ *
+ * This reserved memory may be used in future versions of Android to
+ * help clients implement backwards compatible features without requiring
+ * IAllocator/IMapper updates.
+ *
+ * @param buffer Imported buffer handle.
+ * @param hidl_cb [in] HIDL callback function generating -
+ * error: Error status of the call, which may be
+ * - NONE upon success.
+ * - BAD_BUFFER if the buffer is invalid.
+ * reservedRegion: CPU-accessible pointer to the reserved region
+ * reservedSize: the size of the reservedRegion that was requested
+ * in the BufferDescriptorInfo.
+ */
+void getReservedRegion(void *buffer, IMapper::getReservedRegion_cb _hidl_cb);
+
+} // namespace common
+} // namespace mapper
+} // namespace arm
+
+#endif /* GRALLOC_COMMON_MAPPER_H */
diff --git a/gralloc4/src/hidl_common/MapperMetadata.cpp b/gralloc4/src/hidl_common/MapperMetadata.cpp
new file mode 100644
index 0000000..3508b6b
--- /dev/null
+++ b/gralloc4/src/hidl_common/MapperMetadata.cpp
@@ -0,0 +1,931 @@
+/*
+ * Copyright (C) 2020 Arm Limited.
+ *
+ * Copyright 2016 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 "MapperMetadata.h"
+#include "SharedMetadata.h"
+#include "core/format_info.h"
+#include "core/mali_gralloc_bufferallocation.h"
+#include "mali_gralloc_buffer.h"
+#include "mali_gralloc_log.h"
+#include "drmutils.h"
+#include "gralloctypes/Gralloc4.h"
+
+#include "exynos_format.h"
+#include "mali_gralloc_formats.h"
+
+#if 0
+#include "aidl/arm/graphics/ArmMetadataType.h"
+#endif
+#include <vector>
+
+namespace arm
+{
+namespace mapper
+{
+namespace common
+{
+
+using aidl::android::hardware::graphics::common::PlaneLayout;
+using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
+using aidl::android::hardware::graphics::common::Rect;
+using aidl::android::hardware::graphics::common::Dataspace;
+using aidl::android::hardware::graphics::common::BlendMode;
+using aidl::android::hardware::graphics::common::StandardMetadataType;
+using aidl::android::hardware::graphics::common::XyColor;
+using aidl::android::hardware::graphics::common::Smpte2086;
+using aidl::android::hardware::graphics::common::Cta861_3;
+#if 0
+using aidl::arm::graphics::ArmMetadataType;
+#endif
+
+using MetadataType = android::hardware::graphics::mapper::V4_0::IMapper::MetadataType;
+
+static int get_num_planes(const private_handle_t *hnd)
+{
+ if (is_exynos_format(hnd->get_alloc_format()))
+ {
+ switch (hnd->get_alloc_format())
+ {
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ case HAL_PIXEL_FORMAT_EXYNOS_YV12_M:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_P_M:
+ return 3;
+
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_TILED:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_FULL:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_S10B:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_S10B:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_P010_M:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_SBWC:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCrCb_420_SP_M_10B_SBWC:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L50:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_SBWC_L75:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L50:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_SBWC_L75:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L40:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L60:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SP_M_10B_SBWC_L80:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L40:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L60:
+ case HAL_PIXEL_FORMAT_EXYNOS_YCbCr_420_SPN_10B_SBWC_L80:
+ return 2;
+ }
+ }
+
+ return hnd->is_multi_plane() ? (hnd->plane_info[2].offset == 0 ? 2 : 3) : 1;
+}
+
+static std::vector<std::vector<PlaneLayoutComponent>> plane_layout_components_from_handle(const private_handle_t *hnd)
+{
+ /* Re-define the component constants to make the table easier to read. */
+ const ExtendableType R = android::gralloc4::PlaneLayoutComponentType_R;
+ const ExtendableType G = android::gralloc4::PlaneLayoutComponentType_G;
+ const ExtendableType B = android::gralloc4::PlaneLayoutComponentType_B;
+ const ExtendableType A = android::gralloc4::PlaneLayoutComponentType_A;
+ const ExtendableType CB = android::gralloc4::PlaneLayoutComponentType_CB;
+ const ExtendableType CR = android::gralloc4::PlaneLayoutComponentType_CR;
+ const ExtendableType Y = android::gralloc4::PlaneLayoutComponentType_Y;
+ const ExtendableType RAW = android::gralloc4::PlaneLayoutComponentType_RAW;
+
+ struct table_entry
+ {
+ uint32_t drm_fourcc;
+ std::vector<std::vector<PlaneLayoutComponent>> components;
+ };
+
+ /* clang-format off */
+ static table_entry table[] = {
+ /* 16 bit RGB(A) */
+ {
+ .drm_fourcc = DRM_FORMAT_RGB565,
+ .components = { { { B, 0, 5 }, { G, 5, 6 }, { R, 11, 5 } } }
+ },
+ {
+ .drm_fourcc = DRM_FORMAT_BGR565,
+ .components = { { { R, 0, 5 }, { G, 5, 6 }, { B, 11, 5 } } }
+ },
+ /* 24 bit RGB(A) */
+ {
+ .drm_fourcc = DRM_FORMAT_BGR888,
+ .components = { { { R, 0, 8 }, { G, 8, 8 }, { B, 16, 8 } } }
+ },
+ /* 32 bit RGB(A) */
+ {
+ .drm_fourcc = DRM_FORMAT_ARGB8888,
+ .components = { { { B, 0, 8 }, { G, 8, 8 }, { R, 16, 8 }, { A, 24, 8 } } }
+ },
+ {
+ .drm_fourcc = DRM_FORMAT_ABGR8888,
+ .components = { { { R, 0, 8 }, { G, 8, 8 }, { B, 16, 8 }, { A, 24, 8 } } }
+ },
+ {
+ .drm_fourcc = DRM_FORMAT_XBGR8888,
+ .components = { { { R, 0, 8 }, { G, 8, 8 }, { B, 16, 8 } } }
+ },
+ {
+ .drm_fourcc = DRM_FORMAT_ABGR2101010,
+ .components = { { { R, 0, 10 }, { G, 10, 10 }, { B, 20, 10 }, { A, 30, 2 } } }
+ },
+ /* 64 bit RGB(A) */
+ {
+ .drm_fourcc = DRM_FORMAT_ABGR16161616F,
+ .components = { { { R, 0, 16 }, { G, 16, 16 }, { B, 32, 16 }, { A, 48, 16 } } }
+ },
+ /* Single plane 8 bit YUV 4:2:2 */
+ {
+ .drm_fourcc = DRM_FORMAT_YUYV,
+ .components = { { { Y, 0, 8 }, { CB, 8, 8 }, { Y, 16, 8 }, { CR, 24, 8 } } }
+ },
+ /* Single plane 10 bit YUV 4:4:4 */
+ {
+ .drm_fourcc = DRM_FORMAT_Y410,
+ .components = { { { CB, 0, 10 }, { Y, 10, 10 }, { CR, 20, 10 }, { A, 30, 2 } } }
+ },
+ /* Single plane 10 bit YUV 4:2:2 */
+ {
+ .drm_fourcc = DRM_FORMAT_Y210,
+ .components = { { { Y, 6, 10 }, { CB, 22, 10 }, { Y, 38, 10 }, { CR, 54, 10 } } }
+ },
+ /* Single plane 10 bit YUV 4:2:0 */
+ {
+ .drm_fourcc = DRM_FORMAT_Y0L2,
+ .components = { {
+ { Y, 0, 10 }, { CB, 10, 10 }, { Y, 20, 10 }, { A, 30, 1 }, { A, 31, 1 },
+ { Y, 32, 10 }, { CR, 42, 10 }, { Y, 52, 10 }, { A, 62, 1 }, { A, 63, 1 }
+ } }
+ },
+ /* Semi-planar 8 bit YUV 4:2:2 */
+ {
+ .drm_fourcc = DRM_FORMAT_NV16,
+ .components = {
+ { { Y, 0, 8 } },
+ { { CB, 0, 8 }, { CR, 8, 8 } }
+ }
+ },
+ /* Semi-planar 8 bit YUV 4:2:0 */
+ {
+ .drm_fourcc = DRM_FORMAT_NV12,
+ .components = {
+ { { Y, 0, 8 } },
+ { { CB, 0, 8 }, { CR, 8, 8 } }
+ }
+ },
+ {
+ .drm_fourcc = DRM_FORMAT_NV21,
+ .components = {
+ { { Y, 0, 8 } },
+ { { CR, 0, 8 }, { CB, 8, 8 } }
+ }
+ },
+ /* Semi-planar 10 bit YUV 4:2:2 */
+ {
+ .drm_fourcc = DRM_FORMAT_P210,
+ .components = {
+ { { Y, 6, 10 } },
+ { { CB, 6, 10 }, { CB, 22, 10 } }
+ }
+ },
+ /* Semi-planar 10 bit YUV 4:2:0 */
+ {
+ .drm_fourcc = DRM_FORMAT_P010,
+ .components = {
+ { { Y, 0, 8 } },
+ { { CB, 0, 8 }, { CR, 16, 8 } }
+ }
+ },
+ /* Planar 8 bit YUV 4:2:0 */
+ {
+ .drm_fourcc = DRM_FORMAT_YVU420,
+ .components = {
+ { { Y, 0, 8 } },
+ { { CR, 0, 8 } },
+ { { CB, 0, 8 } }
+ }
+ },
+ /* Planar 8 bit YUV 4:4:4 */
+ {
+ .drm_fourcc = DRM_FORMAT_YUV444,
+ .components = {
+ { { Y, 0, 8 } },
+ { { CB, 0, 8 } },
+ { { CR, 0, 8 } }
+ }
+ },
+
+ /* AFBC Only FourCC */
+ {.drm_fourcc = DRM_FORMAT_YUV420_8BIT, .components = { {} } },
+ {.drm_fourcc = DRM_FORMAT_YUV420_10BIT, .components = { {} } },
+ };
+ /* clang-format on */
+
+ const uint32_t drm_fourcc = drm_fourcc_from_handle(hnd);
+ if (drm_fourcc != DRM_FORMAT_INVALID)
+ {
+ for (const auto& entry : table)
+ {
+ if (entry.drm_fourcc == drm_fourcc)
+ {
+ return entry.components;
+ }
+ }
+ }
+
+ switch (hnd->get_alloc_format())
+ {
+ case HAL_PIXEL_FORMAT_RAW10:
+ return {{{RAW, 0, -1}}};
+ case HAL_PIXEL_FORMAT_RAW12:
+ return {{{RAW, 0, -1}}};
+ case HAL_PIXEL_FORMAT_BLOB:
+ break;
+ default:
+ MALI_GRALLOC_LOGW("Could not find component description for Format(%#x) FourCC value(%#x)",
+ hnd->get_alloc_format(), drm_fourcc);
+ }
+
+ return std::vector<std::vector<PlaneLayoutComponent>>(0);
+}
+
+static android::status_t get_plane_layouts(const private_handle_t *handle, std::vector<PlaneLayout> *layouts)
+{
+ const int num_planes = get_num_planes(handle);
+ int32_t format_index = get_format_index(handle->alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK);
+ if (format_index < 0)
+ {
+ MALI_GRALLOC_LOGE("Negative format index in get_plane_layouts");
+ return android::BAD_VALUE;
+ }
+ const format_info_t format_info = formats[format_index];
+ layouts->reserve(num_planes);
+
+ if (is_exynos_format(handle->get_alloc_format()))
+ {
+ std::vector<std::vector<PlaneLayoutComponent>> components = plane_layout_components_from_handle(handle);
+ for (size_t plane_index = 0; plane_index < num_planes; ++plane_index)
+ {
+ int64_t plane_size = handle->plane_info[plane_index].size;
+ int64_t sample_increment_in_bits = format_info.bpp[plane_index];
+ int64_t offset = handle->plane_info[plane_index].offset;
+
+ if (handle->plane_info[plane_index].fd_idx == plane_index)
+ {
+ offset = (int64_t)handle->bases[plane_index] - handle->bases[0];
+ }
+
+ /* sample increments in bits must be 8 for y plane for lock */
+ if (plane_index == 0)
+ {
+ sample_increment_in_bits = 8;
+ }
+ /* sample increments in bits must be 8 or 16 for cb/cr plane for lock */
+ else if (sample_increment_in_bits > 16)
+ {
+ sample_increment_in_bits = 16;
+ }
+
+ PlaneLayout layout = {.offsetInBytes = offset,
+ .sampleIncrementInBits = sample_increment_in_bits,
+ .strideInBytes = handle->plane_info[plane_index].byte_stride,
+ .widthInSamples = handle->plane_info[plane_index].alloc_width,
+ .heightInSamples = handle->plane_info[plane_index].alloc_height,
+ .totalSizeInBytes = plane_size,
+ .horizontalSubsampling = (plane_index == 0 ? 1 : format_info.hsub),
+ .verticalSubsampling = (plane_index == 0 ? 1 : format_info.vsub),
+ .components = components.size() > plane_index ? components[plane_index] :
+ std::vector<PlaneLayoutComponent>(0) };
+ layouts->push_back(layout);
+ }
+ }
+ else
+ {
+ std::vector<std::vector<PlaneLayoutComponent>> components = plane_layout_components_from_handle(handle);
+ for (size_t plane_index = 0; plane_index < num_planes; ++plane_index)
+ {
+ int64_t plane_size;
+ if (plane_index < num_planes - 1)
+ {
+ plane_size = handle->plane_info[plane_index + 1].offset;
+ }
+ else
+ {
+ int64_t layer_size = handle->alloc_sizes[0] / handle->layer_count;
+ plane_size = layer_size - handle->plane_info[plane_index].offset;
+ }
+
+ if (handle->fd_count > 1 && handle->plane_info[plane_index].fd_idx == plane_index)
+ {
+ plane_size = handle->plane_info[plane_index].size;
+ }
+
+ int64_t sample_increment_in_bits = 0;
+ if (handle->alloc_format & MALI_GRALLOC_INTFMT_AFBC_BASIC)
+ {
+ sample_increment_in_bits = format_info.bpp_afbc[plane_index];
+ }
+ else
+ {
+ sample_increment_in_bits = format_info.bpp[plane_index];
+ }
+
+ switch (handle->get_alloc_format())
+ {
+ case HAL_PIXEL_FORMAT_RAW10:
+ case HAL_PIXEL_FORMAT_RAW12:
+ sample_increment_in_bits = 0;
+ break;
+ default:
+ break;
+ }
+
+ PlaneLayout layout = {.offsetInBytes = handle->plane_info[plane_index].offset,
+ .sampleIncrementInBits = sample_increment_in_bits,
+ .strideInBytes = handle->plane_info[plane_index].byte_stride,
+ .widthInSamples = handle->plane_info[plane_index].alloc_width,
+ .heightInSamples = handle->plane_info[plane_index].alloc_height,
+ .totalSizeInBytes = plane_size,
+ .horizontalSubsampling = (plane_index == 0 ? 1 : format_info.hsub),
+ .verticalSubsampling = (plane_index == 0 ? 1 : format_info.vsub),
+ .components = components.size() > plane_index ? components[plane_index] :
+ std::vector<PlaneLayoutComponent>(0) };
+ layouts->push_back(layout);
+ }
+ }
+
+ return android::OK;
+}
+
+#if 0
+static android::status_t get_plane_fds(const private_handle_t *hnd, std::vector<int64_t> *fds)
+{
+ const int num_planes = get_num_planes(hnd);
+
+ fds->resize(num_planes, static_cast<int64_t>(hnd->share_fd));
+
+ return android::OK;
+}
+
+/* Encode the number of fds as an int64_t followed by the int64_t fds themselves */
+static android::status_t encodeArmPlaneFds(const std::vector<int64_t>& fds, hidl_vec<uint8_t>* output)
+{
+ int64_t n_fds = fds.size();
+
+ output->resize((n_fds + 1) * sizeof(int64_t));
+
+ memcpy(output->data(), &n_fds, sizeof(n_fds));
+ memcpy(output->data() + sizeof(n_fds), fds.data(), sizeof(int64_t) * n_fds);
+
+ return android::OK;
+}
+
+/* TODO GPUCORE-22819 Move to test code */
+android::status_t decodeArmPlaneFds(hidl_vec<uint8_t>& input, std::vector<int64_t>* fds)
+{
+ int64_t size = 0;
+
+ memcpy(input.data(), &size, sizeof(int64_t));
+ if (size < 0)
+ {
+ return android::BAD_VALUE;
+ }
+
+ fds->resize(size);
+
+ uint8_t *tmp = input.data() + sizeof(int64_t);
+ memcpy(fds->data(), tmp, sizeof(int64_t) * size);
+
+ return android::OK;
+}
+
+static bool isArmMetadataType(const MetadataType& metadataType)
+{
+ return metadataType.name == GRALLOC_ARM_METADATA_TYPE_NAME;
+}
+
+static ArmMetadataType getArmMetadataTypeValue(const MetadataType& metadataType) {
+ return static_cast<ArmMetadataType>(metadataType.value);
+}
+#endif
+
+void get_metadata(const private_handle_t *handle, const IMapper::MetadataType &metadataType, IMapper::get_cb hidl_cb)
+{
+ /* This will hold the metadata that is returned. */
+ hidl_vec<uint8_t> vec;
+
+ if (android::gralloc4::isStandardMetadataType(metadataType))
+ {
+ android::status_t err = android::OK;
+
+ switch (android::gralloc4::getStandardMetadataTypeValue(metadataType))
+ {
+ case StandardMetadataType::BUFFER_ID:
+ err = android::gralloc4::encodeBufferId(handle->backing_store_id, &vec);
+ break;
+ case StandardMetadataType::NAME:
+ {
+ std::string name;
+ get_name(handle, &name);
+ err = android::gralloc4::encodeName(name, &vec);
+ break;
+ }
+ case StandardMetadataType::WIDTH:
+ err = android::gralloc4::encodeWidth(handle->width, &vec);
+ break;
+ case StandardMetadataType::HEIGHT:
+ err = android::gralloc4::encodeHeight(handle->height, &vec);
+ break;
+ case StandardMetadataType::LAYER_COUNT:
+ err = android::gralloc4::encodeLayerCount(handle->layer_count, &vec);
+ break;
+ case StandardMetadataType::PIXEL_FORMAT_REQUESTED:
+ err = android::gralloc4::encodePixelFormatRequested(static_cast<PixelFormat>(handle->req_format), &vec);
+ break;
+ case StandardMetadataType::PIXEL_FORMAT_FOURCC:
+ err = android::gralloc4::encodePixelFormatFourCC(drm_fourcc_from_handle(handle), &vec);
+ break;
+ case StandardMetadataType::PIXEL_FORMAT_MODIFIER:
+ err = android::gralloc4::encodePixelFormatModifier(drm_modifier_from_handle(handle), &vec);
+ break;
+ case StandardMetadataType::USAGE:
+ err = android::gralloc4::encodeUsage(handle->consumer_usage | handle->producer_usage, &vec);
+ break;
+ case StandardMetadataType::ALLOCATION_SIZE:
+ {
+ uint64_t total_size = 0;
+ for (int fidx = 0; fidx < handle->fd_count; fidx++)
+ {
+ total_size += handle->alloc_sizes[fidx];
+ }
+ err = android::gralloc4::encodeAllocationSize(total_size, &vec);
+ break;
+ }
+ case StandardMetadataType::PROTECTED_CONTENT:
+ {
+ /* This is set to 1 if the buffer has protected content. */
+ const int is_protected =
+ (((handle->consumer_usage | handle->producer_usage) & BufferUsage::PROTECTED) == 0) ? 0 : 1;
+ err = android::gralloc4::encodeProtectedContent(is_protected, &vec);
+ break;
+ }
+ case StandardMetadataType::COMPRESSION:
+ {
+ ExtendableType compression;
+ if (handle->alloc_format & MALI_GRALLOC_INTFMT_AFBC_BASIC)
+ {
+ compression = Compression_AFBC;
+ }
+ else
+ {
+ compression = android::gralloc4::Compression_None;
+ }
+ err = android::gralloc4::encodeCompression(compression, &vec);
+ break;
+ }
+ case StandardMetadataType::INTERLACED:
+ err = android::gralloc4::encodeInterlaced(android::gralloc4::Interlaced_None, &vec);
+ break;
+ case StandardMetadataType::CHROMA_SITING:
+ {
+ int format_index = get_format_index(handle->alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK);
+ if (format_index < 0)
+ {
+ err = android::BAD_VALUE;
+ break;
+ }
+ ExtendableType siting = android::gralloc4::ChromaSiting_None;
+ if (formats[format_index].is_yuv)
+ {
+ siting = android::gralloc4::ChromaSiting_Unknown;
+ }
+ err = android::gralloc4::encodeChromaSiting(siting, &vec);
+ break;
+ }
+ case StandardMetadataType::PLANE_LAYOUTS:
+ {
+ std::vector<PlaneLayout> layouts;
+ err = get_plane_layouts(handle, &layouts);
+ if (!err)
+ {
+ err = android::gralloc4::encodePlaneLayouts(layouts, &vec);
+ }
+ break;
+ }
+ case StandardMetadataType::DATASPACE:
+ {
+ std::optional<Dataspace> dataspace;
+ get_dataspace(handle, &dataspace);
+ err = android::gralloc4::encodeDataspace(dataspace.value_or(Dataspace::UNKNOWN), &vec);
+ break;
+ }
+ case StandardMetadataType::BLEND_MODE:
+ {
+ std::optional<BlendMode> blend_mode;
+ get_blend_mode(handle, &blend_mode);
+ err = android::gralloc4::encodeBlendMode(blend_mode.value_or(BlendMode::INVALID), &vec);
+ break;
+ }
+ case StandardMetadataType::CROP:
+ {
+ const int num_planes = get_num_planes(handle);
+ std::vector<Rect> crops(num_planes);
+ for (size_t plane_index = 0; plane_index < num_planes; ++plane_index)
+ {
+ /* Set the default crop rectangle. Android mandates that it must fit [0, 0, widthInSamples, heightInSamples]
+ * We always require using the requested width and height for the crop rectangle size.
+ * For planes > 0 the size might need to be scaled, but since we only use plane[0] for crop set it to the
+ * Android default of [0, 0, widthInSamples, heightInSamples] for other planes.
+ */
+ Rect rect = {.top = 0,
+ .left = 0,
+ .right = static_cast<int32_t>(handle->plane_info[plane_index].alloc_width),
+ .bottom = static_cast<int32_t>(handle->plane_info[plane_index].alloc_height) };
+ if (plane_index == 0)
+ {
+ std::optional<Rect> crop_rect;
+ get_crop_rect(handle, &crop_rect);
+ if (crop_rect.has_value())
+ {
+ rect = crop_rect.value();
+ }
+ else
+ {
+ rect = {.top = 0, .left = 0, .right = handle->width, .bottom = handle->height };
+ }
+ }
+ crops[plane_index] = rect;
+ }
+ err = android::gralloc4::encodeCrop(crops, &vec);
+ break;
+ }
+ case StandardMetadataType::SMPTE2086:
+ {
+ std::optional<Smpte2086> smpte2086;
+ get_smpte2086(handle, &smpte2086);
+ err = android::gralloc4::encodeSmpte2086(smpte2086, &vec);
+ break;
+ }
+ case StandardMetadataType::CTA861_3:
+ {
+ std::optional<Cta861_3> cta861_3;
+ get_cta861_3(handle, &cta861_3);
+ err = android::gralloc4::encodeCta861_3(cta861_3, &vec);
+ break;
+ }
+ case StandardMetadataType::SMPTE2094_40:
+ {
+ std::optional<std::vector<uint8_t>> smpte2094_40;
+ get_smpte2094_40(handle, &smpte2094_40);
+ err = android::gralloc4::encodeSmpte2094_40(smpte2094_40, &vec);
+ break;
+ }
+ case StandardMetadataType::INVALID:
+ default:
+ err = android::BAD_VALUE;
+ }
+ hidl_cb((err) ? Error::UNSUPPORTED : Error::NONE, vec);
+ }
+ /* TODO: either remove or add support for get_plane_fds */
+#if 0
+ else if (isArmMetadataType(metadataType))
+ {
+ android::status_t err = android::OK;
+
+ switch (getArmMetadataTypeValue(metadataType))
+ {
+ case ArmMetadataType::PLANE_FDS:
+ {
+ std::vector<int64_t> fds;
+
+ err = get_plane_fds(handle, &fds);
+ if (!err)
+ {
+ err = encodeArmPlaneFds(fds, &vec);
+ }
+ break;
+ }
+ default:
+ err = android::BAD_VALUE;
+ }
+ hidl_cb((err) ? Error::UNSUPPORTED : Error::NONE, vec);
+ }
+#endif
+ else
+ {
+ /* If known vendor type, return it */
+ hidl_cb(Error::UNSUPPORTED, vec);
+ }
+}
+
+Error set_metadata(const private_handle_t *handle, const IMapper::MetadataType &metadataType,
+ const hidl_vec<uint8_t> &metadata)
+{
+ if (android::gralloc4::isStandardMetadataType(metadataType))
+ {
+ android::status_t err = android::OK;
+ switch (android::gralloc4::getStandardMetadataTypeValue(metadataType))
+ {
+ case StandardMetadataType::DATASPACE:
+ {
+ Dataspace dataspace;
+ err = android::gralloc4::decodeDataspace(metadata, &dataspace);
+ if (!err)
+ {
+ set_dataspace(handle, dataspace);
+ }
+ break;
+ }
+ case StandardMetadataType::BLEND_MODE:
+ {
+ BlendMode blend_mode;
+ err = android::gralloc4::decodeBlendMode(metadata, &blend_mode);
+ if (!err)
+ {
+ set_blend_mode(handle, blend_mode);
+ }
+ break;
+ }
+ case StandardMetadataType::SMPTE2086:
+ {
+ std::optional<Smpte2086> smpte2086;
+ err = android::gralloc4::decodeSmpte2086(metadata, &smpte2086);
+ if (!err)
+ {
+ err = set_smpte2086(handle, smpte2086);
+ }
+ break;
+ }
+ case StandardMetadataType::CTA861_3:
+ {
+ std::optional<Cta861_3> cta861_3;
+ err = android::gralloc4::decodeCta861_3(metadata, &cta861_3);
+ if (!err)
+ {
+ err = set_cta861_3(handle, cta861_3);
+ }
+ break;
+ }
+ case StandardMetadataType::SMPTE2094_40:
+ {
+ std::optional<std::vector<uint8_t>> smpte2094_40;
+ err = android::gralloc4::decodeSmpte2094_40(metadata, &smpte2094_40);
+ if (!err)
+ {
+ err = set_smpte2094_40(handle, smpte2094_40);
+ }
+ break;
+ }
+ case StandardMetadataType::CROP:
+ {
+ std::vector<Rect> crops;
+ err = android::gralloc4::decodeCrop(metadata, &crops);
+ if (!err)
+ {
+ err = set_crop_rect(handle, crops[0]);
+ }
+ break;
+ }
+ /* The following meta data types cannot be changed after allocation. */
+ case StandardMetadataType::BUFFER_ID:
+ case StandardMetadataType::NAME:
+ case StandardMetadataType::WIDTH:
+ case StandardMetadataType::HEIGHT:
+ case StandardMetadataType::LAYER_COUNT:
+ case StandardMetadataType::PIXEL_FORMAT_REQUESTED:
+ case StandardMetadataType::USAGE:
+ return Error::BAD_VALUE;
+ /* Changing other metadata types is unsupported. */
+ case StandardMetadataType::PLANE_LAYOUTS:
+ case StandardMetadataType::PIXEL_FORMAT_FOURCC:
+ case StandardMetadataType::PIXEL_FORMAT_MODIFIER:
+ case StandardMetadataType::ALLOCATION_SIZE:
+ case StandardMetadataType::PROTECTED_CONTENT:
+ case StandardMetadataType::COMPRESSION:
+ case StandardMetadataType::INTERLACED:
+ case StandardMetadataType::CHROMA_SITING:
+ case StandardMetadataType::INVALID:
+ default:
+ return Error::UNSUPPORTED;
+ }
+ return ((err) ? Error::UNSUPPORTED : Error::NONE);
+ }
+ else
+ {
+ /* None of the vendor types support set. */
+ return Error::UNSUPPORTED;
+ }
+}
+
+void getFromBufferDescriptorInfo(IMapper::BufferDescriptorInfo const &description,
+ IMapper::MetadataType const &metadataType,
+ IMapper::getFromBufferDescriptorInfo_cb hidl_cb)
+{
+ /* This will hold the metadata that is returned. */
+ hidl_vec<uint8_t> vec;
+
+ buffer_descriptor_t descriptor;
+ descriptor.width = description.width;
+ descriptor.height = description.height;
+ descriptor.layer_count = description.layerCount;
+ descriptor.hal_format = static_cast<uint64_t>(description.format);
+ descriptor.producer_usage = static_cast<uint64_t>(description.usage);
+ descriptor.consumer_usage = descriptor.producer_usage;
+ descriptor.format_type = MALI_GRALLOC_FORMAT_TYPE_USAGE;
+
+ /* Check if it is possible to allocate a buffer for the given description */
+ const int alloc_result = mali_gralloc_derive_format_and_size(&descriptor);
+ if (alloc_result != 0)
+ {
+ MALI_GRALLOC_LOGV("Allocation for the given description will not succeed. error: %d", alloc_result);
+ hidl_cb(Error::BAD_VALUE, vec);
+ return;
+ }
+ /* Create buffer handle from the initialized descriptor without a backing store or shared metadata region.
+ * Used to share functionality with the normal metadata get function that can only use the allocated buffer handle
+ * and does not have the buffer descriptor available. */
+ private_handle_t partial_handle(0, descriptor.alloc_sizes, descriptor.consumer_usage, descriptor.producer_usage,
+ nullptr, descriptor.fd_count,
+ descriptor.hal_format, descriptor.alloc_format,
+ descriptor.width, descriptor.height, descriptor.pixel_stride,
+ descriptor.layer_count, descriptor.plane_info);
+ if (android::gralloc4::isStandardMetadataType(metadataType))
+ {
+ android::status_t err = android::OK;
+
+ switch (android::gralloc4::getStandardMetadataTypeValue(metadataType))
+ {
+ case StandardMetadataType::NAME:
+ err = android::gralloc4::encodeName(description.name, &vec);
+ break;
+ case StandardMetadataType::WIDTH:
+ err = android::gralloc4::encodeWidth(description.width, &vec);
+ break;
+ case StandardMetadataType::HEIGHT:
+ err = android::gralloc4::encodeHeight(description.height, &vec);
+ break;
+ case StandardMetadataType::LAYER_COUNT:
+ err = android::gralloc4::encodeLayerCount(description.layerCount, &vec);
+ break;
+ case StandardMetadataType::PIXEL_FORMAT_REQUESTED:
+ err = android::gralloc4::encodePixelFormatRequested(static_cast<PixelFormat>(description.format), &vec);
+ break;
+ case StandardMetadataType::USAGE:
+ err = android::gralloc4::encodeUsage(description.usage, &vec);
+ break;
+ case StandardMetadataType::PIXEL_FORMAT_FOURCC:
+ err = android::gralloc4::encodePixelFormatFourCC(drm_fourcc_from_handle(&partial_handle), &vec);
+ break;
+ case StandardMetadataType::PIXEL_FORMAT_MODIFIER:
+ err = android::gralloc4::encodePixelFormatModifier(drm_modifier_from_handle(&partial_handle), &vec);
+ break;
+ case StandardMetadataType::ALLOCATION_SIZE:
+ {
+ /* TODO: Returns expetected size if the buffer was actually allocated.
+ * Is this the right behavior?
+ */
+ uint64_t total_size = 0;
+ for (int fidx = 0; fidx < descriptor.fd_count; fidx++)
+ {
+ total_size += descriptor.alloc_sizes[fidx];
+ }
+ err = android::gralloc4::encodeAllocationSize(total_size, &vec);
+ break;
+ }
+ case StandardMetadataType::PROTECTED_CONTENT:
+ {
+ /* This is set to 1 if the buffer has protected content. */
+ const int is_protected =
+ (((partial_handle.consumer_usage | partial_handle.producer_usage) & BufferUsage::PROTECTED)) ? 1 : 0;
+ err = android::gralloc4::encodeProtectedContent(is_protected, &vec);
+ break;
+ }
+ case StandardMetadataType::COMPRESSION:
+ {
+ ExtendableType compression;
+ if (partial_handle.alloc_format & MALI_GRALLOC_INTFMT_AFBC_BASIC)
+ {
+ compression = Compression_AFBC;
+ }
+ else
+ {
+ compression = android::gralloc4::Compression_None;
+ }
+ err = android::gralloc4::encodeCompression(compression, &vec);
+ break;
+ }
+ case StandardMetadataType::INTERLACED:
+ err = android::gralloc4::encodeInterlaced(android::gralloc4::Interlaced_None, &vec);
+ break;
+ case StandardMetadataType::CHROMA_SITING:
+ {
+ int format_index = get_format_index(partial_handle.alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK);
+ if (format_index < 0)
+ {
+ err = android::BAD_VALUE;
+ break;
+ }
+ ExtendableType siting = android::gralloc4::ChromaSiting_None;
+ if (formats[format_index].is_yuv)
+ {
+ siting = android::gralloc4::ChromaSiting_Unknown;
+ }
+ err = android::gralloc4::encodeChromaSiting(siting, &vec);
+ break;
+ }
+ case StandardMetadataType::PLANE_LAYOUTS:
+ {
+ std::vector<PlaneLayout> layouts;
+ err = get_plane_layouts(&partial_handle, &layouts);
+ if (!err)
+ {
+ err = android::gralloc4::encodePlaneLayouts(layouts, &vec);
+ }
+ break;
+ }
+ case StandardMetadataType::DATASPACE:
+ {
+ android_dataspace_t dataspace;
+ get_format_dataspace(partial_handle.alloc_format & MALI_GRALLOC_INTFMT_FMT_MASK,
+ partial_handle.consumer_usage | partial_handle.producer_usage, partial_handle.width,
+ partial_handle.height, &dataspace);
+ err = android::gralloc4::encodeDataspace(static_cast<Dataspace>(dataspace), &vec);
+ break;
+ }
+ case StandardMetadataType::BLEND_MODE:
+ err = android::gralloc4::encodeBlendMode(BlendMode::INVALID, &vec);
+ break;
+ case StandardMetadataType::CROP:
+ {
+ const int num_planes = get_num_planes(&partial_handle);
+ std::vector<Rect> crops(num_planes);
+ for (size_t plane_index = 0; plane_index < num_planes; ++plane_index)
+ {
+ Rect rect = {.top = 0,
+ .left = 0,
+ .right = static_cast<int32_t>(partial_handle.plane_info[plane_index].alloc_width),
+ .bottom = static_cast<int32_t>(partial_handle.plane_info[plane_index].alloc_height) };
+ if (plane_index == 0)
+ {
+ rect = {.top = 0, .left = 0, .right = partial_handle.width, .bottom = partial_handle.height };
+ }
+ crops[plane_index] = rect;
+ }
+ err = android::gralloc4::encodeCrop(crops, &vec);
+ break;
+ }
+ case StandardMetadataType::SMPTE2086:
+ {
+ std::optional<Smpte2086> smpte2086{};
+ err = android::gralloc4::encodeSmpte2086(smpte2086, &vec);
+ break;
+ }
+ case StandardMetadataType::CTA861_3:
+ {
+ std::optional<Cta861_3> cta861_3{};
+ err = android::gralloc4::encodeCta861_3(cta861_3, &vec);
+ break;
+ }
+ case StandardMetadataType::SMPTE2094_40:
+ {
+ std::optional<std::vector<uint8_t>> smpte2094_40{};
+ err = android::gralloc4::encodeSmpte2094_40(smpte2094_40, &vec);
+ break;
+ }
+
+ case StandardMetadataType::BUFFER_ID:
+ case StandardMetadataType::INVALID:
+ default:
+ err = android::BAD_VALUE;
+ }
+ hidl_cb((err) ? Error::UNSUPPORTED : Error::NONE, vec);
+ }
+ else
+ {
+ hidl_cb(Error::UNSUPPORTED, vec);
+ }
+}
+
+} // namespace common
+} // namespace mapper
+} // namespace arm
diff --git a/gralloc4/src/hidl_common/MapperMetadata.h b/gralloc4/src/hidl_common/MapperMetadata.h
new file mode 100644
index 0000000..cbf9b47
--- /dev/null
+++ b/gralloc4/src/hidl_common/MapperMetadata.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2020 Arm Limited. All rights reserved.
+ *
+ * Copyright 2016 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_COMMON_MAPPER_METADATA_H
+#define GRALLOC_COMMON_MAPPER_METADATA_H
+
+#include <inttypes.h>
+#include "mali_gralloc_log.h"
+#include "core/mali_gralloc_bufferdescriptor.h"
+#include "mali_gralloc_buffer.h"
+
+#include "4.x/gralloc_mapper_hidl_header.h"
+
+#include <aidl/arm/graphics/Compression.h>
+#include <aidl/arm/graphics/ArmMetadataType.h>
+
+
+namespace arm
+{
+namespace mapper
+{
+namespace common
+{
+using android::hardware::hidl_vec;
+using aidl::android::hardware::graphics::common::ExtendableType;
+
+#define GRALLOC_ARM_COMPRESSION_TYPE_NAME "arm.graphics.Compression"
+const static ExtendableType Compression_AFBC{ GRALLOC_ARM_COMPRESSION_TYPE_NAME,
+ static_cast<int64_t>(aidl::arm::graphics::Compression::AFBC) };
+
+#define GRALLOC_ARM_METADATA_TYPE_NAME "arm.graphics.ArmMetadataType"
+const static IMapper::MetadataType ArmMetadataType_PLANE_FDS{ GRALLOC_ARM_METADATA_TYPE_NAME,
+ static_cast<int64_t>(aidl::arm::graphics::ArmMetadataType::PLANE_FDS) };
+
+/**
+ * Retrieves a Buffer's metadata value.
+ *
+ * @param handle [in] The private handle of the buffer to query for metadata.
+ * @param metadataType [in] The type of metadata queried.
+ * @param hidl_cb [in] HIDL callback function generating -
+ * error: NONE on success.
+ * UNSUPPORTED on error when reading or unsupported metadata type.
+ * metadata: Vector of bytes representing the metadata value.
+ */
+void get_metadata(const private_handle_t *handle, const IMapper::MetadataType &metadataType, IMapper::get_cb hidl_cb);
+
+/**
+ * Sets a Buffer's metadata value.
+ *
+ * @param handle [in] The private handle of the buffer for which to modify metadata.
+ * @param metadataType [in] The type of metadata to modify.
+ * @param metadata [in] Vector of bytes representing the new value for the metadata associated with the buffer.
+ *
+ * @return Error::NONE on success.
+ * Error::UNSUPPORTED on error when writing or unsupported metadata type.
+ */
+Error set_metadata(const private_handle_t *handle, const IMapper::MetadataType &metadataType,
+ const hidl_vec<uint8_t> &metadata);
+
+/**
+ * Query basic metadata information about a buffer form its descriptor before allocation.
+ *
+ * @param description [in] The buffer descriptor.
+ * @param metadataType [in] The type of metadata to query
+ * @param hidl_cb [in] HIDL callback function generating -
+ * error: NONE on success.
+ * UNSUPPORTED on unsupported metadata type.
+ * metadata: Vector of bytes representing the metadata value.
+ */
+void getFromBufferDescriptorInfo(IMapper::BufferDescriptorInfo const &description,
+ IMapper::MetadataType const &metadataType,
+ IMapper::getFromBufferDescriptorInfo_cb hidl_cb);
+
+} // namespace common
+} // namespace mapper
+} // namespace arm
+
+#endif
diff --git a/gralloc4/src/hidl_common/RegisteredHandlePool.cpp b/gralloc4/src/hidl_common/RegisteredHandlePool.cpp
new file mode 100644
index 0000000..b598d8a
--- /dev/null
+++ b/gralloc4/src/hidl_common/RegisteredHandlePool.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 ARM Limited. All rights reserved.
+ *
+ * Copyright 2016 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 "RegisteredHandlePool.h"
+
+bool RegisteredHandlePool::add(buffer_handle_t bufferHandle)
+{
+ std::lock_guard<std::mutex> lock(mutex);
+ return bufPool.insert(bufferHandle).second;
+}
+
+native_handle_t* RegisteredHandlePool::remove(void* buffer)
+{
+ auto bufferHandle = static_cast<native_handle_t*>(buffer);
+
+ std::lock_guard<std::mutex> lock(mutex);
+ return bufPool.erase(bufferHandle) == 1 ? bufferHandle : nullptr;
+}
+
+buffer_handle_t RegisteredHandlePool::get(const void* buffer)
+{
+ auto bufferHandle = static_cast<buffer_handle_t>(buffer);
+
+ std::lock_guard<std::mutex> lock(mutex);
+ return bufPool.count(bufferHandle) == 1 ? bufferHandle : nullptr;
+}
+
+void RegisteredHandlePool::for_each(std::function<void(const buffer_handle_t &)> fn)
+{
+ std::lock_guard<std::mutex> lock(mutex);
+ std::for_each(bufPool.begin(), bufPool.end(), fn);
+} \ No newline at end of file
diff --git a/gralloc4/src/hidl_common/RegisteredHandlePool.h b/gralloc4/src/hidl_common/RegisteredHandlePool.h
new file mode 100644
index 0000000..d3fb9b0
--- /dev/null
+++ b/gralloc4/src/hidl_common/RegisteredHandlePool.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2020 ARM Limited. All rights reserved.
+ *
+ * Copyright 2016 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_COMMON_REGISTERED_HANDLE_POOL_H
+ #define GRALLOC_COMMON_REGISTERED_HANDLE_POOL_H
+
+#include <cutils/native_handle.h>
+#include <mutex>
+#include <unordered_set>
+#include <algorithm>
+#include <functional>
+
+/* An unordered set to internally store / retrieve imported buffer handles */
+class RegisteredHandlePool
+{
+public:
+ /* Stores the buffer handle in the internal list */
+ bool add(buffer_handle_t bufferHandle);
+
+ /* Retrieves and removes the buffer handle from internal list */
+ native_handle_t* remove(void* buffer);
+
+ /* Retrieves the buffer handle from internal list */
+ buffer_handle_t get(const void* buffer);
+
+ /* Applies a function to each buffer handle */
+ void for_each(std::function<void(const buffer_handle_t &)> fn);
+
+private:
+ std::mutex mutex;
+ std::unordered_set<buffer_handle_t> bufPool;
+};
+
+#endif /* GRALLOC_COMMON_REGISTERED_HANDLE_POOL_H */
diff --git a/gralloc4/src/hidl_common/SharedMetadata.cpp b/gralloc4/src/hidl_common/SharedMetadata.cpp
new file mode 100644
index 0000000..bab1048
--- /dev/null
+++ b/gralloc4/src/hidl_common/SharedMetadata.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2020 Arm Limited.
+ *
+ * Copyright 2016 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 "SharedMetadata.h"
+#include "mali_gralloc_log.h"
+//#include <VendorVideoAPI.h>
+
+namespace arm
+{
+namespace mapper
+{
+namespace common
+{
+
+void shared_metadata_init(void *memory, std::string_view name)
+{
+ shared_metadata *m = new(memory) shared_metadata(name);
+}
+
+size_t shared_metadata_size()
+{
+ return sizeof(shared_metadata);
+}
+
+void get_name(const private_handle_t *hnd, std::string *name)
+{
+ auto *metadata = reinterpret_cast<const shared_metadata *>(hnd->attr_base);
+ *name = metadata->get_name();
+}
+
+void get_crop_rect(const private_handle_t *hnd, std::optional<Rect> *crop)
+{
+ auto *metadata = reinterpret_cast<const shared_metadata *>(hnd->attr_base);
+ *crop = metadata->crop.to_std_optional();
+}
+
+android::status_t set_crop_rect(const private_handle_t *hnd, const Rect &crop)
+{
+ auto *metadata = reinterpret_cast<shared_metadata *>(hnd->attr_base);
+
+ if (crop.top < 0 || crop.left < 0 ||
+ crop.left > crop.right || crop.right > hnd->plane_info[0].alloc_width ||
+ crop.top > crop.bottom || crop.bottom > hnd->plane_info[0].alloc_height ||
+ (crop.right - crop.left) != hnd->width ||
+ (crop.bottom - crop.top) != hnd->height)
+ {
+ MALI_GRALLOC_LOGE("Attempt to set invalid crop rectangle");
+ return android::BAD_VALUE;
+ }
+
+ metadata->crop = aligned_optional(crop);
+ return android::OK;
+}
+
+void get_dataspace(const private_handle_t *hnd, std::optional<Dataspace> *dataspace)
+{
+ auto *metadata = reinterpret_cast<const shared_metadata *>(hnd->attr_base);
+ *dataspace = metadata->dataspace.to_std_optional();
+}
+
+void set_dataspace(const private_handle_t *hnd, const Dataspace &dataspace)
+{
+ auto *metadata = reinterpret_cast<shared_metadata *>(hnd->attr_base);
+ metadata->dataspace = aligned_optional(dataspace);
+}
+
+void get_blend_mode(const private_handle_t *hnd, std::optional<BlendMode> *blend_mode)
+{
+ auto *metadata = reinterpret_cast<const shared_metadata *>(hnd->attr_base);
+ *blend_mode = metadata->blend_mode.to_std_optional();
+}
+
+void set_blend_mode(const private_handle_t *hnd, const BlendMode &blend_mode)
+{
+ auto *metadata = reinterpret_cast<shared_metadata *>(hnd->attr_base);
+ metadata->blend_mode = aligned_optional(blend_mode);
+}
+
+void get_smpte2086(const private_handle_t *hnd, std::optional<Smpte2086> *smpte2086)
+{
+ auto *metadata = reinterpret_cast<const shared_metadata *>(hnd->attr_base);
+ *smpte2086 = metadata->smpte2086.to_std_optional();
+}
+
+android::status_t set_smpte2086(const private_handle_t *hnd, const std::optional<Smpte2086> &smpte2086)
+{
+ if (!smpte2086.has_value())
+ {
+ return android::BAD_VALUE;
+ }
+
+ auto *metadata = reinterpret_cast<shared_metadata *>(hnd->attr_base);
+ metadata->smpte2086 = aligned_optional(smpte2086);
+
+ return android::OK;
+}
+
+void get_cta861_3(const private_handle_t *hnd, std::optional<Cta861_3> *cta861_3)
+{
+ auto *metadata = reinterpret_cast<const shared_metadata *>(hnd->attr_base);
+ *cta861_3 = metadata->cta861_3.to_std_optional();
+}
+
+android::status_t set_cta861_3(const private_handle_t *hnd, const std::optional<Cta861_3> &cta861_3)
+{
+ if (!cta861_3.has_value())
+ {
+ return android::BAD_VALUE;
+ }
+
+ auto *metadata = reinterpret_cast<shared_metadata *>(hnd->attr_base);
+ metadata->cta861_3 = aligned_optional(cta861_3);
+
+ return android::OK;
+}
+
+void get_smpte2094_40(const private_handle_t *hnd, std::optional<std::vector<uint8_t>> *smpte2094_40)
+{
+ auto *metadata = reinterpret_cast<const shared_metadata *>(hnd->attr_base);
+ if (metadata->smpte2094_40.size > 0)
+ {
+ const uint8_t *begin = metadata->smpte2094_40.data();
+ const uint8_t *end = begin + metadata->smpte2094_40.size;
+ smpte2094_40->emplace(begin, end);
+ }
+ else
+ {
+ smpte2094_40->reset();
+ }
+}
+
+android::status_t set_smpte2094_40(const private_handle_t *hnd, const std::optional<std::vector<uint8_t>> &smpte2094_40)
+{
+ if (!smpte2094_40.has_value() || smpte2094_40->size() == 0)
+ {
+ MALI_GRALLOC_LOGE("Empty SMPTE 2094-40 data");
+ return android::BAD_VALUE;
+ }
+
+ auto *metadata = reinterpret_cast<shared_metadata *>(hnd->attr_base);
+ const size_t size = smpte2094_40.has_value() ? smpte2094_40->size() : 0;
+ if (size > metadata->smpte2094_40.capacity())
+ {
+ MALI_GRALLOC_LOGE("SMPTE 2094-40 metadata too large to fit in shared metadata region");
+ return android::BAD_VALUE;
+ }
+
+ metadata->smpte2094_40.size = size;
+ std::memcpy(metadata->smpte2094_40.data(), smpte2094_40->data(), size);
+
+ return android::OK;
+}
+
+} // namespace common
+} // namespace mapper
+} // namespace arm
diff --git a/gralloc4/src/hidl_common/SharedMetadata.h b/gralloc4/src/hidl_common/SharedMetadata.h
new file mode 100644
index 0000000..e1f6d0b
--- /dev/null
+++ b/gralloc4/src/hidl_common/SharedMetadata.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2020 Arm Limited.
+ *
+ * Copyright 2016 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_COMMON_SHARED_METADATA_H
+#define GRALLOC_COMMON_SHARED_METADATA_H
+
+#include <optional>
+#include <vector>
+#include "gralloctypes/Gralloc4.h"
+#include "mali_gralloc_buffer.h"
+#include "allocator/mali_gralloc_shared_memory.h"
+#include "core/mali_gralloc_bufferdescriptor.h"
+#include "gralloc_helper.h"
+
+#include "4.x/gralloc_mapper_hidl_header.h"
+
+#include "SharedMetadata_struct.h"
+
+namespace arm
+{
+namespace mapper
+{
+namespace common
+{
+
+using android::hardware::hidl_vec;
+using aidl::android::hardware::graphics::common::Rect;
+using aidl::android::hardware::graphics::common::Smpte2086;
+using aidl::android::hardware::graphics::common::Cta861_3;
+using aidl::android::hardware::graphics::common::BlendMode;
+using aidl::android::hardware::graphics::common::Dataspace;
+
+void shared_metadata_init(void *memory, std::string_view name);
+size_t shared_metadata_size();
+
+void get_name(const private_handle_t *hnd, std::string *name);
+
+void get_crop_rect(const private_handle_t *hnd, std::optional<Rect> *crop);
+android::status_t set_crop_rect(const private_handle_t *hnd, const Rect &crop_rectangle);
+
+void get_dataspace(const private_handle_t *hnd, std::optional<Dataspace> *dataspace);
+void set_dataspace(const private_handle_t *hnd, const Dataspace &dataspace);
+
+void get_blend_mode(const private_handle_t *hnd, std::optional<BlendMode> *blend_mode);
+void set_blend_mode(const private_handle_t *hnd, const BlendMode &blend_mode);
+
+void get_smpte2086(const private_handle_t *hnd, std::optional<Smpte2086> *smpte2086);
+android::status_t set_smpte2086(const private_handle_t *hnd, const std::optional<Smpte2086> &smpte2086);
+
+void get_cta861_3(const private_handle_t *hnd, std::optional<Cta861_3> *cta861_3);
+android::status_t set_cta861_3(const private_handle_t *hnd, const std::optional<Cta861_3> &cta861_3);
+
+void get_smpte2094_40(const private_handle_t *hnd, std::optional<std::vector<uint8_t>> *smpte2094_40);
+android::status_t set_smpte2094_40(const private_handle_t *hnd, const std::optional<std::vector<uint8_t>> &smpte2094_40);
+
+} // namespace common
+} // namespace mapper
+} // namespace arm
+
+#endif
diff --git a/gralloc4/src/hidl_common/SharedMetadata_struct.h b/gralloc4/src/hidl_common/SharedMetadata_struct.h
new file mode 100644
index 0000000..60df44c
--- /dev/null
+++ b/gralloc4/src/hidl_common/SharedMetadata_struct.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2020 Arm Limited.
+ *
+ * Copyright 2016 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.
+ */
+
+#pragma once
+
+#include <optional>
+#include <vector>
+#include <VendorVideoAPI.h>
+#include "gralloctypes/Gralloc4.h"
+
+namespace arm
+{
+namespace mapper
+{
+namespace common
+{
+
+using aidl::android::hardware::graphics::common::Rect;
+using aidl::android::hardware::graphics::common::Smpte2086;
+using aidl::android::hardware::graphics::common::Cta861_3;
+using aidl::android::hardware::graphics::common::BlendMode;
+using aidl::android::hardware::graphics::common::Dataspace;
+
+template <typename T>
+struct aligned_optional
+{
+ enum class state : uint32_t
+ {
+ vacant,
+ occupied,
+ };
+
+ state item_state { state::vacant };
+ T item {};
+
+ aligned_optional() = default;
+
+ aligned_optional(T initial_value)
+ : item_state(state::occupied)
+ , item(initial_value)
+ {
+ }
+
+ aligned_optional(std::optional<T> std_optional)
+ : item_state(std_optional ? state::occupied : state::vacant)
+ {
+ if (std_optional)
+ {
+ item = *std_optional;
+ }
+ }
+
+ std::optional<T> to_std_optional() const
+ {
+ switch (item_state)
+ {
+ case state::vacant: return std::nullopt;
+ case state::occupied: return std::make_optional(item);
+ }
+ }
+};
+
+template <typename T, size_t N>
+struct aligned_inline_vector
+{
+ uint32_t size;
+ T contents[N];
+
+ constexpr uint32_t capacity() const
+ {
+ return N;
+ }
+
+ const T *data() const
+ {
+ return &contents[0];
+ }
+
+ T *data()
+ {
+ return &contents[0];
+ }
+};
+
+struct shared_metadata
+{
+ ExynosVideoMeta video_private_data;
+
+ aligned_optional<BlendMode> blend_mode {};
+ aligned_optional<Rect> crop {};
+ aligned_optional<Cta861_3> cta861_3 {};
+ aligned_optional<Dataspace> dataspace {};
+ aligned_optional<Smpte2086> smpte2086 {};
+ aligned_inline_vector<uint8_t, 2048> smpte2094_40 {};
+ aligned_inline_vector<char, 256> name {};
+
+ shared_metadata() = default;
+
+ shared_metadata(std::string_view in_name)
+ {
+ name.size = std::min(name.capacity(), static_cast<uint32_t>(in_name.size()));
+ std::memcpy(name.data(), in_name.data(), name.size);
+ }
+
+ std::string_view get_name() const
+ {
+ return name.size > 0
+ ? std::string_view(name.data(), name.size)
+ : std::string_view();
+ }
+};
+
+/* TODO: convert alignment assert taking video metadata into account */
+#if 0
+static_assert(offsetof(shared_metadata, blend_mode) == 0, "bad alignment");
+static_assert(sizeof(shared_metadata::blend_mode) == 8, "bad size");
+
+static_assert(offsetof(shared_metadata, crop) == 8, "bad alignment");
+static_assert(sizeof(shared_metadata::crop) == 20, "bad size");
+
+static_assert(offsetof(shared_metadata, cta861_3) == 28, "bad alignment");
+static_assert(sizeof(shared_metadata::cta861_3) == 12, "bad size");
+
+static_assert(offsetof(shared_metadata, dataspace) == 40, "bad alignment");
+static_assert(sizeof(shared_metadata::dataspace) == 8, "bad size");
+
+static_assert(offsetof(shared_metadata, smpte2086) == 48, "bad alignment");
+static_assert(sizeof(shared_metadata::smpte2086) == 44, "bad size");
+
+static_assert(offsetof(shared_metadata, smpte2094_40) == 92, "bad alignment");
+static_assert(sizeof(shared_metadata::smpte2094_40) == 2052, "bad size");
+
+static_assert(offsetof(shared_metadata, name) == 2144, "bad alignment");
+static_assert(sizeof(shared_metadata::name) == 260, "bad size");
+
+static_assert(alignof(shared_metadata) == 4, "bad alignment");
+static_assert(sizeof(shared_metadata) == 2404, "bad size");
+#endif
+
+} // namespace common
+} // namespace mapper
+} // namespace arm
+
diff --git a/gralloc4/src/mali_fourcc.h b/gralloc4/src/mali_fourcc.h
new file mode 100644
index 0000000..9dcec0c
--- /dev/null
+++ b/gralloc4/src/mali_fourcc.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2019-2020 ARM Limited. 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 MALI_FOURCC_H_
+#define MALI_FOURCC_H_
+
+extern "C"
+{
+
+#include <drm_fourcc.h>
+#include <stdint.h>
+
+/* FOURCCs for formats that exist upstream, but may not be in the drm_fourcc.h header included above.
+ *
+ * Below we define DRM FOURCC formats that are upstreamed, but may not be in the drm_fourcc.h header that we include
+ * above, merely because that header is too old. As drm_fourcc.h is an external header that we cannot control, the best
+ * we can do is to define here the missing formats.
+ */
+#ifndef DRM_FORMAT_INVALID
+#define DRM_FORMAT_INVALID 0
+#endif
+
+#ifndef DRM_FORMAT_P010
+#define DRM_FORMAT_P010 fourcc_code('P', '0', '1', '0')
+#endif
+
+#ifndef DRM_FORMAT_Y0L2
+#define DRM_FORMAT_Y0L2 fourcc_code('Y', '0', 'L', '2')
+#endif
+
+#ifndef DRM_FORMAT_P210
+#define DRM_FORMAT_P210 fourcc_code('P', '2', '1', '0')
+#endif
+
+#ifndef DRM_FORMAT_Y210
+#define DRM_FORMAT_Y210 fourcc_code('Y', '2', '1', '0')
+#endif
+
+#ifndef DRM_FORMAT_Y410
+#define DRM_FORMAT_Y410 fourcc_code('Y', '4', '1', '0')
+#endif
+
+#ifndef DRM_FORMAT_YUV420_8BIT
+#define DRM_FORMAT_YUV420_8BIT fourcc_code('Y', 'U', '0', '8')
+#endif
+
+#ifndef DRM_FORMAT_YUV420_10BIT
+#define DRM_FORMAT_YUV420_10BIT fourcc_code('Y', 'U', '1', '0')
+#endif
+
+#ifndef DRM_FORMAT_ABGR16161616F
+#define DRM_FORMAT_ABGR16161616F fourcc_code('A', 'B', '4', 'H')
+#endif
+
+#ifndef DRM_FORMAT_R16
+#define DRM_FORMAT_R16 fourcc_code('R', '1', '6', ' ')
+#endif
+
+/* ARM specific modifiers. */
+#ifndef DRM_FORMAT_MOD_VENDOR_ARM
+#define DRM_FORMAT_MOD_VENDOR_ARM 0x08
+#endif
+
+#ifndef fourcc_mod_code
+#define fourcc_mod_code(vendor, val) \
+ ((((uint64_t)DRM_FORMAT_MOD_VENDOR_## vendor) << 56) | ((val) & 0x00ffffffffffffffULL))
+#endif
+
+#ifndef DRM_FORMAT_MOD_ARM_AFBC
+/* AFBC modifiers. */
+
+#define DRM_FORMAT_MOD_ARM_AFBC(__afbc_mode) fourcc_mod_code(ARM, (__afbc_mode))
+/* AFBC superblock size. */
+#ifndef AFBC_FORMAT_MOD_BLOCK_SIZE_16x16
+#define AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 ((uint64_t)0x1)
+#endif
+
+#ifndef AFBC_FORMAT_MOD_BLOCK_SIZE_32x8
+#define AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 ((uint64_t)0x2)
+#endif
+
+#ifndef AFBC_FORMAT_MOD_BLOCK_SIZE_MASK
+#define AFBC_FORMAT_MOD_BLOCK_SIZE_MASK ((uint64_t)0xf)
+#endif
+
+/* AFBC lossless transform. */
+#ifndef AFBC_FORMAT_MOD_YTR
+#define AFBC_FORMAT_MOD_YTR (((uint64_t)1) << 4)
+#endif
+
+/* AFBC block-split. */
+#ifndef AFBC_FORMAT_MOD_SPLIT
+#define AFBC_FORMAT_MOD_SPLIT (((uint64_t)1) << 5)
+#endif
+
+/* AFBC sparse layout. */
+#ifndef AFBC_FORMAT_MOD_SPARSE
+#define AFBC_FORMAT_MOD_SPARSE (((uint64_t)1) << 6)
+#endif
+
+/* AFBC tiled layout. */
+#ifndef AFBC_FORMAT_MOD_TILED
+#define AFBC_FORMAT_MOD_TILED (((uint64_t)1) << 8)
+#endif
+
+#endif /* DRM_FORMAT_MOD_ARM_AFBC */
+
+/* AFBC 1.3 block sizes. */
+#ifndef AFBC_FORMAT_MOD_BLOCK_SIZE_64x4
+#define AFBC_FORMAT_MOD_BLOCK_SIZE_64x4 ((uint64_t)0x3)
+#endif
+
+#ifndef AFBC_FORMAT_MOD_BLOCK_SIZE_32x8_64x4
+#define AFBC_FORMAT_MOD_BLOCK_SIZE_32x8_64x4 ((uint64_t)0x4)
+#endif
+
+/* AFBC double-buffer. */
+#ifndef AFBC_FORMAT_MOD_DB
+#define AFBC_FORMAT_MOD_DB (((uint64_t)1) << 10)
+#endif
+
+/* AFBC buffer content hints. */
+#ifndef AFBC_FORMAT_MOD_BCH
+#define AFBC_FORMAT_MOD_BCH (((uint64_t)1) << 11)
+#endif
+
+}
+
+#endif /* MALI_FOURCC_H_ */
diff --git a/gralloc4/src/mali_gralloc_buffer.h b/gralloc4/src/mali_gralloc_buffer.h
new file mode 100644
index 0000000..56e4f59
--- /dev/null
+++ b/gralloc4/src/mali_gralloc_buffer.h
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2017-2020 ARM Limited. All rights reserved.
+ *
+ * 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 MALI_GRALLOC_BUFFER_H_
+#define MALI_GRALLOC_BUFFER_H_
+
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <cutils/native_handle.h>
+#include <string.h>
+#include <log/log.h>
+#include <inttypes.h>
+
+/* the max string size of GRALLOC_HARDWARE_GPU0 & GRALLOC_HARDWARE_FB0
+ * 8 is big enough for "gpu0" & "fb0" currently
+ */
+#define MALI_GRALLOC_HARDWARE_MAX_STR_LEN 8
+
+/* Define number of shared file descriptors. Not guaranteed to be constant for a private_handle_t object
+ * as fds that do not get initialized may instead be treated as integers.
+ */
+
+#define NUM_INTS_IN_PRIVATE_HANDLE ((sizeof(struct private_handle_t) - sizeof(native_handle)) / sizeof(int))
+
+#define SZ_4K 0x00001000
+#define SZ_2M 0x00200000
+
+/*
+ * Maximum number of pixel format planes.
+ * Plane [0]: Single plane formats (inc. RGB, YUV) and Y
+ * Plane [1]: U/V, UV
+ * Plane [2]: V/U
+ */
+#define MAX_PLANES 3
+
+#ifdef __cplusplus
+#define DEFAULT_INITIALIZER(x) = x
+#else
+#define DEFAULT_INITIALIZER(x)
+#endif
+
+typedef struct plane_info {
+
+ /*
+ * Offset to plane (in bytes),
+ * from the start of the allocation.
+ */
+ int64_t offset;
+
+ uint32_t fd_idx;
+ uint64_t size;
+
+ /*
+ * Byte Stride: number of bytes between two vertically adjacent
+ * pixels in given plane. This can be mathematically described by:
+ *
+ * byte_stride = ALIGN((alloc_width * bpp)/8, alignment)
+ *
+ * where,
+ *
+ * alloc_width: width of plane in pixels (c.f. pixel_stride)
+ * bpp: average bits per pixel
+ * alignment (in bytes): dependent upon pixel format and usage
+ *
+ * For uncompressed allocations, byte_stride might contain additional
+ * padding beyond the alloc_width. For AFBC, alignment is zero.
+ */
+ uint32_t byte_stride;
+
+ /*
+ * Dimensions of plane (in pixels).
+ *
+ * For single plane formats, pixels equates to luma samples.
+ * For multi-plane formats, pixels equates to the number of sample sites
+ * for the corresponding plane, even if subsampled.
+ *
+ * AFBC compressed formats: requested width/height are rounded-up
+ * to a whole AFBC superblock/tile (next superblock at minimum).
+ * Uncompressed formats: dimensions typically match width and height
+ * but might require pixel stride alignment.
+ *
+ * See 'byte_stride' for relationship between byte_stride and alloc_width.
+ *
+ * Any crop rectangle defined by GRALLOC_ARM_BUFFER_ATTR_CROP_RECT must
+ * be wholly within the allocation dimensions. The crop region top-left
+ * will be relative to the start of allocation.
+ */
+ uint32_t alloc_width;
+ uint32_t alloc_height;
+} plane_info_t;
+
+struct private_handle_t;
+
+#ifndef __cplusplus
+/* C99 with pedantic don't allow anonymous unions which is used in below struct
+ * Disable pedantic for C for this struct only.
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+#endif
+
+#ifdef __cplusplus
+struct private_handle_t : public native_handle
+{
+#else
+struct private_handle_t
+{
+ struct native_handle nativeHandle;
+#endif
+
+#ifdef __cplusplus
+ /* Never intended to be used from C code */
+ enum
+ {
+ PRIV_FLAGS_USES_2PRIVATE_DATA = 1U << 4,
+ PRIV_FLAGS_USES_3PRIVATE_DATA = 1U << 5,
+ PRIV_FLAGS_USES_HFR_MODE = 1U << 6,
+ };
+
+ enum
+ {
+ LOCK_STATE_WRITE = 1 << 31,
+ LOCK_STATE_MAPPED = 1 << 30,
+ LOCK_STATE_READ_MASK = 0x3FFFFFFF
+ };
+#endif
+
+ /*
+ * Shared file descriptor for dma_buf sharing. This must be the first element in the
+ * structure so that binder knows where it is and can properly share it between
+ * processes.
+ * DO NOT MOVE THIS ELEMENT!
+ */
+ union {
+ int fds[5];
+ };
+
+ // ints
+ int magic DEFAULT_INITIALIZER(sMagic);
+ int flags DEFAULT_INITIALIZER(0);
+
+ int fd_count DEFAULT_INITIALIZER(1);
+
+ /*
+ * Input properties.
+ *
+ * req_format: Pixel format, base + private modifiers.
+ * width/height: Buffer dimensions.
+ * producer/consumer_usage: Buffer usage (indicates IP)
+ */
+ int width DEFAULT_INITIALIZER(0);
+ int height DEFAULT_INITIALIZER(0);
+ int req_format DEFAULT_INITIALIZER(0);
+ uint64_t producer_usage DEFAULT_INITIALIZER(0);
+ uint64_t consumer_usage DEFAULT_INITIALIZER(0);
+
+ /*
+ * DEPRECATED members.
+ * Equivalent information can be obtained from other fields:
+ *
+ * - 'internal_format' --> alloc_format
+ * - 'stride' (pixel stride) ~= plane_info[0].alloc_width
+ * - 'byte_stride' ~= plane_info[0].byte_stride
+ * - 'internalWidth' ~= plane_info[0].alloc_width
+ * - 'internalHeight' ~= plane_info[0].alloc_height
+ *
+ * '~=' (approximately equal) is used because the fields were either previously
+ * incorrectly populated by gralloc or the meaning has slightly changed.
+ *
+ * NOTE: 'stride' values sometimes vary significantly from plane_info[0].alloc_width.
+ */
+ int stride DEFAULT_INITIALIZER(0);
+
+ /*
+ * Allocation properties.
+ *
+ * alloc_format: Pixel format (base + modifiers). NOTE: base might differ from requested
+ * format (req_format) where fallback to single-plane format was required.
+ * plane_info: Per plane allocation information.
+ * size: Total bytes allocated for buffer (inc. all planes, layers. etc.).
+ * layer_count: Number of layers allocated to buffer.
+ * All layers are the same size (in bytes).
+ * Multi-layers supported in v1.0, where GRALLOC1_CAPABILITY_LAYERED_BUFFERS is enabled.
+ * Layer size: 'size' / 'layer_count'.
+ * Layer (n) offset: n * ('size' / 'layer_count'), n=0 for the first layer.
+ *
+ */
+ uint64_t alloc_format DEFAULT_INITIALIZER(0);
+ plane_info_t plane_info[MAX_PLANES] DEFAULT_INITIALIZER({});
+ uint32_t layer_count DEFAULT_INITIALIZER(0);
+
+ uint64_t backing_store_id DEFAULT_INITIALIZER(0x0);
+ int cpu_read DEFAULT_INITIALIZER(0); /**< Buffer is locked for CPU read when non-zero. */
+ int cpu_write DEFAULT_INITIALIZER(0); /**< Buffer is locked for CPU write when non-zero. */
+ int allocating_pid DEFAULT_INITIALIZER(0);
+ int remote_pid DEFAULT_INITIALIZER(-1);
+ int ref_count DEFAULT_INITIALIZER(0);
+ // locally mapped shared attribute area
+
+ int ion_handles[3];
+ uint64_t bases[3];
+ uint64_t alloc_sizes[3];
+
+ void *attr_base __attribute__((aligned (8))) DEFAULT_INITIALIZER(nullptr);
+ off_t offset __attribute__((aligned (8))) DEFAULT_INITIALIZER(0);
+
+ /* Size of the attribute shared region in bytes. */
+ uint64_t attr_size __attribute__((aligned (8))) DEFAULT_INITIALIZER(0);
+
+ uint64_t reserved_region_size DEFAULT_INITIALIZER(0);
+
+ uint64_t imapper_version DEFAULT_INITIALIZER(0);
+
+#ifdef __cplusplus
+ /*
+ * We track the number of integers in the structure. There are 16 unconditional
+ * integers (magic - pid, yuv_info, fd and offset). Note that the fd element is
+ * considered an int not an fd because it is not intended to be used outside the
+ * surface flinger process. The GRALLOC_ARM_NUM_INTS variable is used to track the
+ * number of integers that are conditionally included. Similar considerations apply
+ * to the number of fds.
+ */
+ static const int sMagic = 0x3141592;
+
+ private_handle_t(
+ int _flags,
+ uint64_t _alloc_sizes[3],
+ uint64_t _consumer_usage, uint64_t _producer_usage,
+ int _fds[5], int _fd_count,
+ int _req_format, uint64_t _alloc_format,
+ int _width, int _height, int _stride,
+ uint64_t _layer_count, plane_info_t _plane_info[MAX_PLANES])
+ : flags(_flags)
+ , fd_count(_fd_count)
+ , width(_width)
+ , height(_height)
+ , req_format(_req_format)
+ , producer_usage(_producer_usage)
+ , consumer_usage(_consumer_usage)
+ , stride(_stride)
+ , alloc_format(_alloc_format)
+ , layer_count(_layer_count)
+ , allocating_pid(getpid())
+ , ref_count(1)
+ {
+ version = sizeof(native_handle);
+ set_numfds(fd_count);
+ memcpy(plane_info, _plane_info, sizeof(plane_info_t) * MAX_PLANES);
+
+ if (_fds)
+ memcpy(fds, _fds, sizeof(fds));
+
+ if (_alloc_sizes)
+ memcpy(alloc_sizes, _alloc_sizes, sizeof(alloc_sizes));
+
+ memset(bases, 0, sizeof(bases));
+ memset(ion_handles, 0, sizeof(ion_handles));
+ }
+
+ ~private_handle_t()
+ {
+ magic = 0;
+ }
+
+ /* Set the number of allocated fds in the handle to n*/
+ void set_numfds(int n)
+ {
+ int total_ints =
+ (sizeof(struct private_handle_t) - sizeof(native_handle)) / sizeof(int);
+
+ numFds = n;
+ numInts = total_ints - n;
+ }
+
+ /* Increments number of allocated fds in the handle by n */
+ int incr_numfds(int n)
+ {
+ numFds += n;
+ numInts -= n;
+
+ return numFds;
+ }
+
+ static int validate(const native_handle *h)
+ {
+ const private_handle_t *hnd = (const private_handle_t *)h;
+ if (!h || h->version != sizeof(native_handle) || hnd->magic != sMagic ||
+ h->numFds + h->numInts != NUM_INTS_IN_PRIVATE_HANDLE)
+ {
+ return -EINVAL;
+ }
+ return 0;
+ }
+
+ bool is_multi_plane() const
+ {
+ /* For multi-plane, the byte stride for the second plane will always be non-zero. */
+ return (plane_info[1].byte_stride != 0);
+ }
+
+ uint64_t get_usage() const
+ {
+ return producer_usage | consumer_usage;
+ }
+
+ int get_share_attr_fd_index() const
+ {
+ /* share_attr can be at idx 1 to 4 */
+ if (fd_count <= 0 || fd_count > 4)
+ return -1;
+
+ return fd_count;
+ }
+
+ int get_share_attr_fd() const
+ {
+ int idx = get_share_attr_fd_index();
+
+ if (idx <= 0)
+ return -1;
+
+ return fds[idx];
+ }
+
+ void set_share_attr_fd(int fd)
+ {
+ int idx = get_share_attr_fd_index();
+
+ if (idx <= 0)
+ return;
+
+ fds[idx] = fd;
+ }
+
+ void close_share_attr_fd()
+ {
+ int fd = get_share_attr_fd();
+
+ if (fd < 0)
+ return;
+
+ close(fd);
+ }
+
+ void dump(const char *str) const
+ {
+ ALOGE("[%s] "
+ "numInts(%d) numFds(%d) fd_count(%d) "
+ "fd(%d %d %d %d %d) "
+ "flags(%d) "
+ "wh(%d %d) "
+ "req_format(%#x) alloc_format(%#" PRIx64 ") "
+ "usage_pc(0x%" PRIx64 " 0x%" PRIx64 ") "
+ "stride(%d) "
+ "psize(%" PRIu64 ") byte_stride(%d) internal_wh(%d %d) "
+ "psize1(%" PRIu64 ") byte_stride1(%d) internal_wh1(%d %d) "
+ "psize2(%" PRIu64 ") byte_stride2(%d) internal_wh2(%d %d) "
+ "alloc_format(0x%" PRIx64 ") "
+ "alloc_sizes(%" PRIu64 " %" PRIu64 " %" PRIu64 ") "
+ "layer_count(%d) "
+ "bases(%p %p %p %p) "
+ "\n",
+ str,
+ numInts, numFds, fd_count,
+ fds[0], fds[1], fds[2], fds[3], fds[4],
+ flags,
+ width, height,
+ req_format, alloc_format,
+ producer_usage, consumer_usage,
+ stride,
+ plane_info[0].size, plane_info[0].byte_stride, plane_info[0].alloc_width, plane_info[0].alloc_height,
+ plane_info[1].size, plane_info[1].byte_stride, plane_info[1].alloc_width, plane_info[1].alloc_height,
+ plane_info[2].size, plane_info[2].byte_stride, plane_info[2].alloc_width, plane_info[2].alloc_height,
+ alloc_format,
+ alloc_sizes[0], alloc_sizes[1], alloc_sizes[2],
+ layer_count,
+ (void*)bases[0], (void*)bases[1], (void*)bases[2], attr_base
+ );
+ }
+
+ int get_alloc_format() const
+ {
+ return (int)(alloc_format & 0x00000000ffffffffULL);
+ }
+
+ static private_handle_t *dynamicCast(const native_handle *in)
+ {
+ if (validate(in) == 0)
+ {
+ return (private_handle_t *)in;
+ }
+
+ return NULL;
+ }
+#endif
+};
+#ifndef __cplusplus
+/* Restore previous diagnostic for pedantic */
+#pragma GCC diagnostic pop
+#endif
+
+#endif /* MALI_GRALLOC_BUFFER_H_ */
diff --git a/gralloc4/src/mali_gralloc_buffer4.h b/gralloc4/src/mali_gralloc_buffer4.h
new file mode 120000
index 0000000..a9c0f1e
--- /dev/null
+++ b/gralloc4/src/mali_gralloc_buffer4.h
@@ -0,0 +1 @@
+mali_gralloc_buffer.h \ No newline at end of file
diff --git a/gralloc4/src/mali_gralloc_formats.h b/gralloc4/src/mali_gralloc_formats.h
new file mode 100644
index 0000000..0acd644
--- /dev/null
+++ b/gralloc4/src/mali_gralloc_formats.h
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2016-2020 ARM Limited. All rights reserved.
+ *
+ * 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 MALI_GRALLOC_FORMATS_H_
+#define MALI_GRALLOC_FORMATS_H_
+
+#include <system/graphics.h>
+
+#include "mali_gralloc_log.h"
+
+/* Internal formats are represented in gralloc as a 64bit identifier
+ * where the 32 lower bits are a base format and the 32 upper bits are modifiers.
+ *
+ * Modifier bits are divided into mutually exclusive ones and those that are not.
+ */
+/* Internal format type */
+typedef uint64_t mali_gralloc_internal_format;
+
+/* Internal format masks */
+#define MALI_GRALLOC_INTFMT_FMT_MASK 0x00000000ffffffffULL
+#define MALI_GRALLOC_INTFMT_EXT_MASK 0xffffffff00000000ULL
+#define MALI_GRALLOC_INTFMT_FMT_WRAP_MASK 0x0000ffffULL
+#define MALI_GRALLOC_INTFMT_EXT_WRAP_MASK 0xffff0000ULL
+#define MALI_GRALLOC_INTFMT_EXT_WRAP_SHIFT 16
+
+/* Format Modifier Bits Locations */
+#define MALI_GRALLOC_INTFMT_EXTENSION_BIT_START 32
+
+/* Internal base formats */
+
+/* Base formats that do not have an identical HAL match
+ * are defined starting at the Android private range
+ */
+#define MALI_GRALLOC_FORMAT_INTERNAL_RANGE_BASE 0x1000
+
+typedef enum
+{
+ MALI_GRALLOC_FORMAT_TYPE_USAGE,
+ MALI_GRALLOC_FORMAT_TYPE_INTERNAL,
+} mali_gralloc_format_type;
+
+/*
+ * Internal formats defined to either match HAL_PIXEL_FORMAT_* or extend
+ * where missing. Private formats can be used where no CPU usage is requested.
+ * All pixel formats in this list must explicitly define a strict memory
+ * layout which can be allocated and used by producer(s) and consumer(s).
+ * Flex formats are therefore not included and will be mapped to suitable
+ * internal formats.
+ */
+typedef enum
+{
+ /* Internal definitions for HAL formats. */
+ MALI_GRALLOC_FORMAT_INTERNAL_UNDEFINED = 0,
+ MALI_GRALLOC_FORMAT_INTERNAL_RGBA_8888 = HAL_PIXEL_FORMAT_RGBA_8888,
+ MALI_GRALLOC_FORMAT_INTERNAL_RGBX_8888 = HAL_PIXEL_FORMAT_RGBX_8888,
+ MALI_GRALLOC_FORMAT_INTERNAL_RGB_888 = HAL_PIXEL_FORMAT_RGB_888,
+ MALI_GRALLOC_FORMAT_INTERNAL_RGB_565 = HAL_PIXEL_FORMAT_RGB_565,
+ MALI_GRALLOC_FORMAT_INTERNAL_BGRA_8888 = HAL_PIXEL_FORMAT_BGRA_8888,
+ MALI_GRALLOC_FORMAT_INTERNAL_RGBA_1010102 = HAL_PIXEL_FORMAT_RGBA_1010102,
+ /* 16-bit floating point format. */
+ MALI_GRALLOC_FORMAT_INTERNAL_RGBA_16161616 = HAL_PIXEL_FORMAT_RGBA_FP16,
+ MALI_GRALLOC_FORMAT_INTERNAL_YV12 = HAL_PIXEL_FORMAT_YV12,
+ MALI_GRALLOC_FORMAT_INTERNAL_Y8 = HAL_PIXEL_FORMAT_Y8,
+ MALI_GRALLOC_FORMAT_INTERNAL_Y16 = HAL_PIXEL_FORMAT_Y16,
+ MALI_GRALLOC_FORMAT_INTERNAL_NV16 = HAL_PIXEL_FORMAT_YCbCr_422_SP,
+
+ /* Camera specific HAL formats */
+ MALI_GRALLOC_FORMAT_INTERNAL_RAW16 = HAL_PIXEL_FORMAT_RAW16,
+ MALI_GRALLOC_FORMAT_INTERNAL_RAW12 = HAL_PIXEL_FORMAT_RAW12,
+ MALI_GRALLOC_FORMAT_INTERNAL_RAW10 = HAL_PIXEL_FORMAT_RAW10,
+ MALI_GRALLOC_FORMAT_INTERNAL_RAW_OPAQUE = HAL_PIXEL_FORMAT_RAW_OPAQUE,
+ MALI_GRALLOC_FORMAT_INTERNAL_BLOB = HAL_PIXEL_FORMAT_BLOB,
+
+ /* Depth and stencil formats */
+ MALI_GRALLOC_FORMAT_INTERNAL_DEPTH_16 = HAL_PIXEL_FORMAT_DEPTH_16,
+ MALI_GRALLOC_FORMAT_INTERNAL_DEPTH_24 = HAL_PIXEL_FORMAT_DEPTH_24,
+ MALI_GRALLOC_FORMAT_INTERNAL_DEPTH_24_STENCIL_8 = HAL_PIXEL_FORMAT_DEPTH_24_STENCIL_8,
+ MALI_GRALLOC_FORMAT_INTERNAL_DEPTH_32F = HAL_PIXEL_FORMAT_DEPTH_32F,
+ MALI_GRALLOC_FORMAT_INTERNAL_DEPTH_32F_STENCIL_8 = HAL_PIXEL_FORMAT_DEPTH_32F_STENCIL_8,
+ MALI_GRALLOC_FORMAT_INTERNAL_STENCIL_8 = HAL_PIXEL_FORMAT_STENCIL_8,
+
+ /* Flexible YUV formats would be parsed but not have any representation as
+ * internal format itself but one of the ones below.
+ */
+
+ /* The internal private formats that have no HAL equivivalent are defined
+ * afterwards starting at a specific base range.
+ */
+ MALI_GRALLOC_FORMAT_INTERNAL_NV12 = MALI_GRALLOC_FORMAT_INTERNAL_RANGE_BASE,
+ MALI_GRALLOC_FORMAT_INTERNAL_NV21,
+ MALI_GRALLOC_FORMAT_INTERNAL_YUV422_8BIT,
+
+ /* Extended YUV formats. */
+ MALI_GRALLOC_FORMAT_INTERNAL_Y0L2,
+ MALI_GRALLOC_FORMAT_INTERNAL_P010,
+ MALI_GRALLOC_FORMAT_INTERNAL_P210,
+ MALI_GRALLOC_FORMAT_INTERNAL_Y210,
+ MALI_GRALLOC_FORMAT_INTERNAL_Y410,
+
+ /*
+ * Single-plane (I = interleaved) variants of 8/10-bit YUV formats,
+ * where previously not defined.
+ */
+ MALI_GRALLOC_FORMAT_INTERNAL_YUV420_8BIT_I,
+ MALI_GRALLOC_FORMAT_INTERNAL_YUV420_10BIT_I,
+ MALI_GRALLOC_FORMAT_INTERNAL_YUV444_10BIT_I,
+
+ /* Add more internal formats here. */
+
+ /* These are legacy 0.3 gralloc formats used only by the wrap/unwrap macros. */
+ MALI_GRALLOC_FORMAT_INTERNAL_YV12_WRAP,
+ MALI_GRALLOC_FORMAT_INTERNAL_Y8_WRAP,
+ MALI_GRALLOC_FORMAT_INTERNAL_Y16_WRAP,
+
+ MALI_GRALLOC_FORMAT_INTERNAL_RANGE_LAST,
+} mali_gralloc_pixel_format;
+
+/*
+ * Compression type
+ */
+
+/* This format will use AFBC */
+#define MALI_GRALLOC_INTFMT_AFBC_BASIC (1ULL << (MALI_GRALLOC_INTFMT_EXTENSION_BIT_START + 0))
+
+
+/*
+ * AFBC modifier bits (valid with MALI_GRALLOC_INTFMT_AFBC_BASIC)
+ */
+
+/* This format uses AFBC split block mode */
+#define MALI_GRALLOC_INTFMT_AFBC_SPLITBLK (1ULL << (MALI_GRALLOC_INTFMT_EXTENSION_BIT_START + 2))
+
+/* This format uses AFBC wide block mode */
+#define MALI_GRALLOC_INTFMT_AFBC_WIDEBLK (1ULL << (MALI_GRALLOC_INTFMT_EXTENSION_BIT_START + 3))
+
+/* This format uses AFBC tiled headers */
+#define MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS (1ULL << (MALI_GRALLOC_INTFMT_EXTENSION_BIT_START + 4))
+
+/* This format uses AFBC extra wide superblocks. */
+#define MALI_GRALLOC_INTFMT_AFBC_EXTRAWIDEBLK (1ULL << (MALI_GRALLOC_INTFMT_EXTENSION_BIT_START + 5))
+
+/* This format is AFBC with double body buffer (used as a frontbuffer) */
+#define MALI_GRALLOC_INTFMT_AFBC_DOUBLE_BODY (1ULL << (MALI_GRALLOC_INTFMT_EXTENSION_BIT_START + 6))
+
+/* This format uses AFBC buffer content hints in LSB of superblock offset. */
+#define MALI_GRALLOC_INTFMT_AFBC_BCH (1ULL << (MALI_GRALLOC_INTFMT_EXTENSION_BIT_START + 7))
+
+/* This format uses AFBC with YUV transform. */
+#define MALI_GRALLOC_INTFMT_AFBC_YUV_TRANSFORM (1ULL << (MALI_GRALLOC_INTFMT_EXTENSION_BIT_START + 8))
+
+/* This format uses Sparse allocated AFBC. */
+#define MALI_GRALLOC_INTFMT_AFBC_SPARSE (1ULL << (MALI_GRALLOC_INTFMT_EXTENSION_BIT_START + 9))
+
+/* This mask should be used to check or clear support for AFBC for an internal format.
+ */
+#define MALI_GRALLOC_INTFMT_AFBCENABLE_MASK (uint64_t)(MALI_GRALLOC_INTFMT_AFBC_BASIC)
+
+
+/* These are legacy Gralloc 0.3 support macros for passing private formats through the 0.3 alloc interface.
+ * It packs modifier bits together with base format into a 32 bit format identifier.
+ * Gralloc 1.0 interface should use private functions to set private buffer format in the buffer descriptor.
+ *
+ * Packing:
+ *
+ * Bits 15-0: mali_gralloc_pixel_format format
+ * Bits 31-16: modifier bits
+ */
+static inline int mali_gralloc_format_wrapper(int format, int modifiers)
+{
+ /* Internal formats that are identical to HAL formats
+ * have the same definition. This is convenient for
+ * client parsing code to not have to parse them separately.
+ *
+ * For 3 of the HAL YUV formats that have very large definitions
+ * this causes problems for packing in modifier bits.
+ * Because of this reason we redefine these three formats
+ * while packing/unpacking them.
+ */
+ if (format == MALI_GRALLOC_FORMAT_INTERNAL_YV12)
+ {
+ format = MALI_GRALLOC_FORMAT_INTERNAL_YV12_WRAP;
+ }
+ else if (format == MALI_GRALLOC_FORMAT_INTERNAL_Y8)
+ {
+ format = MALI_GRALLOC_FORMAT_INTERNAL_Y8_WRAP;
+ }
+ else if (format == MALI_GRALLOC_FORMAT_INTERNAL_Y16)
+ {
+ format = MALI_GRALLOC_FORMAT_INTERNAL_Y16_WRAP;
+ }
+
+ if (format & ~MALI_GRALLOC_INTFMT_FMT_WRAP_MASK)
+ {
+ format = MALI_GRALLOC_FORMAT_INTERNAL_UNDEFINED;
+ MALI_GRALLOC_LOGE("Format is too large for private format wrapping");
+ }
+
+ return (modifiers | format);
+}
+
+static inline uint64_t mali_gralloc_format_unwrap(int x)
+{
+ uint64_t internal_format = (uint64_t)(((((uint64_t)(x)) & MALI_GRALLOC_INTFMT_EXT_WRAP_MASK) << MALI_GRALLOC_INTFMT_EXT_WRAP_SHIFT) | // Modifier bits
+ (((uint64_t)(x)) & MALI_GRALLOC_INTFMT_FMT_WRAP_MASK)); // Private format
+
+ uint64_t base_format = internal_format & MALI_GRALLOC_INTFMT_FMT_MASK;
+ uint64_t modifiers = internal_format & MALI_GRALLOC_INTFMT_EXT_MASK;
+
+ if (base_format == MALI_GRALLOC_FORMAT_INTERNAL_YV12_WRAP)
+ {
+ base_format = MALI_GRALLOC_FORMAT_INTERNAL_YV12;
+ }
+ else if (base_format == MALI_GRALLOC_FORMAT_INTERNAL_Y8_WRAP)
+ {
+ base_format = MALI_GRALLOC_FORMAT_INTERNAL_Y8;
+ }
+ else if (base_format == MALI_GRALLOC_FORMAT_INTERNAL_Y16_WRAP)
+ {
+ base_format = MALI_GRALLOC_FORMAT_INTERNAL_Y16;
+ }
+
+ return (modifiers | base_format);
+}
+
+/*
+ * Macro to add additional modifier(s) to existing wrapped private format.
+ * Arguments include wrapped private format and new modifier(s) to add.
+ */
+#define GRALLOC_PRIVATE_FORMAT_WRAPPER_ADD_MODIFIER(x, modifiers) \
+ ((int)((x) | ((unsigned)((modifiers) >> MALI_GRALLOC_INTFMT_EXT_WRAP_SHIFT))))
+
+/*
+ * Macro to remove modifier(s) to existing wrapped private format.
+ * Arguments include wrapped private format and modifier(s) to remove.
+ */
+#define GRALLOC_PRIVATE_FORMAT_WRAPPER_REMOVE_MODIFIER(x, modifiers) \
+ ((int)((x) & ~((unsigned)((modifiers) >> MALI_GRALLOC_INTFMT_EXT_WRAP_SHIFT))))
+
+#define GRALLOC_PRIVATE_FORMAT_WRAPPER(x) (mali_gralloc_format_wrapper(x, 0))
+
+#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC(x) \
+ mali_gralloc_format_wrapper(x, (MALI_GRALLOC_INTFMT_AFBC_BASIC | MALI_GRALLOC_INTFMT_AFBC_SPARSE) >> \
+ MALI_GRALLOC_INTFMT_EXT_WRAP_SHIFT)
+
+#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_SPLITBLK(x) \
+ GRALLOC_PRIVATE_FORMAT_WRAPPER_ADD_MODIFIER(GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC(x), \
+ MALI_GRALLOC_INTFMT_AFBC_SPLITBLK)
+
+#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_WIDEBLK(x) \
+ GRALLOC_PRIVATE_FORMAT_WRAPPER_ADD_MODIFIER(GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC(x), \
+ MALI_GRALLOC_INTFMT_AFBC_WIDEBLK)
+
+#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_WIDE_SPLIT(x) \
+ GRALLOC_PRIVATE_FORMAT_WRAPPER_ADD_MODIFIER(GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_SPLITBLK(x), \
+ MALI_GRALLOC_INTFMT_AFBC_WIDEBLK)
+
+#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_TILED_HEADERS_BASIC(x) \
+ GRALLOC_PRIVATE_FORMAT_WRAPPER_ADD_MODIFIER(GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC(x), \
+ MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS)
+
+#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_TILED_HEADERS_WIDE(x) \
+ GRALLOC_PRIVATE_FORMAT_WRAPPER_ADD_MODIFIER(GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_WIDEBLK(x), \
+ MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS)
+
+#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_TILED_HEADERS_SPLIT(x) \
+ GRALLOC_PRIVATE_FORMAT_WRAPPER_ADD_MODIFIER(GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_SPLITBLK(x), \
+ MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS)
+
+#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_TILED_HEADERS_WIDE_SPLIT(x) \
+ GRALLOC_PRIVATE_FORMAT_WRAPPER_ADD_MODIFIER(GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_WIDE_SPLIT(x), \
+ MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS)
+
+/*
+ * AFBC format with extra-wide (64x4) superblocks.
+ *
+ * NOTE: Tiled headers are mandatory for this format.
+ */
+#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_EXTRAWIDEBLK(x) \
+ GRALLOC_PRIVATE_FORMAT_WRAPPER_ADD_MODIFIER(GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_TILED_HEADERS_BASIC(x), \
+ MALI_GRALLOC_INTFMT_AFBC_EXTRAWIDEBLK)
+
+/*
+ * AFBC multi-plane YUV format where luma (wide, 32x8) and
+ * chroma (extra-wide, 64x4) planes are stored in separate AFBC buffers.
+ *
+ * NOTE: Tiled headers are mandatory for this format.
+ * NOTE: Base format (x) must be a multi-plane YUV format.
+ */
+#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_WIDE_EXTRAWIDE(x) \
+ GRALLOC_PRIVATE_FORMAT_WRAPPER_ADD_MODIFIER(GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_EXTRAWIDEBLK(x), \
+ MALI_GRALLOC_INTFMT_AFBC_WIDEBLK)
+
+#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_TILED_DOUBLE_BODY(x) \
+ GRALLOC_PRIVATE_FORMAT_WRAPPER_ADD_MODIFIER(GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_TILED_HEADERS_BASIC(x), \
+ MALI_GRALLOC_INTFMT_AFBC_DOUBLE_BODY)
+
+#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_TILED_SPLIT_DOUBLE_BODY(x) \
+ GRALLOC_PRIVATE_FORMAT_WRAPPER_ADD_MODIFIER(GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_TILED_HEADERS_SPLIT(x), \
+ MALI_GRALLOC_INTFMT_AFBC_DOUBLE_BODY)
+
+#define GRALLOC_PRIVATE_FORMAT_UNWRAP(x) mali_gralloc_format_unwrap(x)
+
+/* IP block capability masks */
+#define MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT ((uint64_t)1 << 0)
+
+/* For IPs which can't read/write YUV with AFBC encoding use flag AFBC_YUV_READ/AFBC_YUV_WRITE */
+#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC ((uint64_t)1 << 1)
+#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_SPLITBLK ((uint64_t)1 << 2)
+#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_WIDEBLK ((uint64_t)1 << 3)
+#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_WRITE_NON_SPARSE ((uint64_t)1 << 4)
+#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_RESERVED_2 ((uint64_t)1 << 5)
+#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_RESERVED_3 ((uint64_t)1 << 6)
+#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_TILED_HEADERS ((uint64_t)1 << 7)
+#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_EXTRAWIDEBLK ((uint64_t)1 << 8)
+#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_MULTIPLANE_READ ((uint64_t)1 << 9)
+#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_DOUBLE_BODY ((uint64_t)1 << 10)
+#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_YUV_READ ((uint64_t)1 << 11)
+#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_YUV_WRITE ((uint64_t)1 << 12)
+#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_RGBA16161616 ((uint64_t)1 << 13)
+
+
+#define MALI_GRALLOC_FORMAT_CAPABILITY_PIXFMT_RGBA1010102 ((uint64_t)1 << 32)
+#define MALI_GRALLOC_FORMAT_CAPABILITY_PIXFMT_RGBA16161616 ((uint64_t)1 << 33)
+
+#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK \
+ ((uint64_t)(MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC | MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_SPLITBLK | \
+ MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_WIDEBLK | MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_TILED_HEADERS))
+
+struct mali_gralloc_format_caps
+{
+ uint64_t caps_mask;
+};
+typedef struct mali_gralloc_format_caps mali_gralloc_format_caps;
+
+#define MALI_GRALLOC_FORMATCAPS_SYM_NAME mali_gralloc_format_capabilities
+#define MALI_GRALLOC_FORMATCAPS_SYM_NAME_STR "mali_gralloc_format_capabilities"
+
+/* Internal prototypes */
+#if defined(GRALLOC_LIBRARY_BUILD)
+
+void mali_gralloc_adjust_dimensions(const uint64_t internal_format,
+ const uint64_t usage,
+ int* const width,
+ int* const height);
+
+uint64_t mali_gralloc_select_format(const uint64_t req_format,
+ const mali_gralloc_format_type type,
+ const uint64_t usage,
+ const int buffer_size);
+
+bool is_subsampled_yuv(const uint32_t base_format);
+#endif
+
+bool is_exynos_format(uint32_t base_format);
+
+#endif /* MALI_GRALLOC_FORMATS_H_ */
diff --git a/gralloc4/src/mali_gralloc_log.h b/gralloc4/src/mali_gralloc_log.h
new file mode 100644
index 0000000..aa4e26c
--- /dev/null
+++ b/gralloc4/src/mali_gralloc_log.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 ARM Limited. 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 MALI_GRALLOC_LOG_H
+#define MALI_GRALLOC_LOG_H
+
+#ifndef LOG_TAG
+#define LOG_TAG "mali_gralloc"
+#endif
+
+#include <log/log.h>
+
+/* Delegate logging to Android */
+#define MALI_GRALLOC_LOGI(...) ALOGI(__VA_ARGS__)
+#define MALI_GRALLOC_LOGV(...) ALOGV(__VA_ARGS__)
+#define MALI_GRALLOC_LOGW(...) ALOGW(__VA_ARGS__)
+#define MALI_GRALLOC_LOGE(...) ALOGE(__VA_ARGS__)
+
+#endif
diff --git a/gralloc4/src/mali_gralloc_usages.h b/gralloc4/src/mali_gralloc_usages.h
new file mode 100644
index 0000000..aff0eb1
--- /dev/null
+++ b/gralloc4/src/mali_gralloc_usages.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2017-2020 ARM Limited. All rights reserved.
+ *
+ * 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 MALI_GRALLOC_USAGES_H_
+#define MALI_GRALLOC_USAGES_H_
+
+#define GRALLOC_USAGE_PRIVATE_MASK (0xffff0000f0000000U)
+
+/*
+ * MALI_GRALLOC_USAGE_AFBC_PADDING is only valid if MALI_GRALLOC_USAGE_NO_AFBC
+ * is not present.
+ */
+
+
+#include <android/hardware/graphics/common/1.2/types.h>
+/* BufferUsage is not defined in 1.2/types.h as there are no changes from previous version */
+namespace hidl_common = android::hardware::graphics::common::V1_1;
+
+
+/* Local macro definitions to emulate Gralloc 1.0 usage interface */
+#define GRALLOC_USAGE_PRIVATE_0 1ULL << 28
+#define GRALLOC_USAGE_PRIVATE_1 1ULL << 29
+#define GRALLOC_USAGE_PRIVATE_2 1ULL << 30
+#define GRALLOC_USAGE_PRIVATE_3 1ULL << 31
+#define GRALLOC_USAGE_PRIVATE_4 1ULL << 63
+#define GRALLOC_USAGE_PRIVATE_5 1ULL << 62
+#define GRALLOC_USAGE_PRIVATE_6 1ULL << 61
+#define GRALLOC_USAGE_PRIVATE_7 1ULL << 60
+#define GRALLOC_USAGE_PRIVATE_8 1ULL << 59
+#define GRALLOC_USAGE_PRIVATE_9 1ULL << 58
+#define GRALLOC_USAGE_PRIVATE_10 1ULL << 57
+#define GRALLOC_USAGE_PRIVATE_11 1ULL << 56
+#define GRALLOC_USAGE_PRIVATE_12 1ULL << 55
+#define GRALLOC_USAGE_PRIVATE_13 1ULL << 54
+#define GRALLOC_USAGE_PRIVATE_14 1ULL << 53
+#define GRALLOC_USAGE_PRIVATE_15 1ULL << 52
+#define GRALLOC_USAGE_PRIVATE_16 1ULL << 51
+#define GRALLOC_USAGE_PRIVATE_17 1ULL << 50
+#define GRALLOC_USAGE_PRIVATE_18 1ULL << 49
+#define GRALLOC_USAGE_PRIVATE_19 1ULL << 48
+
+typedef enum
+{
+ MALI_GRALLOC_USAGE_FRONTBUFFER = GRALLOC_USAGE_PRIVATE_12,
+ MALI_GRALLOC_USAGE_FORCE_BACKBUFFER = GRALLOC_USAGE_PRIVATE_13,
+ MALI_GRALLOC_USAGE_NO_AFBC = GRALLOC_USAGE_PRIVATE_1,
+ MALI_GRALLOC_USAGE_AFBC_PADDING = GRALLOC_USAGE_PRIVATE_14,
+
+ /* SLSI specific usages */
+ GRALLOC_USAGE_PROTECTED_DPB = GRALLOC_USAGE_PRIVATE_0,
+ GRALLOC_USAGE_CAMERA_RESERVED = GRALLOC_USAGE_PRIVATE_2,
+ GRALLOC_USAGE_SECURE_CAMERA_RESERVED = GRALLOC_USAGE_PRIVATE_3,
+ GRALLOC_USAGE_PRIVATE_NONSECURE = GRALLOC_USAGE_PRIVATE_8,
+ GRALLOC_USAGE_NOZEROED = GRALLOC_USAGE_PRIVATE_9,
+
+ GRALLOC_USAGE_YUV_RANGE_FULL = GRALLOC_USAGE_PRIVATE_4,
+ GRALLOC_USAGE_DAYDREAM_SINGLE_BUFFER_MODE = GRALLOC_USAGE_PRIVATE_5,
+ GRALLOC_USAGE_VIDEO_EXT = GRALLOC_USAGE_PRIVATE_6,
+ GRALLOC_USAGE_VIDEO_PRIVATE_DATA = GRALLOC_USAGE_PRIVATE_7,
+
+ GRALLOC_USAGE_HFR_MODE = GRALLOC_USAGE_PRIVATE_10,
+ GRALLOC_USAGE_SBWC_REQUEST_10BIT = GRALLOC_USAGE_PRIVATE_11,
+
+ GRALLOC_USAGE_ROIINFO = GRALLOC_USAGE_PRIVATE_15,
+
+} mali_gralloc_usage_type;
+
+#define GRALLOC_USAGE_SW_WRITE_RARELY static_cast<uint64_t>(hidl_common::BufferUsage::CPU_WRITE_RARELY)
+#define GRALLOC_USAGE_SW_WRITE_OFTEN static_cast<uint64_t>(hidl_common::BufferUsage::CPU_WRITE_OFTEN)
+#define GRALLOC_USAGE_SW_READ_RARELY static_cast<uint64_t>(hidl_common::BufferUsage::CPU_READ_RARELY)
+#define GRALLOC_USAGE_SW_READ_OFTEN static_cast<uint64_t>(hidl_common::BufferUsage::CPU_READ_OFTEN)
+#define GRALLOC_USAGE_RENDERSCRIPT static_cast<uint64_t>(hidl_common::BufferUsage::RENDERSCRIPT)
+#define GRALLOC_USAGE_HW_FB static_cast<uint64_t>(hidl_common::BufferUsage::COMPOSER_CLIENT_TARGET)
+
+/* Bit 10 must be zero as per Gralloc 2.x interface specification. Used, however, for backward compatibility */
+#define GRALLOC_USAGE_HW_2D static_cast<uint64_t>(0x00000400)
+
+#define GRALLOC_USAGE_SW_WRITE_MASK static_cast<uint64_t>(hidl_common::BufferUsage::CPU_WRITE_MASK)
+#define GRALLOC_USAGE_SW_READ_MASK static_cast<uint64_t>(hidl_common::BufferUsage::CPU_READ_MASK)
+#define GRALLOC_USAGE_PROTECTED static_cast<uint64_t>(hidl_common::BufferUsage::PROTECTED)
+#define GRALLOC_USAGE_CURSOR static_cast<uint64_t>(hidl_common::BufferUsage::COMPOSER_CURSOR)
+#define GRALLOC_USAGE_HW_RENDER static_cast<uint64_t>(hidl_common::BufferUsage::GPU_RENDER_TARGET)
+#define GRALLOC_USAGE_HW_CAMERA_WRITE static_cast<uint64_t>(hidl_common::BufferUsage::CAMERA_OUTPUT)
+#define GRALLOC_USAGE_HW_CAMERA_READ static_cast<uint64_t>(hidl_common::BufferUsage::CAMERA_INPUT)
+#define GRALLOC_USAGE_HW_TEXTURE static_cast<uint64_t>(hidl_common::BufferUsage::GPU_TEXTURE)
+#define GRALLOC_USAGE_HW_VIDEO_ENCODER static_cast<uint64_t>(hidl_common::BufferUsage::VIDEO_ENCODER)
+#define GRALLOC_USAGE_HW_VIDEO_DECODER static_cast<uint64_t>(hidl_common::BufferUsage::VIDEO_DECODER)
+#define GRALLOC_USAGE_HW_COMPOSER static_cast<uint64_t>(hidl_common::BufferUsage::COMPOSER_OVERLAY)
+#define GRALLOC_USAGE_EXTERNAL_DISP static_cast<uint64_t>(0x00002000)
+
+#define GRALLOC_USAGE_SENSOR_DIRECT_DATA static_cast<uint64_t>(hidl_common::BufferUsage::SENSOR_DIRECT_DATA)
+#define GRALLOC_USAGE_GPU_DATA_BUFFER static_cast<uint64_t>(hidl_common::BufferUsage::GPU_DATA_BUFFER)
+
+
+/* Originally (Gralloc 0.x), Android did not provide an explicit DECODER usage. This was rectified in Android N-MR1/7.1
+ * when Gralloc 1.0 defined GRALLOC1_PRODUCER_USAGE_VIDEO_DECODER. However, libstagefright continues
+ * (currently, Android P/9.0) to use this old combination of flags to indicate decoder producer
+ */
+#define GRALLOC_USAGE_DECODER (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_EXTERNAL_DISP)
+
+static const uint64_t VALID_USAGE =
+ GRALLOC_USAGE_SW_READ_MASK | /* 0x0FU */
+ GRALLOC_USAGE_SW_WRITE_MASK | /* 0xF0U */
+ GRALLOC_USAGE_HW_TEXTURE | /* 1U << 8 */
+ GRALLOC_USAGE_HW_RENDER | /* 1U << 9 */
+ GRALLOC_USAGE_HW_2D | /* 1U << 10 */
+ GRALLOC_USAGE_HW_COMPOSER | /* 1U << 11 */
+ GRALLOC_USAGE_HW_FB | /* 1U << 12 */
+ GRALLOC_USAGE_EXTERNAL_DISP | /* 1U << 13 */
+ GRALLOC_USAGE_PROTECTED | /* 1U << 14 */
+ GRALLOC_USAGE_CURSOR | /* 1U << 15 */
+ GRALLOC_USAGE_HW_VIDEO_ENCODER | /* 1U << 16 */
+ GRALLOC_USAGE_HW_CAMERA_WRITE | /* 1U << 17 */
+ GRALLOC_USAGE_HW_CAMERA_READ | /* 1U << 18 */
+ GRALLOC_USAGE_RENDERSCRIPT | /* 1U << 20 */
+ GRALLOC_USAGE_HW_VIDEO_DECODER | /* 1U << 22 */
+ /* Producer and consumer usage are combined, but on Gralloc version 1 there is no way to differentiate these as they
+ * are mapped to the same value (1U << 23). */
+ GRALLOC_USAGE_SENSOR_DIRECT_DATA | /* 1U << 23 */
+ GRALLOC_USAGE_GPU_DATA_BUFFER | /* 1U << 24 */
+
+ GRALLOC_USAGE_PRIVATE_19 | /* 1U << 48 */
+ GRALLOC_USAGE_PRIVATE_18 | /* 1U << 49 */
+ GRALLOC_USAGE_PRIVATE_17 | /* 1U << 50 */
+ GRALLOC_USAGE_PRIVATE_16 | /* 1U << 51 */
+ GRALLOC_USAGE_PRIVATE_15 | /* 1U << 52 */
+ GRALLOC_USAGE_PRIVATE_14 | /* 1U << 53 */
+ GRALLOC_USAGE_PRIVATE_13 | /* 1U << 54 */
+ GRALLOC_USAGE_PRIVATE_11 | /* 1U << 56 */
+ GRALLOC_USAGE_PRIVATE_0 | /* 1U << 28 */
+ GRALLOC_USAGE_PRIVATE_1 | /* 1U << 29 */
+ 0 |
+ -1;
+
+#endif /*MALI_GRALLOC_USAGES_H_*/