You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
726 lines
19 KiB
726 lines
19 KiB
/*
|
|
* Copyright 2016 The Chromium OS Authors. All rights reserved.
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
/*
|
|
* Please run clang-format on this file after making changes:
|
|
*
|
|
* clang-format -style=file -i gralloctest.c
|
|
*
|
|
*/
|
|
|
|
#define _GNU_SOURCE
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include <cutils/native_handle.h>
|
|
#include <hardware/gralloc.h>
|
|
#include <sync/sync.h>
|
|
#include <system/graphics.h>
|
|
|
|
#define ALIGN(A, B) (((A) + (B)-1) / (B) * (B))
|
|
#define ARRAY_SIZE(A) (sizeof(A) / sizeof(*(A)))
|
|
|
|
#define CHECK(cond) \
|
|
do { \
|
|
if (!(cond)) { \
|
|
fprintf(stderr, "[ FAILED ] check in %s() %s:%d\n", __func__, __FILE__, \
|
|
__LINE__); \
|
|
return 0; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define CHECK_NO_MSG(cond) \
|
|
do { \
|
|
if (!(cond)) { \
|
|
return 0; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define BUFFER_USAGE_FRONT_RENDERING GRALLOC_USAGE_PRIVATE_0
|
|
|
|
/* Private API enumeration -- see <gralloc_drm.h> */
|
|
enum {
|
|
GRALLOC_DRM_GET_STRIDE,
|
|
GRALLOC_DRM_GET_FORMAT,
|
|
GRALLOC_DRM_GET_DIMENSIONS,
|
|
GRALLOC_DRM_GET_BACKING_STORE,
|
|
GRALLOC_DRM_GET_BUFFER_INFO,
|
|
GRALLOC_DRM_GET_USAGE,
|
|
};
|
|
|
|
enum {
|
|
GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT = 0x00000001,
|
|
};
|
|
|
|
struct gralloctest_context {
|
|
struct gralloc_module_t *module;
|
|
struct alloc_device_t *device;
|
|
int api;
|
|
};
|
|
|
|
struct gralloc_testcase {
|
|
const char *name;
|
|
int (*run_test)(struct gralloctest_context *ctx);
|
|
int required_api;
|
|
};
|
|
|
|
struct combinations {
|
|
int32_t format;
|
|
int32_t usage;
|
|
};
|
|
|
|
// clang-format off
|
|
static struct combinations combos[] = {
|
|
{ HAL_PIXEL_FORMAT_RGBA_8888,
|
|
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
|
|
GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER |
|
|
GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_CURSOR },
|
|
{ HAL_PIXEL_FORMAT_RGBA_8888,
|
|
GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER |
|
|
GRALLOC_USAGE_HW_COMPOSER },
|
|
{ HAL_PIXEL_FORMAT_RGBX_8888,
|
|
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN },
|
|
{ HAL_PIXEL_FORMAT_YCbCr_420_888,
|
|
GRALLOC_USAGE_EXTERNAL_DISP | GRALLOC_USAGE_HW_COMPOSER |
|
|
GRALLOC_USAGE_HW_TEXTURE },
|
|
{ HAL_PIXEL_FORMAT_YCbCr_420_888,
|
|
GRALLOC_USAGE_RENDERSCRIPT | GRALLOC_USAGE_SW_READ_OFTEN |
|
|
GRALLOC_USAGE_SW_WRITE_OFTEN },
|
|
{ HAL_PIXEL_FORMAT_YV12,
|
|
GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_COMPOSER |
|
|
GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP },
|
|
{ HAL_PIXEL_FORMAT_RGB_565,
|
|
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN },
|
|
{ HAL_PIXEL_FORMAT_BGRA_8888,
|
|
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN },
|
|
{ HAL_PIXEL_FORMAT_BLOB,
|
|
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN },
|
|
};
|
|
// clang-format on
|
|
|
|
struct grallocinfo {
|
|
buffer_handle_t handle; /* handle to the buffer */
|
|
int w; /* width of buffer */
|
|
int h; /* height of buffer */
|
|
int format; /* format of the buffer */
|
|
int usage; /* bitfield indicating usage */
|
|
int fence_fd; /* fence file descriptor */
|
|
void *vaddr; /* buffer virtual memory address */
|
|
int stride; /* stride in pixels */
|
|
struct android_ycbcr ycbcr; /* sw access for yuv buffers */
|
|
};
|
|
|
|
/* This function is meant to initialize the test to commonly used defaults. */
|
|
void grallocinfo_init(struct grallocinfo *info, int w, int h, int format, int usage)
|
|
{
|
|
info->w = w;
|
|
info->h = h;
|
|
info->format = format;
|
|
info->usage = usage;
|
|
info->fence_fd = -1;
|
|
info->vaddr = NULL;
|
|
info->ycbcr.y = NULL;
|
|
info->ycbcr.cb = NULL;
|
|
info->ycbcr.cr = NULL;
|
|
info->stride = 0;
|
|
}
|
|
|
|
static native_handle_t *duplicate_buffer_handle(buffer_handle_t handle)
|
|
{
|
|
native_handle_t *hnd = native_handle_create(handle->numFds, handle->numInts);
|
|
|
|
if (hnd == NULL)
|
|
return NULL;
|
|
|
|
const int *old_data = handle->data;
|
|
int *new_data = hnd->data;
|
|
|
|
int i;
|
|
for (i = 0; i < handle->numFds; i++) {
|
|
*new_data = dup(*old_data);
|
|
old_data++;
|
|
new_data++;
|
|
}
|
|
|
|
memcpy(new_data, old_data, sizeof(int) * handle->numInts);
|
|
|
|
return hnd;
|
|
}
|
|
|
|
/****************************************************************
|
|
* Wrappers around gralloc_module_t and alloc_device_t functions.
|
|
* GraphicBufferMapper/GraphicBufferAllocator could replace this
|
|
* in theory.
|
|
***************************************************************/
|
|
|
|
static int allocate(struct alloc_device_t *device, struct grallocinfo *info)
|
|
{
|
|
int ret;
|
|
|
|
ret = device->alloc(device, info->w, info->h, info->format, info->usage, &info->handle,
|
|
&info->stride);
|
|
|
|
CHECK_NO_MSG(ret == 0);
|
|
CHECK_NO_MSG(info->handle->version > 0);
|
|
CHECK_NO_MSG(info->handle->numInts >= 0);
|
|
CHECK_NO_MSG(info->handle->numFds >= 0);
|
|
CHECK_NO_MSG(info->stride >= 0);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int deallocate(struct alloc_device_t *device, struct grallocinfo *info)
|
|
{
|
|
int ret;
|
|
ret = device->free(device, info->handle);
|
|
CHECK(ret == 0);
|
|
return 1;
|
|
}
|
|
|
|
static int register_buffer(struct gralloc_module_t *module, struct grallocinfo *info)
|
|
{
|
|
int ret;
|
|
ret = module->registerBuffer(module, info->handle);
|
|
return (ret == 0);
|
|
}
|
|
|
|
static int unregister_buffer(struct gralloc_module_t *module, struct grallocinfo *info)
|
|
{
|
|
int ret;
|
|
ret = module->unregisterBuffer(module, info->handle);
|
|
return (ret == 0);
|
|
}
|
|
|
|
static int lock(struct gralloc_module_t *module, struct grallocinfo *info)
|
|
{
|
|
int ret;
|
|
|
|
ret = module->lock(module, info->handle, info->usage, 0, 0, (info->w) / 2, (info->h) / 2,
|
|
&info->vaddr);
|
|
|
|
return (ret == 0);
|
|
}
|
|
|
|
static int unlock(struct gralloc_module_t *module, struct grallocinfo *info)
|
|
{
|
|
int ret;
|
|
ret = module->unlock(module, info->handle);
|
|
return (ret == 0);
|
|
}
|
|
|
|
static int lock_ycbcr(struct gralloc_module_t *module, struct grallocinfo *info)
|
|
{
|
|
int ret;
|
|
|
|
ret = module->lock_ycbcr(module, info->handle, info->usage, 0, 0, (info->w) / 2,
|
|
(info->h) / 2, &info->ycbcr);
|
|
|
|
return (ret == 0);
|
|
}
|
|
|
|
static int lock_async(struct gralloc_module_t *module, struct grallocinfo *info)
|
|
{
|
|
int ret;
|
|
|
|
ret = module->lockAsync(module, info->handle, info->usage, 0, 0, (info->w) / 2,
|
|
(info->h) / 2, &info->vaddr, info->fence_fd);
|
|
|
|
return (ret == 0);
|
|
}
|
|
|
|
static int unlock_async(struct gralloc_module_t *module, struct grallocinfo *info)
|
|
{
|
|
int ret;
|
|
|
|
ret = module->unlockAsync(module, info->handle, &info->fence_fd);
|
|
|
|
return (ret == 0);
|
|
}
|
|
|
|
static int lock_async_ycbcr(struct gralloc_module_t *module, struct grallocinfo *info)
|
|
{
|
|
int ret;
|
|
|
|
ret = module->lockAsync_ycbcr(module, info->handle, info->usage, 0, 0, (info->w) / 2,
|
|
(info->h) / 2, &info->ycbcr, info->fence_fd);
|
|
|
|
return (ret == 0);
|
|
}
|
|
|
|
/**************************************************************
|
|
* END WRAPPERS *
|
|
**************************************************************/
|
|
|
|
/* This function tests initialization of gralloc module and allocator. */
|
|
static struct gralloctest_context *test_init_gralloc()
|
|
{
|
|
int err;
|
|
hw_module_t const *hw_module;
|
|
struct gralloctest_context *ctx = calloc(1, sizeof(*ctx));
|
|
|
|
err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &hw_module);
|
|
if (err)
|
|
return NULL;
|
|
|
|
gralloc_open(hw_module, &ctx->device);
|
|
ctx->module = (gralloc_module_t *)hw_module;
|
|
if (!ctx->module || !ctx->device)
|
|
return NULL;
|
|
|
|
switch (ctx->module->common.module_api_version) {
|
|
case GRALLOC_MODULE_API_VERSION_0_3:
|
|
ctx->api = 3;
|
|
break;
|
|
case GRALLOC_MODULE_API_VERSION_0_2:
|
|
ctx->api = 2;
|
|
break;
|
|
default:
|
|
ctx->api = 1;
|
|
}
|
|
|
|
return ctx;
|
|
}
|
|
|
|
static int test_close_gralloc(struct gralloctest_context *ctx)
|
|
{
|
|
CHECK(gralloc_close(ctx->device) == 0);
|
|
return 1;
|
|
}
|
|
|
|
/* This function tests allocation with varying buffer dimensions. */
|
|
static int test_alloc_varying_sizes(struct gralloctest_context *ctx)
|
|
{
|
|
struct grallocinfo info;
|
|
int i;
|
|
|
|
grallocinfo_init(&info, 0, 0, HAL_PIXEL_FORMAT_BGRA_8888, GRALLOC_USAGE_SW_READ_OFTEN);
|
|
|
|
for (i = 1; i < 1920; i++) {
|
|
info.w = i;
|
|
info.h = i;
|
|
CHECK(allocate(ctx->device, &info));
|
|
CHECK(deallocate(ctx->device, &info));
|
|
}
|
|
|
|
info.w = 1;
|
|
for (i = 1; i < 1920; i++) {
|
|
info.h = i;
|
|
CHECK(allocate(ctx->device, &info));
|
|
CHECK(deallocate(ctx->device, &info));
|
|
}
|
|
|
|
info.h = 1;
|
|
for (i = 1; i < 1920; i++) {
|
|
info.w = i;
|
|
CHECK(allocate(ctx->device, &info));
|
|
CHECK(deallocate(ctx->device, &info));
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* This function tests that we find at least one working format for each
|
|
* combos which we consider important.
|
|
*/
|
|
static int test_alloc_combinations(struct gralloctest_context *ctx)
|
|
{
|
|
int i;
|
|
|
|
struct grallocinfo info;
|
|
grallocinfo_init(&info, 512, 512, 0, 0);
|
|
|
|
for (i = 0; i < ARRAY_SIZE(combos); i++) {
|
|
info.format = combos[i].format;
|
|
info.usage = combos[i].usage;
|
|
CHECK(allocate(ctx->device, &info));
|
|
CHECK(deallocate(ctx->device, &info));
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* This function tests the advertised API version.
|
|
* Version_0_2 added (*lock_ycbcr)() method.
|
|
* Version_0_3 added fence passing to/from lock/unlock.
|
|
*/
|
|
static int test_api(struct gralloctest_context *ctx)
|
|
{
|
|
|
|
CHECK(ctx->module->registerBuffer);
|
|
CHECK(ctx->module->unregisterBuffer);
|
|
CHECK(ctx->module->lock);
|
|
CHECK(ctx->module->unlock);
|
|
|
|
switch (ctx->module->common.module_api_version) {
|
|
case GRALLOC_MODULE_API_VERSION_0_3:
|
|
CHECK(ctx->module->lock_ycbcr);
|
|
CHECK(ctx->module->lockAsync);
|
|
CHECK(ctx->module->unlockAsync);
|
|
CHECK(ctx->module->lockAsync_ycbcr);
|
|
break;
|
|
case GRALLOC_MODULE_API_VERSION_0_2:
|
|
CHECK(ctx->module->lock_ycbcr);
|
|
CHECK(ctx->module->lockAsync == NULL);
|
|
CHECK(ctx->module->unlockAsync == NULL);
|
|
CHECK(ctx->module->lockAsync_ycbcr == NULL);
|
|
break;
|
|
case GRALLOC_MODULE_API_VERSION_0_1:
|
|
CHECK(ctx->module->lockAsync == NULL);
|
|
CHECK(ctx->module->unlockAsync == NULL);
|
|
CHECK(ctx->module->lockAsync_ycbcr == NULL);
|
|
CHECK(ctx->module->lock_ycbcr == NULL);
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* This function registers, unregisters, locks and unlocks the buffer in
|
|
* various orders.
|
|
*/
|
|
static int test_gralloc_order(struct gralloctest_context *ctx)
|
|
{
|
|
struct grallocinfo info, duplicate;
|
|
|
|
grallocinfo_init(&info, 512, 512, HAL_PIXEL_FORMAT_BGRA_8888, GRALLOC_USAGE_SW_READ_OFTEN);
|
|
|
|
grallocinfo_init(&duplicate, 512, 512, HAL_PIXEL_FORMAT_BGRA_8888,
|
|
GRALLOC_USAGE_SW_READ_OFTEN);
|
|
|
|
CHECK(allocate(ctx->device, &info));
|
|
|
|
/*
|
|
* Duplicate the buffer handle to simulate an additional reference
|
|
* in same process.
|
|
*/
|
|
native_handle_t *native_handle = duplicate_buffer_handle(info.handle);
|
|
duplicate.handle = native_handle;
|
|
|
|
CHECK(unregister_buffer(ctx->module, &duplicate) == 0);
|
|
CHECK(register_buffer(ctx->module, &duplicate));
|
|
|
|
CHECK(unlock(ctx->module, &duplicate) == 0);
|
|
|
|
CHECK(lock(ctx->module, &duplicate));
|
|
CHECK(duplicate.vaddr);
|
|
CHECK(unlock(ctx->module, &duplicate));
|
|
|
|
CHECK(unregister_buffer(ctx->module, &duplicate));
|
|
|
|
CHECK(register_buffer(ctx->module, &duplicate));
|
|
CHECK(unregister_buffer(ctx->module, &duplicate));
|
|
CHECK(unregister_buffer(ctx->module, &duplicate) == 0);
|
|
|
|
CHECK(register_buffer(ctx->module, &duplicate));
|
|
CHECK(deallocate(ctx->device, &info));
|
|
|
|
CHECK(lock(ctx->module, &duplicate));
|
|
CHECK(lock(ctx->module, &duplicate));
|
|
CHECK(unlock(ctx->module, &duplicate));
|
|
CHECK(unlock(ctx->module, &duplicate));
|
|
CHECK(unlock(ctx->module, &duplicate) == 0);
|
|
CHECK(unregister_buffer(ctx->module, &duplicate));
|
|
|
|
CHECK(native_handle_close(duplicate.handle) == 0);
|
|
CHECK(native_handle_delete(native_handle) == 0);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* This function tests CPU reads and writes. */
|
|
static int test_mapping(struct gralloctest_context *ctx)
|
|
{
|
|
struct grallocinfo info;
|
|
uint32_t *ptr = NULL;
|
|
uint32_t magic_number = 0x000ABBA;
|
|
|
|
grallocinfo_init(&info, 512, 512, HAL_PIXEL_FORMAT_BGRA_8888,
|
|
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
|
|
|
|
CHECK(allocate(ctx->device, &info));
|
|
CHECK(lock(ctx->module, &info));
|
|
|
|
ptr = (uint32_t *)info.vaddr;
|
|
CHECK(ptr);
|
|
ptr[(info.w) / 2] = magic_number;
|
|
|
|
CHECK(unlock(ctx->module, &info));
|
|
info.vaddr = NULL;
|
|
ptr = NULL;
|
|
|
|
CHECK(lock(ctx->module, &info));
|
|
ptr = (uint32_t *)info.vaddr;
|
|
CHECK(ptr);
|
|
CHECK(ptr[info.w / 2] == magic_number);
|
|
|
|
CHECK(unlock(ctx->module, &info));
|
|
CHECK(deallocate(ctx->device, &info));
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* This function tests the private API we use in ARC++ -- not part of official
|
|
* gralloc. */
|
|
static int test_perform(struct gralloctest_context *ctx)
|
|
{
|
|
int32_t format;
|
|
uint64_t id1, id2;
|
|
uint32_t stride, width, height, req_usage, gralloc_usage;
|
|
struct grallocinfo info, duplicate;
|
|
struct gralloc_module_t *mod = ctx->module;
|
|
|
|
grallocinfo_init(&info, 650, 408, HAL_PIXEL_FORMAT_BGRA_8888, GRALLOC_USAGE_SW_READ_OFTEN);
|
|
|
|
CHECK(allocate(ctx->device, &info));
|
|
|
|
CHECK(mod->perform(mod, GRALLOC_DRM_GET_STRIDE, info.handle, &stride) == 0);
|
|
CHECK(stride >= info.stride);
|
|
|
|
CHECK(mod->perform(mod, GRALLOC_DRM_GET_FORMAT, info.handle, &format) == 0);
|
|
CHECK(format == info.format);
|
|
|
|
CHECK(mod->perform(mod, GRALLOC_DRM_GET_DIMENSIONS, info.handle, &width, &height) == 0);
|
|
CHECK(width == info.w);
|
|
CHECK(height == info.h);
|
|
|
|
native_handle_t *native_handle = duplicate_buffer_handle(info.handle);
|
|
duplicate.handle = native_handle;
|
|
|
|
CHECK(mod->perform(mod, GRALLOC_DRM_GET_BACKING_STORE, duplicate.handle, &id2));
|
|
CHECK(register_buffer(mod, &duplicate));
|
|
|
|
CHECK(mod->perform(mod, GRALLOC_DRM_GET_BACKING_STORE, info.handle, &id1) == 0);
|
|
CHECK(mod->perform(mod, GRALLOC_DRM_GET_BACKING_STORE, duplicate.handle, &id2) == 0);
|
|
CHECK(id1 == id2);
|
|
|
|
CHECK(unregister_buffer(mod, &duplicate));
|
|
CHECK(deallocate(ctx->device, &info));
|
|
|
|
req_usage = 0;
|
|
gralloc_usage = 0;
|
|
CHECK(mod->perform(mod, GRALLOC_DRM_GET_USAGE, req_usage, &gralloc_usage) == 0);
|
|
CHECK(gralloc_usage == 0);
|
|
|
|
req_usage = GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT;
|
|
gralloc_usage = 0;
|
|
CHECK(mod->perform(mod, GRALLOC_DRM_GET_USAGE, req_usage, &gralloc_usage) == 0);
|
|
CHECK(gralloc_usage == BUFFER_USAGE_FRONT_RENDERING);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* This function tests that only YUV buffers work with *lock_ycbcr. */
|
|
static int test_ycbcr(struct gralloctest_context *ctx)
|
|
|
|
{
|
|
struct grallocinfo info;
|
|
grallocinfo_init(&info, 512, 512, HAL_PIXEL_FORMAT_YCbCr_420_888,
|
|
GRALLOC_USAGE_SW_READ_OFTEN);
|
|
|
|
CHECK(allocate(ctx->device, &info));
|
|
|
|
CHECK(lock(ctx->module, &info) == 0);
|
|
CHECK(lock_ycbcr(ctx->module, &info));
|
|
CHECK(info.ycbcr.y);
|
|
CHECK(info.ycbcr.cb);
|
|
CHECK(info.ycbcr.cr);
|
|
CHECK(unlock(ctx->module, &info));
|
|
|
|
CHECK(deallocate(ctx->device, &info));
|
|
|
|
info.format = HAL_PIXEL_FORMAT_BGRA_8888;
|
|
CHECK(allocate(ctx->device, &info));
|
|
|
|
CHECK(lock_ycbcr(ctx->module, &info) == 0);
|
|
CHECK(lock(ctx->module, &info));
|
|
CHECK(unlock(ctx->module, &info));
|
|
|
|
CHECK(deallocate(ctx->device, &info));
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* This function tests a method ARC++ uses to query YUV buffer
|
|
* info -- not part of official gralloc API. This is used in
|
|
* Mali, Mesa, the ArcCodec and wayland_service.
|
|
*/
|
|
static int test_yuv_info(struct gralloctest_context *ctx)
|
|
{
|
|
struct grallocinfo info;
|
|
uintptr_t y_size, c_stride, c_size, cr_offset, cb_offset;
|
|
uint32_t width, height;
|
|
width = height = 512;
|
|
|
|
/* <system/graphics.h> defines YV12 as having:
|
|
* - an even width
|
|
* - an even height
|
|
* - a horizontal stride multiple of 16 pixels
|
|
* - a vertical stride equal to the height
|
|
*
|
|
* y_size = stride * height.
|
|
* c_stride = ALIGN(stride/2, 16).
|
|
* c_size = c_stride * height/2.
|
|
* size = y_size + c_size * 2.
|
|
* cr_offset = y_size.
|
|
* cb_offset = y_size + c_size.
|
|
*/
|
|
|
|
grallocinfo_init(&info, width, height, HAL_PIXEL_FORMAT_YV12, GRALLOC_USAGE_SW_READ_OFTEN);
|
|
|
|
CHECK(allocate(ctx->device, &info));
|
|
|
|
y_size = info.stride * height;
|
|
c_stride = ALIGN(info.stride / 2, 16);
|
|
c_size = c_stride * height / 2;
|
|
cr_offset = y_size;
|
|
cb_offset = y_size + c_size;
|
|
|
|
info.usage = 0;
|
|
|
|
/*
|
|
* Check if the (*lock_ycbcr) with usage of zero returns the
|
|
* offsets and strides of the YV12 buffer. This is unofficial
|
|
* behavior we are testing here.
|
|
*/
|
|
CHECK(lock_ycbcr(ctx->module, &info));
|
|
|
|
CHECK(info.stride == info.ycbcr.ystride);
|
|
CHECK(c_stride == info.ycbcr.cstride);
|
|
CHECK(cr_offset == (uintptr_t)info.ycbcr.cr);
|
|
CHECK(cb_offset == (uintptr_t)info.ycbcr.cb);
|
|
|
|
CHECK(unlock(ctx->module, &info));
|
|
|
|
CHECK(deallocate(ctx->device, &info));
|
|
|
|
return 1;
|
|
}
|
|
|
|
/* This function tests asynchronous locking and unlocking of buffers. */
|
|
static int test_async(struct gralloctest_context *ctx)
|
|
|
|
{
|
|
struct grallocinfo rgba_info, ycbcr_info;
|
|
grallocinfo_init(&rgba_info, 512, 512, HAL_PIXEL_FORMAT_BGRA_8888,
|
|
GRALLOC_USAGE_SW_READ_OFTEN);
|
|
grallocinfo_init(&ycbcr_info, 512, 512, HAL_PIXEL_FORMAT_YCbCr_420_888,
|
|
GRALLOC_USAGE_SW_READ_OFTEN);
|
|
|
|
CHECK(allocate(ctx->device, &rgba_info));
|
|
CHECK(allocate(ctx->device, &ycbcr_info));
|
|
|
|
CHECK(lock_async(ctx->module, &rgba_info));
|
|
CHECK(lock_async_ycbcr(ctx->module, &ycbcr_info));
|
|
|
|
CHECK(rgba_info.vaddr);
|
|
CHECK(ycbcr_info.ycbcr.y);
|
|
CHECK(ycbcr_info.ycbcr.cb);
|
|
CHECK(ycbcr_info.ycbcr.cr);
|
|
|
|
/*
|
|
* Wait on the fence returned from unlock_async and check it doesn't
|
|
* return an error.
|
|
*/
|
|
CHECK(unlock_async(ctx->module, &rgba_info));
|
|
CHECK(unlock_async(ctx->module, &ycbcr_info));
|
|
|
|
if (rgba_info.fence_fd >= 0) {
|
|
CHECK(sync_wait(rgba_info.fence_fd, 10000) >= 0);
|
|
CHECK(close(rgba_info.fence_fd) == 0);
|
|
}
|
|
|
|
if (ycbcr_info.fence_fd >= 0) {
|
|
CHECK(sync_wait(ycbcr_info.fence_fd, 10000) >= 0);
|
|
CHECK(close(ycbcr_info.fence_fd) == 0);
|
|
}
|
|
|
|
CHECK(deallocate(ctx->device, &rgba_info));
|
|
CHECK(deallocate(ctx->device, &ycbcr_info));
|
|
|
|
return 1;
|
|
}
|
|
|
|
static const struct gralloc_testcase tests[] = {
|
|
{ "alloc_varying_sizes", test_alloc_varying_sizes, 1 },
|
|
{ "alloc_combinations", test_alloc_combinations, 1 },
|
|
{ "api", test_api, 1 },
|
|
{ "gralloc_order", test_gralloc_order, 1 },
|
|
{ "mapping", test_mapping, 1 },
|
|
{ "perform", test_perform, 1 },
|
|
{ "ycbcr", test_ycbcr, 2 },
|
|
{ "yuv_info", test_yuv_info, 2 },
|
|
{ "async", test_async, 3 },
|
|
};
|
|
|
|
static void print_help(const char *argv0)
|
|
{
|
|
uint32_t i;
|
|
printf("usage: %s <test_name>\n\n", argv0);
|
|
printf("A valid name test is one the following:\n");
|
|
for (i = 0; i < ARRAY_SIZE(tests); i++)
|
|
printf("%s\n", tests[i].name);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int ret = 0;
|
|
uint32_t num_run = 0;
|
|
|
|
setbuf(stdout, NULL);
|
|
if (argc == 2) {
|
|
uint32_t i;
|
|
char *name = argv[1];
|
|
|
|
struct gralloctest_context *ctx = test_init_gralloc();
|
|
if (!ctx) {
|
|
fprintf(stderr, "[ FAILED ] to initialize gralloc.\n");
|
|
return 1;
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_SIZE(tests); i++) {
|
|
if (strcmp(tests[i].name, name) && strcmp("all", name))
|
|
continue;
|
|
|
|
printf("[ RUN ] gralloctest.%s\n", tests[i].name);
|
|
|
|
int success = 1;
|
|
if (ctx->api >= tests[i].required_api)
|
|
success = tests[i].run_test(ctx);
|
|
|
|
if (!success) {
|
|
fprintf(stderr, "[ FAILED ] gralloctest.%s\n", tests[i].name);
|
|
ret |= 1;
|
|
} else {
|
|
printf("[ PASSED ] gralloctest.%s\n", tests[i].name);
|
|
}
|
|
|
|
num_run++;
|
|
}
|
|
|
|
if (!test_close_gralloc(ctx)) {
|
|
fprintf(stderr, "[ FAILED ] to close gralloc.\n");
|
|
return 1;
|
|
}
|
|
|
|
if (!num_run)
|
|
goto print_usage;
|
|
|
|
return ret;
|
|
}
|
|
|
|
print_usage:
|
|
print_help(argv[0]);
|
|
return 0;
|
|
}
|