blob: 818e71c4b8fe1363c8d479495b561dda51155491 [file] [log] [blame]
/*
* Copyright (C) 2013 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/fb.h>
#include "gralloc_helper.h"
#include "mali_gralloc_bufferdescriptor.h"
#include "mali_gralloc_bufferallocation.h"
#include "mali_gralloc_reference.h"
#include "mali_gralloc_bufferaccess.h"
/*****************************************************************************/
struct gralloc_context_t {
gralloc1_device_t device;
/* our private data here */
};
typedef struct mali_gralloc_func
{
gralloc1_function_descriptor_t desc;
gralloc1_function_pointer_t func;
} mali_gralloc_func;
/*****************************************************************************/
int fb_device_open(const hw_module_t* module, const char* name, hw_device_t** device);
static int gralloc_close(struct hw_device_t *dev)
{
gralloc_context_t* ctx = reinterpret_cast<gralloc_context_t*>(dev);
if (ctx) {
/* TODO: keep a list of all buffer_handle_t created, and free them
* all here.
*/
free(ctx);
}
return 0;
}
static void mali_gralloc_dump(gralloc1_device_t* device,
uint32_t* outSize, char* outBuffer)
{
GRALLOC_UNUSED(device);
GRALLOC_UNUSED(outSize);
GRALLOC_UNUSED(outBuffer);
}
static int32_t mali_gralloc_create_descriptor(gralloc1_device_t* device,
gralloc1_buffer_descriptor_t* outDescriptor)
{
int ret = 0;
ret = mali_gralloc_create_descriptor_internal(outDescriptor);
GRALLOC_UNUSED(device);
return ret;
}
static int32_t mali_gralloc_destroy_descriptor(gralloc1_device_t* device,
gralloc1_buffer_descriptor_t descriptor)
{
int ret = 0;
ret = mali_gralloc_destroy_descriptor_internal(descriptor);
GRALLOC_UNUSED(device);
return ret;
}
static int32_t mali_gralloc_set_consumer_usage(gralloc1_device_t* device,
gralloc1_buffer_descriptor_t descriptor, /*uint64_t */gralloc1_consumer_usage_t usage)
{
int ret = 0;
ret = mali_gralloc_set_consumerusage_internal(descriptor, usage);
GRALLOC_UNUSED(device);
return ret;
}
static int32_t mali_gralloc_set_dimensions(gralloc1_device_t* device,
gralloc1_buffer_descriptor_t descriptor, uint32_t width, uint32_t height)
{
int ret = 0;
ret = mali_gralloc_set_dimensions_internal(descriptor, width, height);
GRALLOC_UNUSED(device);
return ret;
}
static int32_t mali_gralloc_set_format(gralloc1_device_t* device,
gralloc1_buffer_descriptor_t descriptor, /*int32_t*/ android_pixel_format_t format)
{
int ret = 0;
ret = mali_gralloc_set_format_internal(descriptor, format);
GRALLOC_UNUSED(device);
return ret;
}
static int32_t mali_gralloc_set_producer_usage(gralloc1_device_t* device,
gralloc1_buffer_descriptor_t descriptor, /*uint64_t */gralloc1_producer_usage_t usage)
{
int ret = 0;
ret = mali_gralloc_set_producerusage_internal(descriptor, usage);
GRALLOC_UNUSED(device);
return ret;
}
static int32_t mali_gralloc_get_backing_store(gralloc1_device_t* device,
buffer_handle_t buffer, gralloc1_backing_store_t* outStore)
{
int ret = 0;
ret = mali_gralloc_get_backing_store_internal(buffer, outStore);
GRALLOC_UNUSED(device);
return ret;
}
static int32_t mali_gralloc_get_consumer_usage(gralloc1_device_t* device,
buffer_handle_t buffer, uint64_t* /*gralloc1_consumer_usage_t*/ outUsage)
{
int ret = 0;
ret = mali_gralloc_get_consumer_usage_internal(buffer, outUsage);
GRALLOC_UNUSED(device);
return ret;
}
static int32_t mali_gralloc_get_dimensions(gralloc1_device_t* device,
buffer_handle_t buffer, uint32_t* outWidth, uint32_t* outHeight)
{
int ret = 0;
ret = mali_gralloc_get_dimensions_internal(buffer, outWidth, outHeight);
GRALLOC_UNUSED(device);
return ret;
}
static int32_t mali_gralloc_get_format(gralloc1_device_t* device,
buffer_handle_t buffer, int32_t* outFormat)
{
int ret = 0;
ret = mali_gralloc_get_format_internal(buffer, outFormat);
GRALLOC_UNUSED(device);
return ret;
}
static int32_t mali_gralloc_get_producer_usage(gralloc1_device_t* device,
buffer_handle_t buffer, uint64_t* /*gralloc1_producer_usage_t*/ outUsage)
{
int ret = 0;
ret = mali_gralloc_get_producer_usage_internal(buffer, outUsage);
GRALLOC_UNUSED(device);
return ret;
}
static int32_t mali_gralloc_get_stride(gralloc1_device_t* device,
buffer_handle_t buffer, uint32_t* outStride)
{
GRALLOC_UNUSED(device);
int stride;
if (mali_gralloc_query_getstride(buffer, &stride) < 0)
{
return GRALLOC1_ERROR_UNSUPPORTED;
}
*outStride = (uint32_t)stride;
return GRALLOC1_ERROR_NONE;
}
static int32_t mali_gralloc_allocate(gralloc1_device_t* device,
uint32_t numDescriptors, const gralloc1_buffer_descriptor_t* descriptors,
buffer_handle_t* outBuffers)
{
mali_gralloc_module* m;
m = reinterpret_cast<private_module_t*>(device->common.module);
int format, width, height;
uint64_t usage;
uint32_t layer_count;
if (numDescriptors != 1)
{
return GRALLOC1_ERROR_UNSUPPORTED;
}
buffer_descriptor_t *bufDescriptor = (buffer_descriptor_t *)(*descriptors);
format = bufDescriptor->hal_format;
usage = bufDescriptor->producer_usage | bufDescriptor->consumer_usage;
width = bufDescriptor->width;
height = bufDescriptor->height;
layer_count = bufDescriptor->layerCount;
#if GRALLOC_FB_SWAP_RED_BLUE == 1
/* match the framebuffer format */
if (usage & GRALLOC1_CONSUMER_USAGE_CLIENT_TARGET)
{
#ifdef GRALLOC_16_BITS
format = HAL_PIXEL_FORMAT_RGB_565;
#else
format = HAL_PIXEL_FORMAT_BGRA_8888;
#endif
}
#endif
if(mali_gralloc_buffer_allocate(m, format, bufDescriptor->consumer_usage, bufDescriptor->producer_usage, width, height, layer_count, outBuffers) < 0)
{
ALOGE("Failed to allocate buffer.");
return GRALLOC1_ERROR_NO_RESOURCES;
}
return GRALLOC1_ERROR_NONE;
}
static int32_t mali_gralloc_retain(gralloc1_device_t* device,
buffer_handle_t buffer)
{
mali_gralloc_module* m;
m = reinterpret_cast<private_module_t*>(device->common.module);
if (private_handle_t::validate(buffer) < 0)
{
return GRALLOC1_ERROR_BAD_HANDLE;
}
if (mali_gralloc_reference_retain(m, buffer) < 0)
{
return GRALLOC1_ERROR_NO_RESOURCES;
}
return GRALLOC1_ERROR_NONE;
}
static int32_t mali_gralloc_release(gralloc1_device_t* device,
buffer_handle_t buffer)
{
mali_gralloc_module* m;
m = reinterpret_cast<private_module_t*>(device->common.module);
if (mali_gralloc_reference_release(m, buffer, true) < 0)
{
return GRALLOC1_ERROR_BAD_HANDLE;
}
return GRALLOC1_ERROR_NONE;
}
static int32_t mali_gralloc1_get_num_flex_planes(gralloc1_device_t* device,
buffer_handle_t buffer, uint32_t* outNumPlanes)
{
mali_gralloc_module* m;
m = reinterpret_cast<private_module_t*>(device->common.module);
if (private_handle_t::validate(buffer) < 0)
{
return GRALLOC1_ERROR_BAD_HANDLE;
}
if (mali_gralloc_get_num_flex_planes(m, buffer, outNumPlanes) < 0)
{
return GRALLOC1_ERROR_UNSUPPORTED;
}
return GRALLOC1_ERROR_NONE;
}
static int32_t mali_gralloc1_lock_async(gralloc1_device_t* device,
buffer_handle_t buffer,
uint64_t /*gralloc1_producer_usage_t*/ producerUsage,
uint64_t /*gralloc1_consumer_usage_t*/ consumerUsage,
const gralloc1_rect_t* accessRegion, void** outData,
int32_t acquireFence)
{
mali_gralloc_module* m;
m = reinterpret_cast<private_module_t*>(device->common.module);
if (private_handle_t::validate(buffer) < 0)
{
return GRALLOC1_ERROR_BAD_HANDLE;
}
if (!((producerUsage | consumerUsage) & (GRALLOC1_USAGE_SW_READ_MASK | GRALLOC1_USAGE_SW_WRITE_MASK)))
{
return GRALLOC1_ERROR_BAD_VALUE;
}
if (mali_gralloc_lock_async(m, buffer, producerUsage | consumerUsage, accessRegion->left, accessRegion->top,
accessRegion->width, accessRegion->height, outData, acquireFence) < 0)
{
return GRALLOC1_ERROR_UNSUPPORTED;
}
return GRALLOC1_ERROR_NONE;
}
static int32_t mali_gralloc1_lock_flex_async(gralloc1_device_t* device,
buffer_handle_t buffer,
uint64_t /*gralloc1_producer_usage_t*/ producerUsage,
uint64_t /*gralloc1_consumer_usage_t*/ consumerUsage,
const gralloc1_rect_t* accessRegion,
struct android_flex_layout* outFlexLayout, int32_t acquireFence)
{
mali_gralloc_module* m;
m = reinterpret_cast<private_module_t*>(device->common.module);
if (private_handle_t::validate(buffer) < 0)
{
return GRALLOC1_ERROR_BAD_HANDLE;
}
if (!((producerUsage | consumerUsage) & (GRALLOC1_USAGE_SW_READ_MASK | GRALLOC1_USAGE_SW_WRITE_MASK)))
{
return GRALLOC1_ERROR_BAD_VALUE;
}
if (mali_gralloc_lock_flex_async(m, buffer, producerUsage | consumerUsage, accessRegion->left, accessRegion->top,
accessRegion->width, accessRegion->height, outFlexLayout, acquireFence) < 0)
{
return GRALLOC1_ERROR_UNSUPPORTED;
}
return GRALLOC1_ERROR_NONE;
}
static int32_t mali_gralloc1_unlock_async(gralloc1_device_t* device,
buffer_handle_t buffer, int32_t* outReleaseFence)
{
mali_gralloc_module* m;
m = reinterpret_cast<private_module_t*>(device->common.module);
if (private_handle_t::validate(buffer) < 0)
{
return GRALLOC1_ERROR_BAD_HANDLE;
}
mali_gralloc_unlock_async(m, buffer, outReleaseFence);
return GRALLOC1_ERROR_NONE;
}
static int32_t mali_gralloc1_set_layer_count(gralloc1_device_t* device,
gralloc1_buffer_descriptor_t descriptor,
uint32_t layerCount)
{
int ret = 0;
ret = mali_gralloc_set_layer_count_internal(descriptor, layerCount);
GRALLOC_UNUSED(device);
return ret;
}
static int32_t mali_gralloc1_get_layer_count(gralloc1_device_t* device, buffer_handle_t buffer, uint32_t* outLayerCount)
{
int ret = 0;
ret = mali_gralloc_get_layer_count_internal(buffer, outLayerCount);
GRALLOC_UNUSED(device);
return ret;
}
static const mali_gralloc_func mali_gralloc_func_list[] =
{
{GRALLOC1_FUNCTION_DUMP, (gralloc1_function_pointer_t)mali_gralloc_dump},
{GRALLOC1_FUNCTION_CREATE_DESCRIPTOR, (gralloc1_function_pointer_t)mali_gralloc_create_descriptor},
{GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR, (gralloc1_function_pointer_t)mali_gralloc_destroy_descriptor},
{GRALLOC1_FUNCTION_SET_CONSUMER_USAGE, (gralloc1_function_pointer_t)mali_gralloc_set_consumer_usage},
{GRALLOC1_FUNCTION_SET_DIMENSIONS, (gralloc1_function_pointer_t)mali_gralloc_set_dimensions},
{GRALLOC1_FUNCTION_SET_FORMAT, (gralloc1_function_pointer_t)mali_gralloc_set_format},
{GRALLOC1_FUNCTION_SET_PRODUCER_USAGE, (gralloc1_function_pointer_t)mali_gralloc_set_producer_usage},
{GRALLOC1_FUNCTION_GET_BACKING_STORE, (gralloc1_function_pointer_t)mali_gralloc_get_backing_store},
{GRALLOC1_FUNCTION_GET_CONSUMER_USAGE, (gralloc1_function_pointer_t)mali_gralloc_get_consumer_usage},
{GRALLOC1_FUNCTION_GET_DIMENSIONS, (gralloc1_function_pointer_t)mali_gralloc_get_dimensions},
{GRALLOC1_FUNCTION_GET_FORMAT, (gralloc1_function_pointer_t)mali_gralloc_get_format},
{GRALLOC1_FUNCTION_GET_PRODUCER_USAGE, (gralloc1_function_pointer_t)mali_gralloc_get_producer_usage},
{GRALLOC1_FUNCTION_GET_STRIDE, (gralloc1_function_pointer_t)mali_gralloc_get_stride},
{GRALLOC1_FUNCTION_ALLOCATE, (gralloc1_function_pointer_t)mali_gralloc_allocate},
{GRALLOC1_FUNCTION_RETAIN, (gralloc1_function_pointer_t)mali_gralloc_retain},
{GRALLOC1_FUNCTION_RELEASE, (gralloc1_function_pointer_t)mali_gralloc_release},
{GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES, (gralloc1_function_pointer_t)mali_gralloc1_get_num_flex_planes},
{GRALLOC1_FUNCTION_LOCK, (gralloc1_function_pointer_t)mali_gralloc1_lock_async},
{GRALLOC1_FUNCTION_LOCK_FLEX, (gralloc1_function_pointer_t)mali_gralloc1_lock_flex_async},
{GRALLOC1_FUNCTION_UNLOCK, (gralloc1_function_pointer_t)mali_gralloc1_unlock_async},
{GRALLOC1_FUNCTION_SET_LAYER_COUNT, (gralloc1_function_pointer_t)mali_gralloc1_set_layer_count},
{GRALLOC1_FUNCTION_GET_LAYER_COUNT, (gralloc1_function_pointer_t)mali_gralloc1_get_layer_count},
/* GRALLOC1_FUNCTION_INVALID has to be the last descriptor on the list. */
{GRALLOC1_FUNCTION_INVALID, NULL}
};
static void mali_gralloc_getCapabilities(gralloc1_device_t *dev, uint32_t *outCount, int32_t *outCapabilities)
{
GRALLOC_UNUSED(dev);
if (outCount != NULL)
*outCount = 1;
if (outCapabilities != NULL)
{
*(outCapabilities++) = GRALLOC1_CAPABILITY_LAYERED_BUFFERS;
}
}
static gralloc1_function_pointer_t mali_gralloc_getFunction(gralloc1_device_t *dev, int32_t descriptor)
{
GRALLOC_UNUSED(dev);
uint32_t pos = 0;
while (mali_gralloc_func_list[pos].desc != GRALLOC1_FUNCTION_INVALID)
{
if (mali_gralloc_func_list[pos].desc == descriptor)
{
return mali_gralloc_func_list[pos].func;
}
pos++;
}
return NULL;
}
int mali_gralloc_device_open(hw_module_t const* module, const char* name, hw_device_t** device)
{
int status = -EINVAL;
if (!strncmp(name, GRALLOC_HARDWARE_MODULE_ID, MALI_GRALLOC_HARDWARE_MAX_STR_LEN))
{
gralloc_context_t *dev;
dev = (gralloc_context_t*)malloc(sizeof(*dev));
/* initialize our state here */
memset(dev, 0, sizeof(*dev));
/* initialize the procs */
dev->device.common.tag = HARDWARE_DEVICE_TAG;
dev->device.common.version = 0;
dev->device.common.module = const_cast<hw_module_t*>(module);
dev->device.common.close = gralloc_close;
dev->device.getCapabilities = mali_gralloc_getCapabilities;
dev->device.getFunction = mali_gralloc_getFunction;
private_module_t *p = reinterpret_cast<private_module_t*>(dev->device.common.module);
if (p->ionfd == -1)
p->ionfd = exynos_ion_open();
*device = &dev->device.common;
status = 0;
}
return status;
}
int mali_gralloc_module_device_open(const hw_module_t* module, const char* name,
hw_device_t** device)
{
int status = -EINVAL;
if (!strncmp(name, GRALLOC_HARDWARE_MODULE_ID, MALI_GRALLOC_HARDWARE_MAX_STR_LEN))
{
status = mali_gralloc_device_open(module, name, device);
}
else if(!strncmp(name, GRALLOC_HARDWARE_FB0, MALI_GRALLOC_HARDWARE_MAX_STR_LEN) )
{
status = fb_device_open(module, name, device);
}
return status;
}
/*****************************************************************************/
static struct hw_module_methods_t mali_gralloc_module_methods = {
mali_gralloc_module_device_open
};
// There is one global instance of the module
struct private_module_t HAL_MODULE_INFO_SYM = {
// gralloc1_module_t
.base = {
// hw_module_t
.common = {
.tag = HARDWARE_MODULE_TAG,
.module_api_version = GRALLOC_MODULE_API_VERSION_1_0,
.hal_api_version = 0,
.id = GRALLOC_HARDWARE_MODULE_ID,
.name = "Graphics Memory Allocator Module",
.author = "ARM Ltd.",
.methods = &mali_gralloc_module_methods,
},
},
.framebuffer = 0,
.flags = 0,
.numBuffers = 0,
.bufferMask = 0,
.lock = PTHREAD_MUTEX_INITIALIZER,
.currentBuffer = 0,
.ionfd = -1,
};