diff options
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_*/ |