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:
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user