From ac4d519f43bd6587b3eafb68dab0861ba4fe4b5b Mon Sep 17 00:00:00 2001 From: Eino-Ville Talvala Date: Tue, 17 Jul 2012 16:13:52 -0700 Subject: [PATCH] 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 --- .../system/OpenglSystemCommon/gralloc_cb.h | 18 ++++- tools/emulator/opengl/system/egl/egl.cpp | 4 +- .../opengl/system/gralloc/gralloc.cpp | 73 +++++++++++++++---- 3 files changed, 76 insertions(+), 19 deletions(-) diff --git a/tools/emulator/opengl/system/OpenglSystemCommon/gralloc_cb.h b/tools/emulator/opengl/system/OpenglSystemCommon/gralloc_cb.h index e879409cb..a3fb8dd00 100644 --- a/tools/emulator/opengl/system/OpenglSystemCommon/gralloc_cb.h +++ b/tools/emulator/opengl/system/OpenglSystemCommon/gralloc_cb.h @@ -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 diff --git a/tools/emulator/opengl/system/egl/egl.cpp b/tools/emulator/opengl/system/egl/egl.cpp index b1be38dfb..da89c4dee 100644 --- a/tools/emulator/opengl/system/egl/egl.cpp +++ b/tools/emulator/opengl/system/egl/egl.cpp @@ -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: diff --git a/tools/emulator/opengl/system/gralloc/gralloc.cpp b/tools/emulator/opengl/system/gralloc/gralloc.cpp index 3953f9c33..dd5e5156d 100644 --- a/tools/emulator/opengl/system/gralloc/gralloc.cpp +++ b/tools/emulator/opengl/system/gralloc/gralloc.cpp @@ -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; }