gralloc: Add automatic format selection

Have gralloc_alloc be able to select the appropriate pixel format
given the endpoints, triggered by new
GRALLOC_EMULATOR_PIXEL_FORMAT_AUTO format.

Currently supports camera->screen, and camera->video encoder.

Bug: 6243944
Change-Id: Ib1bf8da8d9184ac99e7f50aad09212c146c32809
This commit is contained in:
Eino-Ville Talvala
2012-07-17 16:13:52 -07:00
parent cefc43263a
commit ac4d519f43
3 changed files with 76 additions and 19 deletions

View File

@@ -24,23 +24,36 @@
#define BUFFER_HANDLE_MAGIC ((int)0xabfabfab)
#define CB_HANDLE_NUM_INTS(nfds) (int)((sizeof(cb_handle_t) - (nfds)*sizeof(int)) / sizeof(int))
//
// Emulator-specific gralloc formats
//
enum {
// Request that gralloc select the proper format given the usage
// flags. Pass this as the format to gralloc_alloc, and then the concrete
// format can be found in cb_handle_t.format. It is invalid for
// cb_handle_t.format to be AUTO; it must be a concrete format in either the
// standard HAL_PIXEL_FORMAT enum or other values in this enum.
GRALLOC_EMULATOR_PIXEL_FORMAT_AUTO = 0x100
};
//
// Our buffer handle structure
//
struct cb_handle_t : public native_handle {
cb_handle_t(int p_fd, int p_ashmemSize, int p_usage,
int p_width, int p_height,
int p_width, int p_height, int p_format,
int p_glFormat, int p_glType) :
fd(p_fd),
magic(BUFFER_HANDLE_MAGIC),
usage(p_usage),
width(p_width),
height(p_height),
format(p_format),
glFormat(p_glFormat),
glType(p_glType),
ashmemSize(p_ashmemSize),
ashmemBase(NULL),
ashmemBase(0),
ashmemBasePid(0),
mappedPid(0),
lockedLeft(0),
@@ -88,6 +101,7 @@ struct cb_handle_t : public native_handle {
int usage; // usage bits the buffer was created with
int width; // buffer width
int height; // buffer height
int format; // real internal pixel format format
int glFormat; // OpenGL format enum used for host h/w color buffer
int glType; // OpenGL type enum used when uploading to host
int ashmemSize; // ashmem region size for the buffer (0 unless is HW_FB buffer or

View File

@@ -1146,7 +1146,9 @@ EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EG
if (native_buffer->common.version != sizeof(android_native_buffer_t))
setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
switch (native_buffer->format) {
cb_handle_t *cb = (cb_handle_t *)(native_buffer->handle);
switch (cb->format) {
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_RGBX_8888:
case HAL_PIXEL_FORMAT_RGB_888:

View File

@@ -133,8 +133,11 @@ static int gralloc_alloc(alloc_device_t* dev,
D("gralloc_alloc w=%d h=%d usage=0x%x\n", w, h, usage);
gralloc_device_t *grdev = (gralloc_device_t *)dev;
if (!grdev || !pHandle || !pStride)
if (!grdev || !pHandle || !pStride) {
ALOGE("gralloc_alloc: Bad inputs (grdev: %p, pHandle: %p, pStride: %p",
grdev, pHandle, pStride);
return -EINVAL;
}
//
// Validate usage: buffer cannot be written both by s/w and h/w access.
@@ -142,9 +145,37 @@ static int gralloc_alloc(alloc_device_t* dev,
bool sw_write = (0 != (usage & GRALLOC_USAGE_SW_WRITE_MASK));
bool hw_write = (usage & GRALLOC_USAGE_HW_RENDER);
if (hw_write && sw_write) {
ALOGE("gralloc_alloc: Mismatched usage flags: %d x %d, usage %x",
w, h, usage);
return -EINVAL;
}
bool sw_read = (0 != (usage & GRALLOC_USAGE_SW_READ_MASK));
bool hw_cam_write = usage & GRALLOC_USAGE_HW_CAMERA_WRITE;
bool hw_cam_read = usage & GRALLOC_USAGE_HW_CAMERA_READ;
bool hw_vid_enc_read = usage & GRALLOC_USAGE_HW_VIDEO_ENCODER;
// Pick the right concrete pixel format given the endpoints as encoded in
// the usage bits. Every end-point pair needs explicit listing here.
if (format == GRALLOC_EMULATOR_PIXEL_FORMAT_AUTO) {
// Camera as producer
if (usage & GRALLOC_USAGE_HW_CAMERA_WRITE) {
if (usage & GRALLOC_USAGE_HW_TEXTURE) {
// Camera-to-display is RGBA
format = HAL_PIXEL_FORMAT_RGBA_8888;
} else if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) {
// Camera-to-encoder is NV21
format = HAL_PIXEL_FORMAT_YCrCb_420_SP;
}
}
if (format == GRALLOC_EMULATOR_PIXEL_FORMAT_AUTO) {
ALOGE("gralloc_alloc: Requested auto format selection, "
"but no known format for this usage: %d x %d, usage %x",
w, h, usage);
return -EINVAL;
}
}
bool yuv_format = false;
int ashmem_size = 0;
@@ -186,8 +217,8 @@ static int gralloc_alloc(alloc_device_t* dev,
case HAL_PIXEL_FORMAT_RAW_SENSOR:
bpp = 2;
align = 16*bpp;
if (! (sw_read && sw_write) ) {
// Raw sensor data cannot be used by HW
if (! ((sw_read && hw_cam_write) || (sw_write && hw_cam_read) ) ) {
// Raw sensor data only goes to/from camera to CPU
return -EINVAL;
}
// Not expecting to actually create any GL surfaces for this
@@ -196,8 +227,8 @@ static int gralloc_alloc(alloc_device_t* dev,
break;
case HAL_PIXEL_FORMAT_BLOB:
bpp = 1;
if (! (sw_read && sw_write) ) {
// Blob data cannot be used by HW
if (! (sw_read && hw_cam_write) ) {
// Blob data cannot be used by HW other than camera emulator
return -EINVAL;
}
// Not expecting to actually create any GL surfaces for this
@@ -210,6 +241,7 @@ static int gralloc_alloc(alloc_device_t* dev,
// Not expecting to actually create any GL surfaces for this
break;
default:
ALOGE("gralloc_alloc: Unknown format %d", format);
return -EINVAL;
}
@@ -218,9 +250,9 @@ static int gralloc_alloc(alloc_device_t* dev,
ashmem_size += sizeof(uint32_t);
}
if (sw_read || sw_write) {
if (sw_read || sw_write || hw_cam_write || hw_vid_enc_read) {
// keep space for image on guest memory if SW access is needed
// or if the camera is doing writing
if (yuv_format) {
// For NV21
ashmem_size += w * h * 3 / 2;
@@ -232,8 +264,8 @@ static int gralloc_alloc(alloc_device_t* dev,
}
}
D("gralloc_alloc ashmem_size=%d, stride=%d, tid %d\n", ashmem_size, stride,
gettid());
D("gralloc_alloc format=%d, ashmem_size=%d, stride=%d, tid %d\n", format,
ashmem_size, stride, gettid());
//
// Allocate space in ashmem if needed
@@ -252,7 +284,7 @@ static int gralloc_alloc(alloc_device_t* dev,
}
cb_handle_t *cb = new cb_handle_t(fd, ashmem_size, usage,
w, h, glFormat, glType);
w, h, format, glFormat, glType);
if (ashmem_size > 0) {
//
@@ -271,8 +303,11 @@ static int gralloc_alloc(alloc_device_t* dev,
//
// Allocate ColorBuffer handle on the host (only if h/w access is allowed)
// Only do this for some h/w usages, not all.
//
if (usage & GRALLOC_USAGE_HW_MASK) {
if (usage & (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_RENDER |
GRALLOC_USAGE_HW_2D | GRALLOC_USAGE_HW_COMPOSER |
GRALLOC_USAGE_HW_FB) ) {
DEFINE_HOST_CONNECTION;
if (hostCon && rcEnc) {
cb->hostHandle = rcEnc->rcCreateColorBuffer(rcEnc, w, h, glFormat);
@@ -565,14 +600,17 @@ static int gralloc_lock(gralloc_module_t const* module,
bool sw_write = (0 != (usage & GRALLOC_USAGE_SW_WRITE_MASK));
bool hw_read = (usage & GRALLOC_USAGE_HW_TEXTURE);
bool hw_write = (usage & GRALLOC_USAGE_HW_RENDER);
bool hw_vid_enc_read = (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER);
bool hw_cam_write = (usage & GRALLOC_USAGE_HW_CAMERA_WRITE);
bool sw_read_allowed = (0 != (cb->usage & GRALLOC_USAGE_SW_READ_MASK));
bool sw_write_allowed = (0 != (cb->usage & GRALLOC_USAGE_SW_WRITE_MASK));
if ( (hw_read || hw_write) ||
(!sw_read && !sw_write) ||
(!sw_read && !sw_write && !hw_cam_write && !hw_vid_enc_read) ||
(sw_read && !sw_read_allowed) ||
(sw_write && !sw_write_allowed) ) {
ALOGE("gralloc_lock usage mismatch usage=0x%x cb->usage=0x%x\n", usage, cb->usage);
ALOGE("gralloc_lock usage mismatch usage=0x%x cb->usage=0x%x\n", usage,
cb->usage);
return -EINVAL;
}
@@ -582,7 +620,7 @@ static int gralloc_lock(gralloc_module_t const* module,
//
// make sure ashmem area is mapped if needed
//
if (cb->canBePosted() || sw_read || sw_write) {
if (cb->canBePosted() || sw_read || sw_write || hw_cam_write || hw_vid_enc_read) {
if (cb->ashmemBasePid != getpid() || !cb->ashmemBase) {
return -EACCES;
}
@@ -619,11 +657,11 @@ static int gralloc_lock(gralloc_module_t const* module,
//
// is virtual address required ?
//
if (sw_read || sw_write) {
if (sw_read || sw_write || hw_cam_write || hw_vid_enc_read) {
*vaddr = cpu_addr;
}
if (sw_write) {
if (sw_write || hw_cam_write) {
//
// Keep locked region if locked for s/w write access.
//
@@ -633,6 +671,9 @@ static int gralloc_lock(gralloc_module_t const* module,
cb->lockedHeight = h;
}
DD("gralloc_lock success. vaddr: %p, *vaddr: %p, usage: %x, cpu_addr: %p",
vaddr, vaddr ? *vaddr : 0, usage, cpu_addr);
return 0;
}