diff options
author | Jon Medhurst <tixy@linaro.org> | 2015-11-13 13:38:50 +0000 |
---|---|---|
committer | Jon Medhurst <tixy@linaro.org> | 2015-11-13 13:38:50 +0000 |
commit | 412524620a714cb35f87e4e16d3efcb1472d73bb (patch) | |
tree | cf4a2bb2ad50cbab8968aad250d59de41d1498fd | |
download | gralloc-master.tar.gz |
Files extracted from
http://malideveloper.arm.com/downloads/drivers/TX041/r8p0-02rel0/TX041-SW-99005-r8p0-02rel0.tgz
Change-Id: I53921cc7e0cd6a52a245f0e76a1e631ffdb0eadf
Signed-off-by: Jon Medhurst <tixy@linaro.org>
-rwxr-xr-x | Android.mk | 119 | ||||
-rwxr-xr-x | alloc_device.cpp | 1026 | ||||
-rwxr-xr-x | alloc_device.h | 37 | ||||
-rwxr-xr-x | alloc_device_allocator_specific.h | 25 | ||||
-rwxr-xr-x | alloc_ion.cpp | 197 | ||||
-rwxr-xr-x | alloc_ump.cpp | 235 | ||||
-rwxr-xr-x | format_chooser.cpp | 304 | ||||
-rwxr-xr-x | format_chooser.h | 195 | ||||
-rwxr-xr-x | format_chooser_blockinit.cpp | 285 | ||||
-rwxr-xr-x | formatdef_files/display_afbc.defs | 35 | ||||
-rwxr-xr-x | formatdef_files/gpu_afbc.defs | 56 | ||||
-rwxr-xr-x | formatdef_files/gpu_afbc_wideblk.defs | 71 | ||||
-rwxr-xr-x | formatdef_files/gpu_default.defs | 66 | ||||
-rwxr-xr-x | framebuffer_device.cpp | 501 | ||||
-rwxr-xr-x | framebuffer_device.h | 25 | ||||
-rwxr-xr-x | gralloc_buffer_priv.cpp | 129 | ||||
-rwxr-xr-x | gralloc_buffer_priv.h | 214 | ||||
-rwxr-xr-x | gralloc_helper.h | 29 | ||||
-rwxr-xr-x | gralloc_module.cpp | 245 | ||||
-rwxr-xr-x | gralloc_module_allocator_specific.h | 21 | ||||
-rwxr-xr-x | gralloc_module_ion.cpp | 137 | ||||
-rwxr-xr-x | gralloc_module_ump.cpp | 116 | ||||
-rwxr-xr-x | gralloc_priv.h | 397 | ||||
-rwxr-xr-x | gralloc_vsync.h | 31 | ||||
-rwxr-xr-x | gralloc_vsync_default.cpp | 58 | ||||
-rwxr-xr-x | gralloc_vsync_report.h | 44 | ||||
-rwxr-xr-x | gralloc_vsync_s3cfb.cpp | 59 |
27 files changed, 4657 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk new file mode 100755 index 0000000..d3bc196 --- /dev/null +++ b/Android.mk @@ -0,0 +1,119 @@ +# +# 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. + +LOCAL_PATH := $(call my-dir) + +MALI_ARCHITECTURE_UTGARD?=0 +MALI_ION?=1 +GRALLOC_VSYNC_BACKEND?=default +DISABLE_FRAMEBUFFER_HAL?=0 +MALI_SUPPORT_AFBC_WIDEBLK?=0 + +# 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 ($(MALI_ARCHITECTURE_UTGARD),1) + # Utgard build settings + MALI_LOCAL_PATH?=hardware/arm/mali + GRALLOC_DEPTH?=GRALLOC_32_BITS + GRALLOC_FB_SWAP_RED_BLUE?=1 + MALI_DDK_INCLUDES=$(MALI_LOCAL_PATH)/include $(MALI_LOCAL_PATH)/src/ump/include + LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw + ifeq ($(MALI_ION),1) + ALLOCATION_LIB := libion + ALLOCATOR_SPECIFIC_FILES := alloc_ion.cpp gralloc_module_ion.cpp + else + ALLOCATION_LIB := libUMP + ALLOCATOR_SPECIFIC_FILES := alloc_ump.cpp gralloc_module_ump.cpp + endif +else + # Midgard build settings + MALI_LOCAL_PATH?=vendor/arm/mali6xx + GRALLOC_DEPTH?=GRALLOC_16_BITS + GRALLOC_FB_SWAP_RED_BLUE?=0 + MALI_DDK_INCLUDES=$(MALI_LOCAL_PATH)/include $(MALI_LOCAL_PATH)/kernel/include + LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_SHARED_LIBRARIES)/hw + ifeq ($(MALI_ION),1) + ALLOCATION_LIB := libion + ALLOCATOR_SPECIFIC_FILES := alloc_ion.cpp gralloc_module_ion.cpp + else + ALLOCATION_LIB := libGLES_mali + ALLOCATOR_SPECIFIC_FILES := alloc_ump.cpp gralloc_module_ump.cpp + endif +endif + +ifeq ($(MALI_AFBC_GRALLOC), 1) +AFBC_FILES = gralloc_buffer_priv.cpp +else +MALI_AFBC_GRALLOC := 0 +AFBC_FILES = +endif + +#If cropping should be enabled for AFBC YUV420 buffers +AFBC_YUV420_EXTRA_MB_ROW_NEEDED = 0 + +ifdef MALI_DISPLAY_VERSION +#if Mali display is available, should disable framebuffer HAL +DISABLE_FRAMEBUFFER_HAL := 1 +endif + +LOCAL_PRELINK_MODULE := false + + +LOCAL_SHARED_LIBRARIES := libhardware liblog libcutils libGLESv1_CM $(ALLOCATION_LIB) +LOCAL_C_INCLUDES := $(MALI_LOCAL_PATH) $(MALI_DDK_INCLUDES) +LOCAL_CFLAGS := -DLOG_TAG=\"gralloc\" -DSTANDARD_LINUX_SCREEN -DMALI_ION=$(MALI_ION) -DMALI_AFBC_GRALLOC=$(MALI_AFBC_GRALLOC) -D$(GRALLOC_DEPTH) -DMALI_ARCHITECTURE_UTGARD=$(MALI_ARCHITECTURE_UTGARD) -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION) -DDISABLE_FRAMEBUFFER_HAL=$(DISABLE_FRAMEBUFFER_HAL) -DMALI_SUPPORT_AFBC_WIDEBLK=$(MALI_SUPPORT_AFBC_WIDEBLK) -DAFBC_YUV420_EXTRA_MB_ROW_NEEDED=$(AFBC_YUV420_EXTRA_MB_ROW_NEEDED) + +ifdef MALI_DISPLAY_VERSION +LOCAL_CFLAGS += -DMALI_DISPLAY_VERSION=$(MALI_DISPLAY_VERSION) +endif + +ifeq ($(wildcard system/core/libion/include/ion/ion.h),) +LOCAL_C_INCLUDES += system/core/include +LOCAL_CFLAGS += -DGRALLOC_OLD_ION_API +else +LOCAL_C_INCLUDES += system/core/libion/include +endif + +ifeq ($(GRALLOC_FB_SWAP_RED_BLUE),1) +LOCAL_CFLAGS += -DGRALLOC_FB_SWAP_RED_BLUE +endif + +LOCAL_MODULE_PATH_32 := $(TARGET_OUT_VENDOR)/lib/hw +LOCAL_MODULE_PATH_64 := $(TARGET_OUT_VENDOR)/lib64/hw +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 \ + $(ALLOCATOR_SPECIFIC_FILES) \ + framebuffer_device.cpp \ + format_chooser.cpp \ + format_chooser_blockinit.cpp \ + $(AFBC_FILES) \ + gralloc_vsync_${GRALLOC_VSYNC_BACKEND}.cpp + +include $(BUILD_SHARED_LIBRARY) diff --git a/alloc_device.cpp b/alloc_device.cpp new file mode 100755 index 0000000..27ecb83 --- /dev/null +++ b/alloc_device.cpp @@ -0,0 +1,1026 @@ +/* + * 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" +#if MALI_AFBC_GRALLOC == 1 +#include "gralloc_buffer_priv.h" +#endif + +#define AFBC_PIXELS_PER_BLOCK 16 +#define AFBC_BODY_BUFFER_BYTE_ALIGNMENT 1024 +#define AFBC_HEADER_BUFFER_BYTES_PER_BLOCKENTRY 16 +#define AFBC_WIDEBLK_WIDTH_ALIGN 32 + +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); + } + + 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), 0); + + /* + * 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); + } + + *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 +}; + +/* + * 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_PIXELS_PER_BLOCK ); + int nblocks; + + if (type == AFBC_PADDED) + { + w_aligned = GRALLOC_ALIGN( width, 64 ); + } + else if (type == AFBC_WIDEBLK) + { + w_aligned = GRALLOC_ALIGN( width, AFBC_WIDEBLK_WIDTH_ALIGN ); + } + else + { + w_aligned = GRALLOC_ALIGN( width, AFBC_PIXELS_PER_BLOCK ); + } + + 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, AFBC_BODY_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) Will store internal height if it is required to have a greater height than + * known to public. If not it will be left untouched. + */ +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; + + if (type == UNCOMPRESSED) + { + AERR(" Buffer must be allocated with AFBC mode for internal pixel format YUV420_10BIT_AFBC!"); + return false; + } + + if (type == AFBC_PADDED) + { + AERR("GRALLOC_USAGE_PRIVATE_2 (64byte header row alignment for AFBC) is not supported for YUV"); + return false; + } + + if (type == AFBC_WIDEBLK) + { + width = GRALLOC_ALIGN(width, AFBC_WIDEBLK_WIDTH_ALIGN); + } + else + { + width = GRALLOC_ALIGN(width, AFBC_PIXELS_PER_BLOCK); + } + height = GRALLOC_ALIGN(height, AFBC_PIXELS_PER_BLOCK); + +#if AFBC_YUV420_EXTRA_MB_ROW_NEEDED + /* 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 + + 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, AFBC_BODY_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) Will store internal height if it is required to have a greater height than + * known to public. If not it will be left untouched. + */ +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 luma_stride; + + /* Android assumes the width and height are even withou checking, so we check here */ + if (width % 2 != 0 || height % 2 != 0) + { + return false; + } + + if (type != UNCOMPRESSED) + { + return get_afbc_yuv420_8bit_stride_and_size(width, height, pixel_stride, byte_stride, size, type, internalHeight); + } + + /* Android assumes the buffer should be aligned to 16. */ + luma_stride = GRALLOC_ALIGN(width, 16); + + if (size != NULL) + { + int chroma_stride = GRALLOC_ALIGN(luma_stride / 2, 16); + /* 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 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; + + if (type == UNCOMPRESSED) + { + AERR(" Buffer must be allocated with AFBC mode for internal pixel format YUV420_10BIT_AFBC!"); + return false; + } + + if (type == AFBC_PADDED) + { + AERR("GRALLOC_USAGE_PRIVATE_2 (64byte header row alignment for AFBC) is not supported for YUV"); + return false; + } + + if (type == AFBC_WIDEBLK) + { + width = GRALLOC_ALIGN(width, AFBC_WIDEBLK_WIDTH_ALIGN); + } + else + { + width = GRALLOC_ALIGN(width, AFBC_PIXELS_PER_BLOCK); + } + height = GRALLOC_ALIGN(height, AFBC_PIXELS_PER_BLOCK); + + 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, AFBC_BODY_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; + } + + /* odd height is allowed for P210 (2x1 sub-sampling) */ + if ((width & 1) || (vss == 2 && (height & 1))) + { + return false; + } + + luma_pixel_stride = GRALLOC_ALIGN(width, 16); + luma_byte_stride = GRALLOC_ALIGN(width * 2, 16); + + if (size != NULL) + { + int chroma_size = GRALLOC_ALIGN(width * 2, 16) * (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 (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; + + if (width & 1) + { + return false; + } + + y210_pixel_stride = GRALLOC_ALIGN(width, 16); + y210_byte_stride = GRALLOC_ALIGN(width * 4, 16); + + if (size != NULL) + { + /* 4x16bits per pixel */ + *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) + */ +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; + + if (width & 3) + { + return false; + } + + y0l2_pixel_stride = GRALLOC_ALIGN(width * 4, 16); /* 4 pixels packed per line */ + y0l2_byte_stride = GRALLOC_ALIGN(width * 4, 16); /* Packed in 64-bit chunks, 2 x downsampled horizontally */ + + if (size != NULL) + { + /* 2 x downsampled vertically */ + *size = y0l2_byte_stride * (height/2); + } + + 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, 16); + y410_byte_stride = GRALLOC_ALIGN(width * 4, 16); + + 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. + * + * @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 yuv420_afbc_byte_stride, yuv420_afbc_pixel_stride; + + if (width & 3) + { + return false; + } + + if (type == UNCOMPRESSED) + { + AERR(" Buffer must be allocated with AFBC mode for internal pixel format YUV420_10BIT_AFBC!"); + return false; + } + + if (type == AFBC_PADDED) + { + AERR("GRALLOC_USAGE_PRIVATE_2 (64byte header row alignment for AFBC) is not supported for YUV"); + return false; + } + + if (type == AFBC_WIDEBLK) + { + width = GRALLOC_ALIGN(width, AFBC_WIDEBLK_WIDTH_ALIGN); + } + else + { + width = GRALLOC_ALIGN(width, AFBC_PIXELS_PER_BLOCK); + } + height = GRALLOC_ALIGN(height/2, AFBC_PIXELS_PER_BLOCK); /* vertically downsampled */ + + 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 * height / AFBC_PIXELS_PER_BLOCK; + *size = yuv420_afbc_byte_stride * height + + GRALLOC_ALIGN(nblocks * AFBC_HEADER_BUFFER_BYTES_PER_BLOCKENTRY, AFBC_BODY_BUFFER_BYTE_ALIGNMENT); + } + + if (byte_stride != NULL) + { + *byte_stride = yuv420_afbc_byte_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; + + if (width & 3) + { + return false; + } + + if (type == UNCOMPRESSED) + { + AERR(" Buffer must be allocated with AFBC mode for internal pixel format YUV420_10BIT_AFBC!"); + return false; + } + + if (type == AFBC_PADDED) + { + AERR("GRALLOC_USAGE_PRIVATE_2 (64byte header row alignment for AFBC) is not supported for YUV"); + return false; + } + + if (type == AFBC_WIDEBLK) + { + width = GRALLOC_ALIGN(width, AFBC_WIDEBLK_WIDTH_ALIGN); + } + else + { + width = GRALLOC_ALIGN(width, AFBC_PIXELS_PER_BLOCK); + } + height = GRALLOC_ALIGN(height, AFBC_PIXELS_PER_BLOCK); /* total number of rows must be even number */ + + 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, AFBC_BODY_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; +} + +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; + bool alloc_for_extended_yuv = false, alloc_for_arm_afbc_yuv = false; + int internalWidth,internalHeight; + +#if defined(GRALLOC_FB_SWAP_RED_BLUE) + /* 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 = gralloc_select_format(format, usage); + + if (internal_format & (GRALLOC_ARM_INTFMT_AFBC | GRALLOC_ARM_INTFMT_AFBC_SPLITBLK | GRALLOC_ARM_INTFMT_AFBC_WIDEBLK)) + { + if (usage & GRALLOC_USAGE_PRIVATE_2) + { + type = AFBC_PADDED; + } + else if (internal_format & GRALLOC_ARM_INTFMT_AFBC_WIDEBLK) + { + type = AFBC_WIDEBLK; + } + else + { + type = AFBC; + } + } + + alloc_for_extended_yuv = (internal_format & GRALLOC_ARM_INTFMT_EXTENDED_YUV) == GRALLOC_ARM_INTFMT_EXTENDED_YUV; + alloc_for_arm_afbc_yuv = (internal_format & GRALLOC_ARM_INTFMT_ARM_AFBC_YUV) == GRALLOC_ARM_INTFMT_ARM_AFBC_YUV; + + if (!alloc_for_extended_yuv && !alloc_for_arm_afbc_yuv) + { + switch (internal_format & GRALLOC_ARM_INTFMT_FMT_MASK) + { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: +#if (PLATFORM_SDK_VERSION >= 19) && (PLATFORM_SDK_VERSION <= 22) + case HAL_PIXEL_FORMAT_sRGB_A_8888: + case HAL_PIXEL_FORMAT_sRGB_X_8888: +#endif + 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: +#if PLATFORM_SDK_VERSION < 19 + case HAL_PIXEL_FORMAT_RGBA_5551: + case HAL_PIXEL_FORMAT_RGBA_4444: +#endif + get_rgb_stride_and_size(w, h, 2, &pixel_stride, &byte_stride, &size, type ); + break; + + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_YV12: + if (!get_yv12_stride_and_size(w, h, &pixel_stride, &byte_stride, &size, type, &internalHeight)) + { + return -EINVAL; + } + break; + + /* + * Additional custom formats can be added here + * and must fill the variables pixel_stride, byte_stride and size. + */ + default: + return -EINVAL; + } + } + else + { + switch (internal_format & GRALLOC_ARM_INTFMT_FMT_MASK) + { + case GRALLOC_ARM_HAL_FORMAT_INDEXED_Y0L2: + /* YUYAAYUVAA 4:2:0 */ + if (false == get_yuv_y0l2_stride_and_size(w, h, &pixel_stride, &byte_stride, &size)) + { + return -EINVAL; + } + break; + + case GRALLOC_ARM_HAL_FORMAT_INDEXED_P010: + /* Y-UV 4:2:0 */ + if (false == get_yuv_pX10_stride_and_size(w, h, 2, &pixel_stride, &byte_stride, &size)) + { + return -EINVAL; + } + break; + + case GRALLOC_ARM_HAL_FORMAT_INDEXED_P210: + /* Y-UV 4:2:2 */ + if (false == get_yuv_pX10_stride_and_size(w, h, 1, &pixel_stride, &byte_stride, &size)) + { + return -EINVAL; + } + break; + + case GRALLOC_ARM_HAL_FORMAT_INDEXED_Y210: + /* YUYV 4:2:0 */ + if (false == get_yuv_y210_stride_and_size(w, h, &pixel_stride, &byte_stride, &size)) + { + return -EINVAL; + } + break; + + case GRALLOC_ARM_HAL_FORMAT_INDEXED_Y410: + /* AVYU 2-10-10-10 */ + if (false == get_yuv_y410_stride_and_size(w, h, &pixel_stride, &byte_stride, &size)) + { + return -EINVAL; + } + break; + /* 8BIT AFBC YUV 4:2:0 testing usage */ + case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV420_8BIT_AFBC: + if (!get_afbc_yuv420_8bit_stride_and_size(w, h, &pixel_stride, &byte_stride, &size, type, &internalHeight)) + { + return -EINVAL; + } + break; + + /* 8BIT AFBC YUV4:2:2 testing usage */ + case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV422_8BIT_AFBC: + if (!get_afbc_yuv422_8bit_stride_and_size(w, h, &pixel_stride, &byte_stride, &size, type)) + { + return -EINVAL; + } + break; + + case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV420_10BIT_AFBC: + /* YUV 4:2:0 compressed */ + if (false == get_yuv420_10bit_afbc_stride_and_size(w, h, &pixel_stride, &byte_stride, &size, type)) + { + return -EINVAL; + } + break; + case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV422_10BIT_AFBC: + /* YUV 4:2:2 compressed */ + if (false == get_yuv422_10bit_afbc_stride_and_size(w, h, &pixel_stride, &byte_stride, &size, type)) + { + return -EINVAL; + } + break; + default: + AERR("Invalid internal format %llx", internal_format & GRALLOC_ARM_INTFMT_FMT_MASK); + 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); + } + + if (err < 0) + { + return err; + } + + private_handle_t *hnd = (private_handle_t *)*pHandle; + +#if MALI_AFBC_GRALLOC == 1 + 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; + } + } +#endif + + hnd->req_format = format; + hnd->byte_stride = byte_stride; + hnd->internal_format = internal_format; + + int private_usage = usage & (GRALLOC_USAGE_PRIVATE_0 | + GRALLOC_USAGE_PRIVATE_1); + switch (private_usage) + { + case 0: + hnd->yuv_info = MALI_YUV_BT601_NARROW; + break; + case GRALLOC_USAGE_PRIVATE_1: + hnd->yuv_info = MALI_YUV_BT601_WIDE; + break; + case GRALLOC_USAGE_PRIVATE_0: + hnd->yuv_info = MALI_YUV_BT709_NARROW; + break; + case (GRALLOC_USAGE_PRIVATE_0 | GRALLOC_USAGE_PRIVATE_1): + hnd->yuv_info = MALI_YUV_BT709_WIDE; + break; + } + + 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); + } + +#if MALI_AFBC_GRALLOC == 1 + gralloc_buffer_attr_free( (private_handle_t *) hnd ); +#endif + 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; + + 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/alloc_device.h b/alloc_device.h new file mode 100755 index 0000000..bcbc1dc --- /dev/null +++ b/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/alloc_device_allocator_specific.h b/alloc_device_allocator_specific.h new file mode 100755 index 0000000..d6bb850 --- /dev/null +++ b/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); + +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/alloc_ion.cpp b/alloc_ion.cpp new file mode 100755 index 0000000..b88f2ac --- /dev/null +++ b/alloc_ion.cpp @@ -0,0 +1,197 @@ +/* + * 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 <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 <linux/ion.h> +#include <ion/ion.h> + +int alloc_backend_alloc(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle) +{ + 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; + int ion_flags = 0; + static int support_protected = 1; /* initially, assume we support protected memory */ + int lock_state = 0; + + /* Select heap type based on usage hints */ + 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 -1; +#endif + } + else + { + heap_mask = ION_HEAP_SYSTEM_MASK; + } + + if ( (usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN ) + { + ion_flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC; + } + + ret = ion_alloc(m->ion_client, size, 0, heap_mask, + ion_flags, &ion_hnd ); + + if ( ret != 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; + } + + private_handle_t *hnd = new private_handle_t( private_handle_t::PRIV_FLAGS_USES_ION, usage, size, cpu_ptr, + lock_state ); + + if ( NULL != hnd ) + { + hnd->share_fd = shared_fd; + hnd->ion_hnd = ion_hnd; + *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); +#if MALI_ARCHITECTURE_UTGARD + /* On Utgard we do not have a strict requirement of DMA-BUF integration */ + return 0; +#else + return -1; +#endif + } +} + +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_UMP) + { + AERR( "Can't free ump memory for handle:%p. Not supported.", hnd ); + } + 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: %p )", 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/alloc_ump.cpp b/alloc_ump.cpp new file mode 100755 index 0000000..63c24ff --- /dev/null +++ b/alloc_ump.cpp @@ -0,0 +1,235 @@ +/* + * 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 <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 <ump/ump.h> +#include <ump/ump_ref_drv.h> + +#if GRALLOC_SIMULATE_FAILURES +#include <cutils/properties.h> + +/* system property keys for controlling simulated UMP allocation failures */ +#define PROP_MALI_TEST_GRALLOC_FAIL_FIRST "mali.test.gralloc.fail_first" +#define PROP_MALI_TEST_GRALLOC_FAIL_INTERVAL "mali.test.gralloc.fail_interval" + +static int __ump_alloc_should_fail() +{ + + static unsigned int call_count = 0; + unsigned int first_fail = 0; + int fail_period = 0; + int fail = 0; + + ++call_count; + + /* read the system properties that control failure simulation */ + { + char prop_value[PROPERTY_VALUE_MAX]; + + if (property_get(PROP_MALI_TEST_GRALLOC_FAIL_FIRST, prop_value, "0") > 0) + { + sscanf(prop_value, "%11u", &first_fail); + } + + if (property_get(PROP_MALI_TEST_GRALLOC_FAIL_INTERVAL, prop_value, "0") > 0) + { + sscanf(prop_value, "%11u", &fail_period); + } + } + + /* failure simulation is enabled by setting the first_fail property to non-zero */ + if (first_fail > 0) + { + LOGI("iteration %u (fail=%u, period=%u)\n", call_count, first_fail, fail_period); + + fail = (call_count == first_fail) || + (call_count > first_fail && fail_period > 0 && 0 == (call_count - first_fail) % fail_period); + + if (fail) + { + AERR("failed ump_ref_drv_allocate on iteration #%d\n", call_count); + } + } + return fail; +} +#endif + +int alloc_backend_alloc(alloc_device_t* dev, size_t size, int usage, buffer_handle_t* pHandle) +{ + { + ump_handle ump_mem_handle; + void *cpu_ptr; + ump_secure_id ump_id; + ump_alloc_constraints constraints; + + size = round_up_to_page_size(size); + + if( (usage&GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN ) + { + constraints = UMP_REF_DRV_CONSTRAINT_USE_CACHE; + } + else + { + constraints = UMP_REF_DRV_CONSTRAINT_NONE; + } + +#ifdef GRALLOC_SIMULATE_FAILURES + /* if the failure condition matches, fail this iteration */ + if (__ump_alloc_should_fail()) + { + ump_mem_handle = UMP_INVALID_MEMORY_HANDLE; + } + else +#endif + { + /* protected memory not supported in UMP */ + if (!(usage & GRALLOC_USAGE_PROTECTED)) + { + ump_mem_handle = ump_ref_drv_allocate(size, constraints); + + if (UMP_INVALID_MEMORY_HANDLE != ump_mem_handle) + { + cpu_ptr = ump_mapped_pointer_get(ump_mem_handle); + if (NULL != cpu_ptr) + { + ump_id = ump_secure_id_get(ump_mem_handle); + if (UMP_INVALID_SECURE_ID != ump_id) + { + private_handle_t* hnd = new private_handle_t(private_handle_t::PRIV_FLAGS_USES_UMP, + usage, + size, + cpu_ptr, + private_handle_t::LOCK_STATE_MAPPED, + ump_id, + ump_mem_handle); + + if (NULL != hnd) + { + *pHandle = hnd; + return 0; + } + else + { + AERR( "gralloc_alloc_buffer() failed to allocate handle. ump_handle = %p, ump_id = %d", ump_mem_handle, ump_id ); + } + } + else + { + AERR( "gralloc_alloc_buffer() failed to retrieve valid secure id. ump_handle = %p", ump_mem_handle ); + } + + ump_mapped_pointer_release(ump_mem_handle); + } + else + { + AERR( "gralloc_alloc_buffer() failed to map UMP memory. ump_handle = %p", ump_mem_handle ); + } + + ump_reference_release(ump_mem_handle); + } + else + { + AERR( "gralloc_alloc_buffer() failed to allocate UMP memory. size:%d constraints: %d", size, constraints ); + } + } + else + { + AERR( "gralloc_alloc_buffer() protected UMP memory is not supported."); + } + } + return -1; + } +} + +int alloc_backend_alloc_framebuffer(private_module_t* m, private_handle_t* hnd) +{ + hnd->ump_id = m->framebuffer->ump_id; + /* create a backing ump memory handle if the framebuffer is exposed as a secure ID */ + if ( (int)UMP_INVALID_SECURE_ID != hnd->ump_id ) + { + hnd->ump_mem_handle = ump_handle_create_from_secure_id( hnd->ump_id ); + if ( UMP_INVALID_MEMORY_HANDLE == hnd->ump_mem_handle ) + { + AERR("unable to create UMP handle from secure ID %i\n", hnd->ump_id); + return -1; + } + } + + return 0; +} + +void alloc_backend_alloc_free(private_handle_t const* hnd, private_module_t* m) +{ + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) + { + if ( UMP_INVALID_MEMORY_HANDLE != hnd->ump_mem_handle ) + { + ump_reference_release((ump_handle)hnd->ump_mem_handle); + } + } + else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) + { + /* Buffer might be unregistered so we need to check for invalid ump handle*/ + if ( UMP_INVALID_MEMORY_HANDLE != hnd->ump_mem_handle ) + { + ump_mapped_pointer_release((ump_handle)hnd->ump_mem_handle); + ump_reference_release((ump_handle)hnd->ump_mem_handle); + } + } + else if ( hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION ) + { + AERR( "Can't free dma_buf memory for handle:%p. Not supported.", hnd); + } +} + +int alloc_backend_open(alloc_device_t *dev) +{ + ump_result ump_res = ump_open(); + if (UMP_OK != ump_res) + { + AERR( "UMP open failed with %d", ump_res ); + 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) + { + ump_close(); // Our UMP memory refs will be released automatically here... + } + return 0; +} diff --git a/format_chooser.cpp b/format_chooser.cpp new file mode 100755 index 0000000..f62f5ad --- /dev/null +++ b/format_chooser.cpp @@ -0,0 +1,304 @@ +/* + * 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 <hardware/hardware.h> +#include <cutils/log.h> +#include <hardware/gralloc.h> +#include "format_chooser.h" + +#define GRALLOC_ANDROID_PRIVATE_IN_RANGE_OF_AFBC(x) \ + (((x) > GRALLOC_ANDROID_PRIVATE_RANGE_BASE_AFBC && \ + (x) <= (GRALLOC_ANDROID_PRIVATE_RANGE_BASE_AFBC + 0xff)) || \ + ((x) == (GRALLOC_ANDROID_PRIVATE_RANGE_BASE_AFBC + HAL_PIXEL_FORMAT_YV12))) +#define GRALLOC_ANDROID_PRIVATE_IN_RANGE_OF_AFBC_SPLITBLK(x) \ + (((x) > GRALLOC_ANDROID_PRIVATE_RANGE_BASE_AFBC_SPLITBLK && \ + (x) <= (GRALLOC_ANDROID_PRIVATE_RANGE_BASE_AFBC_SPLITBLK + 0xff)) || \ + ((x) == ( GRALLOC_ANDROID_PRIVATE_RANGE_BASE_AFBC_SPLITBLK + HAL_PIXEL_FORMAT_YV12))) +#define GRALLOC_ANDROID_PRIVATE_IN_RANGE_OF_AFBC_WIDEBLK(x) \ + (((x) > GRALLOC_ANDROID_PRIVATE_RANGE_BASE_AFBC_WIDEBLK && \ + (x) <= (GRALLOC_ANDROID_PRIVATE_RANGE_BASE_AFBC_WIDEBLK + 0xff)) || \ + ((x) == ( GRALLOC_ANDROID_PRIVATE_RANGE_BASE_AFBC_WIDEBLK + HAL_PIXEL_FORMAT_YV12))) +#define GRALLOC_ANDROID_PRIVATE_IN_RANGE_OF_BASE_YUVEXT(x) \ + (((x & GRALLOC_ARM_INTFMT_FMT_MASK) >= \ + (GRALLOC_ARM_HAL_FORMAT_INDEXED_Y0L2 + GRALLOC_ANDROID_PRIVATE_RANGE_BASE_YUVEXT)) && \ + ((x & GRALLOC_ARM_INTFMT_FMT_MASK) <= \ + (GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV422_10BIT_AFBC + GRALLOC_ANDROID_PRIVATE_RANGE_BASE_YUVEXT))) + +static inline int find_format_index(int format) +{ + int index=-1; + + switch ( format ) + { + case HAL_PIXEL_FORMAT_RGBA_8888: + index = GRALLOC_ARM_HAL_FORMAT_INDEXED_RGBA_8888; + break; + case HAL_PIXEL_FORMAT_RGBX_8888: + index = GRALLOC_ARM_HAL_FORMAT_INDEXED_RGBX_8888; + break; + case HAL_PIXEL_FORMAT_RGB_888: + index = GRALLOC_ARM_HAL_FORMAT_INDEXED_RGB_888; + break; + case HAL_PIXEL_FORMAT_RGB_565: + index = GRALLOC_ARM_HAL_FORMAT_INDEXED_RGB_565; + break; + case HAL_PIXEL_FORMAT_BGRA_8888: + index = GRALLOC_ARM_HAL_FORMAT_INDEXED_BGRA_8888; + break; +#if (PLATFORM_SDK_VERSION >= 19) && (PLATFORM_SDK_VERSION <= 22) + case HAL_PIXEL_FORMAT_sRGB_A_8888: + index = GRALLOC_ARM_HAL_FORMAT_INDEXED_sRGB_A_8888; + break; + case HAL_PIXEL_FORMAT_sRGB_X_8888: + index = GRALLOC_ARM_HAL_FORMAT_INDEXED_sRGB_X_8888; + break; +#endif + case HAL_PIXEL_FORMAT_YV12: + index = GRALLOC_ARM_HAL_FORMAT_INDEXED_YV12; + break; +#if PLATFORM_SDK_VERSION >= 18 + case HAL_PIXEL_FORMAT_Y8: + index = GRALLOC_ARM_HAL_FORMAT_INDEXED_Y8; + break; + case HAL_PIXEL_FORMAT_Y16: + index = GRALLOC_ARM_HAL_FORMAT_INDEXED_Y16; + break; +#endif + } + + return index; +} + +/* + * Define GRALLOC_ARM_FORMAT_SELECTION_DISABLE to disable the format selection completely + */ +uint64_t gralloc_select_format(int req_format, int usage) +{ +#if defined(GRALLOC_ARM_FORMAT_SELECTION_DISABLE) + + (void) usage; + return (uint64_t) req_format; + +#else + uint64_t new_format = req_format; + int intformat_ind; + int n=0; + int largest_weight_ind=-1; + int16_t accum_weights[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_LAST] = {0}; + int afbc_split_mode = 0; + + ALOGV("gralloc_select_format: req_format=0x%x usage=0x%x\n",req_format,usage); + + /* The GRALLOC_USAGE_PRIVATE_3 set in the usage field indicates the req_format is + * to be treated as encoded private format instead of trying to find closest match. + * At the time being, the flag is used for testing AFBC and 10bit YUV that are not + * yet supported by Android HAL */ + /* Decode the passed in private format and get the gralloc indexed formats */ + if (usage & GRALLOC_USAGE_PRIVATE_3) + { + uint64_t result = 0; + /* req_format is within the range for normal AFBC formats */ + if (GRALLOC_ANDROID_PRIVATE_IN_RANGE_OF_AFBC(req_format)) + { + req_format = req_format - GRALLOC_ANDROID_PRIVATE_RANGE_BASE_AFBC; + result = req_format | GRALLOC_ARM_INTFMT_AFBC; + switch (req_format & GRALLOC_ARM_INTFMT_FMT_MASK) + { + case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV420_8BIT_AFBC: + case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV422_8BIT_AFBC: + result |= GRALLOC_ARM_INTFMT_ARM_AFBC_YUV; + break; + } + return result; + } + else if (GRALLOC_ANDROID_PRIVATE_IN_RANGE_OF_AFBC_SPLITBLK(req_format)) + { + req_format = req_format - GRALLOC_ANDROID_PRIVATE_RANGE_BASE_AFBC_SPLITBLK; + result = req_format | GRALLOC_ARM_INTFMT_AFBC_SPLITBLK; + /* We don't support yuv 4:2:2 afbc split mode */ + if (req_format == GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV420_8BIT_AFBC) + { + result |= GRALLOC_ARM_INTFMT_ARM_AFBC_YUV; + } + return result; + } + else if (GRALLOC_ANDROID_PRIVATE_IN_RANGE_OF_BASE_YUVEXT(req_format)) + { + req_format = req_format - GRALLOC_ANDROID_PRIVATE_RANGE_BASE_YUVEXT; + switch (req_format & GRALLOC_ARM_INTFMT_FMT_MASK) + { + case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV420_10BIT_AFBC: + case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV422_10BIT_AFBC: + result = (GRALLOC_ARM_INTFMT_AFBC | GRALLOC_ARM_INTFMT_ARM_AFBC_YUV); + /* pass through */ + case GRALLOC_ARM_HAL_FORMAT_INDEXED_Y0L2: + case GRALLOC_ARM_HAL_FORMAT_INDEXED_P010: + case GRALLOC_ARM_HAL_FORMAT_INDEXED_P210: + case GRALLOC_ARM_HAL_FORMAT_INDEXED_Y210: + case GRALLOC_ARM_HAL_FORMAT_INDEXED_Y410: + /* preserve the format + possible AFBC flag, and add extended-yuv flag */ + result |= GRALLOC_ARM_INTFMT_EXTENDED_YUV; + result |= (req_format & (GRALLOC_ARM_INTFMT_FMT_MASK | GRALLOC_ARM_INTFMT_AFBC | GRALLOC_ARM_INTFMT_ARM_AFBC_YUV)); + break; + } + return result; + } + else if (GRALLOC_ANDROID_PRIVATE_IN_RANGE_OF_AFBC_WIDEBLK(req_format)) + { + req_format = req_format - GRALLOC_ANDROID_PRIVATE_RANGE_BASE_AFBC_WIDEBLK; + switch (req_format & GRALLOC_ARM_INTFMT_FMT_MASK) + { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: + case HAL_PIXEL_FORMAT_RGB_888: + result = req_format | GRALLOC_ARM_INTFMT_AFBC_SPLITBLK | GRALLOC_ARM_INTFMT_AFBC_WIDEBLK; + break; + case HAL_PIXEL_FORMAT_RGB_565: + case HAL_PIXEL_FORMAT_YV12: + result = req_format | GRALLOC_ARM_INTFMT_AFBC_WIDEBLK; + break; + case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV420_8BIT_AFBC: + case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV422_8BIT_AFBC: + result = req_format | GRALLOC_ARM_INTFMT_AFBC_WIDEBLK | GRALLOC_ARM_INTFMT_ARM_AFBC_YUV; + break; + case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV420_10BIT_AFBC: + case GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV422_10BIT_AFBC: + result = GRALLOC_ARM_INTFMT_EXTENDED_YUV | GRALLOC_ARM_INTFMT_ARM_AFBC_YUV; + result |= (req_format & ( GRALLOC_ARM_INTFMT_FMT_MASK | GRALLOC_ARM_INTFMT_AFBC_WIDEBLK )); + break; + default: + ALOGV("Gralloc gets internal HAL pixel format: 0x%llX", (req_format & GRALLOC_ARM_INTFMT_FMT_MASK)); + result = req_format | GRALLOC_ARM_INTFMT_AFBC_WIDEBLK; + break; + } + return result; + } + else + { + /* invalid format value */ + return -EINVAL; + } + } + + if( req_format == 0 ) + { + return 0; + } + + if( (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) != 0 || + usage == 0 ) + { + return new_format; + } + +#if DISABLE_FRAMEBUFFER_HAL != 1 + /* This is currently a limitation with the display and will be removed eventually + * We can't allocate fbdev framebuffer buffers in AFBC format */ + if( usage & GRALLOC_USAGE_HW_FB ) + { + return new_format; + } +#endif + + /* if this format can't be classified in one of the groups we + * have pre-defined, ignore it. + */ + intformat_ind = find_format_index( req_format ); + if( intformat_ind < 0 ) + { + return new_format; + } + + while( blklist[n].blk_init != 0 ) + { + if( (blklist[n].hwblkconf.usage & usage) != 0 ) + { + uint32_t m; + + for(m=GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_FIRST; m<GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_LAST; m++) + { + if( blklist[n].hwblkconf.weights[intformat_ind][m] != DEFAULT_WEIGHT_UNSUPPORTED ) + { + accum_weights[m] += blklist[n].hwblkconf.weights[intformat_ind][m]; + + if( largest_weight_ind < 0 || + accum_weights[m] > accum_weights[largest_weight_ind]) + { + largest_weight_ind = m; + } + } + else + { + /* Format not supported by this hwblk */ + accum_weights[m] = DEFAULT_WEIGHT_UNSUPPORTED; + } + } + } + n++; + } + + if( largest_weight_ind < 0 ) + { + new_format = 0; + } + else + { + new_format = translate_internal_indexed[largest_weight_ind].internal_extended_format; + } + + ALOGV("Returned iterated format: 0x%llX", new_format); + + return new_format; +#endif +} + +extern "C" +{ +void *gralloc_get_internal_info(int *blkconf_size, int *gpu_conf) +{ + void *blkinit_address = NULL; + +#if !defined(GRALLOC_ARM_FORMAT_SELECTION_DISABLE) + + if(blkconf_size != NULL && gpu_conf != NULL) + { + blkinit_address = (void*) blklist; + *blkconf_size = blklist_array_size; + +/* + * Tests intended to verify gralloc format selection behavior are GPU version aware in runtime. + * They need to know what configuration we built for. For now this is simply AFBC on or off. This + * will likely change in the future to mean something else. + */ +#if MALI_AFBC_GRALLOC == 1 + *gpu_conf = 1; +#else + *gpu_conf = 0; +#endif /* MALI_AFBC_GRALLOC */ + } + +#endif /* GRALLOC_ARM_FORMAT_SELECTION_DISABLE */ + + return blkinit_address; +} + +int gralloc_get_internal_format(int hal_format) +{ + return find_format_index(hal_format); +} +} diff --git a/format_chooser.h b/format_chooser.h new file mode 100755 index 0000000..f70182e --- /dev/null +++ b/format_chooser.h @@ -0,0 +1,195 @@ +/* + * 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 FORMAT_CHOOSER_H_ +#define FORMAT_CHOOSER_H_ + +#include <hardware/hardware.h> + + +#define GRALLOC_ARM_INTFMT_EXTENSION_BIT_START 32 + +/* This format will be use AFBC */ +#define GRALLOC_ARM_INTFMT_AFBC (1ULL << (GRALLOC_ARM_INTFMT_EXTENSION_BIT_START+0)) + +/* This format uses AFBC split block mode */ +#define GRALLOC_ARM_INTFMT_AFBC_SPLITBLK (1ULL << (GRALLOC_ARM_INTFMT_EXTENSION_BIT_START+1)) + +/* 10bit or 16bit, "extended" YUV format bit */ +#define GRALLOC_ARM_INTFMT_EXTENDED_YUV (1ULL << (GRALLOC_ARM_INTFMT_EXTENSION_BIT_START+2)) + +/* This format uses AFBC wide block mode */ +#define GRALLOC_ARM_INTFMT_AFBC_WIDEBLK (1ULL << (GRALLOC_ARM_INTFMT_EXTENSION_BIT_START+3)) + +/* 8bit or 10bit, Compressed ARM YUV formats */ +#define GRALLOC_ARM_INTFMT_ARM_AFBC_YUV (1ULL << (GRALLOC_ARM_INTFMT_EXTENSION_BIT_START+4)) + +/* Internal format masks */ +#define GRALLOC_ARM_INTFMT_FMT_MASK 0x00000000ffffffffULL +#define GRALLOC_ARM_INTFMT_EXT_MASK 0xffffffff00000000ULL + +/* Android pixel format private range start from 0x100 */ +#define GRALLOC_ANDROID_PRIVATE_RANGE_BASE_AFBC 0x100 +#define GRALLOC_ANDROID_PRIVATE_RANGE_BASE_AFBC_SPLITBLK 0x200 +#define GRALLOC_ANDROID_PRIVATE_RANGE_BASE_YUVEXT 0x400 +#define GRALLOC_ANDROID_PRIVATE_RANGE_BASE_AFBC_WIDEBLK 0x800 + +#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC(x) (GRALLOC_ANDROID_PRIVATE_RANGE_BASE_AFBC + (x)) +#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_SPLITBLK(x) (GRALLOC_ANDROID_PRIVATE_RANGE_BASE_AFBC_SPLITBLK + (x)) +#define GRALLOC_PRIVATE_FORMAT_WRAPPER_YUVEXT(x) (GRALLOC_ANDROID_PRIVATE_RANGE_BASE_YUVEXT + (x)) +#define GRALLOC_PRIVATE_FORMAT_WRAPPER_AFBC_WIDEBLK(x) (GRALLOC_ANDROID_PRIVATE_RANGE_BASE_AFBC_WIDEBLK + (x)) + +/* Index of the internal formats */ +typedef enum +{ + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_FIRST, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBA_8888=GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_FIRST, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBX_8888, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_888, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_565, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_BGRA_8888, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_sRGB_A_8888, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_sRGB_X_8888, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YV12, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_Y8, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_Y16, + + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBA_8888_AFBC, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBX_8888_AFBC, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_888_AFBC, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_565_AFBC, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_BGRA_8888_AFBC, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YUV420_8BIT_AFBC, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YUV422_8BIT_AFBC, + + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_AFBC_SPLITBLK_FIRST, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBA_8888_AFBC_SPLITBLK=GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_AFBC_SPLITBLK_FIRST, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBX_8888_AFBC_SPLITBLK, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_888_AFBC_SPLITBLK, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_565_AFBC_SPLITBLK, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_BGRA_8888_AFBC_SPLITBLK, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YUV420_8BIT_AFBC_SPLITBLK, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_AFBC_SPLITBLK_LAST=GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YUV420_8BIT_AFBC_SPLITBLK, + + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_AFBC_WIDEBLK_FIRST, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBA_8888_AFBC_SPLITBLK_WIDEBLK=GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_AFBC_WIDEBLK_FIRST, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBX_8888_AFBC_SPLITBLK_WIDEBLK, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_888_AFBC_SPLITBLK_WIDEBLK, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_565_AFBC_WIDEBLK, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_BGRA_8888_AFBC_SPLITBLK_WIDEBLK, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YUV420_8BIT_AFBC_WIDEBLK, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YUV422_8BIT_AFBC_WIDEBLK, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_AFBC_WIDEBLK_LAST=GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YUV422_8BIT_AFBC_WIDEBLK, + + /* Extended YUV formats */ + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_Y0L2, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_P010, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_P210, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_Y210, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_Y410, + + /* Compressed extended YUV formats */ + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YUV420_10BIT_AFBC, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YUV422_10BIT_AFBC, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YUV420_10BIT_AFBC_WIDEBLK, + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YUV422_10BIT_AFBC_WIDEBLK, + + /* Add more internal formats here */ + + GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_LAST +} gralloc_arm_internal_index_format; + +typedef enum +{ + /* Having an invalid format catches lists which are initialized with not all entries. */ + GRALLOC_ARM_HAL_FORMAT_INDEXED_INVALID, + GRALLOC_ARM_HAL_FORMAT_INDEXED_RGBA_8888, + GRALLOC_ARM_HAL_FORMAT_INDEXED_RGBX_8888, + GRALLOC_ARM_HAL_FORMAT_INDEXED_RGB_888, + GRALLOC_ARM_HAL_FORMAT_INDEXED_RGB_565, + GRALLOC_ARM_HAL_FORMAT_INDEXED_BGRA_8888, + GRALLOC_ARM_HAL_FORMAT_INDEXED_sRGB_A_8888, + GRALLOC_ARM_HAL_FORMAT_INDEXED_sRGB_X_8888, + GRALLOC_ARM_HAL_FORMAT_INDEXED_YV12, + GRALLOC_ARM_HAL_FORMAT_INDEXED_Y8, + GRALLOC_ARM_HAL_FORMAT_INDEXED_Y16, + + /* Compressed 8BIT YUV format */ + GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV420_8BIT_AFBC, + GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV422_8BIT_AFBC, + + /* Extended YUV formats */ + GRALLOC_ARM_HAL_FORMAT_INDEXED_Y0L2, + GRALLOC_ARM_HAL_FORMAT_INDEXED_P010, + GRALLOC_ARM_HAL_FORMAT_INDEXED_P210, + GRALLOC_ARM_HAL_FORMAT_INDEXED_Y210, + GRALLOC_ARM_HAL_FORMAT_INDEXED_Y410, + + /* Compressed extended YUV formats */ + GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV420_10BIT_AFBC, + GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV422_10BIT_AFBC, + + GRALLOC_ARM_HAL_FORMAT_INDEXED_LAST +} gralloc_arm_hal_index_format; + +#define MAX_COMPATIBLE 3 +#define DEFAULT_WEIGHT_SUPPORTED 50 +#define DEFAULT_WEIGHT_MOST_PREFERRED 100 +#define DEFAULT_WEIGHT_UNSUPPORTED -1 + +typedef struct +{ + /* The internal extended format exported outside of gralloc */ + uint64_t internal_extended_format; + + /* Swizzled versions of the requested format for this internal format */ + gralloc_arm_hal_index_format comp_format_list[MAX_COMPATIBLE]; +} internal_fmt_info; + +uint64_t gralloc_select_format(int req_format, int usage); + +struct hwblk +{ + uint32_t usage; + int16_t weights[GRALLOC_ARM_HAL_FORMAT_INDEXED_LAST][GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_LAST]; +}; + + +typedef struct +{ + void (*blk_init)(struct hwblk *format_matrix, int16_t **array); + struct hwblk hwblkconf; +} blkinit; + + +extern void initialize_blk_conf(); +extern const internal_fmt_info translate_internal_indexed[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_LAST]; +extern blkinit blklist[]; +extern uint32_t blklist_array_size; + +#ifdef __cplusplus +extern "C" +{ +#endif + int gralloc_get_internal_format(int hal_format); + void *gralloc_get_internal_info(int *blkconf_size, int *gpu_conf); +#ifdef __cplusplus +} +#endif + +#endif /* FORMAT_CHOOSER_H_ */ diff --git a/format_chooser_blockinit.cpp b/format_chooser_blockinit.cpp new file mode 100755 index 0000000..6eddc41 --- /dev/null +++ b/format_chooser_blockinit.cpp @@ -0,0 +1,285 @@ +/* + * 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 <hardware/hardware.h> +#include <hardware/gralloc.h> + +/* The extension bits are defined for indexed formats when setting + * up the definitions. This define exports them before including + * the block definitions. + */ +#include "format_chooser.h" + +#include "formatdef_files/gpu_default.defs" + +#if MALI_AFBC_GRALLOC == 1 +#if MALI_SUPPORT_AFBC_WIDEBLK == 1 +#include "formatdef_files/gpu_afbc_wideblk.defs" +#else +#include "formatdef_files/gpu_afbc.defs" +#endif +#ifdef MALI_DISPLAY_VERSION +#include "formatdef_files/display_afbc.defs" +#endif +#endif + + +/* Defines a translation list of requested formats that are compatible with the internal indexed format */ +const internal_fmt_info translate_internal_indexed[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_LAST] = +{ + { + HAL_PIXEL_FORMAT_RGBA_8888, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_RGBA_8888, GRALLOC_ARM_HAL_FORMAT_INDEXED_BGRA_8888} + }, + + { + HAL_PIXEL_FORMAT_RGBX_8888, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_RGBX_8888, GRALLOC_ARM_HAL_FORMAT_INDEXED_RGB_888} + }, + + { + HAL_PIXEL_FORMAT_RGB_888, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_RGB_888, GRALLOC_ARM_HAL_FORMAT_INDEXED_RGBX_8888} + }, + + { + HAL_PIXEL_FORMAT_RGB_565, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_RGB_565} + }, + + { + HAL_PIXEL_FORMAT_BGRA_8888, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_BGRA_8888, GRALLOC_ARM_HAL_FORMAT_INDEXED_RGBA_8888} + }, + +#if (PLATFORM_SDK_VERSION >= 19) && (PLATFORM_SDK_VERSION <= 22) + {HAL_PIXEL_FORMAT_sRGB_A_8888, {GRALLOC_ARM_HAL_FORMAT_INDEXED_sRGB_A_8888} }, + {HAL_PIXEL_FORMAT_sRGB_X_8888, {GRALLOC_ARM_HAL_FORMAT_INDEXED_sRGB_X_8888} }, +#else + {0, {GRALLOC_ARM_HAL_FORMAT_INDEXED_sRGB_A_8888} }, + {0, {GRALLOC_ARM_HAL_FORMAT_INDEXED_sRGB_X_8888} }, +#endif + + { + HAL_PIXEL_FORMAT_YV12, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_YV12} + }, + +#if PLATFORM_SDK_VERSION >= 18 + {HAL_PIXEL_FORMAT_Y8, {GRALLOC_ARM_HAL_FORMAT_INDEXED_Y8} }, + {HAL_PIXEL_FORMAT_Y16, {GRALLOC_ARM_HAL_FORMAT_INDEXED_Y16} }, +#else + {0, {GRALLOC_ARM_HAL_FORMAT_INDEXED_Y8} }, + {0, {GRALLOC_ARM_HAL_FORMAT_INDEXED_Y16} }, +#endif + + + { + HAL_PIXEL_FORMAT_RGBA_8888 | GRALLOC_ARM_INTFMT_AFBC, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_RGBA_8888, GRALLOC_ARM_HAL_FORMAT_INDEXED_BGRA_8888} + }, + + { + HAL_PIXEL_FORMAT_RGBX_8888 | GRALLOC_ARM_INTFMT_AFBC, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_RGBX_8888, GRALLOC_ARM_HAL_FORMAT_INDEXED_RGB_888} + }, + + { + HAL_PIXEL_FORMAT_RGB_888 | GRALLOC_ARM_INTFMT_AFBC, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_RGB_888, GRALLOC_ARM_HAL_FORMAT_INDEXED_RGBX_8888} + }, + + { + HAL_PIXEL_FORMAT_RGB_565 | GRALLOC_ARM_INTFMT_AFBC, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_RGB_565} + }, + + { + HAL_PIXEL_FORMAT_BGRA_8888 | GRALLOC_ARM_INTFMT_AFBC, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_BGRA_8888, GRALLOC_ARM_HAL_FORMAT_INDEXED_RGBA_8888} + }, + + { + HAL_PIXEL_FORMAT_YV12 | GRALLOC_ARM_INTFMT_AFBC, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_YV12, GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV420_8BIT_AFBC} + }, + + {0, {GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV422_8BIT_AFBC}}, + + { + HAL_PIXEL_FORMAT_RGBA_8888 | GRALLOC_ARM_INTFMT_AFBC_SPLITBLK, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_RGBA_8888, GRALLOC_ARM_HAL_FORMAT_INDEXED_BGRA_8888} + }, + + { + HAL_PIXEL_FORMAT_RGBX_8888 | GRALLOC_ARM_INTFMT_AFBC_SPLITBLK, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_RGBX_8888, GRALLOC_ARM_HAL_FORMAT_INDEXED_RGB_888} + }, + + { + HAL_PIXEL_FORMAT_RGB_888 | GRALLOC_ARM_INTFMT_AFBC_SPLITBLK, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_RGB_888, GRALLOC_ARM_HAL_FORMAT_INDEXED_RGBX_8888} + }, + + { + HAL_PIXEL_FORMAT_RGB_565 | GRALLOC_ARM_INTFMT_AFBC_SPLITBLK, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_RGB_565} + }, + + { + HAL_PIXEL_FORMAT_BGRA_8888 | GRALLOC_ARM_INTFMT_AFBC_SPLITBLK, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_BGRA_8888, GRALLOC_ARM_HAL_FORMAT_INDEXED_RGBA_8888} + }, + + { + HAL_PIXEL_FORMAT_YV12 | GRALLOC_ARM_INTFMT_AFBC_SPLITBLK, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_YV12, GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV420_8BIT_AFBC} + }, + + { + HAL_PIXEL_FORMAT_RGBA_8888 | GRALLOC_ARM_INTFMT_AFBC_SPLITBLK | GRALLOC_ARM_INTFMT_AFBC_WIDEBLK, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_RGBA_8888, GRALLOC_ARM_HAL_FORMAT_INDEXED_BGRA_8888} + }, + + { + HAL_PIXEL_FORMAT_RGBX_8888 | GRALLOC_ARM_INTFMT_AFBC_SPLITBLK | GRALLOC_ARM_INTFMT_AFBC_WIDEBLK, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_RGBX_8888, GRALLOC_ARM_HAL_FORMAT_INDEXED_RGB_888} + }, + + { + HAL_PIXEL_FORMAT_RGB_888 | GRALLOC_ARM_INTFMT_AFBC_SPLITBLK | GRALLOC_ARM_INTFMT_AFBC_WIDEBLK, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_RGB_888, GRALLOC_ARM_HAL_FORMAT_INDEXED_RGBX_8888} + }, + + { + HAL_PIXEL_FORMAT_RGB_565 | GRALLOC_ARM_INTFMT_AFBC_WIDEBLK, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_RGB_565} + }, + + { + HAL_PIXEL_FORMAT_BGRA_8888 | GRALLOC_ARM_INTFMT_AFBC_SPLITBLK | GRALLOC_ARM_INTFMT_AFBC_WIDEBLK, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_BGRA_8888, GRALLOC_ARM_HAL_FORMAT_INDEXED_RGBA_8888} + }, + + { + HAL_PIXEL_FORMAT_YV12 | GRALLOC_ARM_INTFMT_AFBC_WIDEBLK, + {GRALLOC_ARM_HAL_FORMAT_INDEXED_YV12, GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV420_8BIT_AFBC} + }, + + {0, {GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV422_8BIT_AFBC}}, + + /* No mapping as there is no corresponding HAL formats */ + {0, {GRALLOC_ARM_HAL_FORMAT_INDEXED_Y0L2}}, + {0, {GRALLOC_ARM_HAL_FORMAT_INDEXED_P010}}, + {0, {GRALLOC_ARM_HAL_FORMAT_INDEXED_P210}}, + {0, {GRALLOC_ARM_HAL_FORMAT_INDEXED_Y210}}, + {0, {GRALLOC_ARM_HAL_FORMAT_INDEXED_Y410}}, + /* Entry at GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YUV420_10BIT_AFBC */ + {0, {GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV420_10BIT_AFBC}}, + /* Entry at GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YUV422_10BIT_AFBC */ + {0, {GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV422_10BIT_AFBC}}, + /* Entry at GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YUV420_10BIT_AFBC_WIDEBLK */ + {0, {GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV420_10BIT_AFBC}}, + /* Entry at GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YUV422_10BIT_AFBC_WIDEBLK */ + {0, {GRALLOC_ARM_HAL_FORMAT_INDEXED_YUV422_10BIT_AFBC}}, +}; + +blkinit blklist[] = +{ +#if MALI_AFBC_GRALLOC == 1 +#ifdef MALI_DISPLAY_VERSION + { + display_afbc_hwc_blkinit,{0,{}} + }, +#endif + { + gpu_afbc_write_blkinit,{0,{}} + }, + { + gpu_afbc_read_blkinit,{0,{}} + }, +#else + { + gpu_write_blkinit,{0,{}} + }, + { + gpu_read_blkinit,{0,{}} + }, +#endif + + /* Empty entry */ + { + NULL,{0,{}} + } +}; + +uint32_t blklist_array_size = sizeof(blklist); + +void initialize_blk_conf() +{ + int i,j,k; + + i=0; + while( blklist[i].blk_init != 0 ) + { + int16_t *array=0; + + for(j=0;j<GRALLOC_ARM_HAL_FORMAT_INDEXED_LAST;j++) + { + for(k=0; k<(int) GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_LAST; k++) + { + blklist[i].hwblkconf.weights[j][k] = DEFAULT_WEIGHT_UNSUPPORTED; + } + } + blklist[i].blk_init( &blklist[i].hwblkconf , &array); + if( *array != 0 ) + { + for(k=GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_FIRST; k<GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_LAST; k++) + { + /* Zero weights are not suppose to be used in the preferred array because that usually means + * uninitialized values. + */ + if( array[k] != DEFAULT_WEIGHT_UNSUPPORTED && array[k] != 0 ) + { + int n; + + /* For this internal format we will for its base format setup matching weights + * for itself as well as swizzled versions of the format. When initializing + * swizzled/compatible formats with same weight, we insert a slight preference + * on the base format(which is listed first) to choose that when the base is selected. + * Other blocks' preference might adjust this. + */ + for(n=0; n<MAX_COMPATIBLE; n++) + { + if( translate_internal_indexed[k].comp_format_list[n] != GRALLOC_ARM_HAL_FORMAT_INDEXED_INVALID ) + { + if(n==0) + { + blklist[i].hwblkconf.weights[translate_internal_indexed[k].comp_format_list[n]][k] = array[k]+1; + } + else + { + blklist[i].hwblkconf.weights[translate_internal_indexed[k].comp_format_list[n]][k] = array[k]; + } + } + } + } + } + } + i++; + } +} diff --git a/formatdef_files/display_afbc.defs b/formatdef_files/display_afbc.defs new file mode 100755 index 0000000..5ac6dbf --- /dev/null +++ b/formatdef_files/display_afbc.defs @@ -0,0 +1,35 @@ +/* + * 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/memory.h> + +static void display_afbc_hwc_blkinit(struct hwblk *blk,int16_t **array) +{ + static int16_t hwc_pref_formats[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_LAST]; + android_memset16((uint16_t*) hwc_pref_formats, (uint16_t) DEFAULT_WEIGHT_UNSUPPORTED, sizeof(uint16_t) * GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_LAST); + blk->usage = GRALLOC_USAGE_HW_COMPOSER; + *array = hwc_pref_formats; + +#if MALI_DISPLAY_VERSION == 500 + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_888_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED + 10; +#elif MALI_DISPLAY_VERSION == 550 + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBA_8888_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED + 10; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_BGRA_8888_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED + 10; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_888_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED + 10; +#endif +} diff --git a/formatdef_files/gpu_afbc.defs b/formatdef_files/gpu_afbc.defs new file mode 100755 index 0000000..42be87d --- /dev/null +++ b/formatdef_files/gpu_afbc.defs @@ -0,0 +1,56 @@ +/* + * 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. + */ + +static void gpu_afbc_read_blkinit(struct hwblk *blk,int16_t **array) +{ + /* Initialiaze GPU default weight setup */ + gpu_read_blkinit(blk, array); + + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBA_8888_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBX_8888_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_BGRA_8888_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_888_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_565_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YUV420_8BIT_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBA_8888_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBX_8888_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_BGRA_8888_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_888_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_565_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YUV420_8BIT_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; +} + + +static void gpu_afbc_write_blkinit(struct hwblk *blk,int16_t **array) +{ + /* Initialiaze GPU default weight setup */ + gpu_write_blkinit(blk, array); + + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBA_8888_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBX_8888_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_BGRA_8888_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_888_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_565_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBA_8888_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBX_8888_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_BGRA_8888_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_888_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_565_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; +} diff --git a/formatdef_files/gpu_afbc_wideblk.defs b/formatdef_files/gpu_afbc_wideblk.defs new file mode 100755 index 0000000..b38c09a --- /dev/null +++ b/formatdef_files/gpu_afbc_wideblk.defs @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2015 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. + */ + +static void gpu_afbc_read_blkinit(struct hwblk *blk,int16_t **array) +{ + /* Initialiaze GPU default weight setup */ + gpu_read_blkinit(blk, array); + + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBA_8888_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBX_8888_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_BGRA_8888_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_888_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_565_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YUV420_8BIT_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBA_8888_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 60; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBX_8888_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 60; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_BGRA_8888_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 60; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_888_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 60; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_565_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 60; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YUV420_8BIT_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 60; + + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBA_8888_AFBC_SPLITBLK_WIDEBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBX_8888_AFBC_SPLITBLK_WIDEBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_BGRA_8888_AFBC_SPLITBLK_WIDEBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_888_AFBC_SPLITBLK_WIDEBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_565_AFBC_WIDEBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YUV420_8BIT_AFBC_WIDEBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; +} + + +static void gpu_afbc_write_blkinit(struct hwblk *blk,int16_t **array) +{ + /* Initialiaze GPU default weight setup */ + gpu_write_blkinit(blk, array); + + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBA_8888_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBX_8888_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_BGRA_8888_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_888_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_565_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YUV420_8BIT_AFBC] = DEFAULT_WEIGHT_MOST_PREFERRED; + + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBA_8888_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 60; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBX_8888_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 60; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_BGRA_8888_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 60; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_888_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 60; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_565_AFBC_SPLITBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 60; + + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBA_8888_AFBC_SPLITBLK_WIDEBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBX_8888_AFBC_SPLITBLK_WIDEBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_BGRA_8888_AFBC_SPLITBLK_WIDEBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_888_AFBC_SPLITBLK_WIDEBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_565_AFBC_WIDEBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; + (*array)[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YUV420_8BIT_AFBC_WIDEBLK] = DEFAULT_WEIGHT_MOST_PREFERRED - 30; +} diff --git a/formatdef_files/gpu_default.defs b/formatdef_files/gpu_default.defs new file mode 100755 index 0000000..e08e658 --- /dev/null +++ b/formatdef_files/gpu_default.defs @@ -0,0 +1,66 @@ +/* + * 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/memory.h> + +static int16_t pref_formats[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_LAST]; + +static void gpu_read_blkinit(struct hwblk *blk,int16_t **array) +{ + android_memset16((uint16_t*) pref_formats, (uint16_t) DEFAULT_WEIGHT_UNSUPPORTED, sizeof(uint16_t) * GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_LAST); + + blk->usage = GRALLOC_USAGE_HW_TEXTURE; + + /* Compatible internal formats for a specific input format will also be initialized */ + /* Preference on RGBA compared to BGRA because of GLES readback */ + pref_formats[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBA_8888] = DEFAULT_WEIGHT_SUPPORTED+10; + pref_formats[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBX_8888] = DEFAULT_WEIGHT_SUPPORTED; + pref_formats[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_BGRA_8888] = DEFAULT_WEIGHT_SUPPORTED; + + pref_formats[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_888] = DEFAULT_WEIGHT_SUPPORTED; + pref_formats[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_565] = DEFAULT_WEIGHT_SUPPORTED; + pref_formats[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YV12] = DEFAULT_WEIGHT_SUPPORTED; + + pref_formats[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_sRGB_A_8888] = DEFAULT_WEIGHT_SUPPORTED; + pref_formats[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_sRGB_X_8888] = DEFAULT_WEIGHT_SUPPORTED; + + *array = pref_formats; +} + + +static void gpu_write_blkinit(struct hwblk *blk,int16_t **array) +{ + android_memset16((uint16_t*) pref_formats, (uint16_t) DEFAULT_WEIGHT_UNSUPPORTED, sizeof(uint16_t) * GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_LAST); + + blk->usage = GRALLOC_USAGE_HW_RENDER; + + /* Compatible internal formats for a specific input format will also be initialized */ + /* Preference on RGBA compared to BGRA because of GLES readback */ + pref_formats[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBA_8888] = DEFAULT_WEIGHT_SUPPORTED+10; + pref_formats[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGBX_8888] = DEFAULT_WEIGHT_SUPPORTED; + pref_formats[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_BGRA_8888] = DEFAULT_WEIGHT_SUPPORTED; + + pref_formats[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_888] = DEFAULT_WEIGHT_SUPPORTED; + pref_formats[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_RGB_565] = DEFAULT_WEIGHT_SUPPORTED; + pref_formats[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_YV12] = DEFAULT_WEIGHT_SUPPORTED; + + pref_formats[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_sRGB_A_8888] = DEFAULT_WEIGHT_SUPPORTED; + pref_formats[GRALLOC_ARM_FORMAT_INTERNAL_INDEXED_sRGB_X_8888] = DEFAULT_WEIGHT_SUPPORTED; + + *array = pref_formats; +} diff --git a/framebuffer_device.cpp b/framebuffer_device.cpp new file mode 100755 index 0000000..b71a88c --- /dev/null +++ b/framebuffer_device.cpp @@ -0,0 +1,501 @@ +/* + * 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" + +// 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, 0); + + module->numBuffers = info.yres_virtual / info.yres; + module->bufferMask = 0; + +#if GRALLOC_ARM_UMP_MODULE + ioctl(fd, IOCTL_GET_FB_UMP_SECURE_ID, &module->framebuffer->ump_id); + if ( (int)UMP_INVALID_SECURE_ID != module->framebuffer->ump_id ) + { + AERR("framebuffer accessed with UMP secure ID %i\n", module->framebuffer->ump_id); + } +#endif + + 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) + { +#if GRALLOC_ARM_UMP_MODULE + ump_close(); +#endif + free(dev); + } + return 0; +} + +int compositionComplete(struct framebuffer_device_t* 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; + + 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/framebuffer_device.h b/framebuffer_device.h new file mode 100755 index 0000000..7e63d5f --- /dev/null +++ b/framebuffer_device.h @@ -0,0 +1,25 @@ +/* + * 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> + +// 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/gralloc_buffer_priv.cpp b/gralloc_buffer_priv.cpp new file mode 100755 index 0000000..a357030 --- /dev/null +++ b/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/gralloc_buffer_priv.h b/gralloc_buffer_priv.h new file mode 100755 index 0000000..6e2def6 --- /dev/null +++ b/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 and YUV_TRANS are intended to be + * written by producers and read by consumers. + * Producers should write these parameters before + * it queues a buffer to the consumer. + */ + + /* CROP RECT, defined as a int array of top, left, height, width. */ + 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/gralloc_helper.h b/gralloc_helper.h new file mode 100755 index 0000000..277364b --- /dev/null +++ b/gralloc_helper.h @@ -0,0 +1,29 @@ +/* + * 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> + +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/gralloc_module.cpp b/gralloc_module.cpp new file mode 100755 index 0000000..2ec2565 --- /dev/null +++ b/gralloc_module.cpp @@ -0,0 +1,245 @@ +/* + * 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 <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 "gralloc_module_allocator_specific.h" + +#if MALI_AFBC_GRALLOC == 1 +#include "gralloc_buffer_priv.h" +#endif + +#include "format_chooser.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) +{ + 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_UMP | + private_handle_t::PRIV_FLAGS_USES_ION)) + { + retval = gralloc_backend_register(hnd); + } + else + { + AERR("registering non-UMP buffer 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) +{ + 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_UMP | + private_handle_t::PRIV_FLAGS_USES_ION)) + { + gralloc_backend_unregister(hnd); + } + else + { + AERR("Unregistering unknown buffer is not supported. Flags = %d", hnd->flags); + } + +#if MALI_AFBC_GRALLOC == 1 + /* + * 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 ); + +#endif + 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) +{ + 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_UMP || 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_unlock(gralloc_module_t const* module, buffer_handle_t handle) +{ + 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_UMP | + 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 = +{ + open: 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.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; + + initialize_blk_conf(); + +#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/gralloc_module_allocator_specific.h b/gralloc_module_allocator_specific.h new file mode 100755 index 0000000..f719e73 --- /dev/null +++ b/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/gralloc_module_ion.cpp b/gralloc_module_ion.cpp new file mode 100755 index 0000000..edf83fd --- /dev/null +++ b/gralloc_module_ion.cpp @@ -0,0 +1,137 @@ +/* + * 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_UMP | + private_handle_t::PRIV_FLAGS_USES_ION)) + { + case private_handle_t::PRIV_FLAGS_USES_UMP: + AERR("Gralloc does not support UMP. Unable to register UMP memory for handle %p", hnd ); + break; + 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_UMP | + private_handle_t::PRIV_FLAGS_USES_ION)) + { + case private_handle_t::PRIV_FLAGS_USES_UMP: + AERR( "Can't unregister UMP buffer for handle %p. Not supported", hnd ); + break; + 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_UMP | + private_handle_t::PRIV_FLAGS_USES_ION)) + { + case private_handle_t::PRIV_FLAGS_USES_UMP: + AERR( "Buffer %p is UMP type but it is not supported", hnd ); + break; + 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) + { + 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/gralloc_module_ump.cpp b/gralloc_module_ump.cpp new file mode 100755 index 0000000..af11491 --- /dev/null +++ b/gralloc_module_ump.cpp @@ -0,0 +1,116 @@ +/* + * 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 <ump/ump_ref_drv.h> +static int s_ump_is_open = 0; + +int gralloc_backend_register(private_handle_t* hnd) +{ + int retval = -EINVAL; + + switch (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_UMP | + private_handle_t::PRIV_FLAGS_USES_ION)) + { + case private_handle_t::PRIV_FLAGS_USES_UMP: + if (!s_ump_is_open) + { + ump_result res = ump_open(); // MJOLL-4012: UMP implementation needs a ump_close() for each ump_open + if (res != UMP_OK) + { + AERR("Failed to open UMP library with res=%d", res); + } + s_ump_is_open = 1; + } + + if (s_ump_is_open) + { + hnd->ump_mem_handle = ump_handle_create_from_secure_id(hnd->ump_id); + if (UMP_INVALID_MEMORY_HANDLE != (ump_handle)hnd->ump_mem_handle) + { + hnd->base = ump_mapped_pointer_get(hnd->ump_mem_handle); + if (0 != hnd->base) + { + hnd->lockState = private_handle_t::LOCK_STATE_MAPPED; + hnd->writeOwner = 0; + hnd->lockState = 0; + + return 0; + } + else + { + AERR("Failed to map UMP handle %p", hnd->ump_mem_handle ); + } + + ump_reference_release((ump_handle)hnd->ump_mem_handle); + } + else + { + AERR("Failed to create UMP handle %p", hnd->ump_mem_handle ); + } + } + break; + case private_handle_t::PRIV_FLAGS_USES_ION: + AERR("Gralloc does not support DMA_BUF. Unable to map memory for handle %p", hnd ); + break; + } + + return retval; +} + +void gralloc_backend_unregister(private_handle_t* hnd) +{ + switch (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_UMP | + private_handle_t::PRIV_FLAGS_USES_ION)) + { + case private_handle_t::PRIV_FLAGS_USES_UMP: + ump_mapped_pointer_release((ump_handle)hnd->ump_mem_handle); + hnd->base = 0; + ump_reference_release((ump_handle)hnd->ump_mem_handle); + hnd->ump_mem_handle = UMP_INVALID_MEMORY_HANDLE; + break; + case private_handle_t::PRIV_FLAGS_USES_ION: + AERR( "Can't unregister DMA_BUF buffer for hnd %p. Not supported", hnd ); + break; + } +} + +void gralloc_backend_sync(private_handle_t* hnd) +{ + switch (hnd->flags & (private_handle_t::PRIV_FLAGS_USES_UMP | + private_handle_t::PRIV_FLAGS_USES_ION)) + { + case private_handle_t::PRIV_FLAGS_USES_UMP: + ump_cpu_msync_now((ump_handle)hnd->ump_mem_handle, UMP_MSYNC_CLEAN_AND_INVALIDATE, (void*)hnd->base, hnd->size); + break; + case private_handle_t::PRIV_FLAGS_USES_ION: + AERR( "Buffer %p is DMA_BUF type but it is not supported", hnd ); + break; + } +} diff --git a/gralloc_priv.h b/gralloc_priv.h new file mode 100755 index 0000000..31c1c41 --- /dev/null +++ b/gralloc_priv.h @@ -0,0 +1,397 @@ +/* + * 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 <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 "format_chooser.h" + +#if MALI_ION == 1 +#define GRALLOC_ARM_UMP_MODULE 0 +#define GRALLOC_ARM_DMA_BUF_MODULE 1 +#if !defined(GRALLOC_OLD_ION_API) +/* new libion */ +typedef int ion_user_handle_t; +#define ION_INVALID_HANDLE 0 +#else +typedef struct ion_handle *ion_user_handle_t; +#define ION_INVALID_HANDLE NULL +#endif /* GRALLOC_OLD_ION_API */ +#else +#define GRALLOC_ARM_UMP_MODULE 1 +#define GRALLOC_ARM_DMA_BUF_MODULE 0 +#endif /* MALI_ION */ + +/* NOTE: + * If your framebuffer device driver is integrated with UMP, you will have to + * change this IOCTL definition to reflect your integration with the framebuffer + * device. + * Expected return value is a UMP secure id backing your framebuffer device memory. + */ +#if GRALLOC_ARM_UMP_MODULE +#define IOCTL_GET_FB_UMP_SECURE_ID _IOWR('m', 0xF8, __u32) +#endif + +/* 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. + */ +#if GRALLOC_ARM_DMA_BUF_MODULE +struct fb_dmabuf_export +{ + __u32 fd; + __u32 flags; +}; +#define FBIOGET_DMABUF _IOR('F', 0x21, struct fb_dmabuf_export) +#endif + +/* 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 */ +#if MALI_AFBC_GRALLOC == 1 && GRALLOC_ARM_DMA_BUF_MODULE +#define GRALLOC_ARM_NUM_FDS 2 +#elif MALI_AFBC_GRALLOC == 1 || GRALLOC_ARM_DMA_BUF_MODULE +#define GRALLOC_ARM_NUM_FDS 1 +#else +#define GRALLOC_ARM_NUM_FDS 0 +#endif + +#define NUM_INTS_IN_PRIVATE_HANDLE ((sizeof(struct private_handle_t) - sizeof(native_handle)) / sizeof(int) - sNumFds) + + + +#if GRALLOC_ARM_UMP_MODULE +#include <ump/ump.h> +#endif + +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; + + enum + { + // flag to indicate we'll post this buffer + PRIV_USAGE_LOCKED_FOR_POST = 0x80000000 + }; + +#ifdef __cplusplus + /* default constructor */ + private_module_t(); +#endif +}; + +#ifdef __cplusplus +struct private_handle_t : public native_handle +{ +#else +struct private_handle_t +{ + struct native_handle nativeHandle; +#endif + + enum + { + PRIV_FLAGS_FRAMEBUFFER = 0x00000001, + PRIV_FLAGS_USES_UMP = 0x00000002, + PRIV_FLAGS_USES_ION = 0x00000004 + }; + + enum + { + LOCK_STATE_WRITE = 1<<31, + LOCK_STATE_MAPPED = 1<<30, + LOCK_STATE_READ_MASK = 0x3FFFFFFF + }; + +#if GRALLOC_ARM_DMA_BUF_MODULE + /* + * 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; +#endif + +#if MALI_AFBC_GRALLOC == 1 + int share_attr_fd; +#endif + +#if GRALLOC_ARM_DMA_BUF_MODULE + ion_user_handle_t ion_hnd; +#endif + + // 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; + +#if MALI_AFBC_GRALLOC == 1 + // locally mapped shared attribute area + union { + void* attr_base; + uint64_t padding3; + }; +#endif + + mali_gralloc_yuv_info yuv_info; + + // Following members is for framebuffer only + int fd; + union { + off_t offset; + uint64_t padding4; + }; + + // Following members are for UMP memory only +#if GRALLOC_ARM_UMP_MODULE + ump_secure_id ump_id; + union { + void* ump_mem_handle; + uint64_t padding5; + }; +#endif + +#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; + +#if GRALLOC_ARM_UMP_MODULE + private_handle_t(int flags, int usage, int size, void *base, int lock_state, ump_secure_id secure_id, ump_handle handle): +#if MALI_AFBC_GRALLOC == 1 + share_attr_fd(-1), +#endif + magic(sMagic), + flags(flags), + usage(usage), + size(size), + width(0), + height(0), + stride(0), + base(base), + lockState(lock_state), + writeOwner(0), + pid(getpid()), +#if MALI_AFBC_GRALLOC == 1 + attr_base(MAP_FAILED), +#endif + yuv_info(MALI_YUV_NO_INFO), + fd(0), + offset(0), + ump_id(secure_id), + ump_mem_handle(handle) + + { + version = sizeof(native_handle); + numFds = sNumFds; + numInts = NUM_INTS_IN_PRIVATE_HANDLE; + } +#endif + + private_handle_t(int flags, int usage, int size, void *base, int lock_state): +#if GRALLOC_ARM_DMA_BUF_MODULE + share_fd(-1), +#endif +#if MALI_AFBC_GRALLOC == 1 + share_attr_fd(-1), +#endif +#if GRALLOC_ARM_DMA_BUF_MODULE + ion_hnd(ION_INVALID_HANDLE), +#endif + magic(sMagic), + flags(flags), + usage(usage), + size(size), + width(0), + height(0), + stride(0), + base(base), + lockState(lock_state), + writeOwner(0), + pid(getpid()), +#if MALI_AFBC_GRALLOC == 1 + attr_base(MAP_FAILED), +#endif + yuv_info(MALI_YUV_NO_INFO), + fd(0), + offset(0) +#if GRALLOC_ARM_UMP_MODULE + ,ump_id(UMP_INVALID_SECURE_ID), + ump_mem_handle(UMP_INVALID_MEMORY_HANDLE) +#endif + + + { + version = sizeof(native_handle); + numFds = sNumFds; + numInts = NUM_INTS_IN_PRIVATE_HANDLE; + } + + private_handle_t(int flags, int usage, int size, void *base, int lock_state, int fb_file, off_t fb_offset, int unused): +#if GRALLOC_ARM_DMA_BUF_MODULE + share_fd(-1), +#endif +#if MALI_AFBC_GRALLOC == 1 + share_attr_fd(-1), +#endif +#if GRALLOC_ARM_DMA_BUF_MODULE + ion_hnd(ION_INVALID_HANDLE), +#endif + magic(sMagic), + flags(flags), + usage(usage), + size(size), + width(0), + height(0), + stride(0), + base(base), + lockState(lock_state), + writeOwner(0), + pid(getpid()), +#if MALI_AFBC_GRALLOC == 1 + attr_base(MAP_FAILED), +#endif + yuv_info(MALI_YUV_NO_INFO), + fd(fb_file), + offset(fb_offset) + +#if GRALLOC_ARM_UMP_MODULE + ,ump_id(UMP_INVALID_SECURE_ID), + ump_mem_handle(UMP_INVALID_MEMORY_HANDLE) +#endif + + { + 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 +}; + +#endif /* GRALLOC_PRIV_H_ */ diff --git a/gralloc_vsync.h b/gralloc_vsync.h new file mode 100755 index 0000000..6027eda --- /dev/null +++ b/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/gralloc_vsync_default.cpp b/gralloc_vsync_default.cpp new file mode 100755 index 0000000..3297d05 --- /dev/null +++ b/gralloc_vsync_default.cpp @@ -0,0 +1,58 @@ +/* + * 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) +{ + return 0; +} + +int gralloc_vsync_disable(framebuffer_device_t *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/gralloc_vsync_report.h b/gralloc_vsync_report.h new file mode 100755 index 0000000..9fd5015 --- /dev/null +++ b/gralloc_vsync_report.h @@ -0,0 +1,44 @@ +/* + * 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_ + +#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); + #endif +} + +#ifdef __cplusplus +} +#endif +#endif /* GRALLOC_VSYNC_REPORT_H_ */ diff --git a/gralloc_vsync_s3cfb.cpp b/gralloc_vsync_s3cfb.cpp new file mode 100755 index 0000000..5740ea9 --- /dev/null +++ b/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; +} |