diff options
author | Vishal Bhoj <vishal.bhoj@linaro.org> | 2015-12-07 01:36:32 +0530 |
---|---|---|
committer | Vishal Bhoj <vishal.bhoj@linaro.org> | 2015-12-07 01:36:32 +0530 |
commit | 78e9049cf98bd4d6fab6e0a4ce76a83f61a82426 (patch) | |
tree | 156c8a540461b880630a33128dc0b68b126e3675 | |
parent | f7507c4f56bf138632dc892c8c1d47ec188e42c2 (diff) | |
download | hikey-78e9049cf98bd4d6fab6e0a4ce76a83f61a82426.tar.gz |
Include gralloc sources
Change-Id: I1c77c89ea568ca69732b507ebab9f1696dec9398
Signed-off-by: Vishal Bhoj <vishal.bhoj@linaro.org>
-rw-r--r-- | device.mk | 4 | ||||
-rw-r--r-- | gralloc/Android.mk | 55 | ||||
-rw-r--r-- | gralloc/alloc_device.cpp | 656 | ||||
-rw-r--r-- | gralloc/alloc_device.h | 35 | ||||
-rw-r--r-- | gralloc/framebuffer_device.cpp | 504 | ||||
-rw-r--r-- | gralloc/framebuffer_device.h | 25 | ||||
-rw-r--r-- | gralloc/gralloc_helper.h | 29 | ||||
-rw-r--r-- | gralloc/gralloc_module.cpp | 385 | ||||
-rw-r--r-- | gralloc/gralloc_priv.h | 337 | ||||
-rw-r--r-- | gralloc/gralloc_vsync_report.h | 41 |
10 files changed, 2069 insertions, 2 deletions
@@ -49,10 +49,10 @@ PRODUCT_PACKAGES += audio.a2dp.default # Include USB speed switch App PRODUCT_PACKAGES += UsbSpeedSwitch -# Build libion for new double-buffering HDLCD driver +# Build libion PRODUCT_PACKAGES += libion -# Build gralloc for Juno +# Build gralloc for hikey PRODUCT_PACKAGES += gralloc.hikey # Set zygote config diff --git a/gralloc/Android.mk b/gralloc/Android.mk new file mode 100644 index 00000000..7dcec5c6 --- /dev/null +++ b/gralloc/Android.mk @@ -0,0 +1,55 @@ +# +# 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) + +# HAL module implemenation, not prelinked and stored in +# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so +include $(CLEAR_VARS) +LOCAL_PRELINK_MODULE := false + +ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 21 && echo OK),OK) + LOCAL_MODULE_RELATIVE_PATH := hw +else + LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +endif + +MALI_DDK_TEST_PATH := hardware/arm/ + +LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM) +#LOCAL_MODULE_TAGS := optional + +# Mali-200/300/400MP DDK +MALI_DDK_PATH := hardware/arm/mali +#SHARED_MEM_LIBS := libUMP +SHARED_MEM_LIBS := libion libhardware +LOCAL_SHARED_LIBRARIES := liblog libcutils libGLESv1_CM $(SHARED_MEM_LIBS) + +LOCAL_C_INCLUDES := system/core/include/ $(MALI_DDK_PATH)/include +# Include the UMP header files +# LOCAL_C_INCLUDES += $(MALI_DDK_PATH)/src/ump/include + +LOCAL_CFLAGS := -DLOG_TAG=\"gralloc\" -DGRALLOC_32_BITS -DSTANDARD_LINUX_SCREEN -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION) + +LOCAL_SRC_FILES := \ + gralloc_module.cpp \ + alloc_device.cpp \ + framebuffer_device.cpp + +#LOCAL_CFLAGS+= -DMALI_VSYNC_EVENT_REPORT_ENABLE +include $(BUILD_SHARED_LIBRARY) diff --git a/gralloc/alloc_device.cpp b/gralloc/alloc_device.cpp new file mode 100644 index 00000000..3ef099f2 --- /dev/null +++ b/gralloc/alloc_device.cpp @@ -0,0 +1,656 @@ +/* + * 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" + +#if GRALLOC_ARM_UMP_MODULE +#include <ump/ump.h> +#include <ump/ump_ref_drv.h> +#endif + +#if GRALLOC_ARM_DMA_BUF_MODULE +#include <linux/ion.h> +#include <ion/ion.h> +#endif + +#define GRALLOC_ALIGN( value, base ) (((value) + ((base) - 1)) & ~((base) - 1)) + + +#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 + + +static int gralloc_alloc_buffer(alloc_device_t *dev, size_t size, int usage, buffer_handle_t *pHandle) +{ +#if GRALLOC_ARM_DMA_BUF_MODULE + { + private_module_t *m = reinterpret_cast<private_module_t *>(dev->common.module); + ion_user_handle_t ion_hnd; + unsigned char *cpu_ptr; + int shared_fd; + int ret; + + ret = ion_alloc(m->ion_client, size, 0, ION_HEAP_SYSTEM_MASK, 0, &(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; + } + + 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; + } + + private_handle_t *hnd = new private_handle_t(private_handle_t::PRIV_FLAGS_USES_ION, usage, size, cpu_ptr, private_handle_t::LOCK_STATE_MAPPED); + + 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); + ret = munmap(cpu_ptr, size); + + if (0 != ret) + { + AERR("munmap failed for base:%p size: %lu", cpu_ptr, (unsigned long)size); + } + + ret = ion_free(m->ion_client, ion_hnd); + + if (0 != ret) + { + AERR("ion_free( %d ) failed", m->ion_client); + } + + return -1; + } +#endif + +#if GRALLOC_ARM_UMP_MODULE + MALI_IGNORE(dev); + { + 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 + { + 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); + } + } + + return -1; + } +#endif + +} + +static int gralloc_alloc_framebuffer_locked(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); + + // 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; + const size_t bufferSize = m->finfo.line_length * m->info.yres; + + 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; + AERR("fallback to single buffering. Virtual Y-res too small %d", m->info.yres); + return gralloc_alloc_buffer(dev, bufferSize, newUsage, pHandle); + } + + if (bufferMask >= ((1LU << numBuffers) - 1)) + { + // We ran out of buffers. + return -ENOMEM; + } + + void *vaddr = 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; + } + + vaddr = (void *)((uintptr_t)vaddr + bufferSize); + } + + // 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, vaddr, + 0, dup(m->framebuffer->fd), (uintptr_t)vaddr - (uintptr_t) m->framebuffer->base); +#if GRALLOC_ARM_UMP_MODULE + 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 = (int)ump_handle_create_from_secure_id(hnd->ump_id); + + if ((int)UMP_INVALID_MEMORY_HANDLE == hnd->ump_mem_handle) + { + AINF("warning: unable to create UMP handle from secure ID %i\n", hnd->ump_id); + } + } + +#endif + +#if GRALLOC_ARM_DMA_BUF_MODULE + { +#ifdef FBIOGET_DMABUF + struct fb_dmabuf_export fb_dma_buf; + + if (ioctl(m->framebuffer->fd, FBIOGET_DMABUF, &fb_dma_buf) == 0) + { + AINF("framebuffer accessed with dma buf (fd 0x%x)\n", (int)fb_dma_buf.fd); + hnd->share_fd = fb_dma_buf.fd; + } + +#endif + } +#endif + + *pHandle = hnd; + + return 0; +} + +static int gralloc_alloc_framebuffer(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); + pthread_mutex_lock(&m->lock); + int err = gralloc_alloc_framebuffer_locked(dev, size, usage, pHandle); + pthread_mutex_unlock(&m->lock); + return err; +} + +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_t stride; + + if (format == HAL_PIXEL_FORMAT_YCrCb_420_SP || format == HAL_PIXEL_FORMAT_YV12 + /* HAL_PIXEL_FORMAT_YCbCr_420_SP, HAL_PIXEL_FORMAT_YCbCr_420_P, HAL_PIXEL_FORMAT_YCbCr_422_I are not defined in Android. + * To enable Mali DDK EGLImage support for those formats, firstly, you have to add them in Android system/core/include/system/graphics.h. + * Then, define SUPPORT_LEGACY_FORMAT in the same header file(Mali DDK will also check this definition). + */ +#ifdef SUPPORT_LEGACY_FORMAT + || format == HAL_PIXEL_FORMAT_YCbCr_420_SP || format == HAL_PIXEL_FORMAT_YCbCr_420_P || format == HAL_PIXEL_FORMAT_YCbCr_422_I +#endif + ) + { + switch (format) + { + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + stride = GRALLOC_ALIGN(w, 16); + size = GRALLOC_ALIGN(h, 16) * (stride + GRALLOC_ALIGN(stride / 2, 16)); + break; + + case HAL_PIXEL_FORMAT_YV12: +#ifdef SUPPORT_LEGACY_FORMAT + case HAL_PIXEL_FORMAT_YCbCr_420_P: +#endif + stride = GRALLOC_ALIGN(w, 16); + size = GRALLOC_ALIGN(h, 2) * (stride + GRALLOC_ALIGN(stride / 2, 16)); + + break; +#ifdef SUPPORT_LEGACY_FORMAT + + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + stride = GRALLOC_ALIGN(w, 16); + size = GRALLOC_ALIGN(h, 16) * (stride + GRALLOC_ALIGN(stride / 2, 16)); + break; + + case HAL_PIXEL_FORMAT_YCbCr_422_I: + stride = GRALLOC_ALIGN(w, 16); + size = h * stride * 2; + + break; +#endif + + default: + return -EINVAL; + } + } + else + { + int bpp = 0; + + switch (format) + { + case HAL_PIXEL_FORMAT_RGBA_8888: + case HAL_PIXEL_FORMAT_RGBX_8888: + case HAL_PIXEL_FORMAT_BGRA_8888: + bpp = 4; + break; + + case HAL_PIXEL_FORMAT_RGB_888: + bpp = 3; + 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 + bpp = 2; + break; + + default: + return -EINVAL; + } + + size_t bpr = GRALLOC_ALIGN(w * bpp, 64); + size = bpr * h; + stride = bpr / bpp; + } + + int err; + +#ifndef MALI_600 + + if (usage & GRALLOC_USAGE_HW_FB) + { + err = gralloc_alloc_framebuffer(dev, size, usage, pHandle); + } + else +#endif + + { + err = gralloc_alloc_buffer(dev, size, usage, pHandle); + } + + if (err < 0) + { + return err; + } + + /* 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 + } + + private_handle_t *hnd = (private_handle_t *)*pHandle; + 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->format = format; + hnd->stride = stride; + + *pStride = 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); + + 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 GRALLOC_ARM_UMP_MODULE + + if ((int)UMP_INVALID_MEMORY_HANDLE != hnd->ump_mem_handle) + { + ump_reference_release((ump_handle)hnd->ump_mem_handle); + } + +#endif + } + else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) + { +#if GRALLOC_ARM_UMP_MODULE + + /* Buffer might be unregistered so we need to check for invalid ump handle*/ + if ((int)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 + AERR("Can't free ump memory for handle:0x%p. Not supported.", hnd); +#endif + } + else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) + { +#if GRALLOC_ARM_DMA_BUF_MODULE + private_module_t *m = reinterpret_cast<private_module_t *>(dev->common.module); + + /* Buffer might be unregistered so we need to check for invalid ump handle*/ + if (0 != hnd->base) + { + if (0 != munmap((void *)hnd->base, hnd->size)) + { + AERR("Failed to munmap handle 0x%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, (void *)(uintptr_t)hnd->ion_hnd); + } + + memset((void *)hnd, 0, sizeof(*hnd)); +#else + AERR("Can't free dma_buf memory for handle:0x%x. Not supported.", (unsigned int)hnd); +#endif + + } + + delete hnd; + + return 0; +} + +static int alloc_device_close(struct hw_device_t *device) +{ + alloc_device_t *dev = reinterpret_cast<alloc_device_t *>(device); + + if (dev) + { +#if GRALLOC_ARM_DMA_BUF_MODULE + private_module_t *m = reinterpret_cast<private_module_t *>(device); + + if (0 != ion_close(m->ion_client)) + { + AERR("Failed to close ion_client: %d", m->ion_client); + } + + close(m->ion_client); +#endif + delete dev; +#if GRALLOC_ARM_UMP_MODULE + ump_close(); // Our UMP memory refs will be released automatically here... +#endif + } + + return 0; +} + +int alloc_device_open(hw_module_t const *module, const char *name, hw_device_t **device) +{ + MALI_IGNORE(name); + alloc_device_t *dev; + + dev = new alloc_device_t; + + if (NULL == dev) + { + return -1; + } + +#if GRALLOC_ARM_UMP_MODULE + ump_result ump_res = ump_open(); + + if (UMP_OK != ump_res) + { + AERR("UMP open failed with %d", ump_res); + delete dev; + return -1; + } + +#endif + + /* 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_device_close; + dev->alloc = alloc_device_alloc; + dev->free = alloc_device_free; + +#if GRALLOC_ARM_DMA_BUF_MODULE + 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)); + delete dev; + return -1; + } + +#endif + + *device = &dev->common; + + return 0; +} diff --git a/gralloc/alloc_device.h b/gralloc/alloc_device.h new file mode 100644 index 00000000..534a0d68 --- /dev/null +++ b/gralloc/alloc_device.h @@ -0,0 +1,35 @@ +/* + * 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 + +// Create an alloc device +int alloc_device_open(hw_module_t const *module, const char *name, hw_device_t **device); diff --git a/gralloc/framebuffer_device.cpp b/gralloc/framebuffer_device.cpp new file mode 100644 index 00000000..48e58f8d --- /dev/null +++ b/gralloc/framebuffer_device.cpp @@ -0,0 +1,504 @@ +/* + * 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 <sys/ioctl.h> +#include <linux/fb.h> +#include <stdlib.h> +#include <cutils/log.h> +#include <cutils/atomic.h> +#include <hardware/hardware.h> +#include <hardware/gralloc.h> + +#include <GLES/gl.h> + +#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE +#include "gralloc_vsync_report.h" +#endif + +#include "alloc_device.h" +#include "gralloc_priv.h" +#include "gralloc_helper.h" + +// numbers of buffers for page flipping +#define NUM_BUFFERS NUM_FB_BUFFERS + +static int swapInterval = 1; + +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; + } + + swapInterval = interval; + + 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 +#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) +#define S3CFB_SET_VSYNC_INT _IOW('F', 206, unsigned int) + + 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 0; + } + + if (swapInterval == 1) + { + // enable VSYNC + interrupt = 1; + + if (ioctl(m->framebuffer->fd, S3CFB_SET_VSYNC_INT, &interrupt) < 0) + { + // AERR("S3CFB_SET_VSYNC_INT enable failed for fd: %d", m->framebuffer->fd); + return 0; + } + + // wait for VSYNC +#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE + gralloc_mali_vsync_report(MALI_VSYNC_EVENT_BEGIN_WAIT); +#endif + int crtc = 0; + + if (ioctl(m->framebuffer->fd, FBIO_WAITFORVSYNC, &crtc) < 0) + { + AERR("FBIO_WAITFORVSYNC failed for fd: %d", m->framebuffer->fd); +#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE + gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT); +#endif + return 0; + } + +#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE + gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT); +#endif + // disable VSYNC + interrupt = 0; + + if (ioctl(m->framebuffer->fd, S3CFB_SET_VSYNC_INT, &interrupt) < 0) + { + AERR("S3CFB_SET_VSYNC_INT disable failed for fd: %d", m->framebuffer->fd); + return 0; + } + } + +#else + /*Standard Android way*/ +#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE + gralloc_mali_vsync_report(MALI_VSYNC_EVENT_BEGIN_WAIT); +#endif + + if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) + { + AERR("FBIOPUT_VSCREENINFO failed for fd: %d", m->framebuffer->fd); +#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE + gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT); +#endif + m->base.unlock(&m->base, buffer); + return -errno; + } + +#ifdef MALI_VSYNC_EVENT_REPORT_ENABLE + gralloc_mali_vsync_report(MALI_VSYNC_EVENT_END_WAIT); +#endif +#endif + + 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); + + memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres); + + 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 = 0; + info.red.length = 8; + info.green.offset = 8; + info.green.length = 8; + info.blue.offset = 16; + info.blue.length = 8; + info.transp.offset = 24; + info.transp.length = 8; +#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 (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; + + /* + * 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, 0, fbSize, vaddr, + 0, dup(fd), 0); + + module->numBuffers = info.yres_virtual / info.yres; + module->bufferMask = 0; + +#if GRALLOC_ARM_UMP_MODULE +#ifdef IOCTL_GET_FB_UMP_SECURE_ID + ioctl(fd, IOCTL_GET_FB_UMP_SECURE_ID, &module->framebuffer->ump_id); +#endif + + if ((int)UMP_INVALID_SECURE_ID != module->framebuffer->ump_id) + { + AINF("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 + delete dev; + } + + return 0; +} + +int compositionComplete(struct framebuffer_device_t *dev) +{ + MALI_IGNORE(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; + status = gralloc_open(module, &gralloc_device); + + if (status < 0) + { + return status; + } + + private_module_t *m = (private_module_t *)module; + status = init_frame_buffer(m); + + if (status < 0) + { + gralloc_close(gralloc_device); + return status; + } + + /* initialize our state here */ + framebuffer_device_t *dev = (framebuffer_device_t*)malloc(sizeof(framebuffer_device_t)); + 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_RGBA_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; + status = 0; + + MALI_IGNORE(name); + return status; +} diff --git a/gralloc/framebuffer_device.h b/gralloc/framebuffer_device.h new file mode 100644 index 00000000..528e65c6 --- /dev/null +++ b/gralloc/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/gralloc_helper.h b/gralloc/gralloc_helper.h new file mode 100644 index 00000000..c8378f81 --- /dev/null +++ b/gralloc/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/gralloc_module.cpp b/gralloc/gralloc_module.cpp new file mode 100644 index 00000000..6dcba157 --- /dev/null +++ b/gralloc/gralloc_module.cpp @@ -0,0 +1,385 @@ +/* + * 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" + +#if GRALLOC_ARM_UMP_MODULE +#include <ump/ump_ref_drv.h> +static int s_ump_is_open = 0; +#endif + +#if GRALLOC_ARM_DMA_BUF_MODULE +#include <linux/ion.h> +#include <ion/ion.h> +#include <sys/mman.h> +#endif + +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) +{ + MALI_IGNORE(module); + + if (private_handle_t::validate(handle) < 0) + { + AERR("Registering invalid buffer 0x%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; + + int retval = -EINVAL; + + pthread_mutex_lock(&s_map_lock); + +#if GRALLOC_ARM_UMP_MODULE + + 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) + { + pthread_mutex_unlock(&s_map_lock); + AERR("Failed to open UMP library with res=%d", res); + return retval; + } + + s_ump_is_open = 1; + } + +#endif + + hnd->pid = getpid(); + + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) + { + AERR("Can't register buffer 0x%p as it is a framebuffer", handle); + } + else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) + { +#if GRALLOC_ARM_UMP_MODULE + hnd->ump_mem_handle = (int)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((ump_handle)hnd->ump_mem_handle); + + if (0 != hnd->base) + { + hnd->lockState = private_handle_t::LOCK_STATE_MAPPED; + hnd->writeOwner = 0; + hnd->lockState = 0; + + pthread_mutex_unlock(&s_map_lock); + return 0; + } + else + { + AERR("Failed to map UMP handle 0x%x", hnd->ump_mem_handle); + } + + ump_reference_release((ump_handle)hnd->ump_mem_handle); + } + else + { + AERR("Failed to create UMP handle 0x%x", hnd->ump_mem_handle); + } + +#else + AERR("Gralloc does not support UMP. Unable to register UMP memory for handle 0x%p", hnd); +#endif + } + else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) + { +#if GRALLOC_ARM_DMA_BUF_MODULE + int ret; + 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: 0x%p", hnd); + retval = -errno; + goto cleanup; + } + + /* 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: 0x%p", hnd); + retval = -errno; + goto cleanup; + } + } + + 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; + goto cleanup; + } + + hnd->base = mappedAddress + hnd->offset; + pthread_mutex_unlock(&s_map_lock); + return 0; +#endif + } + else + { + AERR("registering non-UMP buffer not supported. flags = %d", hnd->flags); + } + +cleanup: + pthread_mutex_unlock(&s_map_lock); + return retval; +} + +static int gralloc_unregister_buffer(gralloc_module_t const *module, buffer_handle_t handle) +{ + MALI_IGNORE(module); + + if (private_handle_t::validate(handle) < 0) + { + AERR("unregistering invalid buffer 0x%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 0x%p as it is a framebuffer", handle); + } + else if (hnd->pid == getpid()) // never unmap buffers that were not registered in this process + { + pthread_mutex_lock(&s_map_lock); + + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP) + { +#if GRALLOC_ARM_UMP_MODULE + ump_mapped_pointer_release((ump_handle)hnd->ump_mem_handle); + ump_reference_release((ump_handle)hnd->ump_mem_handle); + hnd->ump_mem_handle = (int)UMP_INVALID_MEMORY_HANDLE; +#else + AERR("Can't unregister UMP buffer for handle 0x%p. Not supported", handle); +#endif + } + else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION) + { +#if GRALLOC_ARM_DMA_BUF_MODULE + void *base = (void *)hnd->base; + size_t size = hnd->size; + + if (munmap(base, size) < 0) + { + AERR("Could not munmap base:0x%p size:%lu '%s'", base, (unsigned long)size, strerror(errno)); + } + +#else + AERR("Can't unregister DMA_BUF buffer for hnd %p. Not supported", hnd); +#endif + + } + else + { + AERR("Unregistering unknown buffer is not supported. Flags = %d", hnd->flags); + } + + hnd->base = 0; + hnd->lockState = 0; + hnd->writeOwner = 0; + + pthread_mutex_unlock(&s_map_lock); + } + else + { + AERR("Trying to unregister buffer 0x%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 0x%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; + } + + MALI_IGNORE(module); + MALI_IGNORE(l); + MALI_IGNORE(t); + MALI_IGNORE(w); + MALI_IGNORE(h); + return 0; +} + +static int gralloc_unlock(gralloc_module_t const *module, buffer_handle_t handle) +{ + MALI_IGNORE(module); + + if (private_handle_t::validate(handle) < 0) + { + AERR("Unlocking invalid buffer 0x%p, returning error", handle); + return -EINVAL; + } + + private_handle_t *hnd = (private_handle_t *)handle; + int32_t current_value; + int32_t new_value; + int retry; + + if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_UMP && hnd->writeOwner) + { +#if GRALLOC_ARM_UMP_MODULE + ump_cpu_msync_now((ump_handle)hnd->ump_mem_handle, UMP_MSYNC_CLEAN_AND_INVALIDATE, (void *)hnd->base, hnd->size); +#else + AERR("Buffer 0x%p is UMP type but it is not supported", hnd); +#endif + } + else if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_ION && hnd->writeOwner) + { +#if GRALLOC_ARM_DMA_BUF_MODULE + 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("Couldnot get gralloc module for handle 0x%p\n", handle); + } + +#endif + } + + 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; + +#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/gralloc_priv.h b/gralloc/gralloc_priv.h new file mode 100644 index 00000000..7b33ae28 --- /dev/null +++ b/gralloc/gralloc_priv.h @@ -0,0 +1,337 @@ +/* + * 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 <hardware/gralloc.h> +#include <cutils/native_handle.h> +#include <alloc_device.h> +#include <utils/Log.h> + +#ifdef MALI_600 +#define GRALLOC_ARM_UMP_MODULE 0 +#define GRALLOC_ARM_DMA_BUF_MODULE 1 +#else + +/* 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. + */ + +/*#define IOCTL_GET_FB_UMP_SECURE_ID _IOR('F', 311, unsigned int)*/ +#define GRALLOC_ARM_UMP_MODULE 0 +#define GRALLOC_ARM_DMA_BUF_MODULE 1 + +/* 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)*/ + +#if PLATFORM_SDK_VERSION >= 21 +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 /* new libion */ + +#endif /* GRALLOC_ARM_DMA_BUF_MODULE */ + + +#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 + +#if GRALLOC_ARM_UMP_MODULE +#include <ump/ump.h> +#endif + +#define MALI_IGNORE(x) (void)x +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; + +struct private_handle_t; + +struct private_module_t +{ + gralloc_module_t base; + + private_handle_t *framebuffer; + uint32_t flags; + uint32_t numBuffers; + uint32_t bufferMask; + pthread_mutex_t lock; + buffer_handle_t currentBuffer; + int ion_client; + + struct fb_var_screeninfo info; + struct fb_fix_screeninfo finfo; + float xdpi; + float ydpi; + float fps; + + enum + { + // flag to indicate we'll post this buffer + PRIV_USAGE_LOCKED_FOR_POST = 0x80000000 + }; + + /* default constructor */ + private_module_t(); +}; + +#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 + }; + + // ints +#if GRALLOC_ARM_DMA_BUF_MODULE + /*shared file descriptor for dma_buf sharing*/ + int share_fd; +#endif + int magic; + int flags; + int usage; + int size; + int width; + int height; + int format; + int stride; + union + { + void *base; + uint64_t padding; + }; + int lockState; + int writeOwner; + int pid; + + mali_gralloc_yuv_info yuv_info; + + // Following members are for UMP memory only +#if GRALLOC_ARM_UMP_MODULE + int ump_id; + int ump_mem_handle; +#endif + + // Following members is for framebuffer only + int fd; + int offset; + +#if GRALLOC_ARM_DMA_BUF_MODULE + ion_user_handle_t ion_hnd; +#endif + +#if GRALLOC_ARM_DMA_BUF_MODULE +#define GRALLOC_ARM_NUM_FDS 1 +#else +#define GRALLOC_ARM_NUM_FDS 0 +#endif + +#ifdef __cplusplus + 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 GRALLOC_ARM_DMA_BUF_MODULE + share_fd(-1), +#endif + magic(sMagic), + flags(flags), + usage(usage), + size(size), + width(0), + height(0), + format(0), + stride(0), + base(base), + lockState(lock_state), + writeOwner(0), + pid(getpid()), + yuv_info(MALI_YUV_NO_INFO), + ump_id((int)secure_id), + ump_mem_handle((int)handle), + fd(0), + offset(0) +#if GRALLOC_ARM_DMA_BUF_MODULE + , + ion_hnd(ION_INVALID_HANDLE) +#endif + + { + version = sizeof(native_handle); + numFds = sNumFds; + numInts = (sizeof(private_handle_t) - sizeof(native_handle)) / sizeof(int) - sNumFds; + } +#endif + +#if GRALLOC_ARM_DMA_BUF_MODULE + private_handle_t(int flags, int usage, int size, void *base, int lock_state): + share_fd(-1), + magic(sMagic), + flags(flags), + usage(usage), + size(size), + width(0), + height(0), + format(0), + stride(0), + base(base), + lockState(lock_state), + writeOwner(0), + pid(getpid()), + yuv_info(MALI_YUV_NO_INFO), +#if GRALLOC_ARM_UMP_MODULE + ump_id((int)UMP_INVALID_SECURE_ID), + ump_mem_handle((int)UMP_INVALID_MEMORY_HANDLE), +#endif + fd(0), + offset(0), + ion_hnd(ION_INVALID_HANDLE) + + { + version = sizeof(native_handle); + numFds = sNumFds; + numInts = (sizeof(private_handle_t) - sizeof(native_handle)) / sizeof(int) - sNumFds; + } + +#endif + + private_handle_t(int flags, int usage, int size, void *base, int lock_state, int fb_file, int fb_offset): +#if GRALLOC_ARM_DMA_BUF_MODULE + share_fd(-1), +#endif + magic(sMagic), + flags(flags), + usage(usage), + size(size), + width(0), + height(0), + format(0), + stride(0), + base(base), + lockState(lock_state), + writeOwner(0), + pid(getpid()), + yuv_info(MALI_YUV_NO_INFO), +#if GRALLOC_ARM_UMP_MODULE + ump_id((int)UMP_INVALID_SECURE_ID), + ump_mem_handle((int)UMP_INVALID_MEMORY_HANDLE), +#endif + fd(fb_file), + offset(fb_offset) +#if GRALLOC_ARM_DMA_BUF_MODULE + , + ion_hnd(ION_INVALID_HANDLE) +#endif + + { + version = sizeof(native_handle); + numFds = sNumFds; + numInts = (sizeof(private_handle_t) - sizeof(native_handle)) / sizeof(int) - sNumFds; + } + + ~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->numFds != sNumFds || + h->numInts != (sizeof(private_handle_t) - sizeof(native_handle)) / sizeof(int) - 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/gralloc_vsync_report.h b/gralloc/gralloc_vsync_report.h new file mode 100644 index 00000000..fde0f2d4 --- /dev/null +++ b/gralloc/gralloc_vsync_report.h @@ -0,0 +1,41 @@ +/* + * 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) +{ + _mali_base_arch_vsync_event_report(event); +} + +#ifdef __cplusplus +} +#endif +#endif /* GRALLOC_VSYNC_REPORT_H_ */ |