diff options
author | John Stultz <john.stultz@linaro.org> | 2017-05-03 11:12:18 -0700 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2017-05-26 22:23:57 -0700 |
commit | 16100f69b8b4444baa661307c5790eae039a1cc3 (patch) | |
tree | abd613b597e2bfdb171c059b06d3b080e4b93e40 | |
parent | a063cbdb355a3067eeda9728a531ec7754dfc099 (diff) | |
download | hikey-16100f69b8b4444baa661307c5790eae039a1cc3.tar.gz |
HiKey960: Integrate ARM's reference gralloc for mali bifrost
This integrates the BX304L01B-SW-99005-r4p0-01rel0
mali bifrost package from ARM available here:
https://developer.arm.com/products/software/mali-drivers/android-gralloc-module
Change-Id: I737bce784d21d1a870229a16bcddd3668738405a
Signed-off-by: John Stultz <john.stultz@linaro.org>
-rw-r--r-- | gralloc960/Android.juno.mk | 20 | ||||
-rwxr-xr-x | gralloc960/Android.mk | 165 | ||||
-rw-r--r-- | gralloc960/Android.vexpress.mk | 20 | ||||
-rw-r--r-- | gralloc960/alloc_device.cpp | 1279 | ||||
-rw-r--r-- | gralloc960/alloc_device.h | 37 | ||||
-rw-r--r-- | gralloc960/alloc_device_allocator_specific.h | 25 | ||||
-rw-r--r-- | gralloc960/alloc_ion.cpp | 365 | ||||
-rw-r--r-- | gralloc960/framebuffer_device.cpp | 496 | ||||
-rw-r--r-- | gralloc960/framebuffer_device.h | 26 | ||||
-rw-r--r-- | gralloc960/gralloc_buffer_priv.cpp | 129 | ||||
-rw-r--r-- | gralloc960/gralloc_buffer_priv.h | 214 | ||||
-rw-r--r-- | gralloc960/gralloc_helper.h | 31 | ||||
-rw-r--r-- | gralloc960/gralloc_module.cpp | 341 | ||||
-rw-r--r-- | gralloc960/gralloc_module_allocator_specific.h | 21 | ||||
-rw-r--r-- | gralloc960/gralloc_module_ion.cpp | 128 | ||||
-rw-r--r-- | gralloc960/gralloc_priv.h | 285 | ||||
-rw-r--r-- | gralloc960/gralloc_vsync.h | 31 | ||||
-rw-r--r-- | gralloc960/gralloc_vsync_default.cpp | 60 | ||||
-rw-r--r-- | gralloc960/gralloc_vsync_report.h | 48 | ||||
-rw-r--r-- | gralloc960/gralloc_vsync_s3cfb.cpp | 59 | ||||
-rw-r--r-- | gralloc960/mali_gralloc_formats.cpp | 666 | ||||
-rw-r--r-- | gralloc960/mali_gralloc_formats.h | 302 |
22 files changed, 4748 insertions, 0 deletions
diff --git a/gralloc960/Android.juno.mk b/gralloc960/Android.juno.mk new file mode 100644 index 00000000..e2ecd4ab --- /dev/null +++ b/gralloc960/Android.juno.mk @@ -0,0 +1,20 @@ +# +# 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. + +$(info gralloc for juno) +GRALLOC_FB_SWAP_RED_BLUE := 1 +GRALLOC_DEPTH := GRALLOC_32_BITS diff --git a/gralloc960/Android.mk b/gralloc960/Android.mk new file mode 100755 index 00000000..d57c728f --- /dev/null +++ b/gralloc960/Android.mk @@ -0,0 +1,165 @@ +# +# 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. + +LOCAL_PATH := $(call my-dir) + +# Include platform specific makefiles +include $(if $(wildcard $(LOCAL_PATH)/Android.$(TARGET_BOARD_PLATFORM).mk), $(LOCAL_PATH)/Android.$(TARGET_BOARD_PLATFORM).mk,) + +# +# Static hardware defines +# +# These defines are used in case runtime detection does not find the +# user-space driver to read out hardware capabilities + +# GPU support for AFBC 1.0 +MALI_GPU_SUPPORT_AFBC_BASIC?=0 +# GPU support for AFBC 1.1 block split +MALI_GPU_SUPPORT_AFBC_SPLITBLK?=0 +# GPU support for AFBC 1.1 wide block +MALI_GPU_SUPPORT_AFBC_WIDEBLK?=0 +# GPU support for AFBC 1.2 tiled headers +MALI_GPU_SUPPORT_AFBC_TILED_HEADERS?=0 +# GPU support YUV AFBC formats in wide block +MALI_GPU_USE_YUV_AFBC_WIDEBLK?=0 + +# VPU version we support +MALI_VIDEO_VERSION?=0 +# DPU version we support +MALI_DISPLAY_VERSION?=0 + +# +# Software behaviour defines +# + +# Use ION DMA heap for all allocations. Default is system heap. +GRALLOC_USE_ION_DMA_HEAP?=0 +# Use ION Compound heap for all allocations. Default is system heap. +GRALLOC_USE_ION_COMPOUND_PAGE_HEAP?=0 +# Properly initializes an empty AFBC buffer +GRALLOC_INIT_AFBC?=0 +# fbdev bitdepth to use +GRALLOC_DEPTH?=GRALLOC_32_BITS +# When enabled, forces display framebuffer format to BGRA_8888 +GRALLOC_FB_SWAP_RED_BLUE?=1 +# Disables the framebuffer HAL device. When a hwc impl is available. +GRALLOC_DISABLE_FRAMEBUFFER_HAL?=0 +# When enabled, buffers will never be allocated with AFBC +GRALLOC_ARM_NO_EXTERNAL_AFBC?=0 +# Minimum buffer dimensions in pixels when buffer will use AFBC +GRALLOC_DISP_W?=0 +GRALLOC_DISP_H?=0 +# Vsync backend(not used) +GRALLOC_VSYNC_BACKEND?=default + +# HAL module implemenation, not prelinked and stored in +# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so +include $(CLEAR_VARS) +include $(BUILD_SYSTEM)/version_defaults.mk + +ifeq ($(TARGET_BOARD_PLATFORM), juno) +ifeq ($(MALI_MMSS), 1) + +# Use latest default MMSS build configuration if not already defined +ifeq ($(MALI_DISPLAY_VERSION), 0) +MALI_DISPLAY_VERSION = 650 +endif +ifeq ($(MALI_VIDEO_VERSION), 0) +MALI_VIDEO_VERSION = 550 +endif + +GRALLOC_FB_SWAP_RED_BLUE = 0 +GRALLOC_USE_ION_DMA_HEAP = 1 +endif +endif + +ifeq ($(TARGET_BOARD_PLATFORM), armboard_v7a) +ifeq ($(GRALLOC_MALI_DP),true) + GRALLOC_FB_SWAP_RED_BLUE = 0 + GRALLOC_DISABLE_FRAMEBUFFER_HAL=1 + MALI_DISPLAY_VERSION = 550 + GRALLOC_USE_ION_DMA_HEAP=1 +endif +endif + +ifneq ($(MALI_DISPLAY_VERSION), 0) +#if Mali display is available, should disable framebuffer HAL +GRALLOC_DISABLE_FRAMEBUFFER_HAL := 1 +#if Mali display is available, AFBC buffers should be initialised after allocation +GRALLOC_INIT_AFBC := 1 +endif + +ifeq ($(GRALLOC_USE_ION_DMA_HEAP), 1) +ifeq ($(GRALLOC_USE_ION_COMPOUND_PAGE_HEAP), 1) +$(error GRALLOC_USE_ION_DMA_HEAP and GRALLOC_USE_ION_COMPOUND_PAGE_HEAP can't be enabled at the same time) +endif +endif + +LOCAL_C_INCLUDES := $(MALI_LOCAL_PATH) $(MALI_DDK_INCLUDES) + +# General compilation flags +LOCAL_CFLAGS := -Werror -DLOG_TAG=\"gralloc\" -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION) + +# Static hw flags +LOCAL_CFLAGS += -DMALI_GPU_SUPPORT_AFBC_BASIC=$(MALI_GPU_SUPPORT_AFBC_BASIC) +LOCAL_CFLAGS += -DMALI_GPU_SUPPORT_AFBC_SPLITBLK=$(MALI_GPU_SUPPORT_AFBC_SPLITBLK) +LOCAL_CFLAGS += -DMALI_GPU_SUPPORT_AFBC_WIDEBLK=$(MALI_GPU_SUPPORT_AFBC_WIDEBLK) +LOCAL_CFLAGS += -DMALI_GPU_USE_YUV_AFBC_WIDEBLK=$(MALI_GPU_USE_YUV_AFBC_WIDEBLK) +LOCAL_CFLAGS += -DMALI_GPU_SUPPORT_AFBC_TILED_HEADERS=$(MALI_GPU_SUPPORT_AFBC_TILED_HEADERS) + +LOCAL_CFLAGS += -DMALI_DISPLAY_VERSION=$(MALI_DISPLAY_VERSION) +LOCAL_CFLAGS += -DMALI_VIDEO_VERSION=$(MALI_VIDEO_VERSION) + +# Software behaviour flags +LOCAL_CFLAGS += -DGRALLOC_DISP_W=$(GRALLOC_DISP_W) +LOCAL_CFLAGS += -DGRALLOC_DISP_H=$(GRALLOC_DISP_H) +LOCAL_CFLAGS += -DDISABLE_FRAMEBUFFER_HAL=$(GRALLOC_DISABLE_FRAMEBUFFER_HAL) +LOCAL_CFLAGS += -DGRALLOC_USE_ION_DMA_HEAP=$(GRALLOC_USE_ION_DMA_HEAP) +LOCAL_CFLAGS += -DGRALLOC_USE_ION_COMPOUND_PAGE_HEAP=$(GRALLOC_USE_ION_COMPOUND_PAGE_HEAP) +LOCAL_CFLAGS += -DGRALLOC_INIT_AFBC=$(GRALLOC_INIT_AFBC) +LOCAL_CFLAGS += -D$(GRALLOC_DEPTH) +LOCAL_CFLAGS += -DGRALLOC_FB_SWAP_RED_BLUE=$(GRALLOC_FB_SWAP_RED_BLUE) +LOCAL_CFLAGS += -DGRALLOC_ARM_NO_EXTERNAL_AFBC=$(GRALLOC_ARM_NO_EXTERNAL_AFBC) + +LOCAL_SHARED_LIBRARIES := libhardware liblog libcutils libGLESv1_CM libion + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_MODULE_PATH_32 := $(TARGET_OUT_VENDOR)/lib +LOCAL_MODULE_PATH_64 := $(TARGET_OUT_VENDOR)/lib64 +ifeq ($(TARGET_BOARD_PLATFORM),) +LOCAL_MODULE := gralloc.default +else +LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM) +endif + +LOCAL_MODULE_TAGS := optional +LOCAL_MULTILIB := both + +LOCAL_SRC_FILES := \ + gralloc_module.cpp \ + alloc_device.cpp \ + alloc_ion.cpp \ + gralloc_module_ion.cpp \ + framebuffer_device.cpp \ + gralloc_buffer_priv.cpp \ + gralloc_vsync_${GRALLOC_VSYNC_BACKEND}.cpp \ + mali_gralloc_formats.cpp + +LOCAL_MODULE_OWNER := arm + +include $(BUILD_SHARED_LIBRARY) diff --git a/gralloc960/Android.vexpress.mk b/gralloc960/Android.vexpress.mk new file mode 100644 index 00000000..73ac1197 --- /dev/null +++ b/gralloc960/Android.vexpress.mk @@ -0,0 +1,20 @@ +# +# 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. + +$(info gralloc for vexpress) +GRALLOC_FB_SWAP_RED_BLUE := 0 +GRALLOC_DEPTH := GRALLOC_16_BITS diff --git a/gralloc960/alloc_device.cpp b/gralloc960/alloc_device.cpp new file mode 100644 index 00000000..8614ae54 --- /dev/null +++ b/gralloc960/alloc_device.cpp @@ -0,0 +1,1279 @@ +/* + * Copyright (C) 2010 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 <pthread.h> + +#include <cutils/log.h> +#include <cutils/atomic.h> +#include <hardware/hardware.h> +#include <hardware/gralloc.h> + +#include <sys/ioctl.h> + +#include "alloc_device.h" +#include "gralloc_priv.h" +#include "gralloc_helper.h" +#include "framebuffer_device.h" + +#include "alloc_device_allocator_specific.h" +#include "gralloc_buffer_priv.h" + +#include "mali_gralloc_formats.h" + +#define AFBC_PIXELS_PER_BLOCK 16 +#define AFBC_HEADER_BUFFER_BYTES_PER_BLOCKENTRY 16 + +#define AFBC_BODY_BUFFER_BYTE_ALIGNMENT 1024 +#define AFBC_NORMAL_WIDTH_ALIGN 16 +#define AFBC_NORMAL_HEIGHT_ALIGN 16 +#define AFBC_WIDEBLK_WIDTH_ALIGN 32 +#define AFBC_WIDEBLK_HEIGHT_ALIGN 16 +// Regarding Tiled Headers AFBC mode, both header and body buffer should aligned to 4KB +// and in non-wide mode (16x16), the width and height should be both rounded up to 128 +// in wide mode (32x8) the width should be rounded up to 256, the height should be rounded up to 64 +#define AFBC_TILED_HEADERS_BASIC_WIDTH_ALIGN 128 +#define AFBC_TILED_HEADERS_BASIC_HEIGHT_ALIGN 128 +#define AFBC_TILED_HEADERS_WIDEBLK_WIDTH_ALIGN 256 +#define AFBC_TILED_HEADERS_WIDEBLK_HEIGHT_ALIGN 64 + +// This value is platform specific and should be set according to hardware YUV planes restrictions. +// Please note that EGL winsys platform config file needs to use the same value when importing buffers. +#define YUV_MALI_PLANE_ALIGN 128 + +// Default YUV stride aligment in Android +#define YUV_ANDROID_PLANE_ALIGN 16 + +static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle, int* stride, int* byte_stride) +{ + private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module); + + // allocate the framebuffer + if (m->framebuffer == NULL) + { + // initialize the framebuffer, the framebuffer is mapped once and forever. + int err = init_frame_buffer_locked(m); + if (err < 0) + { + return err; + } + } + + const uint32_t bufferMask = m->bufferMask; + const uint32_t numBuffers = m->numBuffers; + /* framebufferSize is used for allocating the handle to the framebuffer and refers + * to the size of the actual framebuffer. + * alignedFramebufferSize is used for allocating a possible internal buffer and + * thus need to consider internal alignment requirements. */ + const size_t framebufferSize = m->finfo.line_length * m->info.yres; + const size_t alignedFramebufferSize = GRALLOC_ALIGN(m->finfo.line_length, 64) * m->info.yres; + + *stride = m->info.xres; + + if (numBuffers == 1) + { + // If we have only one buffer, we never use page-flipping. Instead, + // we return a regular buffer which will be memcpy'ed to the main + // screen when post is called. + int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D; + AWAR( "fallback to single buffering. Virtual Y-res too small %d", m->info.yres ); + *byte_stride = GRALLOC_ALIGN(m->finfo.line_length, 64); + return alloc_backend_alloc(dev, alignedFramebufferSize, newUsage, pHandle, 0, 0, 0); + } + + if (bufferMask >= ((1LU<<numBuffers)-1)) + { + // We ran out of buffers. + return -ENOMEM; + } + + uintptr_t framebufferVaddr = (uintptr_t)m->framebuffer->base; + // find a free slot + for (uint32_t i=0 ; i<numBuffers ; i++) + { + if ((bufferMask & (1LU<<i)) == 0) + { + m->bufferMask |= (1LU<<i); + break; + } + framebufferVaddr += framebufferSize; + } + + // The entire framebuffer memory is already mapped, now create a buffer object for parts of this memory + private_handle_t* hnd = new private_handle_t(private_handle_t::PRIV_FLAGS_FRAMEBUFFER, usage, size, + (void*)framebufferVaddr, 0, dup(m->framebuffer->fd), + (framebufferVaddr - (uintptr_t)m->framebuffer->base)); + + /* + * Perform allocator specific actions. If these fail we fall back to a regular buffer + * which will be memcpy'ed to the main screen when fb_post is called. + */ + if (alloc_backend_alloc_framebuffer(m, hnd) == -1) + { + delete hnd; + int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D; + AERR( "Fallback to single buffering. Unable to map framebuffer memory to handle:%p", hnd ); + *byte_stride = GRALLOC_ALIGN(m->finfo.line_length, 64); + return alloc_backend_alloc(dev, alignedFramebufferSize, newUsage, pHandle, 0, 0, 0); + } + + *pHandle = hnd; + *byte_stride = m->finfo.line_length; + + return 0; +} + +static int gralloc_alloc_framebuffer(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle, int* stride, int* byte_stride) +{ + private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module); + pthread_mutex_lock(&m->lock); + int err = gralloc_alloc_framebuffer_locked(dev, size, usage, pHandle, stride, byte_stride); + pthread_mutex_unlock(&m->lock); + return err; +} + +/* + * Type of allocation + */ +enum AllocType +{ + UNCOMPRESSED = 0, + AFBC, + /* AFBC_WIDEBLK mode requires buffer to have 32 * 16 pixels alignment */ + AFBC_WIDEBLK, + /* AN AFBC buffer with additional padding to ensure a 64-bte alignment + * for each row of blocks in the header */ + AFBC_PADDED, + /* AFBC_TILED_HEADERS_AFBC_BASIC mode requires buffer to have 128*128 pixels alignment(16x16 superblocks) */ + AFBC_TILED_HEADERS_BASIC, + /* AFBC_TILED_HEADERS_AFBC_WIDEBLK mode requires buffer to have 256*64 pixels alignment(32x8 superblocks) */ + AFBC_TILED_HEADERS_WIDEBLK, +}; + +/* + * Computes the strides and size for an RGB buffer + * + * width width of the buffer in pixels + * height height of the buffer in pixels + * pixel_size size of one pixel in bytes + * + * pixel_stride (out) stride of the buffer in pixels + * byte_stride (out) stride of the buffer in bytes + * size (out) size of the buffer in bytes + * type (in) if buffer should be allocated for afbc + */ +static void get_rgb_stride_and_size(int width, int height, int pixel_size, + int* pixel_stride, int* byte_stride, size_t* size, AllocType type) +{ + int stride; + + stride = width * pixel_size; + + /* Align the lines to 64 bytes. + * It's more efficient to write to 64-byte aligned addresses because it's the burst size on the bus */ + stride = GRALLOC_ALIGN(stride, 64); + + if (size != NULL) + { + *size = stride * height; + } + + if (byte_stride != NULL) + { + *byte_stride = stride; + } + + if (pixel_stride != NULL) + { + *pixel_stride = stride / pixel_size; + } + + if (type != UNCOMPRESSED) + { + int w_aligned; + int h_aligned = GRALLOC_ALIGN( height, AFBC_NORMAL_HEIGHT_ALIGN ); + int nblocks; + int buffer_byte_alignment = AFBC_BODY_BUFFER_BYTE_ALIGNMENT; + + if (type == AFBC_TILED_HEADERS_BASIC) + { + w_aligned = GRALLOC_ALIGN( width, AFBC_TILED_HEADERS_BASIC_WIDTH_ALIGN ); + h_aligned = GRALLOC_ALIGN( height, AFBC_TILED_HEADERS_BASIC_HEIGHT_ALIGN ); + buffer_byte_alignment = 4 * AFBC_BODY_BUFFER_BYTE_ALIGNMENT; + } + else if (type == AFBC_TILED_HEADERS_WIDEBLK) + { + w_aligned = GRALLOC_ALIGN( width, AFBC_TILED_HEADERS_WIDEBLK_WIDTH_ALIGN ); + h_aligned = GRALLOC_ALIGN( height, AFBC_TILED_HEADERS_WIDEBLK_HEIGHT_ALIGN ); + buffer_byte_alignment = 4 * AFBC_BODY_BUFFER_BYTE_ALIGNMENT; + } + else if (type == AFBC_PADDED) + { + w_aligned = GRALLOC_ALIGN( width, 64 ); + } + else if (type == AFBC_WIDEBLK) + { + w_aligned = GRALLOC_ALIGN( width, AFBC_WIDEBLK_WIDTH_ALIGN ); + h_aligned = GRALLOC_ALIGN( height, AFBC_WIDEBLK_HEIGHT_ALIGN ); + } + else + { + w_aligned = GRALLOC_ALIGN( width, AFBC_NORMAL_WIDTH_ALIGN ); + } + + nblocks = w_aligned / AFBC_PIXELS_PER_BLOCK * h_aligned / AFBC_PIXELS_PER_BLOCK; + + if ( size != NULL ) + { + *size = w_aligned * h_aligned * pixel_size + + GRALLOC_ALIGN( nblocks * AFBC_HEADER_BUFFER_BYTES_PER_BLOCKENTRY, buffer_byte_alignment ); + } + } +} + +/* + * Computes the strides and size for an AFBC 8BIT YUV 4:2:0 buffer + * + * width Public known width of the buffer in pixels + * height Public known height of the buffer in pixels + * + * pixel_stride (out) stride of the buffer in pixels + * byte_stride (out) stride of the buffer in bytes + * size (out) size of the buffer in bytes + * type if buffer should be allocated for a certain afbc type + * internalHeight (out) The internal height, which may be greater than the public known height. + */ +static bool get_afbc_yuv420_8bit_stride_and_size(int width, int height, int* pixel_stride, int* byte_stride, + size_t* size, AllocType type, int *internalHeight) +{ + int yuv420_afbc_luma_stride, yuv420_afbc_chroma_stride; + int buffer_byte_alignment = AFBC_BODY_BUFFER_BYTE_ALIGNMENT; + + *internalHeight = height; + +#if MALI_VIDEO_VERSION != 0 + + /* If we have a greater internal height than public we set the internalHeight. This + * implies that cropping will be applied of internal dimensions to fit the public one. + * + * NOTE: This should really only be done when the producer is determined to be VPU decoder. + */ + *internalHeight += AFBC_PIXELS_PER_BLOCK; +#endif + + /* The actual height used in size calculation must include the possible extra row. But + * it must also be AFBC-aligned. Only the extra row-padding should be reported back in + * internalHeight. This as only this row needs to be considered when cropping. */ + + if (type == UNCOMPRESSED) + { + AERR(" Buffer must be allocated with AFBC mode for internal pixel format YUV420_8BIT_AFBC!"); + return false; + } + else if (type == AFBC_TILED_HEADERS_BASIC) + { + width = GRALLOC_ALIGN( width, AFBC_TILED_HEADERS_BASIC_WIDTH_ALIGN ); + height = GRALLOC_ALIGN( *internalHeight, AFBC_TILED_HEADERS_BASIC_HEIGHT_ALIGN ); + buffer_byte_alignment = 4 * AFBC_BODY_BUFFER_BYTE_ALIGNMENT; + } + else if (type == AFBC_TILED_HEADERS_WIDEBLK) + { + width = GRALLOC_ALIGN( width, AFBC_TILED_HEADERS_WIDEBLK_WIDTH_ALIGN ); + height = GRALLOC_ALIGN( *internalHeight, AFBC_TILED_HEADERS_WIDEBLK_HEIGHT_ALIGN ); + buffer_byte_alignment = 4 * AFBC_BODY_BUFFER_BYTE_ALIGNMENT; + } + else if (type == AFBC_PADDED) + { + AERR("GRALLOC_USAGE_PRIVATE_2 (64byte header row alignment for AFBC) is not supported for YUV"); + return false; + } + else if (type == AFBC_WIDEBLK) + { + width = GRALLOC_ALIGN(width, AFBC_WIDEBLK_WIDTH_ALIGN); + height = GRALLOC_ALIGN( *internalHeight, AFBC_WIDEBLK_HEIGHT_ALIGN ); + } + else + { + width = GRALLOC_ALIGN(width, AFBC_NORMAL_WIDTH_ALIGN); + height = GRALLOC_ALIGN( *internalHeight, AFBC_NORMAL_HEIGHT_ALIGN ); + } + + yuv420_afbc_luma_stride = width; + yuv420_afbc_chroma_stride = GRALLOC_ALIGN(yuv420_afbc_luma_stride / 2, 16); /* Horizontal downsampling*/ + + if (size != NULL) + { + int nblocks = width / AFBC_PIXELS_PER_BLOCK * height / AFBC_PIXELS_PER_BLOCK; + /* Simplification of (height * luma-stride + 2 * (height /2 * chroma_stride) */ + *size = + ( yuv420_afbc_luma_stride + yuv420_afbc_chroma_stride ) * height + + GRALLOC_ALIGN( nblocks * AFBC_HEADER_BUFFER_BYTES_PER_BLOCKENTRY, buffer_byte_alignment ); + } + + if (byte_stride != NULL) + { + *byte_stride = yuv420_afbc_luma_stride; + } + + if (pixel_stride != NULL) + { + *pixel_stride = yuv420_afbc_luma_stride; + } + + return true; +} + +/* + * Computes the strides and size for an YV12 buffer + * + * width Public known width of the buffer in pixels + * height Public known height of the buffer in pixels + * + * pixel_stride (out) stride of the buffer in pixels + * byte_stride (out) stride of the buffer in bytes + * size (out) size of the buffer in bytes + * type (in) if buffer should be allocated for a certain afbc type + * internalHeight (out) The internal height, which may be greater than the public known height. + * stride_alignment (in) stride aligment value in bytes. + */ +static bool get_yv12_stride_and_size(int width, int height, int* pixel_stride, int* byte_stride, size_t* size, + AllocType type, int* internalHeight, int stride_alignment) +{ + int luma_stride; + + if (type != UNCOMPRESSED) + { + return get_afbc_yuv420_8bit_stride_and_size(width, height, pixel_stride, byte_stride, size, type, internalHeight); + } + + /* 4:2:0 formats must have buffers with even height and width as the clump size is 2x2 pixels. + * Width will be even stride aligned anyway so just adjust height here for size calculation. */ + height = GRALLOC_ALIGN(height, 2); + + luma_stride = GRALLOC_ALIGN(width, stride_alignment); + + if (size != NULL) + { + int chroma_stride = GRALLOC_ALIGN(luma_stride / 2, stride_alignment); + /* Simplification of ((height * luma_stride ) + 2 * ((height / 2) * chroma_stride)). */ + *size = height * (luma_stride + chroma_stride); + } + + if (byte_stride != NULL) + { + *byte_stride = luma_stride; + } + + if (pixel_stride != NULL) + { + *pixel_stride = luma_stride; + } + + return true; +} +/* + * Computes the strides and size for an 8 bit YUYV 422 buffer + * + * width Public known width of the buffer in pixels + * height Public known height of the buffer in pixels + * + * pixel_stride (out) stride of the buffer in pixels + * byte_stride (out) stride of the buffer in bytes + * size (out) size of the buffer in bytes + */ +static bool get_yuv422_8bit_stride_and_size(int width, int height, int* pixel_stride, int* byte_stride, size_t* size) +{ + int local_byte_stride, local_pixel_stride; + + /* 4:2:2 formats must have buffers with even width as the clump size is 2x1 pixels. + * This is taken care of by the even stride alignment. */ + + local_pixel_stride = GRALLOC_ALIGN(width, YUV_MALI_PLANE_ALIGN); + local_byte_stride = GRALLOC_ALIGN(width * 2, YUV_MALI_PLANE_ALIGN); /* 4 bytes per 2 pixels */ + + if (size != NULL) + { + *size = local_byte_stride * height; + } + + if (byte_stride != NULL) + { + *byte_stride = local_byte_stride; + } + + if (pixel_stride != NULL) + { + *pixel_stride = local_pixel_stride; + } + + return true; +} + +/* + * Computes the strides and size for an AFBC 8BIT YUV 4:2:2 buffer + * + * width width of the buffer in pixels + * height height of the buffer in pixels + * + * pixel_stride (out) stride of the buffer in pixels + * byte_stride (out) stride of the buffer in bytes + * size (out) size of the buffer in bytes + * type if buffer should be allocated for a certain afbc type + */ +static bool get_afbc_yuv422_8bit_stride_and_size(int width, int height, int* pixel_stride, int* byte_stride, size_t* size, AllocType type) +{ + int yuv422_afbc_luma_stride; + int buffer_byte_alignment = AFBC_BODY_BUFFER_BYTE_ALIGNMENT; + + if (type == UNCOMPRESSED) + { + AERR(" Buffer must be allocated with AFBC mode for internal pixel format YUV422_8BIT_AFBC!"); + return false; + } + else if (type == AFBC_TILED_HEADERS_BASIC) + { + width = GRALLOC_ALIGN(width, AFBC_TILED_HEADERS_BASIC_WIDTH_ALIGN); + height = GRALLOC_ALIGN(height, AFBC_TILED_HEADERS_BASIC_HEIGHT_ALIGN); + buffer_byte_alignment = 4 * AFBC_BODY_BUFFER_BYTE_ALIGNMENT; + } + else if (type == AFBC_TILED_HEADERS_WIDEBLK) + { + width = GRALLOC_ALIGN(width, AFBC_TILED_HEADERS_WIDEBLK_WIDTH_ALIGN); + height = GRALLOC_ALIGN(height, AFBC_TILED_HEADERS_WIDEBLK_HEIGHT_ALIGN); + buffer_byte_alignment = 4 * AFBC_BODY_BUFFER_BYTE_ALIGNMENT; + } + else if (type == AFBC_PADDED) + { + AERR("GRALLOC_USAGE_PRIVATE_2 (64byte header row alignment for AFBC) is not supported for YUV"); + return false; + } + else if (type == AFBC_WIDEBLK) + { + width = GRALLOC_ALIGN(width, AFBC_WIDEBLK_WIDTH_ALIGN); + height = GRALLOC_ALIGN(height, AFBC_WIDEBLK_HEIGHT_ALIGN); + } + else + { + width = GRALLOC_ALIGN(width, AFBC_NORMAL_WIDTH_ALIGN); + height = GRALLOC_ALIGN(height, AFBC_NORMAL_HEIGHT_ALIGN); + } + + yuv422_afbc_luma_stride = width; + + if (size != NULL) + { + int nblocks = width / AFBC_PIXELS_PER_BLOCK * height / AFBC_PIXELS_PER_BLOCK; + /* YUV 4:2:2 luma size equals chroma size */ + *size = yuv422_afbc_luma_stride * height * 2 + + GRALLOC_ALIGN(nblocks * AFBC_HEADER_BUFFER_BYTES_PER_BLOCKENTRY, buffer_byte_alignment); + } + + if (byte_stride != NULL) + { + *byte_stride = yuv422_afbc_luma_stride; + } + + if (pixel_stride != NULL) + { + *pixel_stride = yuv422_afbc_luma_stride; + } + + return true; +} + +/* + * Calculate strides and sizes for a P010 (Y-UV 4:2:0) or P210 (Y-UV 4:2:2) buffer. + * + * @param width [in] Buffer width. + * @param height [in] Buffer height. + * @param vss [in] Vertical sub-sampling factor (2 for P010, 1 for + * P210. Anything else is invalid). + * @param pixel_stride [out] Pixel stride; number of pixels between + * consecutive rows. + * @param byte_stride [out] Byte stride; number of bytes between + * consecutive rows. + * @param size [out] Size of the buffer in bytes. Cumulative sum of + * sizes of all planes. + * + * @return true if the calculation was successful; false otherwise (invalid + * parameter) + */ +static bool get_yuv_pX10_stride_and_size(int width, int height, int vss, int* pixel_stride, int* byte_stride, size_t* size) +{ + int luma_pixel_stride, luma_byte_stride; + + if (vss < 1 || vss > 2) + { + AERR("Invalid vertical sub-sampling factor: %d, should be 1 or 2", vss); + return false; + } + + /* 4:2:2 must have even width as the clump size is 2x1 pixels. This will be taken care of by the + * even stride alignment */ + if (vss == 2) + { + /* 4:2:0 must also have even height as the clump size is 2x2 */ + height = GRALLOC_ALIGN(height, 2); + } + + luma_pixel_stride = GRALLOC_ALIGN(width, YUV_MALI_PLANE_ALIGN); + luma_byte_stride = GRALLOC_ALIGN(width * 2, YUV_MALI_PLANE_ALIGN); + + if (size != NULL) + { + int chroma_size = GRALLOC_ALIGN(width * 2, YUV_MALI_PLANE_ALIGN) * (height / vss); + *size = luma_byte_stride * height + chroma_size; + } + + if (byte_stride != NULL) + { + *byte_stride = luma_byte_stride; + } + + if (pixel_stride != NULL) + { + *pixel_stride = luma_pixel_stride; + } + + return true; +} + +/* + * Calculate strides and strides for Y210 (10 bit YUYV packed, 4:2:2) format buffer. + * + * @param width [in] Buffer width. + * @param height [in] Buffer height. + * @param pixel_stride [out] Pixel stride; number of pixels between + * consecutive rows. + * @param byte_stride [out] Byte stride; number of bytes between + * consecutive rows. + * @param size [out] Size of the buffer in bytes. Cumulative sum of + * sizes of all planes. + * + * @return true if the calculation was successful; false otherwise (invalid + * parameter) + */ +static bool get_yuv_y210_stride_and_size(int width, int height, int* pixel_stride, int* byte_stride, size_t* size) +{ + int y210_byte_stride, y210_pixel_stride; + + /* 4:2:2 formats must have buffers with even width as the clump size is 2x1 pixels. + * This is taken care of by the even stride alignment */ + + y210_pixel_stride = GRALLOC_ALIGN(width, YUV_MALI_PLANE_ALIGN); + /* 4x16 bits per 2 pixels */ + y210_byte_stride = GRALLOC_ALIGN(width * 4, YUV_MALI_PLANE_ALIGN); + + if (size != NULL) + { + *size = y210_byte_stride * height; + } + + if (byte_stride != NULL) + { + *byte_stride = y210_byte_stride; + } + + if (pixel_stride != NULL) + { + *pixel_stride = y210_pixel_stride; + } + + return true; +} + +/* + * Calculate strides and strides for Y0L2 (YUYAAYVYAA, 4:2:0) format buffer. + * + * @param width [in] Buffer width. + * @param height [in] Buffer height. + * @param pixel_stride [out] Pixel stride; number of pixels between + * consecutive rows. + * @param byte_stride [out] Byte stride; number of bytes between + * consecutive rows. + * @param size [out] Size of the buffer in bytes. Cumulative sum of + * sizes of all planes. + * + * @return true if the calculation was successful; false otherwise (invalid + * parameter) + * + * @note Each YUYAAYVYAA clump encodes a 2x2 area of pixels. YU&V are 10 bits. A is 1 bit. total 8 bytes + * + */ +static bool get_yuv_y0l2_stride_and_size(int width, int height, int* pixel_stride, int* byte_stride, size_t* size) +{ + int y0l2_byte_stride, y0l2_pixel_stride; + + /* 4:2:0 formats must have buffers with even height and width as the clump size is 2x2 pixels. + * Width is take care of by the even stride alignment so just adjust height here for size calculation. */ + height = GRALLOC_ALIGN(height, 2); + + y0l2_pixel_stride = GRALLOC_ALIGN(width, YUV_MALI_PLANE_ALIGN); + y0l2_byte_stride = GRALLOC_ALIGN(width * 4, YUV_MALI_PLANE_ALIGN); /* 2 horiz pixels per 8 byte clump */ + + if (size != NULL) + { + *size = y0l2_byte_stride * height / 2; /* byte stride covers 2 vert pixels */ + } + + if (byte_stride != NULL) + { + *byte_stride = y0l2_byte_stride; + } + + if (pixel_stride != NULL) + { + *pixel_stride = y0l2_pixel_stride; + } + return true; +} +/* + * Calculate strides and strides for Y410 (AVYU packed, 4:4:4) format buffer. + * + * @param width [in] Buffer width. + * @param height [in] Buffer height. + * @param pixel_stride [out] Pixel stride; number of pixels between + * consecutive rows. + * @param byte_stride [out] Byte stride; number of bytes between + * consecutive rows. + * @param size [out] Size of the buffer in bytes. Cumulative sum of + * sizes of all planes. + * + * @return true if the calculation was successful; false otherwise (invalid + * parameter) + */ +static bool get_yuv_y410_stride_and_size(int width, int height, int* pixel_stride, int* byte_stride, size_t* size) +{ + int y410_byte_stride, y410_pixel_stride; + + y410_pixel_stride = GRALLOC_ALIGN(width, YUV_MALI_PLANE_ALIGN); + y410_byte_stride = GRALLOC_ALIGN(width * 4, YUV_MALI_PLANE_ALIGN); + + if (size != NULL) + { + /* 4x8bits per pixel */ + *size = y410_byte_stride * height; + } + + if (byte_stride != NULL) + { + *byte_stride = y410_byte_stride; + } + + if (pixel_stride != NULL) + { + *pixel_stride = y410_pixel_stride; + } + return true; +} + +/* + * Calculate strides and strides for YUV420_10BIT_AFBC (Compressed, 4:2:0) format buffer. + * + * @param width [in] Buffer width. + * @param height [in] Buffer height. + * @param pixel_stride [out] Pixel stride; number of pixels between + * consecutive rows. + * @param byte_stride [out] Byte stride; number of bytes between + * consecutive rows. + * @param size [out] Size of the buffer in bytes. Cumulative sum of + * sizes of all planes. + * @param type [in] afbc mode that buffer should be allocated with. + * + * @param internalHeight [out] Internal buffer height that used by consumer or producer + * + * @return true if the calculation was successful; false otherwise (invalid + * parameter) + */ +static bool get_yuv420_10bit_afbc_stride_and_size(int width, int height, int* pixel_stride, int* byte_stride, size_t* size, AllocType type, int* internalHeight) +{ + int yuv420_afbc_byte_stride, yuv420_afbc_pixel_stride; + int buffer_byte_alignment = AFBC_BODY_BUFFER_BYTE_ALIGNMENT; + + if (width & 3) + { + return false; + } + + *internalHeight = height; +#if MALI_VIDEO_VERSION + /* If we have a greater internal height than public we set the internalHeight. This + * implies that cropping will be applied of internal dimensions to fit the public one. */ + *internalHeight += AFBC_PIXELS_PER_BLOCK; +#endif + /* The actual height used in size calculation must include the possible extra row. But + * it must also be AFBC-aligned. Only the extra row-padding should be reported back in + * internalHeight. This as only this row needs to be considered when cropping. */ + if (type == UNCOMPRESSED) + { + AERR(" Buffer must be allocated with AFBC mode for internal pixel format YUV420_10BIT_AFBC!"); + return false; + } + else if (type == AFBC_TILED_HEADERS_BASIC) + { + width = GRALLOC_ALIGN(width, AFBC_TILED_HEADERS_BASIC_WIDTH_ALIGN); + height = GRALLOC_ALIGN(*internalHeight/2, AFBC_TILED_HEADERS_BASIC_HEIGHT_ALIGN); + buffer_byte_alignment = 4 * AFBC_BODY_BUFFER_BYTE_ALIGNMENT; + } + else if (type == AFBC_TILED_HEADERS_WIDEBLK) + { + width = GRALLOC_ALIGN(width, AFBC_TILED_HEADERS_WIDEBLK_WIDTH_ALIGN); + height = GRALLOC_ALIGN(*internalHeight/2, AFBC_TILED_HEADERS_WIDEBLK_HEIGHT_ALIGN); + buffer_byte_alignment = 4 * AFBC_BODY_BUFFER_BYTE_ALIGNMENT; + } + else if (type == AFBC_PADDED) + { + AERR("GRALLOC_USAGE_PRIVATE_2 (64byte header row alignment for AFBC) is not supported for YUV"); + return false; + } + else if (type == AFBC_WIDEBLK) + { + width = GRALLOC_ALIGN(width, AFBC_WIDEBLK_WIDTH_ALIGN); + height = GRALLOC_ALIGN(*internalHeight/2, AFBC_WIDEBLK_HEIGHT_ALIGN); + } + else + { + width = GRALLOC_ALIGN(width, AFBC_NORMAL_WIDTH_ALIGN); + height = GRALLOC_ALIGN(*internalHeight/2, AFBC_NORMAL_HEIGHT_ALIGN); + } + + yuv420_afbc_pixel_stride = GRALLOC_ALIGN(width, 16); + yuv420_afbc_byte_stride = GRALLOC_ALIGN(width * 4, 16); /* 64-bit packed and horizontally downsampled */ + + if (size != NULL) + { + int nblocks = width / AFBC_PIXELS_PER_BLOCK * (*internalHeight) / AFBC_PIXELS_PER_BLOCK; + *size = yuv420_afbc_byte_stride * height + + GRALLOC_ALIGN(nblocks * AFBC_HEADER_BUFFER_BYTES_PER_BLOCKENTRY, buffer_byte_alignment); + } + + if (byte_stride != NULL) + { + *byte_stride = yuv420_afbc_pixel_stride; + } + + if (pixel_stride != NULL) + { + *pixel_stride = yuv420_afbc_pixel_stride; + } + + return true; +} + +/* + * Calculate strides and strides for YUV422_10BIT_AFBC (Compressed, 4:2:2) format buffer. + * + * @param width [in] Buffer width. + * @param height [in] Buffer height. + * @param pixel_stride [out] Pixel stride; number of pixels between + * consecutive rows. + * @param byte_stride [out] Byte stride; number of bytes between + * consecutive rows. + * @param size [out] Size of the buffer in bytes. Cumulative sum of + * sizes of all planes. + * @param type [in] afbc mode that buffer should be allocated with. + * + * @return true if the calculation was successful; false otherwise (invalid + * parameter) + */ +static bool get_yuv422_10bit_afbc_stride_and_size(int width, int height, int* pixel_stride, int* byte_stride, size_t* size, AllocType type) +{ + int yuv422_afbc_byte_stride, yuv422_afbc_pixel_stride; + int buffer_byte_alignment = AFBC_BODY_BUFFER_BYTE_ALIGNMENT; + + if (width & 3) + { + return false; + } + + if (type == UNCOMPRESSED) + { + AERR(" Buffer must be allocated with AFBC mode for internal pixel format YUV422_10BIT_AFBC!"); + return false; + } + else if (type == AFBC_TILED_HEADERS_BASIC) + { + width = GRALLOC_ALIGN(width, AFBC_TILED_HEADERS_BASIC_WIDTH_ALIGN); + height = GRALLOC_ALIGN(height, AFBC_TILED_HEADERS_BASIC_HEIGHT_ALIGN); + buffer_byte_alignment = 4 * AFBC_BODY_BUFFER_BYTE_ALIGNMENT; + } + else if (type == AFBC_TILED_HEADERS_WIDEBLK) + { + width = GRALLOC_ALIGN(width, AFBC_TILED_HEADERS_WIDEBLK_WIDTH_ALIGN); + height = GRALLOC_ALIGN(height, AFBC_TILED_HEADERS_WIDEBLK_HEIGHT_ALIGN); + buffer_byte_alignment = 4 * AFBC_BODY_BUFFER_BYTE_ALIGNMENT; + } + else if (type == AFBC_PADDED) + { + AERR("GRALLOC_USAGE_PRIVATE_2 (64byte header row alignment for AFBC) is not supported for YUV"); + return false; + } + else if (type == AFBC_WIDEBLK) + { + width = GRALLOC_ALIGN(width, AFBC_WIDEBLK_WIDTH_ALIGN); + height = GRALLOC_ALIGN(height, AFBC_WIDEBLK_HEIGHT_ALIGN); + } + else + { + width = GRALLOC_ALIGN(width, AFBC_NORMAL_WIDTH_ALIGN); + height = GRALLOC_ALIGN(height, AFBC_NORMAL_HEIGHT_ALIGN); + } + + yuv422_afbc_pixel_stride = GRALLOC_ALIGN(width, 16); + yuv422_afbc_byte_stride = GRALLOC_ALIGN(width * 2, 16); + + if (size != NULL) + { + int nblocks = width / AFBC_PIXELS_PER_BLOCK * height / AFBC_PIXELS_PER_BLOCK; + /* YUV 4:2:2 chroma size equals to luma size */ + *size = yuv422_afbc_byte_stride * height * 2 + + GRALLOC_ALIGN(nblocks * AFBC_HEADER_BUFFER_BYTES_PER_BLOCKENTRY, buffer_byte_alignment); + } + + if (byte_stride != NULL) + { + *byte_stride = yuv422_afbc_byte_stride; + } + + if (pixel_stride != NULL) + { + *pixel_stride = yuv422_afbc_pixel_stride; + } + + return true; +} + +/* + * Calculate strides and strides for Camera RAW and Blob formats + * + * @param w [in] Buffer width. + * @param h [in] Buffer height. + * @param format [in] Requested HAL format + * @param out_stride [out] Pixel stride; number of pixels/bytes between + * consecutive rows. Format description calls for + * either bytes or pixels. + * @param size [out] Size of the buffer in bytes. Cumulative sum of + * sizes of all planes. + * + * @return true if the calculation was successful; false otherwise (invalid + * parameter) + */ +static bool get_camera_formats_stride_and_size(int w, int h, uint64_t format, int *out_stride, size_t *out_size) +{ + int stride, size; + + switch (format) + { + case HAL_PIXEL_FORMAT_RAW16: + stride = w; /* Format assumes stride in pixels */ + stride = GRALLOC_ALIGN(stride, 16); /* Alignment mandated by Android */ + size = stride * h * 2; /* 2 bytes per pixel */ + break; + + case HAL_PIXEL_FORMAT_RAW12: + if (w % 4 != 0) + { + ALOGE("ERROR: Width for HAL_PIXEL_FORMAT_RAW12 buffers has to be multiple of 4."); + return false; + } + stride = (w / 2) * 3; /* Stride in bytes; 2 pixels in 3 bytes */ + size = stride * h; + break; + + case HAL_PIXEL_FORMAT_RAW10: + if (w % 4 != 0) + { + ALOGE("ERROR: Width for HAL_PIXEL_FORMAT_RAW10 buffers has to be multiple of 4."); + return false; + } + stride = (w / 4) * 5; /* Stride in bytes; 4 pixels in 5 bytes */ + size = stride * h; + break; + + case HAL_PIXEL_FORMAT_BLOB: + if (h != 1) + { + ALOGE("ERROR: Height for HAL_PIXEL_FORMAT_BLOB must be 1."); + return false; + } + stride = 0; /* No 'rows', it's effectively a long one dimensional array */ + size = w; + break; + + default: + return false; + + } + + if (out_size != NULL) + { + *out_size = size; + } + + if (out_stride != NULL) + { + *out_stride = stride; + } + + return true; +} + +static int alloc_device_alloc(alloc_device_t* dev, int w, int h, int format, int usage, buffer_handle_t* pHandle, int* pStride) +{ + + if (!pHandle || !pStride) + { + return -EINVAL; + } + + size_t size; // Size to be allocated for the buffer + int byte_stride; // Stride of the buffer in bytes + int pixel_stride; // Stride of the buffer in pixels - as returned in pStride + uint64_t internal_format; + AllocType type = UNCOMPRESSED; + int internalWidth,internalHeight; + +#if GRALLOC_FB_SWAP_RED_BLUE == 1 + /* match the framebuffer format */ + if (usage & GRALLOC_USAGE_HW_FB) + { +#ifdef GRALLOC_16_BITS + format = HAL_PIXEL_FORMAT_RGB_565; +#else + format = HAL_PIXEL_FORMAT_BGRA_8888; +#endif + } +#endif + + /* Some formats require an internal width and height that may be used by + * consumers/producers. + */ + internalWidth = w; + internalHeight = h; + + internal_format = mali_gralloc_select_format(format, usage, w*h); + if(internal_format == 0) + { + ALOGE("Unrecognized and/or unsupported format(0x%08X) and usage(0x%08X).",format,usage); + return -EINVAL; + } + + if (internal_format & MALI_GRALLOC_INTFMT_AFBCENABLE_MASK) + { + if (internal_format & MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS) + { + if (internal_format & MALI_GRALLOC_INTFMT_AFBC_WIDEBLK) + { + type = AFBC_TILED_HEADERS_WIDEBLK; + } + else if (internal_format & MALI_GRALLOC_INTFMT_AFBC_BASIC) + { + type = AFBC_TILED_HEADERS_BASIC; + } + else if (internal_format & MALI_GRALLOC_INTFMT_AFBC_SPLITBLK) + { + ALOGE("Unsupported format. Splitblk in tiled header configuration."); + return -EINVAL; + } + } + else if (usage & MALI_GRALLOC_USAGE_AFBC_PADDING) + { + type = AFBC_PADDED; + } + else if (internal_format & MALI_GRALLOC_INTFMT_AFBC_WIDEBLK) + { + type = AFBC_WIDEBLK; + } + else + { + type = AFBC; + } + } + + uint64_t base_format = internal_format & MALI_GRALLOC_INTFMT_FMT_MASK; + switch (base_format) + { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: + get_rgb_stride_and_size(w, h, 4, &pixel_stride, &byte_stride, &size, type ); + break; + case HAL_PIXEL_FORMAT_RGB_888: + get_rgb_stride_and_size(w, h, 3, &pixel_stride, &byte_stride, &size, type ); + break; + case HAL_PIXEL_FORMAT_RGB_565: + get_rgb_stride_and_size(w, h, 2, &pixel_stride, &byte_stride, &size, type ); + break; + + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case MALI_GRALLOC_FORMAT_INTERNAL_YV12: + case MALI_GRALLOC_FORMAT_INTERNAL_NV12: + case MALI_GRALLOC_FORMAT_INTERNAL_NV21: + { + /* Mali subsystem prefers higher stride alignment values (128 bytes) for YUV, but software components assume + * default of 16. We only need to care about YV12 as it's the only, implicit, HAL YUV format in Android. + */ + int yv12_align = YUV_MALI_PLANE_ALIGN; + if(usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) + { + yv12_align = YUV_ANDROID_PLANE_ALIGN; + } + + if (!get_yv12_stride_and_size(w, h, &pixel_stride, &byte_stride, &size, type, + &internalHeight, yv12_align)) + { + return -EINVAL; + } + break; + } + case HAL_PIXEL_FORMAT_YCbCr_422_I: + { + /* YUYV 4:2:2 */ + if (type != UNCOMPRESSED || !get_yuv422_8bit_stride_and_size(w, h, &pixel_stride, &byte_stride, &size)) + { + return -EINVAL; + } + break; + } + case HAL_PIXEL_FORMAT_RAW16: + case HAL_PIXEL_FORMAT_RAW12: + case HAL_PIXEL_FORMAT_RAW10: + case HAL_PIXEL_FORMAT_BLOB: + if (type != UNCOMPRESSED) + { + return -EINVAL; + } + get_camera_formats_stride_and_size(w, h, base_format, &pixel_stride, &size); + byte_stride = pixel_stride; /* For Raw/Blob formats stride is defined to be either in bytes or pixels per format */ + break; + + case MALI_GRALLOC_FORMAT_INTERNAL_Y0L2: + /* YUYAAYUVAA 4:2:0 with and without AFBC */ + if (type != UNCOMPRESSED) + { + if (!get_yuv420_10bit_afbc_stride_and_size(w, h, &pixel_stride, &byte_stride, &size, type, &internalHeight)) + { + return -EINVAL; + } + } + else + { + if(!get_yuv_y0l2_stride_and_size(w, h, &pixel_stride, &byte_stride, &size)) + { + return -EINVAL; + } + } + break; + + case MALI_GRALLOC_FORMAT_INTERNAL_P010: + /* Y-UV 4:2:0 */ + if (type != UNCOMPRESSED || !get_yuv_pX10_stride_and_size(w, h, 2, &pixel_stride, &byte_stride, &size)) + { + return -EINVAL; + } + break; + + case MALI_GRALLOC_FORMAT_INTERNAL_P210: + /* Y-UV 4:2:2 */ + if (type != UNCOMPRESSED || !get_yuv_pX10_stride_and_size(w, h, 1, &pixel_stride, &byte_stride, &size)) + { + return -EINVAL; + } + break; + + case MALI_GRALLOC_FORMAT_INTERNAL_Y210: + /* YUYV 4:2:2 with and without AFBC */ + if (type != UNCOMPRESSED) + { + if (!get_yuv422_10bit_afbc_stride_and_size(w, h, &pixel_stride, &byte_stride, &size, type)) + { + return -EINVAL; + } + } + else + { + if(!get_yuv_y210_stride_and_size(w, h, &pixel_stride, &byte_stride, &size)) + { + return -EINVAL; + } + } + break; + + case MALI_GRALLOC_FORMAT_INTERNAL_Y410: + /* AVYU 2-10-10-10 */ + if (type != UNCOMPRESSED || !get_yuv_y410_stride_and_size(w, h, &pixel_stride, &byte_stride, &size)) + { + return -EINVAL; + } + break; + + case MALI_GRALLOC_FORMAT_INTERNAL_YUV422_8BIT: + /* 8BIT AFBC YUV4:2:2 testing usage */ + + /* We only support compressed for this format right now. + * Below will fail in case format is uncompressed. + */ + if (!get_afbc_yuv422_8bit_stride_and_size(w, h, &pixel_stride, &byte_stride, &size, type)) + { + return -EINVAL; + } + break; + /* + * Additional custom formats can be added here + * and must fill the variables pixel_stride, byte_stride and size. + */ + default: + return -EINVAL; + } + + int err; +#if DISABLE_FRAMEBUFFER_HAL != 1 + if (usage & GRALLOC_USAGE_HW_FB) + { + err = gralloc_alloc_framebuffer(dev, size, usage, pHandle, &pixel_stride, &byte_stride); + } + else +#endif + { + err = alloc_backend_alloc(dev, size, usage, pHandle, internal_format, w, h); + } + + if (err < 0) + { + return err; + } + + private_handle_t *hnd = (private_handle_t *)*pHandle; + + err = gralloc_buffer_attr_allocate( hnd ); + if( err < 0 ) + { + private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module); + + if ( (usage & GRALLOC_USAGE_HW_FB) ) + { + /* + * Having the attribute region is not critical for the framebuffer so let it pass. + */ + err = 0; + } + else + { + alloc_backend_alloc_free( hnd, m ); + return err; + } + } + + hnd->req_format = format; + hnd->byte_stride = byte_stride; + hnd->internal_format = internal_format; + + int private_usage = usage & MALI_GRALLOC_USAGE_YUV_CONF_MASK; + + switch (private_usage) + { + case MALI_GRALLOC_USAGE_YUV_CONF_0: + hnd->yuv_info = MALI_YUV_BT601_NARROW; + break; + case MALI_GRALLOC_USAGE_YUV_CONF_1: + hnd->yuv_info = MALI_YUV_BT601_WIDE; + break; + case MALI_GRALLOC_USAGE_YUV_CONF_2: + hnd->yuv_info = MALI_YUV_BT709_NARROW; + break; + case MALI_GRALLOC_USAGE_YUV_CONF_3: + hnd->yuv_info = MALI_YUV_BT709_WIDE; + break; + } + + /* Workaround 10bit YUV only support BT709_WIDE in GPU DDK */ + if ((hnd->internal_format & MALI_GRALLOC_INTFMT_FMT_MASK) == MALI_GRALLOC_FORMAT_INTERNAL_Y0L2) + { + hnd->yuv_info = MALI_YUV_BT709_WIDE; + } + hnd->width = w; + hnd->height = h; + hnd->stride = pixel_stride; + hnd->internalWidth = internalWidth; + hnd->internalHeight = internalHeight; + + *pStride = pixel_stride; + return 0; +} + +static int alloc_device_free(alloc_device_t* dev, buffer_handle_t handle) +{ + if (private_handle_t::validate(handle) < 0) + { + return -EINVAL; + } + + private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(handle); + private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module); + + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) + { + // free this buffer + private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module); + const size_t bufferSize = m->finfo.line_length * m->info.yres; + int index = ((uintptr_t)hnd->base - (uintptr_t)m->framebuffer->base) / bufferSize; + m->bufferMask &= ~(1 << index); + close(hnd->fd); + } + + gralloc_buffer_attr_free( (private_handle_t *) hnd ); + alloc_backend_alloc_free(hnd, m); + + delete hnd; + + return 0; +} + +int alloc_device_open(hw_module_t const* module, const char* name, hw_device_t** device) +{ + alloc_device_t *dev; + + GRALLOC_UNUSED(name); + + dev = new alloc_device_t; + if (NULL == dev) + { + return -1; + } + + /* initialize our state here */ + memset(dev, 0, sizeof(*dev)); + + /* initialize the procs */ + dev->common.tag = HARDWARE_DEVICE_TAG; + dev->common.version = 0; + dev->common.module = const_cast<hw_module_t*>(module); + dev->common.close = alloc_backend_close; + dev->alloc = alloc_device_alloc; + dev->free = alloc_device_free; + + if (0 != alloc_backend_open(dev)) { + delete dev; + return -1; + } + + *device = &dev->common; + + return 0; +} diff --git a/gralloc960/alloc_device.h b/gralloc960/alloc_device.h new file mode 100644 index 00000000..bcbc1dc1 --- /dev/null +++ b/gralloc960/alloc_device.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2010 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/hardware.h> + +#ifndef AWAR +#define AWAR(fmt, args...) __android_log_print(ANDROID_LOG_WARN, "[Gralloc-Warning]", "%s:%d " fmt,__func__,__LINE__,##args) +#endif +#ifndef AINF +#define AINF(fmt, args...) __android_log_print(ANDROID_LOG_INFO, "[Gralloc]", fmt,##args) +#endif +#ifndef AERR +#define AERR(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, "[Gralloc-ERROR]", "%s:%d " fmt,__func__,__LINE__,##args) +#endif +#ifndef AERR_IF +#define AERR_IF( eq, fmt, args...) if ( (eq) ) AERR( fmt, args ) +#endif + +#define GRALLOC_ALIGN( value, base ) (((value) + ((base) - 1)) & ~((base) - 1)) + +// Create an alloc device +int alloc_device_open(hw_module_t const* module, const char* name, hw_device_t** device); diff --git a/gralloc960/alloc_device_allocator_specific.h b/gralloc960/alloc_device_allocator_specific.h new file mode 100644 index 00000000..2de38b5d --- /dev/null +++ b/gralloc960/alloc_device_allocator_specific.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2013 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. + */ + +int alloc_backend_alloc(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle, uint64_t fmt, int w, int h); + +int alloc_backend_alloc_framebuffer(struct private_module_t* m, struct private_handle_t* hnd); + +void alloc_backend_alloc_free(struct private_handle_t const* hnd, struct private_module_t* m); + +int alloc_backend_open(alloc_device_t *dev); + +int alloc_backend_close(struct hw_device_t *device); diff --git a/gralloc960/alloc_ion.cpp b/gralloc960/alloc_ion.cpp new file mode 100644 index 00000000..2f9efc05 --- /dev/null +++ b/gralloc960/alloc_ion.cpp @@ -0,0 +1,365 @@ +/* + * Copyright (C) 2013 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 <cutils/log.h> +#include <cutils/atomic.h> +#include <hardware/hardware.h> +#include <hardware/gralloc.h> + +#include <sys/ioctl.h> + +#include "alloc_device.h" +#include "gralloc_priv.h" +#include "gralloc_helper.h" +#include "framebuffer_device.h" + +#include "mali_gralloc_formats.h" + +#include <linux/ion.h> +#include <ion/ion.h> + +static void init_afbc(uint8_t *buf, uint64_t internal_format, int w, int h) +{ + uint32_t n_headers = (w * h) / 64; + uint32_t body_offset = n_headers * 16; + uint32_t headers[][4] = { {body_offset, 0x1, 0x0, 0x0}, /* Layouts 0, 3, 4 */ + {(body_offset + (1 << 28)), 0x200040, 0x4000, 0x80} /* Layouts 1, 5 */ + }; + uint32_t i, layout; + + /* map format if necessary (also removes internal extension bits) */ + uint64_t base_format = internal_format & MALI_GRALLOC_INTFMT_FMT_MASK; + + switch (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: + layout = 0; + break; + + case MALI_GRALLOC_FORMAT_INTERNAL_YV12: + case MALI_GRALLOC_FORMAT_INTERNAL_NV12: + case MALI_GRALLOC_FORMAT_INTERNAL_NV21: + layout = 1; + break; + default: + layout = 0; + } + + ALOGV("Writing AFBC header layout %d for format %" PRIu64, layout, base_format); + + for (i = 0; i < n_headers; i++) + { + memcpy(buf, headers[layout], sizeof(headers[layout])); + buf += sizeof(headers[layout]); + } + +} + +static ion_user_handle_t alloc_from_ion_heap(int ion_fd, size_t size, unsigned int heap_mask, + unsigned int flags, int *min_pgsz) +{ + ion_user_handle_t ion_hnd = -1; + int ret; + + if ((ion_fd < 0) || (size <= 0) || (heap_mask == 0) || (min_pgsz == NULL)) + return -1; + + ret = ion_alloc(ion_fd, size, 0, heap_mask, flags, &ion_hnd); + if (ret < 0) + { +#if defined(ION_HEAP_SECURE_MASK) + if (heap_mask == ION_HEAP_SECURE_MASK) + { + return -1; + } + else +#endif + { + /* If everything else failed try system heap */ + flags = 0; /* Fallback option flags are not longer valid */ + heap_mask = ION_HEAP_SYSTEM_MASK; + ret = ion_alloc(ion_fd, size, 0, heap_mask, flags, &ion_hnd); + } + } + + if (ret >= 0) + { + switch (heap_mask) + { + case ION_HEAP_SYSTEM_MASK: + *min_pgsz = SZ_4K; + break; + case ION_HEAP_SYSTEM_CONTIG_MASK: + case ION_HEAP_CARVEOUT_MASK: +#ifdef ION_HEAP_TYPE_DMA_MASK + case ION_HEAP_TYPE_DMA_MASK: +#endif + *min_pgsz = size; + break; +#ifdef ION_HEAP_CHUNK_MASK + /* NOTE: if have this heap make sure your ION chunk size is 2M*/ + case ION_HEAP_CHUNK_MASK: + *min_pgsz = SZ_2M; + break; +#endif +#ifdef ION_HEAP_COMPOUND_PAGE_MASK + case ION_HEAP_COMPOUND_PAGE_MASK: + *min_pgsz = SZ_2M; + break; +#endif + /* If have customized heap please set the suitable pg type according to + * the customized ION implementation + */ +#ifdef ION_HEAP_CUSTOM_MASK + case ION_HEAP_CUSTOM_MASK: + *min_pgsz = SZ_4K; + break; +#endif + default: + *min_pgsz = SZ_4K; + break; + } + } + + return ion_hnd; +} + +unsigned int pick_ion_heap(int usage) +{ + unsigned int heap_mask; + + if(usage & GRALLOC_USAGE_PROTECTED) + { +#if defined(ION_HEAP_SECURE_MASK) + heap_mask = ION_HEAP_SECURE_MASK; +#else + AERR("Protected ION memory is not supported on this platform."); + return 0; +#endif + } +#if defined(ION_HEAP_TYPE_COMPOUND_PAGE_MASK) && GRALLOC_USE_ION_COMPOUND_PAGE_HEAP + else if(!(usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) && (usage & (GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER))) + { + heap_mask = ION_HEAP_TYPE_COMPOUND_PAGE_MASK; + } +#elif defined(ION_HEAP_TYPE_DMA_MASK) && GRALLOC_USE_ION_DMA_HEAP + else if(!(usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) && (usage & (GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER))) + { + heap_mask = ION_HEAP_TYPE_DMA_MASK; + } +#endif + else + { + heap_mask = ION_HEAP_SYSTEM_MASK; + } + + return heap_mask; +} + +void set_ion_flags(unsigned int heap_mask, int usage, unsigned int *priv_heap_flag, int *ion_flags) +{ +#if !GRALLOC_USE_ION_DMA_HEAP + GRALLOC_UNUSED(heap_mask); +#endif + + if (priv_heap_flag) + { +#if defined(ION_HEAP_TYPE_DMA_MASK) && GRALLOC_USE_ION_DMA_HEAP + if (heap_mask == ION_HEAP_TYPE_DMA_MASK) + { + *priv_heap_flag = private_handle_t::PRIV_FLAGS_USES_ION_DMA_HEAP; + } +#endif + } + + if (ion_flags) + { +#if defined(ION_HEAP_TYPE_DMA_MASK) && GRALLOC_USE_ION_DMA_HEAP + if(heap_mask != ION_HEAP_TYPE_DMA_MASK) + { +#endif + if ( (usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN ) + { + *ion_flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC; + } +#if defined(ION_HEAP_TYPE_DMA_MASK) && GRALLOC_USE_ION_DMA_HEAP + } +#endif + } +} + +int alloc_backend_alloc(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle, uint64_t fmt, int w, int h) +{ + private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module); + ion_user_handle_t ion_hnd; + unsigned char *cpu_ptr = NULL; + int shared_fd; + int ret; + unsigned int heap_mask, priv_heap_flag = 0; + int ion_flags = 0; + static int support_protected = 1; /* initially, assume we support protected memory */ + int lock_state = 0; + int min_pgsz = 0; + + heap_mask = pick_ion_heap(usage); + if(heap_mask == 0) + { + AERR("Failed to find an appropriate ion heap"); + return -1; + } + set_ion_flags(heap_mask, usage, &priv_heap_flag, &ion_flags); + + ion_hnd = alloc_from_ion_heap(m->ion_client, size, heap_mask, ion_flags, &min_pgsz); + if (ion_hnd < 0) + { + AERR("Failed to ion_alloc from ion_client:%d", m->ion_client); + return -1; + } + + ret = ion_share( m->ion_client, ion_hnd, &shared_fd ); + if ( ret != 0 ) + { + AERR( "ion_share( %d ) failed", m->ion_client ); + if ( 0 != ion_free( m->ion_client, ion_hnd ) ) AERR( "ion_free( %d ) failed", m->ion_client ); + return -1; + } + + if (!(usage & GRALLOC_USAGE_PROTECTED)) + { + cpu_ptr = (unsigned char*)mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shared_fd, 0 ); + + if ( MAP_FAILED == cpu_ptr ) + { + AERR( "ion_map( %d ) failed", m->ion_client ); + if ( 0 != ion_free( m->ion_client, ion_hnd ) ) AERR( "ion_free( %d ) failed", m->ion_client ); + close( shared_fd ); + return -1; + } + lock_state = private_handle_t::LOCK_STATE_MAPPED; + +#if GRALLOC_INIT_AFBC == 1 + if (fmt & MALI_GRALLOC_INTFMT_AFBCENABLE_MASK) + { + init_afbc(cpu_ptr, fmt, w, h); + } +#else + GRALLOC_UNUSED(fmt); + GRALLOC_UNUSED(w); + GRALLOC_UNUSED(h); + +#endif /* GRALLOC_INIT_AFBC == 1 */ + } + + private_handle_t *hnd = new private_handle_t( private_handle_t::PRIV_FLAGS_USES_ION | priv_heap_flag, usage, size, cpu_ptr, + lock_state, -1, 0); + + if ( NULL != hnd ) + { + hnd->share_fd = shared_fd; + hnd->ion_hnd = ion_hnd; + hnd->min_pgsz = min_pgsz; + *pHandle = hnd; + return 0; + } + else + { + AERR( "Gralloc out of mem for ion_client:%d", m->ion_client ); + } + + close( shared_fd ); + + if(!(usage & GRALLOC_USAGE_PROTECTED)) + { + ret = munmap( cpu_ptr, size ); + if ( 0 != ret ) AERR( "munmap failed for base:%p size: %zd", cpu_ptr, size ); + } + + ret = ion_free( m->ion_client, ion_hnd ); + if ( 0 != ret ) AERR( "ion_free( %d ) failed", m->ion_client ); + return -1; +} + +int alloc_backend_alloc_framebuffer(private_module_t* m, private_handle_t* hnd) +{ + struct fb_dmabuf_export fb_dma_buf; + int res; + res = ioctl( m->framebuffer->fd, FBIOGET_DMABUF, &fb_dma_buf ); + if(res == 0) + { + hnd->share_fd = fb_dma_buf.fd; + return 0; + } + else + { + AINF("FBIOGET_DMABUF ioctl failed(%d). See gralloc_priv.h and the integration manual for vendor framebuffer integration", res); + return -1; + } +} + +void alloc_backend_alloc_free(private_handle_t const* hnd, private_module_t* m) +{ + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) + { + return; + } + else if ( hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION ) + { + /* Buffer might be unregistered already so we need to assure we have a valid handle*/ + if ( 0 != hnd->base ) + { + if ( 0 != munmap( (void*)hnd->base, hnd->size ) ) AERR( "Failed to munmap handle %p", hnd ); + } + close( hnd->share_fd ); + if ( 0 != ion_free( m->ion_client, hnd->ion_hnd ) ) AERR( "Failed to ion_free( ion_client: %d ion_hnd: %d )", m->ion_client, hnd->ion_hnd ); + memset( (void*)hnd, 0, sizeof( *hnd ) ); + } +} + +int alloc_backend_open(alloc_device_t *dev) +{ + private_module_t *m = reinterpret_cast<private_module_t *>(dev->common.module); + m->ion_client = ion_open(); + if ( m->ion_client < 0 ) + { + AERR( "ion_open failed with %s", strerror(errno) ); + return -1; + } + + return 0; +} + +int alloc_backend_close(struct hw_device_t *device) +{ + alloc_device_t* dev = reinterpret_cast<alloc_device_t*>(device); + if (dev) + { + private_module_t *m = reinterpret_cast<private_module_t*>(dev->common.module); + if ( 0 != ion_close(m->ion_client) ) AERR( "Failed to close ion_client: %d err=%s", m->ion_client , strerror(errno)); + delete dev; + } + return 0; +} diff --git a/gralloc960/framebuffer_device.cpp b/gralloc960/framebuffer_device.cpp new file mode 100644 index 00000000..873b5f4c --- /dev/null +++ b/gralloc960/framebuffer_device.cpp @@ -0,0 +1,496 @@ +/* + * Copyright (C) 2010 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 <fcntl.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <linux/fb.h> + +#include <cutils/log.h> +#include <cutils/atomic.h> +#include <hardware/hardware.h> +#include <hardware/gralloc.h> + +#include <GLES/gl.h> + +#include "alloc_device.h" +#include "gralloc_priv.h" +#include "gralloc_helper.h" +#include "gralloc_vsync.h" + +#define STANDARD_LINUX_SCREEN + +// numbers of buffers for page flipping +#define NUM_BUFFERS NUM_FB_BUFFERS + +enum +{ + PAGE_FLIP = 0x00000001, +}; + + +static int fb_set_swap_interval(struct framebuffer_device_t* dev, int interval) +{ + if (interval < dev->minSwapInterval) + { + interval = dev->minSwapInterval; + } + else if (interval > dev->maxSwapInterval) + { + interval = dev->maxSwapInterval; + } + + private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module); + m->swapInterval = interval; + + if (0 == interval) gralloc_vsync_disable(dev); + else gralloc_vsync_enable(dev); + + return 0; +} + +static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) +{ + if (private_handle_t::validate(buffer) < 0) + { + return -EINVAL; + } + + private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(buffer); + private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module); + + if (m->currentBuffer) + { + m->base.unlock(&m->base, m->currentBuffer); + m->currentBuffer = 0; + } + + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) + { + m->base.lock(&m->base, buffer, private_module_t::PRIV_USAGE_LOCKED_FOR_POST, + 0, 0, m->info.xres, m->info.yres, NULL); + + const size_t offset = (uintptr_t)hnd->base - (uintptr_t)m->framebuffer->base; + int interrupt; + m->info.activate = FB_ACTIVATE_VBL; + m->info.yoffset = offset / m->finfo.line_length; + +#ifdef STANDARD_LINUX_SCREEN + if (ioctl(m->framebuffer->fd, FBIOPAN_DISPLAY, &m->info) == -1) + { + AERR( "FBIOPAN_DISPLAY failed for fd: %d", m->framebuffer->fd ); + m->base.unlock(&m->base, buffer); + return -errno; + } +#else /*Standard Android way*/ + if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) + { + AERR( "FBIOPUT_VSCREENINFO failed for fd: %d", m->framebuffer->fd ); + m->base.unlock(&m->base, buffer); + return -errno; + } +#endif + if ( 0 != gralloc_wait_for_vsync(dev) ) + { + AERR( "Gralloc wait for vsync failed for fd: %d", m->framebuffer->fd ); + m->base.unlock(&m->base, buffer); + return -errno; + } + m->currentBuffer = buffer; + } + else + { + void* fb_vaddr; + void* buffer_vaddr; + + m->base.lock(&m->base, m->framebuffer, GRALLOC_USAGE_SW_WRITE_RARELY, + 0, 0, m->info.xres, m->info.yres, &fb_vaddr); + + m->base.lock(&m->base, buffer, GRALLOC_USAGE_SW_READ_RARELY, + 0, 0, m->info.xres, m->info.yres, &buffer_vaddr); + + // If buffer's alignment match framebuffer alignment we can do a direct copy. + // If not we must fallback to do an aligned copy of each line. + if ( hnd->byte_stride == (int)m->finfo.line_length ) + { + memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres); + } + else + { + uintptr_t fb_offset = 0; + uintptr_t buffer_offset = 0; + unsigned int i; + + for (i = 0; i < m->info.yres; i++) + { + memcpy((void *)((uintptr_t)fb_vaddr + fb_offset), + (void *)((uintptr_t)buffer_vaddr + buffer_offset), + m->finfo.line_length); + + fb_offset += m->finfo.line_length; + buffer_offset += hnd->byte_stride; + } + } + m->base.unlock(&m->base, buffer); + m->base.unlock(&m->base, m->framebuffer); + } + + return 0; +} + +int init_frame_buffer_locked(struct private_module_t* module) +{ + if (module->framebuffer) + { + return 0; // Nothing to do, already initialized + } + + char const * const device_template[] = + { + "/dev/graphics/fb%u", + "/dev/fb%u", + NULL + }; + + int fd = -1; + int i = 0; + char name[64]; + + while ((fd == -1) && device_template[i]) + { + snprintf(name, 64, device_template[i], 0); + fd = open(name, O_RDWR, 0); + i++; + } + + if (fd < 0) + { + return -errno; + } + + struct fb_fix_screeninfo finfo; + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) + { + return -errno; + } + + struct fb_var_screeninfo info; + if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) + { + return -errno; + } + + info.reserved[0] = 0; + info.reserved[1] = 0; + info.reserved[2] = 0; + info.xoffset = 0; + info.yoffset = 0; + info.activate = FB_ACTIVATE_NOW; + +#ifdef GRALLOC_16_BITS + /* + * Explicitly request 5/6/5 + */ + info.bits_per_pixel = 16; + info.red.offset = 11; + info.red.length = 5; + info.green.offset = 5; + info.green.length = 6; + info.blue.offset = 0; + info.blue.length = 5; + info.transp.offset = 0; + info.transp.length = 0; +#else + /* + * Explicitly request 8/8/8 + */ + info.bits_per_pixel = 32; + info.red.offset = 16; + info.red.length = 8; + info.green.offset = 8; + info.green.length = 8; + info.blue.offset = 0; + info.blue.length = 8; + info.transp.offset = 0; + info.transp.length = 0; +#endif + + /* + * Request NUM_BUFFERS screens (at lest 2 for page flipping) + */ + info.yres_virtual = info.yres * NUM_BUFFERS; + + uint32_t flags = PAGE_FLIP; + if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) + { + info.yres_virtual = info.yres; + flags &= ~PAGE_FLIP; + AWAR( "FBIOPUT_VSCREENINFO failed, page flipping not supported fd: %d", fd ); + } + + if (info.yres_virtual < info.yres * 2) + { + // we need at least 2 for page-flipping + info.yres_virtual = info.yres; + flags &= ~PAGE_FLIP; + AWAR( "page flipping not supported (yres_virtual=%d, requested=%d)", info.yres_virtual, info.yres*2 ); + } + + if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) + { + return -errno; + } + + int refreshRate = 0; + if ( info.pixclock > 0 ) + { + refreshRate = 1000000000000000LLU / + ( + uint64_t( info.upper_margin + info.lower_margin + info.yres + info.hsync_len ) + * ( info.left_margin + info.right_margin + info.xres + info.vsync_len ) + * info.pixclock + ); + } + else + { + AWAR( "fbdev pixclock is zero for fd: %d", fd ); + } + + if (refreshRate == 0) + { + refreshRate = 60*1000; // 60 Hz + } + + if (int(info.width) <= 0 || int(info.height) <= 0) + { + // the driver doesn't return that information + // default to 160 dpi + info.width = ((info.xres * 25.4f)/160.0f + 0.5f); + info.height = ((info.yres * 25.4f)/160.0f + 0.5f); + } + + float xdpi = (info.xres * 25.4f) / info.width; + float ydpi = (info.yres * 25.4f) / info.height; + float fps = refreshRate / 1000.0f; + + AINF("using (fd=%d)\n" + "id = %s\n" + "xres = %d px\n" + "yres = %d px\n" + "xres_virtual = %d px\n" + "yres_virtual = %d px\n" + "bpp = %d\n" + "r = %2u:%u\n" + "g = %2u:%u\n" + "b = %2u:%u\n", + fd, + finfo.id, + info.xres, + info.yres, + info.xres_virtual, + info.yres_virtual, + info.bits_per_pixel, + info.red.offset, info.red.length, + info.green.offset, info.green.length, + info.blue.offset, info.blue.length); + + AINF("width = %d mm (%f dpi)\n" + "height = %d mm (%f dpi)\n" + "refresh rate = %.2f Hz\n", + info.width, xdpi, + info.height, ydpi, + fps); + + if (0 == strncmp(finfo.id, "CLCD FB", 7)) + { + module->dpy_type = MALI_DPY_TYPE_CLCD; + } + else if (0 == strncmp(finfo.id, "ARM Mali HDLCD", 14)) + { + module->dpy_type = MALI_DPY_TYPE_HDLCD; + } + else + { + module->dpy_type = MALI_DPY_TYPE_UNKNOWN; + } + + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) + { + return -errno; + } + + if (finfo.smem_len <= 0) + { + return -errno; + } + + module->flags = flags; + module->info = info; + module->finfo = finfo; + module->xdpi = xdpi; + module->ydpi = ydpi; + module->fps = fps; + module->swapInterval = 1; + + /* + * map the framebuffer + */ + size_t fbSize = round_up_to_page_size(finfo.line_length * info.yres_virtual); + void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (vaddr == MAP_FAILED) + { + AERR( "Error mapping the framebuffer (%s)", strerror(errno) ); + return -errno; + } + + memset(vaddr, 0, fbSize); + + + // Create a "fake" buffer object for the entire frame buffer memory, and store it in the module + module->framebuffer = new private_handle_t(private_handle_t::PRIV_FLAGS_FRAMEBUFFER, GRALLOC_USAGE_HW_FB, fbSize, vaddr, + 0, dup(fd), 0); + + module->numBuffers = info.yres_virtual / info.yres; + module->bufferMask = 0; + + return 0; +} + +static int init_frame_buffer(struct private_module_t* module) +{ + pthread_mutex_lock(&module->lock); + int err = init_frame_buffer_locked(module); + pthread_mutex_unlock(&module->lock); + return err; +} + +static int fb_close(struct hw_device_t *device) +{ + framebuffer_device_t* dev = reinterpret_cast<framebuffer_device_t*>(device); + if (dev) + { + free(dev); + } + return 0; +} + +int compositionComplete(struct framebuffer_device_t* dev) +{ + GRALLOC_UNUSED(dev); + + /* By doing a finish here we force the GL driver to start rendering + all the drawcalls up to this point, and to wait for the rendering to be complete.*/ + glFinish(); + /* The rendering of the backbuffer is now completed. + When SurfaceFlinger later does a call to eglSwapBuffer(), the swap will be done + synchronously in the same thread, and not asynchronoulsy in a background thread later. + The SurfaceFlinger requires this behaviour since it releases the lock on all the + SourceBuffers (Layers) after the compositionComplete() function returns. + However this "bad" behaviour by SurfaceFlinger should not affect performance, + since the Applications that render the SourceBuffers (Layers) still get the + full renderpipeline using asynchronous rendering. So they perform at maximum speed, + and because of their complexity compared to the Surface flinger jobs, the Surface flinger + is normally faster even if it does everyhing synchronous and serial. + */ + return 0; +} + +int framebuffer_device_open(hw_module_t const* module, const char* name, hw_device_t** device) +{ + int status = -EINVAL; + + GRALLOC_UNUSED(name); + + alloc_device_t* gralloc_device; +#if DISABLE_FRAMEBUFFER_HAL == 1 + AERR("Framebuffer HAL not support/disabled %s", +#ifdef MALI_DISPLAY_VERSION + "with MALI display enable"); +#else + ""); +#endif + return -ENODEV; +#endif + status = gralloc_open(module, &gralloc_device); + if (status < 0) + { + return status; + } + + private_module_t* m = (private_module_t*)module; + status = init_frame_buffer(m); + + /* malloc is used instead of 'new' to instantiate the struct framebuffer_device_t + * C++11 spec specifies that if a class/struct has a const member,default constructor + * is deleted. So, if 'new' is used to instantiate the class/struct, it will throw + * error complaining about deleted constructor. Even if the struct is wrapped in a class + * it will still try to use the base class constructor to initialize the members, resulting + * in error 'deleted constructor'. + * This leaves two options + * Option 1: initialize the const members at the instantiation time. With {value1, value2 ..} + * Which relies on the order of the members, and if members are reordered or a new member is introduced + * it will end up assiging wrong value to members. Designated assignment as well has been removed in C++11 + * Option 2: use malloc instead of 'new' to allocate the class/struct and initialize the members in code. + * This is the only maintainable option available. + */ + + framebuffer_device_t *dev = reinterpret_cast<framebuffer_device_t*> (malloc(sizeof(framebuffer_device_t))); + + /* if either or both of init_frame_buffer() and malloc failed */ + if ((status < 0) || (!dev)) + { + gralloc_close(gralloc_device); + (!dev)? (void)(status = -ENOMEM) : free(dev); + return status; + } + + memset(dev, 0, sizeof(*dev)); + + /* initialize the procs */ + dev->common.tag = HARDWARE_DEVICE_TAG; + dev->common.version = 0; + dev->common.module = const_cast<hw_module_t*>(module); + dev->common.close = fb_close; + dev->setSwapInterval = fb_set_swap_interval; + dev->post = fb_post; + dev->setUpdateRect = 0; + dev->compositionComplete = &compositionComplete; + + int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3); + const_cast<uint32_t&>(dev->flags) = 0; + const_cast<uint32_t&>(dev->width) = m->info.xres; + const_cast<uint32_t&>(dev->height) = m->info.yres; + const_cast<int&>(dev->stride) = stride; +#ifdef GRALLOC_16_BITS + const_cast<int&>(dev->format) = HAL_PIXEL_FORMAT_RGB_565; +#else + const_cast<int&>(dev->format) = HAL_PIXEL_FORMAT_BGRA_8888; +#endif + const_cast<float&>(dev->xdpi) = m->xdpi; + const_cast<float&>(dev->ydpi) = m->ydpi; + const_cast<float&>(dev->fps) = m->fps; + const_cast<int&>(dev->minSwapInterval) = 0; + const_cast<int&>(dev->maxSwapInterval) = 1; + *device = &dev->common; + + gralloc_vsync_enable(dev); + + return status; +} diff --git a/gralloc960/framebuffer_device.h b/gralloc960/framebuffer_device.h new file mode 100644 index 00000000..a653cefc --- /dev/null +++ b/gralloc960/framebuffer_device.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2010 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/hardware.h> +#include "gralloc_priv.h" + +// Create a framebuffer device +int framebuffer_device_open(hw_module_t const* module, const char* name, hw_device_t** device); + +// Initialize the framebuffer (must keep module lock before calling +int init_frame_buffer_locked(struct private_module_t* module); diff --git a/gralloc960/gralloc_buffer_priv.cpp b/gralloc960/gralloc_buffer_priv.cpp new file mode 100644 index 00000000..a3570308 --- /dev/null +++ b/gralloc960/gralloc_buffer_priv.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2014 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 <cutils/ashmem.h> +#include <cutils/log.h> +#include <sys/mman.h> +#include "gralloc_priv.h" +#include "gralloc_buffer_priv.h" + + +/* + * Allocate shared memory for attribute storage. Only to be + * used by gralloc internally. + * + * Return 0 on success. + */ +int gralloc_buffer_attr_allocate( private_handle_t *hnd ) +{ + int rval = -1; + + if( !hnd ) + goto out; + + if( hnd->share_attr_fd >= 0 ) + { + ALOGW("Warning share attribute fd already exists during create. Closing."); + close( hnd->share_attr_fd ); + } + + hnd->share_attr_fd = ashmem_create_region( "gralloc_shared_attr", PAGE_SIZE ); + if(hnd->share_attr_fd < 0) + { + ALOGE("Failed to allocate page for shared attribute region"); + goto err_ashmem; + } + + /* + * Default protection on the shm region is PROT_EXEC | PROT_READ | PROT_WRITE. + * + * Personality flag READ_IMPLIES_EXEC which is used by some processes, namely gdbserver, + * causes a mmap with PROT_READ to be translated to PROT_READ | PROT_EXEC. + * + * If we were to drop PROT_EXEC here with a call to ashmem_set_prot_region() + * this can potentially cause clients to fail importing this gralloc attribute buffer + * with EPERM error since PROT_EXEC is not allowed. + * + * Because of this we keep the PROT_EXEC flag. + */ + + hnd->attr_base = mmap( NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, hnd->share_attr_fd, 0 ); + if(hnd->attr_base != MAP_FAILED) + { + /* The attribute region contains signed integers only. + * The reason for this is because we can set a value less than 0 for + * not-initialized values. + */ + attr_region *region = (attr_region *) hnd->attr_base; + + memset(hnd->attr_base, 0xff, PAGE_SIZE); + munmap( hnd->attr_base, PAGE_SIZE ); + hnd->attr_base = MAP_FAILED; + } + else + { + ALOGE("Failed to mmap shared attribute region"); + goto err_ashmem; + } + + rval = 0; + goto out; + +err_ashmem: + if( hnd->share_attr_fd >= 0 ) + { + close( hnd->share_attr_fd ); + hnd->share_attr_fd = -1; + } + +out: + return rval; +} + +/* + * Frees the shared memory allocated for attribute storage. + * Only to be used by gralloc internally. + + * Return 0 on success. + */ +int gralloc_buffer_attr_free( private_handle_t *hnd ) +{ + int rval = -1; + + if( !hnd ) + goto out; + + if( hnd->share_attr_fd < 0 ) + { + ALOGE("Shared attribute region not avail to free"); + goto out; + } + if( hnd->attr_base != MAP_FAILED ) + { + ALOGW("Warning shared attribute region mapped at free. Unmapping"); + munmap( hnd->attr_base, PAGE_SIZE ); + hnd->attr_base = MAP_FAILED; + } + + close( hnd->share_attr_fd ); + hnd->share_attr_fd = -1; + rval = 0; + +out: + return rval; +} diff --git a/gralloc960/gralloc_buffer_priv.h b/gralloc960/gralloc_buffer_priv.h new file mode 100644 index 00000000..516781cb --- /dev/null +++ b/gralloc960/gralloc_buffer_priv.h @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2014 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_BUFFER_PRIV_H_ +#define GRALLOC_BUFFER_PRIV_H_ + +#include "gralloc_priv.h" +#include <errno.h> +#include <string.h> + +// private gralloc buffer manipulation API + +struct attr_region +{ + /* Rectangle to be cropped from the full frame (Origin in top-left corner!) */ + int crop_top; + int crop_left; + int crop_height; + int crop_width; + int use_yuv_transform; + int use_sparse_alloc; +} __attribute__ ((packed)); + +typedef struct attr_region attr_region; + +enum +{ + /* CROP_RECT and YUV_TRANS are intended to be + * written by producers and read by consumers. + * A producer should write these parameters before + * it queues a buffer to the consumer. + */ + + /* CROP RECT, defined as an int array of top, left, height, width. Origin in top-left corner */ + GRALLOC_ARM_BUFFER_ATTR_CROP_RECT = 1, + + /* Set if the AFBC format used a YUV transform before compressing */ + GRALLOC_ARM_BUFFER_ATTR_AFBC_YUV_TRANS = 2, + + /* Set if the AFBC format uses sparse allocation */ + GRALLOC_ARM_BUFFER_ATTR_AFBC_SPARSE_ALLOC = 3, + GRALLOC_ARM_BUFFER_ATTR_LAST +}; + +typedef uint32_t buf_attr; + +/* + * Allocate shared memory for attribute storage. Only to be + * used by gralloc internally. + * + * Return 0 on success. + */ +int gralloc_buffer_attr_allocate( struct private_handle_t *hnd ); + +/* + * Frees the shared memory allocated for attribute storage. + * Only to be used by gralloc internally. + + * Return 0 on success. + */ +int gralloc_buffer_attr_free( struct private_handle_t *hnd ); + +/* + * Map the attribute storage area before attempting to + * read/write from it. + * + * Return 0 on success. + */ +static inline int gralloc_buffer_attr_map( struct private_handle_t *hnd, int readwrite) +{ + int rval = -1; + int prot_flags = PROT_READ; + + if( !hnd ) + goto out; + + if( hnd->share_attr_fd < 0 ) + { + ALOGE("Shared attribute region not available to be mapped"); + goto out; + } + + if( readwrite ) + { + prot_flags |= PROT_WRITE; + } + + hnd->attr_base = mmap( NULL, PAGE_SIZE, prot_flags, MAP_SHARED, hnd->share_attr_fd, 0 ); + if(hnd->attr_base == MAP_FAILED) + { + ALOGE("Failed to mmap shared attribute region err=%s",strerror(errno)); + goto out; + } + + rval = 0; + +out: + return rval; +} + +/* + * Unmap the attribute storage area when done with it. + * + * Return 0 on success. + */ +static inline int gralloc_buffer_attr_unmap( struct private_handle_t *hnd ) +{ + int rval = -1; + + if( !hnd ) + goto out; + + if( hnd->attr_base != MAP_FAILED ) + { + if ( munmap( hnd->attr_base, PAGE_SIZE ) == 0 ) + { + hnd->attr_base = MAP_FAILED; + rval = 0; + } + } + +out: + return rval; +} + +/* + * Read or write an attribute from/to the storage area. + * + * Return 0 on success. + */ +static inline int gralloc_buffer_attr_write( struct private_handle_t *hnd, buf_attr attr, int *val ) +{ + int rval = -1; + + if( !hnd || !val || attr >= GRALLOC_ARM_BUFFER_ATTR_LAST ) + goto out; + + if( hnd->attr_base != MAP_FAILED ) + { + attr_region *region = (attr_region *) hnd->attr_base; + + switch( attr ) + { + case GRALLOC_ARM_BUFFER_ATTR_CROP_RECT: + memcpy( ®ion->crop_top, val, sizeof(int)*4 ); + rval = 0; + break; + + case GRALLOC_ARM_BUFFER_ATTR_AFBC_YUV_TRANS: + region->use_yuv_transform = *val; + rval = 0; + break; + + case GRALLOC_ARM_BUFFER_ATTR_AFBC_SPARSE_ALLOC: + region->use_sparse_alloc = *val; + rval = 0; + break; + } + } + +out: + return rval; +} + +static inline int gralloc_buffer_attr_read( struct private_handle_t *hnd, buf_attr attr, int *val ) +{ + int rval = -1; + + if( !hnd || !val || attr >= GRALLOC_ARM_BUFFER_ATTR_LAST ) + goto out; + + if( hnd->attr_base != MAP_FAILED ) + { + attr_region *region = (attr_region *) hnd->attr_base; + + switch( attr ) + { + case GRALLOC_ARM_BUFFER_ATTR_CROP_RECT: + memcpy( val, ®ion->crop_top, sizeof(int)*4 ); + rval = 0; + break; + + case GRALLOC_ARM_BUFFER_ATTR_AFBC_YUV_TRANS: + *val = region->use_yuv_transform; + rval = 0; + break; + + case GRALLOC_ARM_BUFFER_ATTR_AFBC_SPARSE_ALLOC: + *val = region->use_sparse_alloc; + rval = 0; + break; + } + } + +out: + return rval; +} + +#endif /* GRALLOC_BUFFER_PRIV_H_ */ diff --git a/gralloc960/gralloc_helper.h b/gralloc960/gralloc_helper.h new file mode 100644 index 00000000..12adb531 --- /dev/null +++ b/gralloc960/gralloc_helper.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2010 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 <sys/mman.h> + +#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/gralloc960/gralloc_module.cpp b/gralloc960/gralloc_module.cpp new file mode 100644 index 00000000..232ecc12 --- /dev/null +++ b/gralloc960/gralloc_module.cpp @@ -0,0 +1,341 @@ +/* + * Copyright (C) 2010 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 <pthread.h> +#include <inttypes.h> + +#include <cutils/log.h> +#include <cutils/atomic.h> +#include <hardware/hardware.h> +#include <hardware/gralloc.h> + +#include "gralloc_priv.h" +#include "gralloc_helper.h" +#include "alloc_device.h" +#include "framebuffer_device.h" + +#include "gralloc_module_allocator_specific.h" +#include "gralloc_buffer_priv.h" + +#include "mali_gralloc_formats.h" + +static pthread_mutex_t s_map_lock = PTHREAD_MUTEX_INITIALIZER; + +static int gralloc_device_open(const hw_module_t* module, const char* name, hw_device_t** device) +{ + int status = -EINVAL; + + if (!strncmp(name, GRALLOC_HARDWARE_GPU0, MALI_GRALLOC_HARDWARE_MAX_STR_LEN)) + { + status = alloc_device_open(module, name, device); + } + else if (!strncmp(name, GRALLOC_HARDWARE_FB0, MALI_GRALLOC_HARDWARE_MAX_STR_LEN)) + { + status = framebuffer_device_open(module, name, device); + } + + return status; +} + +static int gralloc_register_buffer(gralloc_module_t const* module, buffer_handle_t handle) +{ + GRALLOC_UNUSED(module); + + if (private_handle_t::validate(handle) < 0) + { + AERR("Registering invalid buffer %p, returning error", handle); + return -EINVAL; + } + + // if this handle was created in this process, then we keep it as is. + private_handle_t* hnd = (private_handle_t*)handle; + + if (hnd->pid == getpid()) + { + // If the handle is created and registered in the same process this is valid, + // but it could also be that application is registering twice which is illegal. + AWAR("Registering handle %p coming from the same process: %d.", hnd, hnd->pid); + } + + int retval = -EINVAL; + + pthread_mutex_lock(&s_map_lock); + + hnd->pid = getpid(); + + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) + { + AERR( "Can't register buffer %p as it is a framebuffer", handle ); + } + else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) + { + retval = gralloc_backend_register(hnd); + } + else + { + AERR("unknown buffer flags not supported. flags = %d", hnd->flags ); + } + + pthread_mutex_unlock(&s_map_lock); + return retval; +} + +static int gralloc_unregister_buffer(gralloc_module_t const* module, buffer_handle_t handle) +{ + GRALLOC_UNUSED(module); + + if (private_handle_t::validate(handle) < 0) + { + AERR("unregistering invalid buffer %p, returning error", handle); + return -EINVAL; + } + + private_handle_t* hnd = (private_handle_t*)handle; + + AERR_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK, "[unregister] handle %p still locked (state=%08x)", hnd, hnd->lockState); + + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) + { + AERR( "Can't unregister buffer %p as it is a framebuffer", handle ); + } + else if (hnd->pid == getpid()) // never unmap buffers that were not created in this process + { + pthread_mutex_lock(&s_map_lock); + + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) + { + gralloc_backend_unregister(hnd); + } + else + { + AERR("Unregistering unknown buffer is not supported. Flags = %d", hnd->flags); + } + + /* + * Close shared attribute region file descriptor. It might seem strange to "free" + * this here since this can happen in a client process, but free here is nothing + * but unmapping and closing the duplicated file descriptor. The original ashmem + * fd instance is still open until alloc_device_free() is called. Even sharing + * of gralloc buffers within the same process should have fds dup:ed. + */ + gralloc_buffer_attr_free( hnd ); + + hnd->base = 0; + hnd->lockState = 0; + hnd->writeOwner = 0; + + pthread_mutex_unlock(&s_map_lock); + } + else + { + AERR( "Trying to unregister buffer %p from process %d that was not created in current process: %d", hnd, hnd->pid, getpid()); + } + + return 0; +} + +static int gralloc_lock(gralloc_module_t const* module, buffer_handle_t handle, int usage, int l, int t, int w, int h, void** vaddr) +{ + GRALLOC_UNUSED(module); + GRALLOC_UNUSED(l); + GRALLOC_UNUSED(t); + GRALLOC_UNUSED(w); + GRALLOC_UNUSED(h); + + if (private_handle_t::validate(handle) < 0) + { + AERR("Locking invalid buffer %p, returning error", handle ); + return -EINVAL; + } + + private_handle_t* hnd = (private_handle_t*)handle; + + if (hnd->req_format == HAL_PIXEL_FORMAT_YCbCr_420_888) + { + AERR("Buffers with format YCbCr_420_888 must be locked using (*lock_ycbcr)" ); + return -EINVAL; + } + + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) + { + hnd->writeOwner = usage & GRALLOC_USAGE_SW_WRITE_MASK; + } + if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) + { + *vaddr = (void*)hnd->base; + } + return 0; +} + +static int gralloc_lock_ycbcr(gralloc_module_t const* module, buffer_handle_t handle, int usage, + int l, int t, int w, int h, + android_ycbcr *ycbcr) +{ + GRALLOC_UNUSED(module); + GRALLOC_UNUSED(l); + GRALLOC_UNUSED(t); + GRALLOC_UNUSED(w); + GRALLOC_UNUSED(h); + + if (private_handle_t::validate(handle) < 0) + { + AERR("Locking invalid buffer %p, returning error", handle ); + return -EINVAL; + } + + private_handle_t* hnd = (private_handle_t*)handle; + + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) + { + hnd->writeOwner = usage & GRALLOC_USAGE_SW_WRITE_MASK; + } + if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK) && + !(hnd->internal_format & MALI_GRALLOC_INTFMT_EXT_MASK)) + { + char* base = (char*)hnd->base; + int y_stride = hnd->byte_stride; + /* Ensure height is aligned for subsampled chroma before calculating buffer parameters */ + int adjusted_height = GRALLOC_ALIGN(hnd->height, 2); + int y_size = y_stride * adjusted_height; + + int u_offset = 0; + int v_offset = 0; + int c_stride = 0; + int step = 0; + + uint64_t base_format = hnd->internal_format & MALI_GRALLOC_INTFMT_FMT_MASK; + + switch (base_format) + { + case MALI_GRALLOC_FORMAT_INTERNAL_NV12: + c_stride = y_stride; + /* Y plane, UV plane */ + u_offset = y_size; + v_offset = y_size + 1; + step = 2; + break; + + case MALI_GRALLOC_FORMAT_INTERNAL_NV21: + c_stride = y_stride; + /* Y plane, UV plane */ + v_offset = y_size; + u_offset = y_size + 1; + step = 2; + break; + + case MALI_GRALLOC_FORMAT_INTERNAL_YV12: + { + int c_size; + + /* Stride alignment set to 16 as the SW access flags were set */ + c_stride = GRALLOC_ALIGN(hnd->byte_stride / 2, 16); + c_size = c_stride * (adjusted_height / 2); + /* Y plane, V plane, U plane */ + v_offset = y_size; + u_offset = y_size + c_size; + step = 1; + break; + } + + default: + AERR("Can't lock buffer %p: wrong format %" PRIx64, hnd, hnd->internal_format); + return -EINVAL; + } + + ycbcr->y = base; + ycbcr->cb = base + u_offset; + ycbcr->cr = base + v_offset; + ycbcr->ystride = y_stride; + ycbcr->cstride = c_stride; + ycbcr->chroma_step = step; + } + return 0; +} + +static int gralloc_unlock(gralloc_module_t const* module, buffer_handle_t handle) +{ + GRALLOC_UNUSED(module); + + if (private_handle_t::validate(handle) < 0) + { + AERR( "Unlocking invalid buffer %p, returning error", handle ); + return -EINVAL; + } + + private_handle_t* hnd = (private_handle_t*)handle; + + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION && hnd->writeOwner) + { + gralloc_backend_sync(hnd); + } + + return 0; +} + +// There is one global instance of the module + +static struct hw_module_methods_t gralloc_module_methods = +{ + gralloc_device_open +}; + +private_module_t::private_module_t() +{ +#define INIT_ZERO(obj) (memset(&(obj),0,sizeof((obj)))) + + base.common.tag = HARDWARE_MODULE_TAG; + base.common.version_major = 1; + base.common.version_minor = 0; + base.common.id = GRALLOC_HARDWARE_MODULE_ID; + base.common.name = "Graphics Memory Allocator Module"; + base.common.author = "ARM Ltd."; + base.common.methods = &gralloc_module_methods; + base.common.dso = NULL; + INIT_ZERO(base.common.reserved); + + base.registerBuffer = gralloc_register_buffer; + base.unregisterBuffer = gralloc_unregister_buffer; + base.lock = gralloc_lock; + base.lock_ycbcr = gralloc_lock_ycbcr; + base.unlock = gralloc_unlock; + base.perform = NULL; + INIT_ZERO(base.reserved_proc); + + framebuffer = NULL; + flags = 0; + numBuffers = 0; + bufferMask = 0; + pthread_mutex_init(&(lock), NULL); + currentBuffer = NULL; + INIT_ZERO(info); + INIT_ZERO(finfo); + xdpi = 0.0f; + ydpi = 0.0f; + fps = 0.0f; + swapInterval = 1; + +#undef INIT_ZERO +}; + +/* + * HAL_MODULE_INFO_SYM will be initialized using the default constructor + * implemented above + */ +struct private_module_t HAL_MODULE_INFO_SYM; + diff --git a/gralloc960/gralloc_module_allocator_specific.h b/gralloc960/gralloc_module_allocator_specific.h new file mode 100644 index 00000000..f719e73a --- /dev/null +++ b/gralloc960/gralloc_module_allocator_specific.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2013 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. + */ + +int gralloc_backend_register(struct private_handle_t* hnd); + +void gralloc_backend_unregister(struct private_handle_t* hnd); + +void gralloc_backend_sync(struct private_handle_t* hnd); diff --git a/gralloc960/gralloc_module_ion.cpp b/gralloc960/gralloc_module_ion.cpp new file mode 100644 index 00000000..d91902c8 --- /dev/null +++ b/gralloc960/gralloc_module_ion.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2013 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 <pthread.h> + +#include <cutils/log.h> +#include <cutils/atomic.h> +#include <hardware/hardware.h> +#include <hardware/gralloc.h> + +#include "gralloc_priv.h" +#include "alloc_device.h" +#include "framebuffer_device.h" + +#include <linux/ion.h> +#include <ion/ion.h> +#include <sys/mman.h> + +int gralloc_backend_register(private_handle_t* hnd) +{ + int retval = -EINVAL; + + switch (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) + { + case private_handle_t::PRIV_FLAGS_USES_ION: + unsigned char *mappedAddress; + size_t size = hnd->size; + hw_module_t * pmodule = NULL; + private_module_t *m=NULL; + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&pmodule) == 0) + { + m = reinterpret_cast<private_module_t *>(pmodule); + } + else + { + AERR("Could not get gralloc module for handle: %p", hnd); + retval = -errno; + break; + } + /* the test condition is set to m->ion_client <= 0 here, because: + * 1) module structure are initialized to 0 if no initial value is applied + * 2) a second user process should get a ion fd greater than 0. + */ + if (m->ion_client <= 0) + { + /* a second user process must obtain a client handle first via ion_open before it can obtain the shared ion buffer*/ + m->ion_client = ion_open(); + + if (m->ion_client < 0) + { + AERR( "Could not open ion device for handle: %p", hnd ); + retval = -errno; + break; + } + } + + mappedAddress = (unsigned char*)mmap( NULL, size, PROT_READ | PROT_WRITE, + MAP_SHARED, hnd->share_fd, 0 ); + + if ( MAP_FAILED == mappedAddress ) + { + AERR( "mmap( share_fd:%d ) failed with %s", hnd->share_fd, strerror( errno ) ); + retval = -errno; + break; + } + + hnd->base = (void*)(uintptr_t(mappedAddress) + hnd->offset); + retval = 0; + break; + } + + return retval; +} + +void gralloc_backend_unregister(private_handle_t* hnd) +{ + switch (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) + { + case private_handle_t::PRIV_FLAGS_USES_ION: + void* base = (void*)hnd->base; + size_t size = hnd->size; + + if ( munmap( base,size ) < 0 ) + { + AERR("Could not munmap base:%p size:%zd '%s'", base, size, strerror(errno)); + } + break; + } +} + +void gralloc_backend_sync(private_handle_t* hnd) +{ + switch (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) + { + case private_handle_t::PRIV_FLAGS_USES_ION: + hw_module_t * pmodule = NULL; + private_module_t *m=NULL; + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **)&pmodule) == 0) + { + if(!(hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION_DMA_HEAP)) + { + m = reinterpret_cast<private_module_t *>(pmodule); + ion_sync_fd(m->ion_client, hnd->share_fd); + } + } + else + { + AERR("Could not get gralloc module for handle %p\n", hnd); + } + break; + } +} diff --git a/gralloc960/gralloc_priv.h b/gralloc960/gralloc_priv.h new file mode 100644 index 00000000..a9453549 --- /dev/null +++ b/gralloc960/gralloc_priv.h @@ -0,0 +1,285 @@ +/* + * Copyright (C) 2010 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 <linux/ion.h> +#include <sys/types.h> +#include <unistd.h> +#include <sys/mman.h> +#include <hardware/gralloc.h> +#include <cutils/native_handle.h> +#include "alloc_device.h" +#include <utils/Log.h> + +#include "mali_gralloc_formats.h" +#include "gralloc_helper.h" + + +/* NOTE: + * If your framebuffer device driver is integrated with dma_buf, you will have to + * change this IOCTL definition to reflect your integration with the framebuffer + * device. + * Expected return value is a structure filled with a file descriptor + * backing your framebuffer device memory. + */ +struct fb_dmabuf_export +{ + __u32 fd; + __u32 flags; +}; +#define FBIOGET_DMABUF _IOR('F', 0x21, struct fb_dmabuf_export) + + +/* 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 NUM_FB_BUFFERS 2 + +/* Define number of shared file descriptors */ +#define GRALLOC_ARM_NUM_FDS 2 + +#define NUM_INTS_IN_PRIVATE_HANDLE ((sizeof(struct private_handle_t) - sizeof(native_handle)) / sizeof(int) - sNumFds) + +#define SZ_4K 0x00001000 +#define SZ_2M 0x00200000 + +typedef enum +{ + MALI_YUV_NO_INFO, + MALI_YUV_BT601_NARROW, + MALI_YUV_BT601_WIDE, + MALI_YUV_BT709_NARROW, + MALI_YUV_BT709_WIDE +} mali_gralloc_yuv_info; + +typedef enum +{ + MALI_DPY_TYPE_UNKNOWN = 0, + MALI_DPY_TYPE_CLCD, + MALI_DPY_TYPE_HDLCD +} mali_dpy_type; + +struct private_handle_t; + +struct private_module_t +{ + gralloc_module_t base; + + struct private_handle_t* framebuffer; + uint32_t flags; + uint32_t numBuffers; + uint32_t bufferMask; + pthread_mutex_t lock; + buffer_handle_t currentBuffer; + int ion_client; + mali_dpy_type dpy_type; + + struct fb_var_screeninfo info; + struct fb_fix_screeninfo finfo; + float xdpi; + float ydpi; + float fps; + int swapInterval; + +#ifdef __cplusplus + /* Never intended to be used from C code */ + enum + { + // flag to indicate we'll post this buffer + PRIV_USAGE_LOCKED_FOR_POST = 0x80000000 + }; +#endif + +#ifdef __cplusplus + /* default constructor */ + private_module_t(); +#endif +}; + +#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_FRAMEBUFFER = 0x00000001, + PRIV_FLAGS_USES_ION_COMPOUND_HEAP = 0x00000002, + PRIV_FLAGS_USES_ION = 0x00000004, + PRIV_FLAGS_USES_ION_DMA_HEAP = 0x00000008 + }; + + 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! + */ + int share_fd; + int share_attr_fd; + + ion_user_handle_t ion_hnd; + + // ints + int magic; + int req_format; + uint64_t internal_format; + int byte_stride; + int flags; + int usage; + int size; + int width; + int height; + int internalWidth; + int internalHeight; + int stride; + union { + void* base; + uint64_t padding; + }; + int lockState; + int writeOwner; + int pid; + + // locally mapped shared attribute area + union { + void* attr_base; + uint64_t padding3; + }; + + mali_gralloc_yuv_info yuv_info; + + // Following members is for framebuffer only + int fd; + union { + off_t offset; + uint64_t padding4; + }; + + /* + * min_pgsz denotes minimum phys_page size used by this buffer. + * if buffer memory is physical contiguous set min_pgsz to buff->size + * if not sure buff's real phys_page size, you can use SZ_4K for safe. + */ + int min_pgsz; +#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 sNumFds = GRALLOC_ARM_NUM_FDS; + static const int sMagic = 0x3141592; + + private_handle_t(int _flags, int _usage, int _size, void *_base, int lock_state, int fb_file, off_t fb_offset): + share_fd(-1), + share_attr_fd(-1), + ion_hnd(-1), + magic(sMagic), + flags(_flags), + usage(_usage), + size(_size), + width(0), + height(0), + stride(0), + base(_base), + lockState(lock_state), + writeOwner(0), + pid(getpid()), + attr_base(MAP_FAILED), + yuv_info(MALI_YUV_NO_INFO), + fd(fb_file), + offset(fb_offset) + { + version = sizeof(native_handle); + numFds = sNumFds; + numInts = NUM_INTS_IN_PRIVATE_HANDLE; + } + + ~private_handle_t() + { + magic = 0; + } + + bool usesPhysicallyContiguousMemory() + { + return (flags & PRIV_FLAGS_FRAMEBUFFER) ? true : false; + } + + static int validate(const native_handle* h) + { + const private_handle_t* hnd = (const private_handle_t*)h; + if (!h || + h->version != sizeof(native_handle) || + h->numInts != NUM_INTS_IN_PRIVATE_HANDLE || + h->numFds != sNumFds || + hnd->magic != sMagic) + { + return -EINVAL; + } + return 0; + } + + static private_handle_t* dynamicCast(const native_handle* in) + { + if (validate(in) == 0) + { + return (private_handle_t*) in; + } + return NULL; + } +#endif +}; +#ifndef __cplusplus +/* Restore previous diagnostic for pedantic */ +#pragma GCC diagnostic pop +#endif + +#endif /* GRALLOC_PRIV_H_ */ diff --git a/gralloc960/gralloc_vsync.h b/gralloc960/gralloc_vsync.h new file mode 100644 index 00000000..6027edaa --- /dev/null +++ b/gralloc960/gralloc_vsync.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2014 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_VSYNC_H_ +#define _GRALLOC_VSYNC_H_ + +struct framebuffer_device_t; + +/* Enables vsync interrupt. */ +int gralloc_vsync_enable(struct framebuffer_device_t* dev); +/* Disables vsync interrupt. */ +int gralloc_vsync_disable(struct framebuffer_device_t* dev); +/* Waits for the vsync interrupt. */ +int gralloc_wait_for_vsync(struct framebuffer_device_t* dev); + +#endif /* _GRALLOC_VSYNC_H_ */ diff --git a/gralloc960/gralloc_vsync_default.cpp b/gralloc960/gralloc_vsync_default.cpp new file mode 100644 index 00000000..40f66999 --- /dev/null +++ b/gralloc960/gralloc_vsync_default.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2014 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_priv.h" +#include "gralloc_vsync.h" +#include "gralloc_vsync_report.h" +#include <sys/ioctl.h> +#include <errno.h> + +#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) + +int gralloc_vsync_enable(framebuffer_device_t *dev) +{ + GRALLOC_UNUSED(dev); + return 0; +} + +int gralloc_vsync_disable(framebuffer_device_t *dev) +{ + GRALLOC_UNUSED(dev); + return 0; +} + +int gralloc_wait_for_vsync(framebuffer_device_t *dev) +{ + private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module); + if (MALI_DPY_TYPE_CLCD == m->dpy_type || MALI_DPY_TYPE_HDLCD == m->dpy_type) + { + /* Silently ignore wait for vsync as neither PL111 nor HDLCD implement this IOCTL. */ + return 0; + } + + if ( m->swapInterval ) + { + int crtc = 0; + gralloc_mali_vsync_report(MALI_VSYNC_EVENT_BEGIN_WAIT); + if(ioctl(m->framebuffer->fd, FBIO_WAITFORVSYNC, &crtc) < 0) + { + gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT); + return -errno; + } + gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT); + } + return 0; +} diff --git a/gralloc960/gralloc_vsync_report.h b/gralloc960/gralloc_vsync_report.h new file mode 100644 index 00000000..ea45cc44 --- /dev/null +++ b/gralloc960/gralloc_vsync_report.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011 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 GRALLOC_VSYNC_REPORT_H_ +#define GRALLOC_VSYNC_REPORT_H_ + +#include "gralloc_helper.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + +typedef enum mali_vsync_event +{ + MALI_VSYNC_EVENT_BEGIN_WAIT = 0, + MALI_VSYNC_EVENT_END_WAIT +} mali_vsync_event; + +extern void _mali_base_arch_vsync_event_report(mali_vsync_event); + +inline void gralloc_mali_vsync_report(mali_vsync_event event) +{ + #ifdef MALI_VSYNC_EVENT_REPORT_ENABLE + _mali_base_arch_vsync_event_report(event); + #else + GRALLOC_UNUSED(event); + #endif +} + +#ifdef __cplusplus +} +#endif +#endif /* GRALLOC_VSYNC_REPORT_H_ */ diff --git a/gralloc960/gralloc_vsync_s3cfb.cpp b/gralloc960/gralloc_vsync_s3cfb.cpp new file mode 100644 index 00000000..5740ea93 --- /dev/null +++ b/gralloc960/gralloc_vsync_s3cfb.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2014 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_priv.h" +#include "gralloc_vsync.h" +#include "gralloc_vsync_report.h" +#include <sys/ioctl.h> +#include <errno.h> + +#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) +#define S3CFB_SET_VSYNC_INT _IOW('F', 206, unsigned int) + +int gralloc_vsync_enable(framebuffer_device_t *dev) +{ + private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module); + int interrupt = 1; + if(ioctl(m->framebuffer->fd, S3CFB_SET_VSYNC_INT, &interrupt) < 0) return -errno; + return 0; +} + +int gralloc_vsync_disable(framebuffer_device_t *dev) +{ + private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module); + int interrupt = 0; + if(ioctl(m->framebuffer->fd, S3CFB_SET_VSYNC_INT, &interrupt) < 0) return -errno; + return 0; +} + +int gralloc_wait_for_vsync(framebuffer_device_t *dev) +{ + private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module); + if ( m->swapInterval ) + { + int crtc = 0; + gralloc_mali_vsync_report(MALI_VSYNC_EVENT_BEGIN_WAIT); + if(ioctl(m->framebuffer->fd, FBIO_WAITFORVSYNC, &crtc) < 0) + { + gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT); + return -errno; + } + gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT); + } + return 0; +} diff --git a/gralloc960/mali_gralloc_formats.cpp b/gralloc960/mali_gralloc_formats.cpp new file mode 100644 index 00000000..090e3386 --- /dev/null +++ b/gralloc960/mali_gralloc_formats.cpp @@ -0,0 +1,666 @@ +/* + * 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. + */ + +#include <string.h> +#include <dlfcn.h> +#include <hardware/gralloc.h> +#include <inttypes.h> +#include <cutils/log.h> + +#include "mali_gralloc_formats.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 + +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(int req_format, uint64_t *producer_runtime_mask) +{ + /* 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; + + /* + * We disable AFBC for NV12 since neither VPU or DPU DDKs support + * them currently. + */ + *producer_runtime_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK; + } + else if(req_format == HAL_PIXEL_FORMAT_YCbCr_422_888) + { + /* To be determined */ + + /* Disable AFBC until we know though */ + *producer_runtime_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK; + } + else if(req_format == HAL_PIXEL_FORMAT_YCbCr_444_888) + { + /* To be determined */ + + /* Disable AFBC until we know though */ + *producer_runtime_mask &= ~MALI_GRALLOC_FORMAT_CAPABILITY_AFBCENABLE_MASK; + } + 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: + rval = true; + break; + } + return rval; +} + +static bool is_afbc_allowed(int buffer_size) +{ + bool afbc_allowed = false; + + (void) buffer_size; + +#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 + + 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(req_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(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(int req_format) +{ + uint64_t internal_format, me_mask, base_format, mapped_base_format; + uint64_t ignore_mask; + + internal_format = GRALLOC_PRIVATE_FORMAT_UNWRAP(req_format); + + 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, &ignore_mask); + + /* 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((vpu_runtime_caps.caps_mask & MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_YUV_NOREAD) && + is_android_yuv_format(req_format)) + { + *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(int req_format, int 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); + int 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) + { + internal_format = decode_internal_format(req_format); + goto out; + } + + /* Re-map special Android formats */ + req_format_mapped = map_flex_formats(req_format, &producer_runtime_mask); + + /* 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%08X Re-Mapped fmt: 0x%08X",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%08X req_fmt_mapped=0x%08X internal_format=0x%" PRIx64 " usage=0x%08X",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)); + } +} +} diff --git a/gralloc960/mali_gralloc_formats.h b/gralloc960/mali_gralloc_formats.h new file mode 100644 index 00000000..5b893b43 --- /dev/null +++ b/gralloc960/mali_gralloc_formats.h @@ -0,0 +1,302 @@ +/* + * 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_FORMATS_H_ +#define MALI_GRALLOC_FORMATS_H_ + +#include <system/graphics.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_ME_EXT_MASK 0x0000ffff00000000ULL +#define MALI_GRALLOC_INTFMT_REG_EXT_MASK 0xffff000000000000ULL + +/* 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 0x100 + +typedef enum +{ + /* Internal definitions for HAL formats. */ + 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_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_YUV420_888 = HAL_PIXEL_FORMAT_YCbCr_420_888, + + /* 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_BLOB = HAL_PIXEL_FORMAT_BLOB, + + /* 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 + * + * NOTE: P010, P210, and Y410 are only supported uncompressed. + */ + 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, + + /* Add more internal formats here. Make sure decode_internal_format() is updated. */ + + /* 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; + + +/* Format Modifier Bits Locations */ +#define MALI_GRALLOC_INTFMT_ME_EXTENSION_BIT_START 32 +#define MALI_GRALLOC_INTFMT_EXTENSION_BIT_START (MALI_GRALLOC_INTFMT_ME_EXTENSION_BIT_START+16) + +/* Mutually Exclusive Modifier Bits */ + +/* This format will use AFBC */ +#define MALI_GRALLOC_INTFMT_AFBC_BASIC (1ULL << (MALI_GRALLOC_INTFMT_ME_EXTENSION_BIT_START+0)) + +/* This format uses AFBC split block mode */ +#define MALI_GRALLOC_INTFMT_AFBC_SPLITBLK (1ULL << (MALI_GRALLOC_INTFMT_ME_EXTENSION_BIT_START+1)) + +#define MALI_GRALLOC_INTFMT_UNUSED (1ULL << (MALI_GRALLOC_INTFMT_ME_EXTENSION_BIT_START+2)) + +/* This format uses AFBC wide block mode */ +#define MALI_GRALLOC_INTFMT_AFBC_WIDEBLK (1ULL << (MALI_GRALLOC_INTFMT_ME_EXTENSION_BIT_START+3)) + + +/* Regular Modifier Bits */ +#define MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS (1ULL << (MALI_GRALLOC_INTFMT_EXTENSION_BIT_START+0)) + + +/* This mask should be used to check or clear support for AFBC for an internal format + * These bits are mutually exclusive so this mask should not be used to enable support + */ +#define MALI_GRALLOC_INTFMT_AFBCENABLE_MASK ((uint64_t) (MALI_GRALLOC_INTFMT_AFBC_BASIC | \ + MALI_GRALLOC_INTFMT_AFBC_SPLITBLK | \ + MALI_GRALLOC_INTFMT_AFBC_WIDEBLK)) + +/* Prototypes */ +uint64_t mali_gralloc_select_format(int req_format,int usage, int buffer_size); + +/* 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 23-16: mutually exclusive modifier bits + * Bits 31-24: regular 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; + } + return (modifiers | format); +} + +static inline uint64_t mali_gralloc_format_unwrap(int x) +{ + uint64_t internal_format = (uint64_t) ( ((((uint64_t)(x)) & 0xff000000) << 24) | // Regular modifier bits + ((((uint64_t)(x)) & 0x00ff0000) << 16) | // Mutually exclusive modifier bits + (((uint64_t)(x)) & 0x0000ffff) ); // 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); +} + +#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 >> 16)) ) +#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_SPLITBLK(x) ( mali_gralloc_format_wrapper(x, (MALI_GRALLOC_INTFMT_AFBC_SPLITBLK >> 16)) ) +#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_WIDEBLK(x) ( mali_gralloc_format_wrapper(x, (MALI_GRALLOC_INTFMT_AFBC_WIDEBLK >> 16)) ) +#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_TILED_HEADERS_BASIC(x) ( mali_gralloc_format_wrapper(x, (MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS >> 24) | \ + (MALI_GRALLOC_INTFMT_AFBC_BASIC >> 16))) +#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_TILED_HEADERS_WIDE(x) ( mali_gralloc_format_wrapper(x, (MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS >> 24) | \ + (MALI_GRALLOC_INTFMT_AFBC_WIDEBLK >> 16))) +#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)) +#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_WIDEBLK_YUV_DISABLE ((uint64_t) (1 << 4)) +#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_YUV_NOREAD ((uint64_t) (1 << 5)) +#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_YUV_NOWRITE ((uint64_t) (1 << 6)) +#define MALI_GRALLOC_FORMAT_CAPABILITY_AFBC_TILED_HEADERS ((uint64_t) (1 << 7)) + +#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" + +/* Producer and Consumer definitions */ +typedef enum +{ + MALI_GRALLOC_PRODUCER_VIDEO_DECODER, + MALI_GRALLOC_PRODUCER_GPU, + MALI_GRALLOC_PRODUCER_CAMERA, +} mali_gralloc_producer_type; + +typedef enum +{ + + /* For surface composition in SurfaceFlinger a producer + * will not know what consumer will process a buffer. + * + * MALI_GRALLOC_CONSUMER_GPU_OR_DISPLAY means the GPU + * MUST support the given format but it should be allocated + * with preference to the DPU. + */ + MALI_GRALLOC_CONSUMER_GPU_OR_DISPLAY, + MALI_GRALLOC_CONSUMER_VIDEO_ENCODER, + + + /* This is used when no known "premium" dpu is configured. + * For example, HDLCD/CLCD would be such a dpu. + */ + MALI_GRALLOC_CONSUMER_GPU_EXCL, +} mali_gralloc_consumer_type; + + +/* + * Below usage types overlap, this is intentional. + * The reason is that for Gralloc 0.3 there are very + * few usage flags we have at our disposal. + * + * The overlapping is handled by processing the definitions + * in a specific order. + * + * MALI_GRALLOC_USAGE_PRIVATE_FORMAT and MALI_GRALLOC_USAGE_NO_AFBC + * don't overlap and are processed first. + * + * MALI_GRALLOC_USAGE_YUV_CONF are only for YUV formats and clients + * using MALI_GRALLOC_USAGE_NO_AFBC must never allocate YUV formats. + * The latter is strictly enforced and allocations will fail. + * + * MALI_GRALLOC_USAGE_AFBC_PADDING is only valid if MALI_GRALLOC_USAGE_NO_AFBC + * is not present. + */ +typedef enum +{ + /* The client has specified a private format in the format parameter */ + MALI_GRALLOC_USAGE_PRIVATE_FORMAT = (int) GRALLOC_USAGE_PRIVATE_3, + + /* Buffer won't be allocated as AFBC */ + MALI_GRALLOC_USAGE_NO_AFBC = (int) (GRALLOC_USAGE_PRIVATE_1 | GRALLOC_USAGE_PRIVATE_2), + + /* Valid only for YUV allocations */ + MALI_GRALLOC_USAGE_YUV_CONF_0 = 0, + MALI_GRALLOC_USAGE_YUV_CONF_1 = (int) GRALLOC_USAGE_PRIVATE_1, + MALI_GRALLOC_USAGE_YUV_CONF_2 = (int) GRALLOC_USAGE_PRIVATE_0, + MALI_GRALLOC_USAGE_YUV_CONF_3 = (int) (GRALLOC_USAGE_PRIVATE_0 | GRALLOC_USAGE_PRIVATE_1), + MALI_GRALLOC_USAGE_YUV_CONF_MASK = MALI_GRALLOC_USAGE_YUV_CONF_3, + + /* A very specific alignment is requested on some buffers */ + MALI_GRALLOC_USAGE_AFBC_PADDING = GRALLOC_USAGE_PRIVATE_2, + +} mali_gralloc_usage_type; + +/* Prototypes */ +uint64_t mali_gralloc_select_format(int req_format,int usage, int buffer_size); + +#ifdef __cplusplus +extern "C" +{ +#endif + +void mali_gralloc_get_gpu_caps(struct mali_gralloc_format_caps *gpu_caps); + +#ifdef __cplusplus +} +#endif + +#endif /* MALI_GRALLOC_FORMATS_H_ */ |