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 BUFFER_HANDLE_MAGIC ((int)0xabfabfab)
|
||||||
#define CB_HANDLE_NUM_INTS(nfds) (int)((sizeof(cb_handle_t) - (nfds)*sizeof(int)) / sizeof(int))
|
#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
|
// Our buffer handle structure
|
||||||
//
|
//
|
||||||
struct cb_handle_t : public native_handle {
|
struct cb_handle_t : public native_handle {
|
||||||
|
|
||||||
cb_handle_t(int p_fd, int p_ashmemSize, int p_usage,
|
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) :
|
int p_glFormat, int p_glType) :
|
||||||
fd(p_fd),
|
fd(p_fd),
|
||||||
magic(BUFFER_HANDLE_MAGIC),
|
magic(BUFFER_HANDLE_MAGIC),
|
||||||
usage(p_usage),
|
usage(p_usage),
|
||||||
width(p_width),
|
width(p_width),
|
||||||
height(p_height),
|
height(p_height),
|
||||||
|
format(p_format),
|
||||||
glFormat(p_glFormat),
|
glFormat(p_glFormat),
|
||||||
glType(p_glType),
|
glType(p_glType),
|
||||||
ashmemSize(p_ashmemSize),
|
ashmemSize(p_ashmemSize),
|
||||||
ashmemBase(NULL),
|
ashmemBase(0),
|
||||||
ashmemBasePid(0),
|
ashmemBasePid(0),
|
||||||
mappedPid(0),
|
mappedPid(0),
|
||||||
lockedLeft(0),
|
lockedLeft(0),
|
||||||
@@ -88,6 +101,7 @@ struct cb_handle_t : public native_handle {
|
|||||||
int usage; // usage bits the buffer was created with
|
int usage; // usage bits the buffer was created with
|
||||||
int width; // buffer width
|
int width; // buffer width
|
||||||
int height; // buffer height
|
int height; // buffer height
|
||||||
|
int format; // real internal pixel format format
|
||||||
int glFormat; // OpenGL format enum used for host h/w color buffer
|
int glFormat; // OpenGL format enum used for host h/w color buffer
|
||||||
int glType; // OpenGL type enum used when uploading to host
|
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
|
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))
|
if (native_buffer->common.version != sizeof(android_native_buffer_t))
|
||||||
setErrorReturn(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
|
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_RGBA_8888:
|
||||||
case HAL_PIXEL_FORMAT_RGBX_8888:
|
case HAL_PIXEL_FORMAT_RGBX_8888:
|
||||||
case HAL_PIXEL_FORMAT_RGB_888:
|
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);
|
D("gralloc_alloc w=%d h=%d usage=0x%x\n", w, h, usage);
|
||||||
|
|
||||||
gralloc_device_t *grdev = (gralloc_device_t *)dev;
|
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;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Validate usage: buffer cannot be written both by s/w and h/w access.
|
// 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 sw_write = (0 != (usage & GRALLOC_USAGE_SW_WRITE_MASK));
|
||||||
bool hw_write = (usage & GRALLOC_USAGE_HW_RENDER);
|
bool hw_write = (usage & GRALLOC_USAGE_HW_RENDER);
|
||||||
if (hw_write && sw_write) {
|
if (hw_write && sw_write) {
|
||||||
|
ALOGE("gralloc_alloc: Mismatched usage flags: %d x %d, usage %x",
|
||||||
|
w, h, usage);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
bool sw_read = (0 != (usage & GRALLOC_USAGE_SW_READ_MASK));
|
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;
|
bool yuv_format = false;
|
||||||
|
|
||||||
int ashmem_size = 0;
|
int ashmem_size = 0;
|
||||||
@@ -186,8 +217,8 @@ static int gralloc_alloc(alloc_device_t* dev,
|
|||||||
case HAL_PIXEL_FORMAT_RAW_SENSOR:
|
case HAL_PIXEL_FORMAT_RAW_SENSOR:
|
||||||
bpp = 2;
|
bpp = 2;
|
||||||
align = 16*bpp;
|
align = 16*bpp;
|
||||||
if (! (sw_read && sw_write) ) {
|
if (! ((sw_read && hw_cam_write) || (sw_write && hw_cam_read) ) ) {
|
||||||
// Raw sensor data cannot be used by HW
|
// Raw sensor data only goes to/from camera to CPU
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
// Not expecting to actually create any GL surfaces for this
|
// Not expecting to actually create any GL surfaces for this
|
||||||
@@ -196,8 +227,8 @@ static int gralloc_alloc(alloc_device_t* dev,
|
|||||||
break;
|
break;
|
||||||
case HAL_PIXEL_FORMAT_BLOB:
|
case HAL_PIXEL_FORMAT_BLOB:
|
||||||
bpp = 1;
|
bpp = 1;
|
||||||
if (! (sw_read && sw_write) ) {
|
if (! (sw_read && hw_cam_write) ) {
|
||||||
// Blob data cannot be used by HW
|
// Blob data cannot be used by HW other than camera emulator
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
// Not expecting to actually create any GL surfaces for this
|
// 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
|
// Not expecting to actually create any GL surfaces for this
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
ALOGE("gralloc_alloc: Unknown format %d", format);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,9 +250,9 @@ static int gralloc_alloc(alloc_device_t* dev,
|
|||||||
ashmem_size += sizeof(uint32_t);
|
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
|
// keep space for image on guest memory if SW access is needed
|
||||||
|
// or if the camera is doing writing
|
||||||
if (yuv_format) {
|
if (yuv_format) {
|
||||||
// For NV21
|
// For NV21
|
||||||
ashmem_size += w * h * 3 / 2;
|
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,
|
D("gralloc_alloc format=%d, ashmem_size=%d, stride=%d, tid %d\n", format,
|
||||||
gettid());
|
ashmem_size, stride, gettid());
|
||||||
|
|
||||||
//
|
//
|
||||||
// Allocate space in ashmem if needed
|
// 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,
|
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) {
|
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)
|
// 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;
|
DEFINE_HOST_CONNECTION;
|
||||||
if (hostCon && rcEnc) {
|
if (hostCon && rcEnc) {
|
||||||
cb->hostHandle = rcEnc->rcCreateColorBuffer(rcEnc, w, h, glFormat);
|
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 sw_write = (0 != (usage & GRALLOC_USAGE_SW_WRITE_MASK));
|
||||||
bool hw_read = (usage & GRALLOC_USAGE_HW_TEXTURE);
|
bool hw_read = (usage & GRALLOC_USAGE_HW_TEXTURE);
|
||||||
bool hw_write = (usage & GRALLOC_USAGE_HW_RENDER);
|
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_read_allowed = (0 != (cb->usage & GRALLOC_USAGE_SW_READ_MASK));
|
||||||
bool sw_write_allowed = (0 != (cb->usage & GRALLOC_USAGE_SW_WRITE_MASK));
|
bool sw_write_allowed = (0 != (cb->usage & GRALLOC_USAGE_SW_WRITE_MASK));
|
||||||
|
|
||||||
if ( (hw_read || hw_write) ||
|
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_read && !sw_read_allowed) ||
|
||||||
(sw_write && !sw_write_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;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -582,7 +620,7 @@ static int gralloc_lock(gralloc_module_t const* module,
|
|||||||
//
|
//
|
||||||
// make sure ashmem area is mapped if needed
|
// 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) {
|
if (cb->ashmemBasePid != getpid() || !cb->ashmemBase) {
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
}
|
}
|
||||||
@@ -619,11 +657,11 @@ static int gralloc_lock(gralloc_module_t const* module,
|
|||||||
//
|
//
|
||||||
// is virtual address required ?
|
// is virtual address required ?
|
||||||
//
|
//
|
||||||
if (sw_read || sw_write) {
|
if (sw_read || sw_write || hw_cam_write || hw_vid_enc_read) {
|
||||||
*vaddr = cpu_addr;
|
*vaddr = cpu_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sw_write) {
|
if (sw_write || hw_cam_write) {
|
||||||
//
|
//
|
||||||
// Keep locked region if locked for s/w write access.
|
// 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;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user