OSDN Git Service

Merge remote-tracking branch 'origin/master' into nougat-x86
[android-x86/external-gbm_gralloc.git] / gralloc_gbm.cpp
index 265d1eb..13a5c24 100644 (file)
 
 #define LOG_TAG "GRALLOC-GBM"
 
-#include <cutils/log.h>
+#include <log/log.h>
 #include <cutils/atomic.h>
 #include <cutils/properties.h>
 #include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <assert.h>
+#include <xf86drm.h>
 
 #include <hardware/gralloc.h>
 #include <system/graphics.h>
 #include <gbm.h>
 
 #include "gralloc_gbm_priv.h"
-#include "gralloc_drm_handle.h"
+#include <android/gralloc_handle.h>
+
+#include <unordered_map>
 
 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
 
 #define unlikely(x) __builtin_expect(!!(x), 0)
 
-struct gralloc_gbm_bo_t {
-       struct gbm_bo *bo;
-       void *map_data;
-
-       struct gralloc_gbm_handle_t *handle;
-
-       int imported;  /* the handle is from a remote proces when true */
+static std::unordered_map<buffer_handle_t, struct gbm_bo *> gbm_bo_handle_map;
 
+struct bo_data_t {
+       void *map_data;
        int lock_count;
        int locked_for;
-
-       unsigned int refcount;
 };
 
-static int32_t gralloc_gbm_pid = 0;
+void gralloc_gbm_destroy_user_data(struct gbm_bo *bo, void *data)
+{
+       struct bo_data_t *bo_data = (struct bo_data_t *)data;
+       delete bo_data;
+
+       (void)bo;
+}
+
+static struct bo_data_t *gbm_bo_data(struct gbm_bo *bo) {
+       return (struct bo_data_t *)gbm_bo_get_user_data(bo);
+}
+
 
 static uint32_t get_gbm_format(int format)
 {
@@ -76,12 +87,15 @@ static uint32_t get_gbm_format(int format)
                fmt = GBM_FORMAT_RGB888;
                break;
        case HAL_PIXEL_FORMAT_RGB_565:
-               fmt = GBM_FORMAT_BGR565;
+               fmt = GBM_FORMAT_RGB565;
                break;
        case HAL_PIXEL_FORMAT_BGRA_8888:
                fmt = GBM_FORMAT_ARGB8888;
                break;
        case HAL_PIXEL_FORMAT_YV12:
+               /* YV12 is planar, but must be a single buffer so ask for GR88 */
+               fmt = GBM_FORMAT_GR88;
+               break;
        case HAL_PIXEL_FORMAT_YCbCr_422_SP:
        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
        default:
@@ -92,6 +106,37 @@ static uint32_t get_gbm_format(int format)
        return fmt;
 }
 
+static int gralloc_gbm_get_bpp(int format)
+{
+       int bpp;
+
+       switch (format) {
+       case HAL_PIXEL_FORMAT_RGBA_8888:
+       case HAL_PIXEL_FORMAT_RGBX_8888:
+       case HAL_PIXEL_FORMAT_BGRA_8888:
+               bpp = 4;
+               break;
+       case HAL_PIXEL_FORMAT_RGB_888:
+               bpp = 3;
+               break;
+       case HAL_PIXEL_FORMAT_RGB_565:
+       case HAL_PIXEL_FORMAT_YCbCr_422_I:
+               bpp = 2;
+               break;
+       /* planar; only Y is considered */
+       case HAL_PIXEL_FORMAT_YV12:
+       case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+       case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+               bpp = 1;
+               break;
+       default:
+               bpp = 0;
+               break;
+       }
+
+       return bpp;
+}
+
 static unsigned int get_pipe_bind(int usage)
 {
        unsigned int bind = 0;
@@ -104,55 +149,61 @@ static unsigned int get_pipe_bind(int usage)
                bind |= GBM_BO_USE_RENDERING;
        if (usage & GRALLOC_USAGE_HW_FB)
                bind |= GBM_BO_USE_SCANOUT;
+       if (usage & GRALLOC_USAGE_HW_COMPOSER)
+               bind |= GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
 
        return bind;
 }
 
-static struct gralloc_gbm_bo_t *gbm_import(struct gbm_device *gbm,
-               struct gralloc_gbm_handle_t *handle)
+static struct gbm_bo *gbm_import(struct gbm_device *gbm,
+               buffer_handle_t _handle)
 {
-       struct gralloc_gbm_bo_t *buf;
+       struct gbm_bo *bo;
+       struct gralloc_handle_t *handle = gralloc_handle(_handle);
+       #ifdef GBM_BO_IMPORT_FD_MODIFIER
+       struct gbm_import_fd_modifier_data data;
+       #else
        struct gbm_import_fd_data data;
-       int format = get_gbm_format(handle->format);
-       int usage = get_pipe_bind(handle->usage);
+       #endif
 
+       int format = get_gbm_format(handle->format);
        if (handle->prime_fd < 0)
                return NULL;
 
-       buf = new struct gralloc_gbm_bo_t();
-       if (!buf) {
-               ALOGE("failed to allocate pipe buffer");
-               return NULL;
+       memset(&data, 0, sizeof(data));
+       data.width = handle->width;
+       data.height = handle->height;
+       data.format = format;
+       /* Adjust the width and height for a GBM GR88 buffer */
+       if (handle->format == HAL_PIXEL_FORMAT_YV12) {
+               data.width /= 2;
+               data.height += handle->height / 2;
        }
 
+       #ifdef GBM_BO_IMPORT_FD_MODIFIER
+       data.num_fds = 1;
+       data.fds[0] = handle->prime_fd;
+       data.strides[0] = handle->stride;
+       data.modifier = handle->modifier;
+       bo = gbm_bo_import(gbm, GBM_BO_IMPORT_FD_MODIFIER, &data, 0);
+       #else
        data.fd = handle->prime_fd;
-       data.width = handle->width;
-       data.height = handle->height;
        data.stride = handle->stride;
-       data.format = format;
+       bo = gbm_bo_import(gbm, GBM_BO_IMPORT_FD, &data, 0);
+       #endif
 
-       buf->bo = gbm_bo_import(gbm, GBM_BO_IMPORT_FD, &data, 0);
-       if (!buf->bo) {
-               delete buf;
-               return NULL;
-       }
-       return buf;
+       return bo;
 }
 
-static struct gralloc_gbm_bo_t *gbm_alloc(struct gbm_device *gbm,
-               struct gralloc_gbm_handle_t *handle)
+static struct gbm_bo *gbm_alloc(struct gbm_device *gbm,
+               buffer_handle_t _handle)
 {
-       struct gralloc_gbm_bo_t *buf;
+       struct gbm_bo *bo;
+       struct gralloc_handle_t *handle = gralloc_handle(_handle);
        int format = get_gbm_format(handle->format);
        int usage = get_pipe_bind(handle->usage);
        int width, height;
 
-       buf = new struct gralloc_gbm_bo_t();
-       if (!buf) {
-               ALOGE("failed to allocate pipe buffer");
-               return NULL;
-       }
-
        width = handle->width;
        height = handle->height;
        if (usage & GBM_BO_USE_CURSOR) {
@@ -162,53 +213,84 @@ static struct gralloc_gbm_bo_t *gbm_alloc(struct gbm_device *gbm,
                        height = 64;
        }
 
-       ALOGD("create BO, size=%dx%d, fmt=%d, usage=%x",
+       /*
+        * For YV12, we request GR88, so halve the width since we're getting
+        * 16bpp. Then increase the height by 1.5 for the U and V planes.
+        */
+       if (handle->format == HAL_PIXEL_FORMAT_YV12) {
+               width /= 2;
+               height += handle->height / 2;
+       }
+
+       ALOGV("create BO, size=%dx%d, fmt=%d, usage=%x",
              handle->width, handle->height, handle->format, usage);
-       buf->bo = gbm_bo_create(gbm, width, height, format, usage);
-       if (!buf->bo) {
+       bo = gbm_bo_create(gbm, width, height, format, usage);
+       if (!bo) {
                ALOGE("failed to create BO, size=%dx%d, fmt=%d, usage=%x",
                      handle->width, handle->height, handle->format, usage);
-               delete buf;
                return NULL;
        }
 
-       handle->prime_fd = gbm_bo_get_fd(buf->bo);
-       handle->stride = gbm_bo_get_stride(buf->bo);
+       handle->prime_fd = gbm_bo_get_fd(bo);
+       handle->stride = gbm_bo_get_stride(bo);
+       #ifdef GBM_BO_IMPORT_FD_MODIFIER
+       handle->modifier = gbm_bo_get_modifier(bo);
+       #endif
 
-       return buf;
+       return bo;
 }
 
-static void gbm_free(struct gralloc_gbm_bo_t *bo)
+int gbm_free(buffer_handle_t handle)
 {
-       struct gralloc_gbm_handle_t *handle = bo->handle;
+       struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
 
-       close(handle->prime_fd);
-       handle->prime_fd = -1;
+       if (!bo)
+               return -EINVAL;
 
-       gbm_bo_destroy(bo->bo);
-       delete bo;
+       gbm_bo_handle_map.erase(handle);
+       gbm_bo_destroy(bo);
+       return 0;
 }
 
-static int gbm_map(struct gralloc_gbm_bo_t *bo, int x, int y, int w, int h,
-               int enable_write, void **addr)
+/*
+ * Return the bo of a registered handle.
+ */
+struct gbm_bo *gralloc_gbm_bo_from_handle(buffer_handle_t handle)
+{
+       return gbm_bo_handle_map[handle];
+}
+
+static int gbm_map(buffer_handle_t handle, int enable_write, void **addr)
 {
        int err = 0;
+       int flags = GBM_BO_TRANSFER_READ;
+       struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
+       struct bo_data_t *bo_data = gbm_bo_data(bo);
+       uint32_t stride;
 
-       if (bo->map_data)
+       if (bo_data->map_data)
                return -EINVAL;
 
-       *addr = gbm_bo_map(bo->bo, x, y, w, h, 0, &bo->map_data);
-       ALOGE("mapped bo %p at %p", bo, *addr);
+       if (enable_write)
+               flags |= GBM_BO_TRANSFER_WRITE;
+
+       *addr = gbm_bo_map(bo, 0, 0, gbm_bo_get_width(bo), gbm_bo_get_height(bo),
+                          flags, &stride, &bo_data->map_data);
+       ALOGV("mapped bo %p at %p", bo, *addr);
        if (*addr == NULL)
-               err = -ENOMEM;
+               return -ENOMEM;
+
+       assert(stride == gbm_bo_get_stride(bo));
 
        return err;
 }
 
-static void gbm_unmap(struct gralloc_gbm_bo_t *bo)
+static void gbm_unmap(struct gbm_bo *bo)
 {
-       gbm_bo_unmap(bo->bo, bo->map_data);
-       bo->map_data = NULL;
+       struct bo_data_t *bo_data = gbm_bo_data(bo);
+
+       gbm_bo_unmap(bo, bo_data->map_data);
+       bo_data->map_data = NULL;
 }
 
 void gbm_dev_destroy(struct gbm_device *gbm)
@@ -219,14 +301,17 @@ void gbm_dev_destroy(struct gbm_device *gbm)
        close(fd);
 }
 
-struct gbm_device *gbm_dev_create(void)
+struct gbm_device *gbm_dev_create(bool master)
 {
        struct gbm_device *gbm;
        char path[PROPERTY_VALUE_MAX];
        int fd;
 
-       property_get("gralloc.gbm.device", path, "/dev/dri/renderD128");
-       fd = open(path, O_RDWR);
+       if (property_get("gralloc.gbm.device", path, NULL) > 0)
+               fd = open(path, O_RDWR | O_CLOEXEC);
+       else
+               fd = drmOpenByFB(0, master ? DRM_NODE_PRIMARY : DRM_NODE_RENDER);
+
        if (fd < 0) {
                ALOGE("failed to open %s", path);
                return NULL;
@@ -235,234 +320,114 @@ struct gbm_device *gbm_dev_create(void)
        gbm = gbm_create_device(fd);
        if (!gbm) {
                ALOGE("failed to create gbm device");
+               close(fd);
        }
 
        return gbm;
 }
 
 /*
- * Return the pid of the process.
- */
-static int gralloc_gbm_get_pid(void)
-{
-       if (unlikely(!gralloc_gbm_pid))
-               android_atomic_write((int32_t) getpid(), &gralloc_gbm_pid);
-
-       return gralloc_gbm_pid;
-}
-
-/*
- * Validate a buffer handle and return the associated bo.
- */
-static struct gralloc_gbm_bo_t *validate_handle(buffer_handle_t _handle,
-               struct gbm_device *gbm)
-{
-       struct gralloc_gbm_bo_t *bo;
-       struct gralloc_gbm_handle_t *handle = gralloc_gbm_handle(_handle);
-
-       if (!handle)
-               return NULL;
-
-       /* the buffer handle is passed to a new process */
-       //ALOGE("data_owner=%d gralloc_pid=%d data=%p\n", handle->data_owner, gralloc_gbm_get_pid(), handle->data);
-       if (handle->data_owner == gralloc_gbm_get_pid())
-               return (struct gralloc_gbm_bo_t *)handle->data;
-
-       /* check only */
-       if (!gbm)
-               return NULL;
-
-       ALOGE("handle: name=%d pfd=%d\n", handle->name,
-               handle->prime_fd);
-       /* create the struct gralloc_gbm_bo_t locally */
-       if (handle->name || handle->prime_fd >= 0)
-               bo = gbm_import(gbm, handle);
-       else /* an invalid handle */
-               bo = NULL;
-       if (bo) {
-               bo->imported = 1;
-               bo->handle = handle;
-               bo->refcount = 1;
-       }
-
-       handle->data_owner = gralloc_gbm_get_pid();
-       handle->data = bo;
-
-       return bo;
-}
-
-/*
  * Register a buffer handle.
  */
-int gralloc_gbm_handle_register(buffer_handle_t handle, struct gbm_device *gbm)
+int gralloc_gbm_handle_register(buffer_handle_t _handle, struct gbm_device *gbm)
 {
-       return (validate_handle(handle, gbm)) ? 0 : -EINVAL;
-}
+       struct gbm_bo *bo;
 
-/*
- * Unregister a buffer handle.  It is no-op for handles created locally.
- */
-int gralloc_gbm_handle_unregister(buffer_handle_t handle)
-{
-       struct gralloc_gbm_bo_t *bo;
+       if (!_handle)
+               return -EINVAL;
+
+       if (gbm_bo_handle_map.count(_handle))
+               return -EINVAL;
 
-       bo = validate_handle(handle, NULL);
+       bo = gbm_import(gbm, _handle);
        if (!bo)
                return -EINVAL;
 
-       if (bo->imported)
-               gralloc_gbm_bo_decref(bo);
+       gbm_bo_handle_map.emplace(_handle, bo);
 
        return 0;
 }
 
 /*
- * Create a buffer handle.
+ * Unregister a buffer handle.  It is no-op for handles created locally.
  */
-static struct gralloc_gbm_handle_t *create_bo_handle(int width,
-               int height, int format, int usage)
+int gralloc_gbm_handle_unregister(buffer_handle_t handle)
 {
-       struct gralloc_gbm_handle_t *handle;
-
-       handle = new gralloc_gbm_handle_t();
-       if (!handle)
-               return NULL;
-
-       handle->base.version = sizeof(handle->base);
-       handle->base.numInts = GRALLOC_GBM_HANDLE_NUM_INTS;
-       handle->base.numFds = GRALLOC_GBM_HANDLE_NUM_FDS;
-
-       handle->magic = GRALLOC_GBM_HANDLE_MAGIC;
-       handle->width = width;
-       handle->height = height;
-       handle->format = format;
-       handle->usage = usage;
-       handle->prime_fd = -1;
-
-       return handle;
+       return gbm_free(handle);
 }
 
 /*
  * Create a bo.
  */
-struct gralloc_gbm_bo_t *gralloc_gbm_bo_create(struct gbm_device *gbm,
-               int width, int height, int format, int usage)
+buffer_handle_t gralloc_gbm_bo_create(struct gbm_device *gbm,
+               int width, int height, int format, int usage, int *stride)
 {
-       struct gralloc_gbm_bo_t *bo;
-       struct gralloc_gbm_handle_t *handle;
+       struct gbm_bo *bo;
+       native_handle_t *handle;
 
-       handle = create_bo_handle(width, height, format, usage);
+       handle = gralloc_handle_create(width, height, format, usage);
        if (!handle)
                return NULL;
 
        bo = gbm_alloc(gbm, handle);
        if (!bo) {
-               delete handle;
+               native_handle_delete(handle);
                return NULL;
        }
 
-       bo->imported = 0;
-       bo->handle = handle;
-       bo->refcount = 1;
-
-       handle->data_owner = gralloc_gbm_get_pid();
-       handle->data = bo;
-
-       return bo;
-}
-
-/*
- * Destroy a bo.
- */
-static void gralloc_gbm_bo_destroy(struct gralloc_gbm_bo_t *bo)
-{
-       struct gralloc_gbm_handle_t *handle = bo->handle;
-       int imported = bo->imported;
-
-       /* gralloc still has a reference */
-       if (bo->refcount)
-               return;
-
-       gbm_free(bo);
-       if (imported) {
-               handle->data_owner = 0;
-               handle->data = 0;
-       }
-       else {
-               delete handle;
-       }
-}
-
-/*
- * Decrease refcount, if no refs anymore then destroy.
- */
-void gralloc_gbm_bo_decref(struct gralloc_gbm_bo_t *bo)
-{
-       if (!--bo->refcount)
-               gralloc_gbm_bo_destroy(bo);
-}
-
-/*
- * Return the bo of a registered handle.
- */
-struct gralloc_gbm_bo_t *gralloc_gbm_bo_from_handle(buffer_handle_t handle)
-{
-       return validate_handle(handle, NULL);
-}
+       gbm_bo_handle_map.emplace(handle, bo);
 
-/*
- * Get the buffer handle and stride of a bo.
- */
-buffer_handle_t gralloc_gbm_bo_get_handle(struct gralloc_gbm_bo_t *bo)
-{
-       return &bo->handle->base;
-}
+       /* in pixels */
+       *stride = gralloc_handle(handle)->stride / gralloc_gbm_get_bpp(format);
 
-/*
- * Get the buffer handle and stride of a bo.
- */
-struct gbm_bo *gralloc_gbm_bo_to_gbm_bo(struct gralloc_gbm_bo_t *_bo)
-{
-       return _bo->bo;
+       return handle;
 }
 
 /*
- * Query YUV component offsets for a buffer handle
- */
-void gralloc_gbm_resolve_format(buffer_handle_t _handle,
-       uint32_t *pitches, uint32_t *offsets, uint32_t *handles)
-{}
-
-/*
  * Lock a bo.  XXX thread-safety?
  */
-int gralloc_gbm_bo_lock(struct gralloc_gbm_bo_t *bo,
-               int usage, int x, int y, int w, int h,
+int gralloc_gbm_bo_lock(buffer_handle_t handle,
+               int usage, int /*x*/, int /*y*/, int /*w*/, int /*h*/,
                void **addr)
 {
-       if ((bo->handle->usage & usage) != usage) {
+       struct gralloc_handle_t *gbm_handle = gralloc_handle(handle);
+       struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
+       struct bo_data_t *bo_data;
+
+       if (!bo)
+               return -EINVAL;
+
+       if ((gbm_handle->usage & usage) != (uint32_t)usage) {
                /* make FB special for testing software renderer with */
 
-               if (!(bo->handle->usage & GRALLOC_USAGE_SW_READ_OFTEN) &&
-                               !(bo->handle->usage & GRALLOC_USAGE_HW_FB) &&
-                               !(bo->handle->usage & GRALLOC_USAGE_HW_TEXTURE)) {
+               if (!(gbm_handle->usage & GRALLOC_USAGE_SW_READ_OFTEN) &&
+                               !(gbm_handle->usage & GRALLOC_USAGE_HW_FB) &&
+                               !(gbm_handle->usage & GRALLOC_USAGE_HW_TEXTURE)) {
                        ALOGE("bo.usage:x%X/usage:x%X is not GRALLOC_USAGE_HW_FB or GRALLOC_USAGE_HW_TEXTURE",
-                               bo->handle->usage, usage);
+                               gbm_handle->usage, usage);
                        return -EINVAL;
                }
        }
 
+       bo_data = gbm_bo_data(bo);
+       if (!bo_data) {
+               bo_data = new struct bo_data_t();
+               gbm_bo_set_user_data(bo, bo_data, gralloc_gbm_destroy_user_data);
+       }
+
+       ALOGV("lock bo %p, cnt=%d, usage=%x", bo, bo_data->lock_count, usage);
+
        /* allow multiple locks with compatible usages */
-       if (bo->lock_count && (bo->locked_for & usage) != usage)
+       if (bo_data->lock_count && (bo_data->locked_for & usage) != usage)
                return -EINVAL;
 
-       usage |= bo->locked_for;
+       usage |= bo_data->locked_for;
 
        if (usage & (GRALLOC_USAGE_SW_WRITE_MASK |
                     GRALLOC_USAGE_SW_READ_MASK)) {
                /* the driver is supposed to wait for the bo */
                int write = !!(usage & GRALLOC_USAGE_SW_WRITE_MASK);
-               int err = gbm_map(bo, x, y, w, h, write, addr);
+               int err = gbm_map(handle, write, addr);
                if (err)
                        return err;
        }
@@ -470,8 +435,8 @@ int gralloc_gbm_bo_lock(struct gralloc_gbm_bo_t *bo,
                /* kernel handles the synchronization here */
        }
 
-       bo->lock_count++;
-       bo->locked_for |= usage;
+       bo_data->lock_count++;
+       bo_data->locked_for |= usage;
 
        return 0;
 }
@@ -479,18 +444,74 @@ int gralloc_gbm_bo_lock(struct gralloc_gbm_bo_t *bo,
 /*
  * Unlock a bo.
  */
-void gralloc_gbm_bo_unlock(struct gralloc_gbm_bo_t *bo)
+int gralloc_gbm_bo_unlock(buffer_handle_t handle)
 {
-       int mapped = bo->locked_for &
+       struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
+       struct bo_data_t *bo_data;
+       if (!bo)
+               return -EINVAL;
+
+       bo_data = gbm_bo_data(bo);
+
+       int mapped = bo_data->locked_for &
                (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_SW_READ_MASK);
 
-       if (!bo->lock_count)
-               return;
+       if (!bo_data->lock_count)
+               return 0;
 
        if (mapped)
                gbm_unmap(bo);
 
-       bo->lock_count--;
-       if (!bo->lock_count)
-               bo->locked_for = 0;
+       bo_data->lock_count--;
+       if (!bo_data->lock_count)
+               bo_data->locked_for = 0;
+
+       return 0;
+}
+
+#define GRALLOC_ALIGN(value, base) (((value) + ((base)-1)) & ~((base)-1))
+
+int gralloc_gbm_bo_lock_ycbcr(buffer_handle_t handle,
+               int usage, int x, int y, int w, int h,
+               struct android_ycbcr *ycbcr)
+{
+       struct gralloc_handle_t *hnd = gralloc_handle(handle);
+       int ystride, cstride;
+       void *addr = 0;
+       int err;
+
+       ALOGV("handle %p, hnd %p, usage 0x%x", handle, hnd, usage);
+
+       err = gralloc_gbm_bo_lock(handle, usage, x, y, w, h, &addr);
+       if (err)
+               return err;
+
+       memset(ycbcr->reserved, 0, sizeof(ycbcr->reserved));
+
+       switch (hnd->format) {
+       case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+               ystride = cstride = GRALLOC_ALIGN(hnd->width, 16);
+               ycbcr->y = addr;
+               ycbcr->cr = (unsigned char *)addr + ystride * hnd->height;
+               ycbcr->cb = (unsigned char *)addr + ystride * hnd->height + 1;
+               ycbcr->ystride = ystride;
+               ycbcr->cstride = cstride;
+               ycbcr->chroma_step = 2;
+               break;
+       case HAL_PIXEL_FORMAT_YV12:
+               ystride = hnd->width;
+               cstride = GRALLOC_ALIGN(ystride / 2, 16);
+               ycbcr->y = addr;
+               ycbcr->cr = (unsigned char *)addr + ystride * hnd->height;
+               ycbcr->cb = (unsigned char *)addr + ystride * hnd->height + cstride * hnd->height / 2;
+               ycbcr->ystride = ystride;
+               ycbcr->cstride = cstride;
+               ycbcr->chroma_step = 1;
+               break;
+       default:
+               ALOGE("Can not lock buffer, invalid format: 0x%x", hnd->format);
+               return -EINVAL;
+       }
+
+       return 0;
 }