| /* |
| * Copyright (C) 2016-2017 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> |
| |
| #if GRALLOC_USE_GRALLOC1_API == 1 |
| #include <hardware/gralloc1.h> |
| #else |
| #include <hardware/gralloc.h> |
| #endif |
| |
| #include "mali_gralloc_module.h" |
| #include "gralloc_priv.h" |
| |
| static mali_gralloc_format_caps dpu_runtime_caps; |
| static mali_gralloc_format_caps vpu_runtime_caps; |
| static mali_gralloc_format_caps gpu_runtime_caps; |
| static mali_gralloc_format_caps cam_runtime_caps; |
| static pthread_mutex_t caps_init_mutex = PTHREAD_MUTEX_INITIALIZER; |
| static bool runtime_caps_read = false; |
| |
| #define MALI_GRALLOC_GPU_LIB_NAME "libGLES_mali.so" |
| #if defined(__LP64__) |
| #define MALI_GRALLOC_GPU_LIBRARY_PATH1 "/vendor/lib64/egl/" |
| #define MALI_GRALLOC_GPU_LIBRARY_PATH2 "/system/lib64/egl/" |
| #else |
| #define MALI_GRALLOC_GPU_LIBRARY_PATH1 "/vendor/lib/egl/" |
| #define MALI_GRALLOC_GPU_LIBRARY_PATH2 "/system/lib/egl/" |
| #endif |
| |
| #define GRALLOC_AFBC_MIN_SIZE 75 |
| |
| static bool get_block_capabilities(bool hal_module, const char *name, mali_gralloc_format_caps *block_caps) |
| { |
| void *dso_handle = NULL; |
| bool rval = false; |
| |
| /* Look for MALI_GRALLOC_FORMATCAPS_SYM_NAME_STR symbol in user-space drivers |
| * to determine hw format capabilities. |
| */ |
| if (!hal_module) |
| { |
| dso_handle = dlopen(name, RTLD_LAZY); |
| } |
| else |
| { |
| /* libhardware does some heuristics to find hal modules |
| * and then stores the dso handle internally. Use this. |
| */ |
| const struct hw_module_t *module = { NULL }; |
| |
| if (hw_get_module(name, &module) >= 0) |
| { |
| dso_handle = module->dso; |
| } |
| } |
| |
| if (dso_handle) |
| { |
| void *sym = dlsym(dso_handle, MALI_GRALLOC_FORMATCAPS_SYM_NAME_STR); |
| |
| if (sym) |
| { |
| memcpy((void *)block_caps, sym, sizeof(mali_gralloc_format_caps)); |
| rval = true; |
| } |
| |
| if (!hal_module) |
| { |
| dlclose(dso_handle); |
| } |
| } |
| |
| return rval; |
| } |
| |
| static int map_flex_formats(uint64_t req_format) |
| { |
| /* Map Android flexible formats to internal base formats */ |
| if(req_format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED || |
| req_format == HAL_PIXEL_FORMAT_YCbCr_420_888) |
| { |
| req_format = MALI_GRALLOC_FORMAT_INTERNAL_NV12; |
| |
| } |
| return req_format; |
| } |
| |
| static bool is_afbc_supported(int req_format_mapped) |
| { |
| bool rval = true; |
| |
| /* These base formats we currently don't support with compression */ |
| switch (req_format_mapped) |
| { |
| case MALI_GRALLOC_FORMAT_INTERNAL_RAW16: |
| case MALI_GRALLOC_FORMAT_INTERNAL_RAW12: |
| case MALI_GRALLOC_FORMAT_INTERNAL_RAW10: |
| case MALI_GRALLOC_FORMAT_INTERNAL_BLOB: |
| case MALI_GRALLOC_FORMAT_INTERNAL_P010: |
| case MALI_GRALLOC_FORMAT_INTERNAL_P210: |
| case MALI_GRALLOC_FORMAT_INTERNAL_Y410: |
| case HAL_PIXEL_FORMAT_YCbCr_422_I: |
| rval = false; |
| break; |
| } |
| |
| return rval; |
| } |
| |
| static bool is_android_yuv_format(int req_format) |
| { |
| bool rval = false; |
| |
| switch (req_format) |
| { |
| case HAL_PIXEL_FORMAT_YV12: |
| case HAL_PIXEL_FORMAT_Y8: |
| case HAL_PIXEL_FORMAT_Y16: |
| case HAL_PIXEL_FORMAT_YCbCr_420_888: |
| case HAL_PIXEL_FORMAT_YCbCr_422_888: |
| case HAL_PIXEL_FORMAT_YCbCr_444_888: |
| case MALI_GRALLOC_FORMAT_INTERNAL_NV12: |
| case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: |
| rval = true; |
| break; |
| } |
| |
| return rval; |
| } |
| |
| static bool is_afbc_allowed(int buffer_size) |
| { |
| bool afbc_allowed = false; |
| |
| (void)buffer_size; |
| |
| #if MALI_DISPLAY_VERSION == 550 || MALI_DISPLAY_VERSION == 650 |
| #if GRALLOC_DISP_W != 0 && GRALLOC_DISP_H != 0 |
| afbc_allowed = ((buffer_size * 100) / (GRALLOC_DISP_W * GRALLOC_DISP_H)) >= GRALLOC_AFBC_MIN_SIZE; |
| |
| #else |
| /* If display size is not valid then always allow AFBC */ |
| afbc_allowed = true; |
| |
| #endif |
| #else |
| /* For cetus, always allow AFBC */ |
| afbc_allowed = true; |
| #endif |
| return afbc_allowed; |
| } |
| |
| static bool is_afbc_format(uint64_t internal_format) |
| { |
| return (internal_format & MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK) != 0; |
| } |
| |
| static uint64_t determine_best_format(int req_format, mali_gralloc_producer_type producer, |
| mali_gralloc_consumer_type consumer, uint64_t producer_runtime_mask, |
| uint64_t consumer_runtime_mask) |
| { |
| /* Default is to return the requested format */ |
| uint64_t internal_format = req_format; |
| uint64_t dpu_mask = dpu_runtime_caps.caps_mask; |
| uint64_t gpu_mask = gpu_runtime_caps.caps_mask; |
| uint64_t vpu_mask = vpu_runtime_caps.caps_mask; |
| uint64_t cam_mask = cam_runtime_caps.caps_mask; |
| |
| if (producer == MALI_GRALLOC_PRODUCER_GPU && |
| gpu_runtime_caps.caps_mask & MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT) |
| { |
| gpu_mask &= producer_runtime_mask; |
| |
| if (consumer == MALI_GRALLOC_CONSUMER_GPU_OR_DISPLAY) |
| { |
| gpu_mask &= consumer_runtime_mask; |
| dpu_mask &= consumer_runtime_mask; |
| |
| if (gpu_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_SPLITBLK && |
| dpu_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_SPLITBLK) |
| { |
| internal_format |= MALI_GRALLOC_INTFMT_AFBC_SPLITBLK; |
| } |
| else if (gpu_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC && |
| dpu_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC) |
| { |
| internal_format |= MALI_GRALLOC_INTFMT_AFBC_BASIC; |
| |
| if (gpu_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_TILED_HEADERS && |
| dpu_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_TILED_HEADERS) |
| { |
| internal_format |= MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS; |
| } |
| } |
| } |
| else if (consumer == MALI_GRALLOC_CONSUMER_GPU_EXCL) |
| { |
| gpu_mask &= consumer_runtime_mask; |
| |
| /* When GPU acts as both producer and consumer it prefers 16x16 superblocks */ |
| if (gpu_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC) |
| { |
| internal_format |= MALI_GRALLOC_INTFMT_AFBC_BASIC; |
| } |
| |
| if (gpu_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_TILED_HEADERS) |
| { |
| internal_format |= MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS; |
| } |
| } |
| else if (consumer == MALI_GRALLOC_CONSUMER_VIDEO_ENCODER) |
| { |
| vpu_mask &= consumer_runtime_mask; |
| |
| if (internal_format == HAL_PIXEL_FORMAT_YV12 || internal_format == MALI_GRALLOC_FORMAT_INTERNAL_NV12) |
| { |
| if (gpu_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC && |
| vpu_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC) |
| { |
| internal_format |= MALI_GRALLOC_INTFMT_AFBC_BASIC; |
| } |
| |
| if (gpu_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_TILED_HEADERS && |
| vpu_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_TILED_HEADERS) |
| { |
| internal_format |= MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS; |
| } |
| } |
| } |
| } |
| else if (producer == MALI_GRALLOC_PRODUCER_VIDEO_DECODER && |
| vpu_runtime_caps.caps_mask & MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT) |
| { |
| vpu_mask &= producer_runtime_mask; |
| |
| if (consumer == MALI_GRALLOC_CONSUMER_GPU_OR_DISPLAY) |
| { |
| gpu_mask &= consumer_runtime_mask; |
| dpu_mask &= consumer_runtime_mask; |
| |
| if (internal_format == HAL_PIXEL_FORMAT_YV12) |
| { |
| if (vpu_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC && |
| gpu_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC && |
| dpu_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC) |
| { |
| internal_format |= MALI_GRALLOC_INTFMT_AFBC_BASIC; |
| } |
| |
| if (vpu_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_TILED_HEADERS && |
| gpu_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_TILED_HEADERS && |
| dpu_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_TILED_HEADERS) |
| { |
| internal_format |= MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS; |
| } |
| } |
| } |
| else if (consumer == MALI_GRALLOC_CONSUMER_GPU_EXCL) |
| { |
| gpu_mask &= consumer_runtime_mask; |
| |
| if (internal_format == HAL_PIXEL_FORMAT_YV12) |
| { |
| if (gpu_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC && |
| vpu_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC) |
| { |
| internal_format |= MALI_GRALLOC_INTFMT_AFBC_BASIC; |
| } |
| |
| if (gpu_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_TILED_HEADERS && |
| vpu_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_TILED_HEADERS) |
| { |
| internal_format |= MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS; |
| } |
| } |
| } |
| else if (consumer == MALI_GRALLOC_CONSUMER_VIDEO_ENCODER) |
| { |
| /* Fall-through. To be decided.*/ |
| } |
| } |
| else if (producer == MALI_GRALLOC_PRODUCER_CAMERA && |
| cam_runtime_caps.caps_mask & MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT) |
| { |
| if (consumer == MALI_GRALLOC_CONSUMER_GPU_OR_DISPLAY) |
| { |
| /* Fall-through. To be decided.*/ |
| } |
| else if (consumer == MALI_GRALLOC_CONSUMER_GPU_EXCL) |
| { |
| /* Fall-through. To be decided.*/ |
| } |
| else if (consumer == MALI_GRALLOC_CONSUMER_VIDEO_ENCODER) |
| { |
| /* Fall-through. To be decided.*/ |
| } |
| } |
| |
| return internal_format; |
| } |
| |
| static uint64_t decode_internal_format(uint64_t req_format, mali_gralloc_format_type type) |
| { |
| uint64_t internal_format, me_mask, base_format, mapped_base_format; |
| |
| if (type == MALI_GRALLOC_FORMAT_TYPE_USAGE) |
| { |
| internal_format = GRALLOC_PRIVATE_FORMAT_UNWRAP((int)req_format); |
| } |
| else if (type == MALI_GRALLOC_FORMAT_TYPE_INTERNAL) |
| { |
| internal_format = req_format; |
| } |
| else |
| { |
| internal_format = 0; |
| goto out; |
| } |
| |
| me_mask = internal_format & MALI_GRALLOC_INTFMT_ME_EXT_MASK; |
| |
| if (me_mask > 0 && ((me_mask - 1) & me_mask) != 0) |
| { |
| ALOGE("Internal format contains multiple mutually exclusive modifier bits: %" PRIx64, internal_format); |
| internal_format = 0; |
| goto out; |
| } |
| |
| base_format = internal_format & MALI_GRALLOC_INTFMT_FMT_MASK; |
| |
| /* Even though private format allocations are intended to be for specific |
| * formats, certain test cases uses the flexible formats that needs to be mapped |
| * to internal ones. |
| */ |
| mapped_base_format = map_flex_formats((uint32_t)base_format); |
| |
| /* Validate the internal base format passed in */ |
| switch (mapped_base_format) |
| { |
| case MALI_GRALLOC_FORMAT_INTERNAL_RGBA_8888: |
| case MALI_GRALLOC_FORMAT_INTERNAL_RGBX_8888: |
| case MALI_GRALLOC_FORMAT_INTERNAL_RGB_888: |
| case MALI_GRALLOC_FORMAT_INTERNAL_RGB_565: |
| case MALI_GRALLOC_FORMAT_INTERNAL_BGRA_8888: |
| case MALI_GRALLOC_FORMAT_INTERNAL_YV12: |
| case MALI_GRALLOC_FORMAT_INTERNAL_Y8: |
| case MALI_GRALLOC_FORMAT_INTERNAL_Y16: |
| case MALI_GRALLOC_FORMAT_INTERNAL_RAW16: |
| case MALI_GRALLOC_FORMAT_INTERNAL_RAW12: |
| case MALI_GRALLOC_FORMAT_INTERNAL_RAW10: |
| case MALI_GRALLOC_FORMAT_INTERNAL_BLOB: |
| case MALI_GRALLOC_FORMAT_INTERNAL_NV12: |
| case MALI_GRALLOC_FORMAT_INTERNAL_NV21: |
| case MALI_GRALLOC_FORMAT_INTERNAL_YUV422_8BIT: |
| case MALI_GRALLOC_FORMAT_INTERNAL_Y0L2: |
| case MALI_GRALLOC_FORMAT_INTERNAL_P010: |
| case MALI_GRALLOC_FORMAT_INTERNAL_P210: |
| case MALI_GRALLOC_FORMAT_INTERNAL_Y210: |
| case MALI_GRALLOC_FORMAT_INTERNAL_Y410: |
| if (mapped_base_format != base_format) |
| { |
| internal_format = (internal_format & MALI_GRALLOC_INTFMT_EXT_MASK) | mapped_base_format; |
| } |
| |
| break; |
| |
| default: |
| ALOGE("Internal base format requested is unrecognized: %" PRIx64, internal_format); |
| internal_format = 0; |
| break; |
| } |
| |
| out: |
| return internal_format; |
| } |
| |
| static bool determine_producer(mali_gralloc_producer_type *producer, uint64_t *producer_runtime_mask, int req_format, |
| int usage) |
| { |
| bool rval = true; |
| |
| /* Default to GPU */ |
| *producer = MALI_GRALLOC_PRODUCER_GPU; |
| |
| if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) |
| { |
| rval = false; |
| } |
| else if (usage & GRALLOC_USAGE_HW_RENDER) |
| { |
| if (is_android_yuv_format(req_format)) |
| { |
| if (gpu_runtime_caps.caps_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_YUV_NOWRITE) |
| { |
| *producer_runtime_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK; |
| } |
| else |
| { |
| /* All GPUs that can write YUV AFBC can only do it in 16x16, optionally with tiled */ |
| *producer_runtime_mask &= |
| ~(MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_SPLITBLK | MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_WIDEBLK); |
| } |
| } |
| |
| *producer = MALI_GRALLOC_PRODUCER_GPU; |
| } |
| else if (usage & GRALLOC_USAGE_HW_CAMERA_MASK) |
| { |
| *producer = MALI_GRALLOC_PRODUCER_CAMERA; |
| } |
| /* HW_TEXTURE+HW_COMPOSER+EXTERNAL_DISP is a definition set by |
| * stagefright for "video decoder". We check for it here. |
| */ |
| else if ((usage & (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_EXTERNAL_DISP)) == |
| (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_EXTERNAL_DISP)) |
| { |
| *producer = MALI_GRALLOC_PRODUCER_VIDEO_DECODER; |
| } |
| |
| return rval; |
| } |
| |
| static bool determine_consumer(mali_gralloc_consumer_type *consumer, uint64_t *consumer_runtime_mask, int req_format, |
| int usage) |
| { |
| bool rval = true; |
| |
| /* Default to GPU */ |
| *consumer = MALI_GRALLOC_CONSUMER_GPU_EXCL; |
| |
| if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) |
| { |
| rval = false; |
| } |
| /* When usage explicitly targets a consumer, as it does with GRALLOC_USAGE_HW_FB, |
| * we pick DPU even if there are no runtime capabilities present. |
| */ |
| else if (usage & GRALLOC_USAGE_HW_FB) |
| { |
| *consumer = MALI_GRALLOC_CONSUMER_GPU_OR_DISPLAY; |
| } |
| else if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) |
| { |
| if (is_android_yuv_format(req_format)) |
| { |
| if (vpu_runtime_caps.caps_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_YUV_NOREAD) |
| *consumer_runtime_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK; |
| } |
| else |
| { |
| *consumer_runtime_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK; |
| } |
| *consumer = MALI_GRALLOC_CONSUMER_VIDEO_ENCODER; |
| } |
| /* GRALLOC_USAGE_HW_COMPOSER is by default applied by SurfaceFlinger so we can't exclusively rely on it |
| * to determine consumer. When a buffer is targeted for either we reject the DPU when it lacks |
| * runtime capabilities, in favor of the more capable GPU. |
| */ |
| else if ((usage & (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER)) == |
| (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER) && |
| dpu_runtime_caps.caps_mask & MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT) |
| { |
| *consumer = MALI_GRALLOC_CONSUMER_GPU_OR_DISPLAY; |
| } |
| else if (usage & GRALLOC_USAGE_HW_TEXTURE) |
| { |
| *consumer = MALI_GRALLOC_CONSUMER_GPU_EXCL; |
| } |
| |
| return rval; |
| } |
| |
| /* |
| * Here we determine format capabilities for the 4 IPs we support. |
| * For now these are controlled by build defines, but in the future |
| * they should be read out from each user-space driver. |
| */ |
| static void determine_format_capabilities() |
| { |
| /* Loading libraries can take some time and |
| * we may see many allocations at boot. |
| */ |
| pthread_mutex_lock(&caps_init_mutex); |
| |
| if (runtime_caps_read) |
| { |
| goto already_init; |
| } |
| |
| 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 DPU format capabilities */ |
| if (!get_block_capabilities(true, "hwcomposer", &dpu_runtime_caps)) |
| { |
| #if MALI_DISPLAY_VERSION >= 500 |
| dpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT; |
| dpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC; |
| |
| #if MALI_DISPLAY_VERSION >= 550 |
| dpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_SPLITBLK; |
| #endif |
| #endif |
| } |
| |
| /* Determine GPU format capabilities */ |
| if (access(MALI_GRALLOC_GPU_LIBRARY_PATH1 MALI_GRALLOC_GPU_LIB_NAME, R_OK) == 0) |
| { |
| get_block_capabilities(false, MALI_GRALLOC_GPU_LIBRARY_PATH1 MALI_GRALLOC_GPU_LIB_NAME, &gpu_runtime_caps); |
| } |
| else if (access(MALI_GRALLOC_GPU_LIBRARY_PATH2 MALI_GRALLOC_GPU_LIB_NAME, R_OK) == 0) |
| { |
| get_block_capabilities(false, MALI_GRALLOC_GPU_LIBRARY_PATH2 MALI_GRALLOC_GPU_LIB_NAME, &gpu_runtime_caps); |
| } |
| |
| if ((gpu_runtime_caps.caps_mask & MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT) == 0) |
| { |
| ALOGW("Failed to find GPU block configuration in %s. Using static build configuration.", |
| MALI_GRALLOC_GPU_LIB_NAME); |
| |
| #if 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; |
| |
| /* Need to verify when to remove this */ |
| gpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_YUV_NOWRITE; |
| |
| #if MALI_SUPPORT_AFBC_SPLITBLK == 1 |
| gpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_SPLITBLK; |
| #endif |
| |
| #if MALI_SUPPORT_AFBC_WIDEBLK == 1 |
| gpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_SPLITBLK; |
| gpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_WIDEBLK; |
| #endif |
| |
| #if MALI_USE_YUV_AFBC_WIDEBLK != 1 |
| gpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_WIDEBLK_YUV_DISABLE; |
| #endif |
| |
| #if MALI_SUPPORT_AFBC_TILED_HEADERS == 1 |
| gpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_SPLITBLK; |
| gpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_WIDEBLK; |
| gpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_TILED_HEADERS; |
| #endif |
| #endif /* MALI_GPU_SUPPORT_AFBC_BASIC == 1 */ |
| } |
| |
| /* Determine VPU format capabilities */ |
| #if MALI_VIDEO_VERSION == 500 || MALI_VIDEO_VERSION == 550 |
| vpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT; |
| vpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC; |
| vpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_YUV_NOREAD; |
| #endif |
| |
| #if MALI_VIDEO_VERSION == 61 |
| vpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_OPTIONS_PRESENT; |
| vpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_BASIC; |
| vpu_runtime_caps.caps_mask |= MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_TILED_HEADERS; |
| #endif |
| |
| /* Build specific capability changes */ |
| #if 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 |
| |
| runtime_caps_read = true; |
| |
| already_init: |
| pthread_mutex_unlock(&caps_init_mutex); |
| |
| ALOGV("GPU format capabilities 0x%" PRIx64, gpu_runtime_caps.caps_mask); |
| ALOGV("DPU format capabilities 0x%" PRIx64, dpu_runtime_caps.caps_mask); |
| ALOGV("VPU format capabilities 0x%" PRIx64, vpu_runtime_caps.caps_mask); |
| ALOGV("CAM format capabilities 0x%" PRIx64, cam_runtime_caps.caps_mask); |
| } |
| |
| uint64_t mali_gralloc_select_format(uint64_t req_format, mali_gralloc_format_type type, uint64_t usage, int buffer_size) |
| { |
| uint64_t internal_format = 0; |
| mali_gralloc_consumer_type consumer; |
| mali_gralloc_producer_type producer; |
| uint64_t producer_runtime_mask = ~(0ULL); |
| uint64_t consumer_runtime_mask = ~(0ULL); |
| uint64_t req_format_mapped = 0; |
| |
| if (!runtime_caps_read) |
| { |
| /* |
| * It is better to initialize these when needed because |
| * not all processes allocates memory. |
| */ |
| determine_format_capabilities(); |
| } |
| |
| /* A unique usage specifies that an internal format is in req_format */ |
| if (usage & MALI_GRALLOC_USAGE_PRIVATE_FORMAT || type == MALI_GRALLOC_FORMAT_TYPE_INTERNAL) |
| { |
| internal_format = decode_internal_format(req_format, type); |
| goto out; |
| } |
| |
| /* Re-map special Android formats */ |
| req_format_mapped = map_flex_formats(req_format); |
| |
| /* Determine producer/consumer */ |
| if (!determine_producer(&producer, &producer_runtime_mask, req_format, usage) || |
| !determine_consumer(&consumer, &consumer_runtime_mask, req_format, usage)) |
| { |
| /* Failing to determine producer/consumer usually means |
| * client has requested sw rendering. |
| */ |
| internal_format = req_format_mapped; |
| goto out; |
| } |
| |
| /* |
| * Determine runtime capability limitations |
| */ |
| |
| /* Disable AFBC based on unique usage */ |
| if ((usage & MALI_GRALLOC_USAGE_NO_AFBC) == MALI_GRALLOC_USAGE_NO_AFBC) |
| { |
| if (is_android_yuv_format(req_format_mapped)) |
| { |
| ALOGE("It is invalid to specify NO_AFBC usage flags when allocating YUV formats.\ |
| Requested fmt: 0x%" PRIx64 " Re-Mapped fmt: 0x%" PRIx64, |
| req_format, req_format_mapped); |
| internal_format = 0; |
| goto out; |
| } |
| |
| producer_runtime_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK; |
| } |
| /* Disable AFBC based on buffer dimensions */ |
| else if (!is_afbc_allowed(buffer_size)) |
| { |
| producer_runtime_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK; |
| } |
| else if (!is_afbc_supported(req_format_mapped)) |
| { |
| producer_runtime_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK; |
| } |
| |
| /* Automatically select format in case producer/consumer identified */ |
| internal_format = |
| determine_best_format(req_format_mapped, producer, consumer, producer_runtime_mask, consumer_runtime_mask); |
| |
| out: |
| ALOGV("mali_gralloc_select_format: req_format=0x%08" PRIx64 " req_fmt_mapped=0x%" PRIx64 |
| " internal_format=0x%" PRIx64 " usage=0x%" PRIx64, |
| req_format, req_format_mapped, internal_format, usage); |
| |
| return internal_format; |
| } |
| |
| extern "C" { |
| void mali_gralloc_get_gpu_caps(struct mali_gralloc_format_caps *gpu_caps) |
| { |
| if (gpu_caps != NULL) |
| { |
| if (!runtime_caps_read) |
| { |
| determine_format_capabilities(); |
| } |
| |
| memcpy(gpu_caps, (void *)&gpu_runtime_caps, sizeof(struct mali_gralloc_format_caps)); |
| } |
| } |
| } |