From 2197d5d9246d0009b63fa8333b5379f256d5f80a Mon Sep 17 00:00:00 2001 From: Naomi Luis Date: Tue, 6 Dec 2011 11:51:27 -0800 Subject: [PATCH] libcopybit: Add support for YUV destination targets. Add support in the c2d copybit for YUV destination. We support 2 and 3 plane yuv formats. Change-Id: Ia2b4dadf2966a324e011fea499da996eee8c8c3c --- libcopybit/copybit_c2d.cpp | 365 +++++++++++++++++++++++++++---------- 1 file changed, 273 insertions(+), 92 deletions(-) diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp index f703f05..e3d6308 100644 --- a/libcopybit/copybit_c2d.cpp +++ b/libcopybit/copybit_c2d.cpp @@ -85,18 +85,26 @@ C2D_STATUS (*LINK_c2dDestroySurface)( uint32 surface_id ); #define COPYBIT_SUCCESS 0 #define COPYBIT_FAILURE -1 - -#define RGB_SURFACE 0 -#define YUV_SURFACE 1 -#define NUM_SRC_SURFACES 2 +#define NUM_SURFACES 3 #define ALIGN(x, align) (((x) + ((align)-1)) & ~((align)-1)) + +enum { + RGB_SURFACE, + YUV_SURFACE_2_PLANES, + YUV_SURFACE_3_PLANES +}; + +enum eC2DFlags { + FLAGS_PREMULTIPLIED_ALPHA = 1<<0, + FLAGS_YUV_DESTINATION = 1<<1 +}; /******************************************************************************/ /** State information for each device instance */ struct copybit_context_t { struct copybit_device_t device; - unsigned int src[NUM_SRC_SURFACES]; - unsigned int dst; /* dst surface */ + unsigned int src[NUM_SURFACES]; /* src surfaces */ + unsigned int dst[NUM_SURFACES]; /* dst surfaces */ unsigned int trg_transform; /* target transform */ C2D_OBJECT blitState; void *libc2d2; @@ -111,6 +119,21 @@ struct blitlist{ C2D_OBJECT blitObjects[12]; }; +struct bufferInfo { + int width; + int height; + int format; +}; + + +struct yuvPlaneInfo { + int yStride; //luma stride + int plane1_stride; + int plane2_stride; + int plane1_offset; + int plane2_offset; +}; + /** * Common hardware methods */ @@ -148,9 +171,25 @@ static int get_format(int format) { case HAL_PIXEL_FORMAT_RGBA_5551: return C2D_COLOR_FORMAT_5551_RGBA; case HAL_PIXEL_FORMAT_RGBA_4444: return C2D_COLOR_FORMAT_4444_RGBA; case HAL_PIXEL_FORMAT_YCbCr_420_SP: return C2D_COLOR_FORMAT_420_NV12; + case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV12; case HAL_PIXEL_FORMAT_YCrCb_420_SP: return C2D_COLOR_FORMAT_420_NV21; case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: return C2D_COLOR_FORMAT_420_NV12 | C2D_FORMAT_MACROTILED; - default: return -EINVAL; + default: LOGE("%s: invalid format (0x%x", __FUNCTION__, format); return -EINVAL; + } + return -EINVAL; +} + +/* Get the C2D formats needed for conversion to YUV */ +static int get_c2d_format_for_yuv_destination(int halFormat) { + switch (halFormat) { + // We do not swap the RB when the target is YUV + case HAL_PIXEL_FORMAT_RGBX_8888: return C2D_COLOR_FORMAT_8888_ARGB | C2D_FORMAT_DISABLE_ALPHA; + case HAL_PIXEL_FORMAT_RGBA_8888: return C2D_COLOR_FORMAT_8888_ARGB; + // The U and V need to be interchanged when the target is YUV + case HAL_PIXEL_FORMAT_YCbCr_420_SP: return C2D_COLOR_FORMAT_420_NV21; + case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV21; + case HAL_PIXEL_FORMAT_YCrCb_420_SP: return C2D_COLOR_FORMAT_420_NV12; + default: return get_format(halFormat); } return -EINVAL; } @@ -254,11 +293,28 @@ static int is_supported_rgb_format(int format) } } +static int get_num_planes(int format) +{ + switch(format) { + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: { + return 2; + } + case HAL_PIXEL_FORMAT_YV12: { + return 3; + } + default: + return COPYBIT_FAILURE; + } +} + static int is_supported_yuv_format(int format) { switch(format) { case HAL_PIXEL_FORMAT_YCbCr_420_SP: case HAL_PIXEL_FORMAT_YCrCb_420_SP: + case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: { return COPYBIT_SUCCESS; } @@ -267,8 +323,21 @@ static int is_supported_yuv_format(int format) } } -static int calculate_yuv_offset_and_stride(int format, int width, int height, int *offset, int *yStride, int *uvStride) +static int is_valid_destination_format(int format) { + if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) { + // C2D does not support NV12Tile as a destination format. + return COPYBIT_FAILURE; + } + return COPYBIT_SUCCESS; +} + +static int calculate_yuv_offset_and_stride(const bufferInfo& info, yuvPlaneInfo& yuvInfo) +{ + int width = info.width; + int height = info.height; + int format = info.format; + int aligned_height = 0; int aligned_width = 0, size = 0; @@ -280,17 +349,23 @@ static int calculate_yuv_offset_and_stride(int format, int width, int height, in aligned_height = ALIGN(height, 32); aligned_width = ALIGN(width, 128); size = aligned_width * aligned_height; - *offset = ALIGN(size,8192); - *yStride = aligned_width; - *uvStride = aligned_width; + yuvInfo.plane1_offset = ALIGN(size,8192); + yuvInfo.yStride = aligned_width; + yuvInfo.plane1_stride = aligned_width; break; } case HAL_PIXEL_FORMAT_YCbCr_420_SP: + case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: case HAL_PIXEL_FORMAT_YCrCb_420_SP: { aligned_width = ALIGN(width, 32); - *offset = aligned_width * height; - *yStride = aligned_width; - *uvStride = aligned_width; + yuvInfo.yStride = aligned_width; + yuvInfo.plane1_stride = aligned_width; + if (HAL_PIXEL_FORMAT_NV12_ENCODEABLE == format) { + // The encoder requires a 2K aligned chroma offset + yuvInfo.plane1_offset = ALIGN(aligned_width * height, 2048); + } else + yuvInfo.plane1_offset = aligned_width * height; + break; } default: { @@ -302,15 +377,20 @@ static int calculate_yuv_offset_and_stride(int format, int width, int height, in /** create C2D surface from copybit image */ static int set_image(int device_fd, uint32 surfaceId, const struct copybit_image_t *rhs, int *cformat, uint32_t *mapped, - const bool isPremultipliedAlpha) + const eC2DFlags flags) { struct private_handle_t* handle = (struct private_handle_t*)rhs->handle; C2D_SURFACE_TYPE surfaceType; int status = COPYBIT_SUCCESS; - *cformat = get_format(rhs->format); + if (flags & FLAGS_YUV_DESTINATION) { + *cformat = get_c2d_format_for_yuv_destination(rhs->format); + } else { + *cformat = get_format(rhs->format); + } + if(*cformat == -EINVAL) { - LOGE("%s: invalid format", __func__); + LOGE("%s: invalid format", __FUNCTION__); return -EINVAL; } @@ -322,6 +402,7 @@ static int set_image(int device_fd, uint32 surfaceId, const struct copybit_image if (handle->gpuaddr == 0) { handle->gpuaddr = c2d_get_gpuaddr(device_fd, handle); if(!handle->gpuaddr) { + LOGE("%s: c2d_get_gpuaddr failed", __FUNCTION__); return COPYBIT_FAILURE; } *mapped = 1; @@ -337,28 +418,31 @@ static int set_image(int device_fd, uint32 surfaceId, const struct copybit_image surfaceDef.phys = (void*) handle->gpuaddr; surfaceDef.buffer = (void*) (handle->base); - surfaceDef.format = *cformat | (isPremultipliedAlpha ? C2D_FORMAT_PREMULTIPLIED : 0); + surfaceDef.format = *cformat | ((flags & FLAGS_PREMULTIPLIED_ALPHA) ? C2D_FORMAT_PREMULTIPLIED : 0); surfaceDef.width = rhs->w; surfaceDef.height = rhs->h; surfaceDef.stride = ALIGN(((surfaceDef.width * c2diGetBpp(surfaceDef.format))>>3), 32); if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType, &surfaceDef)) { - LOGE("%s: RGB Surface c2dUpdateSurface ERROR", __func__); + LOGE("%s: RGB Surface c2dUpdateSurface ERROR", __FUNCTION__); goto error; status = COPYBIT_FAILURE; } } else if (is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) { C2D_YUV_SURFACE_DEF surfaceDef; - int offset = 0; - int yStride = 0; - int uvStride = 0; memset(&surfaceDef, 0, sizeof(surfaceDef)); surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS); surfaceDef.format = *cformat; - status = calculate_yuv_offset_and_stride(rhs->format, rhs->w, rhs->h, &offset, &yStride, &uvStride); + bufferInfo info; + info.width = rhs->w; + info.height = rhs->h; + info.format = rhs->format; + + yuvPlaneInfo yuvInfo; + status = calculate_yuv_offset_and_stride(info, yuvInfo); if(status != COPYBIT_SUCCESS) { - LOGE("calculate_yuv_offset_and_stride error"); + LOGE("%s: calculate_yuv_offset_and_stride error", __FUNCTION__); goto error; } @@ -366,19 +450,24 @@ static int set_image(int device_fd, uint32 surfaceId, const struct copybit_image surfaceDef.height = rhs->h; surfaceDef.plane0 = (void*) (handle->base); surfaceDef.phys0 = (void*) (handle->gpuaddr); - surfaceDef.stride0 = yStride; + surfaceDef.stride0 = yuvInfo.yStride; - surfaceDef.plane1 = (void*) (handle->base + offset); - surfaceDef.phys1 = (void*) (handle->gpuaddr + offset); - surfaceDef.stride1 = uvStride; + surfaceDef.plane1 = (void*) (handle->base + yuvInfo.plane1_offset); + surfaceDef.phys1 = (void*) (handle->gpuaddr + yuvInfo.plane1_offset); + surfaceDef.stride1 = yuvInfo.plane1_stride; + if (3 == get_num_planes(rhs->format)) { + surfaceDef.plane2 = (void*) (handle->base + yuvInfo.plane2_offset); + surfaceDef.phys2 = (void*) (handle->gpuaddr + yuvInfo.plane2_offset); + surfaceDef.stride2 = yuvInfo.plane2_stride; + } if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType, &surfaceDef)) { - LOGE("%s: YUV Surface c2dUpdateSurface ERROR", __func__); + LOGE("%s: YUV Surface c2dUpdateSurface ERROR", __FUNCTION__); goto error; status = COPYBIT_FAILURE; } } else { - LOGE("%s: invalid format %x", __func__, rhs->format); + LOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format); goto error; status = COPYBIT_FAILURE; } @@ -427,7 +516,7 @@ static int set_src_image(int device_fd, uint32 *surfaceId, const struct copybit_ surfaceDef.stride = ALIGN(((surfaceDef.width * c2diGetBpp(surfaceDef.format))>>3), 32); if(LINK_c2dCreateSurface( surfaceId, C2D_TARGET, surfaceType,(void*)&surfaceDef)) { - LOGE("%s: LINK_c2dCreateSurface error", __func__); + LOGE("%s: LINK_c2dCreateSurface error", __FUNCTION__); status = COPYBIT_FAILURE; goto error; } @@ -441,9 +530,15 @@ static int set_src_image(int device_fd, uint32 *surfaceId, const struct copybit_ surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS); surfaceDef.format = get_format(rhs->format); - status = calculate_yuv_offset_and_stride(rhs->format, rhs->w, rhs->h, &offset, &yStride, &uvStride); + bufferInfo info; + info.width = rhs->w; + info.height = rhs->h; + info.format = rhs->format; + + yuvPlaneInfo yuvInfo; + status = calculate_yuv_offset_and_stride(info, yuvInfo); if(status != COPYBIT_SUCCESS) { - LOGE("calculate_yuv_offset_and_stride error"); + LOGE("%s: calculate_yuv_offset_and_stride error", __FUNCTION__); goto error; } @@ -451,11 +546,11 @@ static int set_src_image(int device_fd, uint32 *surfaceId, const struct copybit_ surfaceDef.height = rhs->h; surfaceDef.plane0 = (void*) (handle->base); surfaceDef.phys0 = (void*) handle->gpuaddr; - surfaceDef.stride0 = yStride; + surfaceDef.stride0 = yuvInfo.yStride; - surfaceDef.plane1 = (void*) (handle->base + offset); - surfaceDef.phys1 = (void*) (handle->gpuaddr + offset); - surfaceDef.stride1 = uvStride; + surfaceDef.plane1 = (void*) (handle->base + yuvInfo.plane1_offset); + surfaceDef.phys1 = (void*) (handle->gpuaddr + yuvInfo.plane1_offset); + surfaceDef.stride1 = yuvInfo.plane1_stride; if(LINK_c2dCreateSurface( surfaceId, C2D_TARGET | C2D_SOURCE, surfaceType, (void*)&surfaceDef)) { LOGE("%s: YUV surface LINK_c2dCreateSurface error", __func__); @@ -463,7 +558,7 @@ static int set_src_image(int device_fd, uint32 *surfaceId, const struct copybit_ goto error; } } else { - LOGE("%s: Invalid format %x", __func__, rhs->format); + LOGE("%s: Invalid format 0x%x", __FUNCTION__, rhs->format); status = COPYBIT_FAILURE; } @@ -598,7 +693,7 @@ static int msm_copybit(struct copybit_context_t *dev, blitlist *list, uint32 tar if(LINK_c2dDraw(target,dev->trg_transform, 0x0, 0, 0, list->blitObjects, list->count)) { - LOGE("%s: LINK_c2dDraw ERROR"); + LOGE("%s: LINK_c2dDraw ERROR", __FUNCTION__); return COPYBIT_FAILURE; } @@ -615,7 +710,7 @@ static int set_parameter_copybit( { struct copybit_context_t* ctx = (struct copybit_context_t*)dev; if (!ctx) { - LOGE("%s: null context", __func__); + LOGE("%s: null context", __FUNCTION__); return -EINVAL; } @@ -746,20 +841,20 @@ static int stretch_copybit_internal( memset(&list, 0, sizeof(list)); int cformat; c2d_ts_handle timestamp; - uint32 surface_index = 0; + uint32 src_surface_index = 0, dst_surface_index = 0; if (!ctx) { - LOGE("%s: null context error", __func__); + LOGE("%s: null context error", __FUNCTION__); return -EINVAL; } if (src->w > MAX_DIMENSION || src->h > MAX_DIMENSION) { - LOGE("%s: src dimension error", __func__); + LOGE("%s: src dimension error", __FUNCTION__); return -EINVAL; } if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) { - LOGE("%s : dst dimension error dst w %d h %d", __func__, dst->w, dst->h); + LOGE("%s : dst dimension error dst w %d h %d", __FUNCTION__, dst->w, dst->h); return -EINVAL; } @@ -768,22 +863,63 @@ static int stretch_copybit_internal( struct copybit_rect_t clip; list.count = 0; - status = set_image(ctx->g12_device_fd, ctx->dst, dst, &cformat, &trg_mapped, ctx->isPremultipliedAlpha); + if (is_valid_destination_format(dst->format) == COPYBIT_FAILURE) { + LOGE("%s: Invalid destination format format = 0x%x", __FUNCTION__, dst->format); + return COPYBIT_FAILURE; + } + + bool isYUVDestination = false; + if (is_supported_rgb_format(dst->format) == COPYBIT_SUCCESS) { + dst_surface_index = RGB_SURFACE; + } else if (is_supported_yuv_format(dst->format) == COPYBIT_SUCCESS) { + isYUVDestination = true; + int num_planes = get_num_planes(dst->format); + if (num_planes == 2) { + dst_surface_index = YUV_SURFACE_2_PLANES; + } else if (num_planes == 3) { + dst_surface_index = YUV_SURFACE_3_PLANES; + } else { + LOGE("%s: dst number of YUV planes is invalid dst format = 0x%x", + __FUNCTION__, dst->format); + return COPYBIT_FAILURE; + } + } else { + LOGE("%s: Invalid dst surface format 0x%x", __FUNCTION__, dst->format); + return COPYBIT_FAILURE; + } + + + int flags = 0; + flags |= (ctx->isPremultipliedAlpha) ? FLAGS_PREMULTIPLIED_ALPHA : 0; + flags |= (isYUVDestination) ? FLAGS_YUV_DESTINATION : 0; + + status = set_image(ctx->g12_device_fd, ctx->dst[dst_surface_index], dst, &cformat, + &trg_mapped, (eC2DFlags)flags); if(status) { LOGE("%s: set_image error", __func__); return COPYBIT_FAILURE; } if(is_supported_rgb_format(src->format) == COPYBIT_SUCCESS) { - surface_index = RGB_SURFACE; + src_surface_index = RGB_SURFACE; } else if (is_supported_yuv_format(src->format) == COPYBIT_SUCCESS) { - surface_index = YUV_SURFACE; + int num_planes = get_num_planes(src->format); + if (num_planes == 2) { + src_surface_index = YUV_SURFACE_2_PLANES; + } else if (num_planes == 3) { + src_surface_index = YUV_SURFACE_3_PLANES; + } else { + LOGE("%s: src number of YUV planes is invalid src format = 0x%x", + __FUNCTION__, src->format); + return -EINVAL; + } } else { LOGE("%s: Invalid source surface format %x", __func__, src->format); return -EINVAL; } - status = set_image(ctx->g12_device_fd, ctx->src[surface_index], src, &cformat, &src_mapped, ctx->isPremultipliedAlpha); + status = set_image(ctx->g12_device_fd, ctx->src[src_surface_index], src, &cformat, + &src_mapped, (eC2DFlags)flags); if(status) { LOGE("%s: set_src_image error", __func__); return COPYBIT_FAILURE; @@ -794,8 +930,8 @@ static int stretch_copybit_internal( ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE; if(!(ctx->blitState.global_alpha)) { // src alpha is zero - unset_image(ctx->g12_device_fd, ctx->src[surface_index], src, src_mapped); - unset_image(ctx->g12_device_fd, ctx->dst, dst, trg_mapped); + unset_image(ctx->g12_device_fd, ctx->src[src_surface_index], src, src_mapped); + unset_image(ctx->g12_device_fd, ctx->dst[dst_surface_index], dst, trg_mapped); return status; } } else { @@ -808,7 +944,7 @@ static int stretch_copybit_internal( ctx->blitState.config_mask |= C2D_ALPHA_BLEND_NONE; } - ctx->blitState.surface_id = ctx->src[surface_index]; + ctx->blitState.surface_id = ctx->src[src_surface_index]; while ((status == 0) && region->next(region, &clip)) { req = &(list.blitObjects[list.count]); @@ -817,21 +953,21 @@ static int stretch_copybit_internal( set_rects(ctx, req, dst_rect, src_rect, &clip); if (++list.count == maxCount) { - status = msm_copybit(ctx, &list, ctx->dst); + status = msm_copybit(ctx, &list, ctx->dst[dst_surface_index]); list.count = 0; } } if ((status == 0) && list.count) { - status = msm_copybit(ctx, &list, ctx->dst); + status = msm_copybit(ctx, &list, ctx->dst[dst_surface_index]); } - if(LINK_c2dFinish(ctx->dst)) { - LOGE("%s: LINK_c2dFinish ERROR", __func__); + if(LINK_c2dFinish(ctx->dst[dst_surface_index])) { + LOGE("%s: LINK_c2dFinish ERROR", __FUNCTION__); } - unset_image(ctx->g12_device_fd, ctx->src[surface_index], src, src_mapped); - unset_image(ctx->g12_device_fd, ctx->dst, dst, trg_mapped); + unset_image(ctx->g12_device_fd, ctx->src[src_surface_index], src, src_mapped); + unset_image(ctx->g12_device_fd, ctx->dst[dst_surface_index], dst, trg_mapped); ctx->isPremultipliedAlpha = false; return status; } @@ -866,8 +1002,8 @@ static int close_copybit(struct hw_device_t *dev) { struct copybit_context_t* ctx = (struct copybit_context_t*)dev; if (ctx) { - LINK_c2dDestroySurface(ctx->dst); - for(int i = 0; i dst[i]); LINK_c2dDestroySurface(ctx->src[i]); } @@ -903,13 +1039,18 @@ static int open_copybit(const struct hw_module_t* module, const char* name, ctx = (struct copybit_context_t *)malloc(sizeof(struct copybit_context_t)); if(!ctx) { - LOGE("%s: malloc failed", __func__); + LOGE("%s: malloc failed", __FUNCTION__); return COPYBIT_FAILURE; } /* initialize drawstate */ memset(ctx, 0, sizeof(*ctx)); + for (int i=0; i< NUM_SURFACES; i++) { + ctx->dst[i] = -1; + ctx->src[i] = -1; + } + ctx->libc2d2 = ::dlopen("libC2D2.so", RTLD_NOW); if (!ctx->libc2d2) { LOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror()); @@ -929,11 +1070,11 @@ static int open_copybit(const struct hw_module_t* module, const char* name, *(void **)&LINK_c2dDestroySurface = ::dlsym(ctx->libc2d2, "c2dDestroySurface"); - if(!LINK_c2dCreateSurface || !LINK_c2dUpdateSurface || !LINK_c2dReadSurface + if (!LINK_c2dCreateSurface || !LINK_c2dUpdateSurface || !LINK_c2dReadSurface || !LINK_c2dDraw || !LINK_c2dFlush || !LINK_c2dWaitTimestamp || !LINK_c2dFinish || !LINK_c2dDestroySurface) { - LOGE("%s: dlsym ERROR", __func__); - goto error1; + LOGE("%s: dlsym ERROR", __FUNCTION__); + goto error; } ctx->device.common.tag = HARDWARE_DEVICE_TAG; @@ -947,9 +1088,9 @@ static int open_copybit(const struct hw_module_t* module, const char* name, ctx->blitState.config_mask = C2D_NO_BILINEAR_BIT | C2D_NO_ANTIALIASING_BIT; ctx->trg_transform = C2D_TARGET_ROTATE_0; ctx->g12_device_fd = open(G12_DEVICE_NAME, O_RDWR | O_SYNC); - if(ctx->g12_device_fd < 0) { - LOGE("%s: g12_device_fd open failed", __func__); - goto error1; + if (ctx->g12_device_fd < 0) { + LOGE("%s: g12_device_fd open failed", __FUNCTION__); + goto error; } /* Create RGB Surface */ @@ -959,19 +1100,21 @@ static int open_copybit(const struct hw_module_t* module, const char* name, surfDefinition.width = 1; surfDefinition.height = 1; surfDefinition.format = C2D_COLOR_FORMAT_8888_ARGB; - - if(LINK_c2dCreateSurface(&ctx->dst,C2D_TARGET | C2D_SOURCE, + if (LINK_c2dCreateSurface(&(ctx->dst[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE, (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS), &surfDefinition)) { - LOGE("%s: create ctx->dst failed", __func__); - goto error2; + LOGE("%s: create ctx->dst[RGB_SURFACE] failed", __FUNCTION__); + ctx->dst[RGB_SURFACE] = -1; + goto error; } - if(LINK_c2dCreateSurface(&(ctx->src[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE, + + if (LINK_c2dCreateSurface(&(ctx->src[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE, (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS), &surfDefinition)) { - LOGE("%s: create ctx->src[RGB_SURFACE] failed", __func__); - goto error3; + LOGE("%s: create ctx->src[RGB_SURFACE] failed", __FUNCTION__); + ctx->src[RGB_SURFACE] = -1; + goto error; } /* Create YUV source surface */ @@ -987,11 +1130,41 @@ static int open_copybit(const struct hw_module_t* module, const char* name, yuvSurfaceDef.phys1 = (void*) 0xaaaaaaaa; yuvSurfaceDef.stride1 = 4; - if(LINK_c2dCreateSurface(&(ctx->src[YUV_SURFACE]),C2D_TARGET | C2D_SOURCE, + if (LINK_c2dCreateSurface(&(ctx->src[YUV_SURFACE_2_PLANES]),C2D_TARGET | C2D_SOURCE, (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS), &yuvSurfaceDef)) { - LOGE("%s: create ctx->src[YUV_SURFACE] failed", __func__); - goto error4; + LOGE("%s: create ctx->src[YUV_SURFACE_2_PLANES] failed", __FUNCTION__); + ctx->src[YUV_SURFACE_2_PLANES] = -1; + goto error; + } + + if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_2_PLANES]),C2D_TARGET | C2D_SOURCE, + (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS), + &yuvSurfaceDef)) { + LOGE("%s: create ctx->dst[YUV_SURFACE_2_PLANES] failed", __FUNCTION__); + ctx->dst[YUV_SURFACE_2_PLANES] = -1; + goto error; + } + + yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_YV12; + yuvSurfaceDef.plane2 = (void*)0xaaaaaaaa; + yuvSurfaceDef.phys2 = (void*) 0xaaaaaaaa; + yuvSurfaceDef.stride2 = 4; + + if (LINK_c2dCreateSurface(&(ctx->src[YUV_SURFACE_3_PLANES]),C2D_TARGET | C2D_SOURCE, + (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS), + &yuvSurfaceDef)) { + LOGE("%s: create ctx->src[YUV_SURFACE_3_PLANES] failed", __FUNCTION__); + ctx->src[YUV_SURFACE_3_PLANES] = -1; + goto error; + } + + if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_3_PLANES]),C2D_TARGET | C2D_SOURCE, + (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS), + &yuvSurfaceDef)) { + LOGE("%s: create ctx->dst[YUV_SURFACE_3_PLANES] failed", __FUNCTION__); + ctx->dst[YUV_SURFACE_3_PLANES] = -1; + goto error; } *device = &ctx->device.common; @@ -1002,11 +1175,11 @@ static int open_copybit(const struct hw_module_t* module, const char* name, i++; } if (fd < 0) - goto error5; + goto error; struct fb_var_screeninfo info; if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1) - goto error6; + goto error; ctx->fb_width = info.xres; ctx->fb_height = info.yres; @@ -1014,21 +1187,29 @@ static int open_copybit(const struct hw_module_t* module, const char* name, ctx->isPremultipliedAlpha = false; return status; -error6: - close(fd); - fd = -1; -error5: - LINK_c2dDestroySurface(ctx->src[YUV_SURFACE]); -error4: - LINK_c2dDestroySurface(ctx->src[RGB_SURFACE]); -error3: - LINK_c2dDestroySurface(ctx->dst); -error2: - close(ctx->g12_device_fd); -error1: - ::dlclose(ctx->libc2d2); error: - free(ctx); + if (fd >= 0) { + close(fd); + fd = -1; + } + + for (int i = 0; isrc[i])) { + LINK_c2dDestroySurface(ctx->src[i]); + ctx->src[i] = -1; + } + if (-1 != (ctx->dst[i])) { + LINK_c2dDestroySurface(ctx->dst[i]); + ctx->dst[i] = -1; + } + } + if (ctx->g12_device_fd >= 0) { + close(ctx->g12_device_fd); + } + if (ctx->libc2d2) + ::dlclose(ctx->libc2d2); + if (ctx) + free(ctx); status = COPYBIT_FAILURE; *device = NULL;