blob: c50683d305841255eb3b9205804bd146b90df4e7 [file] [log] [blame]
/*
* Copyright (C) 2016, 2018-2019 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 <inttypes.h>
#include <hardware/hardware.h>
#include <hardware/gralloc1.h>
#include "mali_gralloc_module.h"
#include "mali_gralloc_private_interface.h"
#include "mali_gralloc_buffer.h"
#include "mali_gralloc_ion.h"
#include "mali_gralloc_bufferdescriptor.h"
#include "mali_gralloc_bufferallocation.h"
#include "mali_gralloc_reference.h"
#include "mali_gralloc_bufferaccess.h"
#include "framebuffer_device.h"
#include "gralloc_buffer_priv.h"
#include "mali_gralloc_debug.h"
typedef struct mali_gralloc_func
{
gralloc1_function_descriptor_t desc;
gralloc1_function_pointer_t func;
} mali_gralloc_func;
static void mali_gralloc_dump(gralloc1_device_t *device, uint32_t *outSize, char *outBuffer)
{
if (NULL == outSize)
{
ALOGE("Invalid pointer to outSize and return");
return;
}
mali_gralloc_dump_internal(outSize, outBuffer);
GRALLOC_UNUSED(device);
}
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;
const int ret = mali_gralloc_query_getstride(buffer, &stride);
if (ret == GRALLOC1_ERROR_NONE)
{
*outStride = (uint32_t)stride;
}
return ret;
}
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);
buffer_descriptor_t *bufDescriptor = (buffer_descriptor_t *)(*descriptors);
uint64_t usage;
bool shared = false;
/* Initialise output parameters. */
for (uint32_t i = 0; i < numDescriptors; i++)
{
outBuffers[i] = NULL;
}
usage = bufDescriptor->producer_usage | bufDescriptor->consumer_usage;
#if DISABLE_FRAMEBUFFER_HAL != 1
if (usage & GRALLOC_USAGE_HW_FB)
{
if (mali_gralloc_fb_allocate(m, bufDescriptor, outBuffers) < 0)
{
return GRALLOC1_ERROR_NO_RESOURCES;
}
}
else
#endif
{
if (mali_gralloc_buffer_allocate(m, (gralloc_buffer_descriptor_t *)descriptors, numDescriptors, outBuffers,
&shared) < 0)
{
ALOGE("Failed to allocate buffer.");
return GRALLOC1_ERROR_NO_RESOURCES;
}
if (!shared && 1 != numDescriptors)
{
return GRALLOC1_ERROR_NOT_SHARED;
}
}
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;
}
/*
* Returns the number of flex layout planes which are needed to represent the
* given buffer.
*
* @param device [in] Gralloc device.
* @param buffer [in] The buffer handle for which the number of planes should be queried
* @param outNumPlanes [out] The number of flex planes required to describe the given buffer
*
* @return GRALLOC1_ERROR_NONE - The locking is successful;
* GRALLOC1_ERROR_BAD_HANDLE - The buffer handle is invalid
* GRALLOC1_ERROR_BAD_VALUE - The flex plane pointer is invalid
* Appropriate error, otherwise
*/
static int32_t mali_gralloc1_get_num_flex_planes(const gralloc1_device_t * const device,
const buffer_handle_t buffer,
uint32_t * const outNumPlanes)
{
mali_gralloc_module *m;
m = reinterpret_cast<private_module_t *>(device->common.module);
if (private_handle_t::validate(buffer) < 0)
{
AERR("Invalid buffer handle");
return GRALLOC1_ERROR_BAD_HANDLE;
}
if (outNumPlanes == NULL)
{
AERR("Invalid flex plane pointer");
return GRALLOC1_ERROR_BAD_VALUE;
}
int status = mali_gralloc_get_num_flex_planes(m, buffer, outNumPlanes);
if (status != 0)
{
return status;
}
return GRALLOC1_ERROR_NONE;
}
/*
* Locks the Gralloc 1.0 buffer for the specified CPU usage.
*
* @param device [in] Gralloc1 device.
* @param buffer [in] The buffer to lock.
* @param producerUsage [in] The producer usage flags to request (gralloc1_producer_usage_t).
* @param consumerUsage [in] The consumer usage flags to request (gralloc1_consumer_usage_t).
* @param accessRegion [in] The portion of the buffer that the client
* intends to access.
* @param outData [out] To be filled with a CPU-accessible pointer to
* the buffer data for CPU usage.
* @param acquireFence [in] Refers to an acquire sync fence object.
*
* @return GRALLOC1_ERROR_NONE, when locking is successful;
* appropriate error, otherwise
*
* @Notes: Locking a buffer simultaneously for write or read/write leaves the
* buffer's content into an indeterminate state.
*/
static int32_t mali_gralloc1_lock_async(gralloc1_device_t *device,
buffer_handle_t buffer,
uint64_t producerUsage,
uint64_t consumerUsage,
const gralloc1_rect_t *accessRegion,
void **outData,
int32_t acquireFence)
{
int status = 0;
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 (accessRegion == NULL)
{
return GRALLOC1_ERROR_BAD_VALUE;
}
/* The lock usage constraints
* 1. Exactly one of producerUsage and consumerUsage must be *_USAGE_NONE.
* 2. The usage which is not *_USAGE_NONE must be one of the *_USAGE_CPU_*
* as applicable.
* are relaxed to accommodate an issue in shims with regard to lock usage mapping.
*/
//if (!((producerUsage | consumerUsage) & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)))
//{
// return GRALLOC1_ERROR_BAD_VALUE;
//}
status = mali_gralloc_lock_async(m, buffer, producerUsage | consumerUsage,
accessRegion->left, accessRegion->top,
accessRegion->width, accessRegion->height,
outData, acquireFence);
if (status != 0)
{
if (status == -EINVAL)
{
return GRALLOC1_ERROR_BAD_VALUE;
}
return GRALLOC1_ERROR_UNSUPPORTED;
}
return GRALLOC1_ERROR_NONE;
}
/*
* Locks the Gralloc 1.0 buffer, for the specified CPU usage, asynchronously.
*
* @param device [in] Gralloc1 device.
* @param buffer [in] The buffer to lock.
* @param producerUsage [in] The producer usage flags requested (gralloc1_producer_usage_t).
* @param consumerUsage [in] The consumer usage flags requested (gralloc1_consumer_usage_t).
* @param accessRegion [in] The portion of the buffer that the client
* intends to access.
* @param outFlexLayout [out] To be filled with the description of the planes
* in the buffer
* @param acquireFence [in] Refers to an acquire sync fence object.
*
* @return GRALLOC1_ERROR_NONE - Locking is successful;
* GRALLOC1_ERROR_BAD_HANDLE - Invalid buffer handle
* GRALLOC1_ERROR_BAD_VALUE - Invalid usage parameters
* GRALLOC1_ERROR_UNSUPPORTED - Any other error, like wrong access
* region parameters, invalid buffer ownership, etc.
*
* @Notes: Locking a buffer simultaneously for write or read/write leaves the
* buffer's content into an indeterminate state.
*/
static int32_t mali_gralloc1_lock_flex_async(gralloc1_device_t *device, buffer_handle_t buffer,
uint64_t producerUsage,
uint64_t consumerUsage,
const gralloc1_rect_t *accessRegion,
struct android_flex_layout *outFlexLayout,
int32_t acquireFence)
{
int status = 0;
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 (outFlexLayout == NULL)
{
return GRALLOC1_ERROR_BAD_VALUE;
}
/* The lock usage constraints
* 1. Exactly one of producerUsage and consumerUsage must be *_USAGE_NONE.
* 2. The usage which is not *_USAGE_NONE must be one of the *_USAGE_CPU_*
* as applicable.
* are relaxed to accommodate an issue in shims with regard to lock usage mapping.
*/
//if (!((producerUsage | consumerUsage) & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)))
//{
// return GRALLOC1_ERROR_BAD_VALUE;
//}
status = mali_gralloc_lock_flex_async(m, buffer, producerUsage | consumerUsage,
accessRegion->left, accessRegion->top,
accessRegion->width, accessRegion->height,
outFlexLayout, acquireFence);
if (status != 0)
{
if (status == -EINVAL)
{
return GRALLOC1_ERROR_BAD_VALUE;
}
return GRALLOC1_ERROR_UNSUPPORTED;
}
return GRALLOC1_ERROR_NONE;
}
/*
* Unlocks the Gralloc 1.0 buffer asynchronously.
*
* @param device [in] Gralloc1 device.
* @param buffer [in] The buffer to unlock.
* @param outReleaseFence [out] Refers to an acquire sync fence object.
*
* @return 0, when the locking is successful;
* Appropriate error, otherwise
*
* Note: unlocking a buffer which is not locked results in an unexpected behaviour.
* Though it is possible to create a state machine to track the buffer state to
* recognize erroneous conditions, it is expected of client to adhere to API
* call sequence
*/
static int32_t mali_gralloc1_unlock_async(const gralloc1_device_t * const device,
buffer_handle_t buffer,
int32_t *const 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;
}
const int status = mali_gralloc_unlock_async(m, buffer, outReleaseFence);
if (status != 0)
{
if (status == -EINVAL)
{
return GRALLOC1_ERROR_BAD_VALUE;
}
return GRALLOC1_ERROR_UNSUPPORTED;
}
return GRALLOC1_ERROR_NONE;
}
#if PLATFORM_SDK_VERSION >= 26
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;
}
#endif
static int32_t mali_gralloc1_validate_buffer_size(gralloc1_device_t* device, buffer_handle_t buffer,
const gralloc1_buffer_descriptor_info_t* descriptorInfo,
uint32_t stride)
{
mali_gralloc_module *m;
m = reinterpret_cast<private_module_t *>(device->common.module);
if (buffer == 0)
{
AERR("Bad input buffer handle %p to validate buffer size", buffer);
return GRALLOC1_ERROR_BAD_HANDLE;
}
if (private_handle_t::validate(buffer) < 0)
{
AERR("Buffer: %p is corrupted, for validating its size", buffer);
return GRALLOC1_ERROR_BAD_HANDLE;
}
if (!descriptorInfo->width || !descriptorInfo->height ||!descriptorInfo->layerCount)
{
AERR("Invalid buffer descriptor attributes, width = %d height = %d layerCount = %d",
descriptorInfo->width, descriptorInfo->height, descriptorInfo->layerCount);
return GRALLOC1_ERROR_BAD_VALUE;
}
if (descriptorInfo->format == 0)
{
AERR("Invalid descriptor format to validate the buffer size");
return GRALLOC1_ERROR_BAD_VALUE;
}
buffer_descriptor_t grallocDescriptor;
grallocDescriptor.width = descriptorInfo->width;
grallocDescriptor.height = descriptorInfo->height;
grallocDescriptor.layer_count = descriptorInfo->layerCount;
grallocDescriptor.hal_format = descriptorInfo->format;
grallocDescriptor.producer_usage = descriptorInfo->producerUsage;
grallocDescriptor.consumer_usage = descriptorInfo->consumerUsage;
grallocDescriptor.format_type = MALI_GRALLOC_FORMAT_TYPE_USAGE;
/* Derive the buffer size for the given descriptor */
const int result = mali_gralloc_derive_format_and_size(m, &grallocDescriptor);
if (result)
{
AERR("Failed to derive format and size for the given descriptor information. error: %d", result);
return GRALLOC1_ERROR_UNSUPPORTED;
}
/* Validate the buffer parameters against descriptor info */
private_handle_t *gralloc_buffer = (private_handle_t *)buffer;
/* The buffer size must be greater than (or equal to) what would have been
* allocated with descriptor
*/
if ((size_t)gralloc_buffer->size < grallocDescriptor.size)
{
ALOGW("Buf size mismatch. Buffer size = %u, Descriptor (derived) size = %zu",
gralloc_buffer->size, grallocDescriptor.size);
return GRALLOC1_ERROR_BAD_VALUE;
}
if ((uint32_t)gralloc_buffer->stride != stride)
{
ALOGW("Stride mismatch. Expected stride = %d, Buffer stride = %d",
stride, gralloc_buffer->stride);
return GRALLOC1_ERROR_BAD_VALUE;
}
return GRALLOC1_ERROR_NONE;
}
static int32_t mali_gralloc1_get_transport_size(gralloc1_device_t* device, buffer_handle_t buffer,
uint32_t *outNumFds, uint32_t *outNumInts)
{
GRALLOC_UNUSED(device);
if (buffer == 0)
{
AERR("Bad input buffer handle %p to query transport size", buffer);
return GRALLOC1_ERROR_BAD_HANDLE;
}
if (outNumFds == 0 || outNumInts == 0)
{
AERR("Bad output pointers outNumFds=%p outNumInts=%p to populate", outNumFds, outNumInts);
return GRALLOC1_ERROR_BAD_HANDLE;
}
if (private_handle_t::validate(buffer) < 0)
{
AERR("Buffer %p, for querying transport size, is corrupted", buffer);
return GRALLOC1_ERROR_BAD_HANDLE;
}
*outNumFds = buffer->numFds;
*outNumInts = buffer->numInts;
return GRALLOC1_ERROR_NONE;
}
static int32_t mali_gralloc1_import_buffer(gralloc1_device_t* device, const buffer_handle_t rawHandle,
buffer_handle_t* outBuffer)
{
mali_gralloc_module *m;
m = reinterpret_cast<private_module_t *>(device->common.module);
if (rawHandle == 0)
{
AERR("Bad input raw handle %p to import", rawHandle);
return GRALLOC1_ERROR_BAD_HANDLE;
}
if (outBuffer == 0)
{
AERR("Bad output buffer pointer %p to populate", outBuffer);
return GRALLOC1_ERROR_BAD_HANDLE;
}
/* The rawHandle could have been cloned locally or received from another
* HAL server/client or another process. Hence clone it locally before
* importing the buffer
*/
native_handle_t* bufferHandle = native_handle_clone(rawHandle);
if (!bufferHandle)
{
AERR("Failed to clone %p for importing it", rawHandle);
return GRALLOC1_ERROR_BAD_HANDLE;
}
if (private_handle_t::validate(bufferHandle) < 0)
{
AERR("Failed to import corrupted buffer: %p", bufferHandle);
return GRALLOC1_ERROR_BAD_HANDLE;
}
if (mali_gralloc_reference_retain(m, bufferHandle) < 0)
{
AERR("Buffer: %p cannot be imported", bufferHandle);
return GRALLOC1_ERROR_NO_RESOURCES;
}
*outBuffer = bufferHandle;
return GRALLOC1_ERROR_NONE;
}
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 },
#if PLATFORM_SDK_VERSION >= 26
{ 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 },
#endif
{ GRALLOC1_FUNCTION_VALIDATE_BUFFER_SIZE, (gralloc1_function_pointer_t)mali_gralloc1_validate_buffer_size },
{ GRALLOC1_FUNCTION_GET_TRANSPORT_SIZE, (gralloc1_function_pointer_t)mali_gralloc1_get_transport_size },
{ GRALLOC1_FUNCTION_IMPORT_BUFFER, (gralloc1_function_pointer_t)mali_gralloc1_import_buffer },
/* 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 PLATFORM_SDK_VERSION >= 26
if (outCount != NULL)
{
*outCount = 1;
}
if (outCapabilities != NULL)
{
*(outCapabilities++) = GRALLOC1_CAPABILITY_LAYERED_BUFFERS;
}
#else
GRALLOC_UNUSED(outCapabilities);
if (outCount != NULL)
{
*outCount = 0;
}
#endif
}
static gralloc1_function_pointer_t mali_gralloc_getFunction(gralloc1_device_t *dev, int32_t descriptor)
{
GRALLOC_UNUSED(dev);
gralloc1_function_pointer_t rval = NULL;
uint32_t pos = 0;
while (mali_gralloc_func_list[pos].desc != GRALLOC1_FUNCTION_INVALID)
{
if (mali_gralloc_func_list[pos].desc == descriptor)
{
rval = mali_gralloc_func_list[pos].func;
break;
}
pos++;
}
if (rval == NULL)
{
rval = mali_gralloc_private_interface_getFunction(descriptor);
}
return rval;
}
static int mali_gralloc_device_close(struct hw_device_t *device)
{
gralloc1_device_t *dev = reinterpret_cast<gralloc1_device_t *>(device);
if (dev)
{
delete dev;
}
mali_gralloc_ion_close();
return 0;
}
int mali_gralloc_device_open(hw_module_t const *module, const char *name, hw_device_t **device)
{
gralloc1_device_t *dev;
GRALLOC_UNUSED(name);
dev = new gralloc1_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 = mali_gralloc_device_close;
dev->getCapabilities = mali_gralloc_getCapabilities;
dev->getFunction = mali_gralloc_getFunction;
private_module_t *p = reinterpret_cast<private_module_t*>(dev->common.module);
if (p->ionfd == -1)
p->ionfd = mali_gralloc_ion_open();
*device = &dev->common;
return 0;
}