From 6b353bd3d634042ad3129755c513f47159f8ff4e Mon Sep 17 00:00:00 2001 From: "Arun Kumar K.R" Date: Tue, 27 Nov 2012 17:18:45 -0800 Subject: libcopybit: Merge copybit HAL from jb Single commit having all the following commits commit f39e512ad6f51cf35ab00995e52a39f31e76e77f Author: Naomi Luis Date: Fri Oct 19 14:41:32 2012 -0700 copybit_c2d: Use a single draw call for surfaces with different rotations - When opening the copybit module, query the c2d driver capabilities. - If supported, use a single draw call for blitting surfaces with different orientations using the target target rotate override flag. - If not supported, invoke finish_copybit to draw the layers with the previous orientation before applying the current orientation. Change-Id: I0446f2817786321c9caa2eabf7b6679e5ecbcabe commit a4008ff75150c1591c0dca46354e6bb8b30a675b Author: Naomi Luis Date: Thu Oct 18 15:26:15 2012 -0700 Display: Add copybit_c2d performance optimizations Following performance optimizations have been made to copybit_c2d - Club all the layers into a single draw call. When finish_copybit is invoked, the draw and finish are executed. - Send the layer blend mode to copybit. - If the blend is set to none, set the pre-multiplied alpha flag. SurfaceFlinger assumes all surfaces have pre-multiplied alpha unless explicitly specified. Copybit_c2d does the same. The following cases are currently exempt from this optimization: - Change in C2D target - The template surfaces limit has been reached - Max. blit object limit has been reached. - Change in target transform. - Use of any temporary source/destination surfaces. Change-Id: I5ad1dc48bbe6d38d319116ccaa800fefb4fbf9f6 commit b188d739f69272c4820e1a33c5e10aa2f2825a5f Author: Naomi Luis Date: Mon Oct 15 11:17:11 2012 -0700 copybit: Add finish API Add the finish API to copybit. This API is used to indicate the end of the drawing required by the copybit client. Change-Id: Ica4d13dbe6e7aeb7f88aabb734bf03e86c043acc commit ecd56ace395fce78c14e2e753d3221218d062899 Author: Naomi Luis Date: Mon Oct 15 11:21:08 2012 -0700 copybit: Clean up copybit_c2d - Remove unused functions - Do nothing for the COPYBIT_BLIT_TO_FRAMEBUFFER case when using c2d composition. Change-Id: Idc416ce3742bb41f060e52ac70add44e584032b9 commit 35d45d0cff5f6fe866fcb5df71444824a45e046e Author: Naomi Luis Date: Wed Oct 17 10:37:33 2012 -0700 copybit: Use correct alignment in get_size() get_size() is used to get the size required by c2d. It's alignment should be 32 and not 16. Change-Id: I9fedca0186d0ea19883b967e127417b059621a99 commit 31311da328cbe2229fcf8d8d8e276ec64005bcb3 Author: Ramakant Singh Date: Thu Sep 20 15:58:29 2012 +0530 HWC: use uncached buffer for tmp yv12 and tmp stretch buffer. Change-Id: Iecc2a9c3c9a365d00d3491ce1007a36484209346 CRs-fixed: 396574 commit 5503c90b5001aa4d863139eebcd9c0c43f265702 Author: Pawan Kumar Date: Mon Sep 3 09:14:13 2012 +0530 copybit: Fix crash when copy_image is called with Tile format Add check for copy_image failure case. CRs-Fixed: 393122 Change-Id: I5765120e87a135795d771c5d331275a66ade7e23 commit 48975bc53702ecba66ecaa5e5769036bb91f5cf2 Merge: feb1cd6 ab25cb4 Author: Linux Build Service Account Date: Sat Sep 1 13:36:47 2012 -0700 Merge "Display ::Use proper ion heap id" into jb commit ab25cb4818d9b87886678972f2861bacc93c580a Author: Ramakant Singh Date: Thu Aug 9 14:23:39 2012 +0530 Display ::Use proper ion heap id Change the MM heap to CAMERA heap for 7627a in use case 1.Intermediate stretch of low resolution clips 2.Software conversion of Y12 format Change-Id: Ib705d3245f601256179e2dedccbc707df85eb431 CRs-Fixed: 383115 commit 90bcaadf41451d89fe80f96961ffc0a07a333145 Author: Prabhanjan Kandula Date: Mon Aug 6 12:50:12 2012 +0530 libcopybit: fix YUV buffer alignments as per gralloc buffer alignment in copybit should be in sync with gralloc allignments while allocating buffer. CRs-fixed: 377051 Change-Id: Ib2ae64e368ea3c92d3494c71da605197ccb4a9a5 Conflicts: libcopybit/copybit_c2d.cpp commit 95cf0038ea6eb02314024d673418464f0739ddb4 Author: Sravan Kumar D.V.N Date: Thu Aug 2 14:37:37 2012 +0530 copybit : Add support for NV12_ENCODABLE format Change-Id: I7087dcad2238a3c35cc15c28d75b76a9e3ca6718 Change-Id: I748bffb4215d27f609beec209af0a5047858a314 --- libcopybit/copybit_c2d.cpp | 886 ++++++++++++++++++++++++--------------------- 1 file changed, 483 insertions(+), 403 deletions(-) (limited to 'libcopybit/copybit_c2d.cpp') diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp index ea5dd2a0..6cda9a54 100644 --- a/libcopybit/copybit_c2d.cpp +++ b/libcopybit/copybit_c2d.cpp @@ -1,6 +1,9 @@ /* * Copyright (C) 2008 The Android Open Source Project - * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved. + * + * Not a Contribution, Apache license notifications and license are retained + * for attribution purposes only. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -76,10 +79,12 @@ C2D_STATUS (*LINK_c2dWaitTimestamp)( c2d_ts_handle timestamp ); C2D_STATUS (*LINK_c2dDestroySurface)( uint32 surface_id ); -C2D_STATUS (*LINK_c2dMapAddr) ( int mem_fd, void * hostptr, uint32 len, uint32 offset, uint32 flags, void ** gpuaddr); +C2D_STATUS (*LINK_c2dMapAddr) ( int mem_fd, void * hostptr, uint32 len, + uint32 offset, uint32 flags, void ** gpuaddr); C2D_STATUS (*LINK_c2dUnMapAddr) ( void * gpuaddr); +C2D_STATUS (*LINK_c2dGetDriverCapabilities) ( C2D_DRIVER_INFO * driver_info); /******************************************************************************/ #if defined(COPYBIT_Z180) @@ -89,7 +94,15 @@ C2D_STATUS (*LINK_c2dUnMapAddr) ( void * gpuaddr); #error "Unsupported HW version" #endif -#define NUM_SURFACES 3 +// The following defines can be changed as required i.e. as we encounter +// complex use cases. +#define MAX_RGB_SURFACES 8 // Max. RGB layers currently supported per draw +#define MAX_YUV_2_PLANE_SURFACES 4// Max. 2-plane YUV layers currently supported per draw +#define MAX_YUV_3_PLANE_SURFACES 1// Max. 3-plane YUV layers currently supported per draw +// +1 for the destination surface. We cannot have multiple destination surfaces. +#define MAX_SURFACES (MAX_RGB_SURFACES + MAX_YUV_2_PLANE_SURFACES + MAX_YUV_3_PLANE_SURFACES + 1) +#define NUM_SURFACE_TYPES 3 // RGB_SURFACE + YUV_SURFACE_2_PLANES + YUV_SURFACE_3_PLANES +#define MAX_BLIT_OBJECT_COUNT 50 // Max. blit objects that can be passed per draw enum { RGB_SURFACE, @@ -103,8 +116,9 @@ enum eConversionType { }; enum eC2DFlags { - FLAGS_PREMULTIPLIED_ALPHA = 1<<0, - FLAGS_YUV_DESTINATION = 1<<1 + FLAGS_PREMULTIPLIED_ALPHA = 1<<0, + FLAGS_YUV_DESTINATION = 1<<1, + FLAGS_TEMP_SRC_DST = 1<<2 }; static gralloc::IAllocController* sAlloc = 0; @@ -113,22 +127,29 @@ static gralloc::IAllocController* sAlloc = 0; /** State information for each device instance */ struct copybit_context_t { struct copybit_device_t device; - unsigned int src[NUM_SURFACES]; /* src surfaces */ - unsigned int dst[NUM_SURFACES]; /* dst surfaces */ - unsigned int trg_transform; /* target transform */ - C2D_OBJECT blitState; + // Templates for the various source surfaces. These templates are created + // to avoid the expensive create/destroy C2D Surfaces + C2D_OBJECT_STR blit_rgb_object[MAX_RGB_SURFACES]; + C2D_OBJECT_STR blit_yuv_2_plane_object[MAX_YUV_2_PLANE_SURFACES]; + C2D_OBJECT_STR blit_yuv_3_plane_object[MAX_YUV_3_PLANE_SURFACES]; + C2D_OBJECT_STR blit_list[MAX_BLIT_OBJECT_COUNT]; // Z-ordered list of blit objects + C2D_DRIVER_INFO c2d_driver_info; void *libc2d2; alloc_data temp_src_buffer; alloc_data temp_dst_buffer; + unsigned int dst[NUM_SURFACE_TYPES]; // dst surfaces + unsigned int mapped_gpu_addr[MAX_SURFACES]; // GPU addresses mapped inside copybit + int blit_rgb_count; // Total RGB surfaces being blit + int blit_yuv_2_plane_count; // Total 2 plane YUV surfaces being + int blit_yuv_3_plane_count; // Total 3 plane YUV surfaces being blit + int blit_count; // Total blit objects. + unsigned int trg_transform; /* target transform */ int fb_width; int fb_height; - bool isPremultipliedAlpha; - bool mBlitToFB; -}; - -struct blitlist{ - uint32_t count; - C2D_OBJECT blitObjects[12]; + int src_global_alpha; + int config_mask; + int dst_surface_type; + bool is_premultiplied_alpha; }; struct bufferInfo { @@ -189,7 +210,9 @@ static int get_format(int format) { 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: ALOGE("%s: invalid format (0x%x", __FUNCTION__, format); return -EINVAL; + default: ALOGE("%s: invalid format (0x%x", + __FUNCTION__, format); + return -EINVAL; } return -EINVAL; } @@ -201,7 +224,7 @@ static int get_c2d_format_for_yuv_destination(int halFormat) { 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 + // 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; @@ -251,7 +274,8 @@ int c2diGetBpp(int32 colorformat) return c2dBpp; } -static uint32 c2d_get_gpuaddr( struct private_handle_t *handle) +static uint32 c2d_get_gpuaddr(copybit_context_t* ctx, struct private_handle_t *handle, + int &mapped_idx) { uint32 memtype, *gpuaddr; C2D_STATUS rc; @@ -271,13 +295,36 @@ static uint32 c2d_get_gpuaddr( struct private_handle_t *handle) return 0; } - rc = LINK_c2dMapAddr(handle->fd, (void*)handle->base, handle->size, handle->offset, memtype, (void**)&gpuaddr); + rc = LINK_c2dMapAddr(handle->fd, (void*)handle->base, handle->size, + handle->offset, memtype, (void**)&gpuaddr); + if (rc == C2D_STATUS_OK) { + // We have mapped the GPU address inside copybit. We need to unmap this + // address after the blit. Store this address + for (int i = 0; i < MAX_SURFACES; i++) { + if (ctx->mapped_gpu_addr[i] == 0) { + ctx->mapped_gpu_addr[i] = (uint32) gpuaddr; + mapped_idx = i; + break; + } + } + return (uint32) gpuaddr; } return 0; } +static void unmap_gpuaddr(copybit_context_t* ctx, int mapped_idx) +{ + if (!ctx || (mapped_idx == -1)) + return; + + if (ctx->mapped_gpu_addr[mapped_idx]) { + LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[mapped_idx]); + ctx->mapped_gpu_addr[mapped_idx] = 0; + } +} + static int is_supported_rgb_format(int format) { switch(format) { @@ -379,20 +426,24 @@ static int calculate_yuv_offset_and_stride(const bufferInfo& info, } /** create C2D surface from copybit image */ -static int set_image( uint32 surfaceId, const struct copybit_image_t *rhs, - int *cformat, uint32_t *mapped, const eC2DFlags flags) +static int set_image(copybit_context_t* ctx, uint32 surfaceId, + const struct copybit_image_t *rhs, + const eC2DFlags flags, int &mapped_idx) { struct private_handle_t* handle = (struct private_handle_t*)rhs->handle; C2D_SURFACE_TYPE surfaceType; int status = COPYBIT_SUCCESS; + uint32 gpuaddr = 0; + int c2d_format; + mapped_idx = -1; if (flags & FLAGS_YUV_DESTINATION) { - *cformat = get_c2d_format_for_yuv_destination(rhs->format); + c2d_format = get_c2d_format_for_yuv_destination(rhs->format); } else { - *cformat = get_format(rhs->format); + c2d_format = get_format(rhs->format); } - if(*cformat == -EINVAL) { + if(c2d_format == -EINVAL) { ALOGE("%s: invalid format", __FUNCTION__); return -EINVAL; } @@ -403,12 +454,13 @@ static int set_image( uint32 surfaceId, const struct copybit_image_t *rhs, } if (handle->gpuaddr == 0) { - handle->gpuaddr = c2d_get_gpuaddr(handle); - if(!handle->gpuaddr) { + gpuaddr = c2d_get_gpuaddr(ctx, handle, mapped_idx); + if(!gpuaddr) { ALOGE("%s: c2d_get_gpuaddr failed", __FUNCTION__); return COPYBIT_FAILURE; } - *mapped = 1; + } else { + gpuaddr = handle->gpuaddr; } /* create C2D surface */ @@ -418,26 +470,27 @@ static int set_image( uint32 surfaceId, const struct copybit_image_t *rhs, surfaceType = (C2D_SURFACE_TYPE) (C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS); - surfaceDef.phys = (void*) handle->gpuaddr; + surfaceDef.phys = (void*) gpuaddr; surfaceDef.buffer = (void*) (handle->base); - surfaceDef.format = *cformat | + surfaceDef.format = c2d_format | ((flags & FLAGS_PREMULTIPLIED_ALPHA) ? C2D_FORMAT_PREMULTIPLIED : 0); surfaceDef.width = rhs->w; surfaceDef.height = rhs->h; int aligned_width = ALIGN(surfaceDef.width,32); surfaceDef.stride = (aligned_width * c2diGetBpp(surfaceDef.format))>>3; - if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType, &surfaceDef)) { + if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType, + &surfaceDef)) { ALOGE("%s: RGB Surface c2dUpdateSurface ERROR", __FUNCTION__); - goto error; + unmap_gpuaddr(ctx, mapped_idx); status = COPYBIT_FAILURE; } } else if (is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) { C2D_YUV_SURFACE_DEF surfaceDef; memset(&surfaceDef, 0, sizeof(surfaceDef)); surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS); - surfaceDef.format = *cformat; + surfaceDef.format = c2d_format; bufferInfo info; info.width = rhs->w; @@ -448,199 +501,88 @@ static int set_image( uint32 surfaceId, const struct copybit_image_t *rhs, status = calculate_yuv_offset_and_stride(info, yuvInfo); if(status != COPYBIT_SUCCESS) { ALOGE("%s: calculate_yuv_offset_and_stride error", __FUNCTION__); - goto error; + unmap_gpuaddr(ctx, mapped_idx); } surfaceDef.width = rhs->w; surfaceDef.height = rhs->h; surfaceDef.plane0 = (void*) (handle->base); - surfaceDef.phys0 = (void*) (handle->gpuaddr); + surfaceDef.phys0 = (void*) (gpuaddr); surfaceDef.stride0 = yuvInfo.yStride; surfaceDef.plane1 = (void*) (handle->base + yuvInfo.plane1_offset); - surfaceDef.phys1 = (void*) (handle->gpuaddr + yuvInfo.plane1_offset); + surfaceDef.phys1 = (void*) (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.phys2 = (void*) (gpuaddr + yuvInfo.plane2_offset); surfaceDef.stride2 = yuvInfo.plane2_stride; } if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType, &surfaceDef)) { ALOGE("%s: YUV Surface c2dUpdateSurface ERROR", __FUNCTION__); - goto error; + unmap_gpuaddr(ctx, mapped_idx); status = COPYBIT_FAILURE; } } else { ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format); - goto error; + unmap_gpuaddr(ctx, mapped_idx); status = COPYBIT_FAILURE; } return status; - -error: - if(*mapped == 1) { - LINK_c2dUnMapAddr( (void*) handle->gpuaddr); - handle->gpuaddr = 0; - *mapped = 0; - } - return status; } -static int set_src_image( uint32 *surfaceId, const struct copybit_image_t *rhs, - int *cformat, uint32 *mapped) +/** copy the bits */ +static int msm_copybit(struct copybit_context_t *ctx, unsigned int target) { - struct private_handle_t* handle = (struct private_handle_t*)rhs->handle; - *cformat = get_format(rhs->format); - C2D_SURFACE_TYPE surfaceType; - uint32 gpuaddr = (uint32)handle->gpuaddr; - int status = COPYBIT_SUCCESS; + if (ctx->blit_count == 0) { + return COPYBIT_SUCCESS; + } - if (handle->gpuaddr == 0) + for (int i = 0; i < ctx->blit_count; i++) { - handle->gpuaddr = c2d_get_gpuaddr( handle); - if(!handle->gpuaddr) - return COPYBIT_FAILURE; - - *mapped = 1; + ctx->blit_list[i].next = &(ctx->blit_list[i+1]); } - /* create C2D surface */ - if(is_supported_rgb_format(rhs->format) == COPYBIT_SUCCESS) { - /* RGB */ - C2D_RGB_SURFACE_DEF surfaceDef; - surfaceType = (C2D_SURFACE_TYPE) (C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY); - - surfaceDef.phys = (void*) handle->gpuaddr; - surfaceDef.buffer = (void*) (handle->base); - surfaceDef.buffer = (void*) (handle->base + handle->offset); - - surfaceDef.format = get_format(rhs->format); - surfaceDef.width = rhs->w; - surfaceDef.height = rhs->h; - surfaceDef.stride = ALIGN(((surfaceDef.width * c2diGetBpp(surfaceDef.format))>>3), 32); - - if(LINK_c2dCreateSurface( surfaceId, C2D_TARGET, surfaceType,(void*)&surfaceDef)) { - ALOGE("%s: LINK_c2dCreateSurface error", __FUNCTION__); - status = COPYBIT_FAILURE; - goto error; - } - } else if(is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) { - /* YUV */ - 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 | C2D_SURFACE_WITH_PHYS_DUMMY); - surfaceDef.format = get_format(rhs->format); - 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) { - ALOGE("%s: calculate_yuv_offset_and_stride error", __FUNCTION__); - goto error; - } - - surfaceDef.width = rhs->w; - surfaceDef.height = rhs->h; - surfaceDef.plane0 = (void*) (handle->base); - surfaceDef.phys0 = (void*) handle->gpuaddr; - surfaceDef.stride0 = yuvInfo.yStride; - - 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)) { - ALOGE("%s: YUV surface LINK_c2dCreateSurface error", __func__); - status = COPYBIT_FAILURE; - goto error; - } - } else { - ALOGE("%s: Invalid format 0x%x", __FUNCTION__, rhs->format); - status = COPYBIT_FAILURE; + ctx->blit_list[ctx->blit_count-1].next = NULL; + if(LINK_c2dDraw(target,ctx->trg_transform, 0x0, 0, 0, ctx->blit_list, + ctx->blit_count)) { + ALOGE("%s: LINK_c2dDraw ERROR", __FUNCTION__); + return COPYBIT_FAILURE; } return COPYBIT_SUCCESS; - -error: - if(*mapped == 1) { - LINK_c2dUnMapAddr( (void*) handle->gpuaddr); - handle->gpuaddr = 0; - *mapped = 0; - } - return status; } -void unset_image( uint32 surfaceId, const struct copybit_image_t *rhs, - uint32 mmapped) -{ - struct private_handle_t* handle = (struct private_handle_t*)rhs->handle; - - if (mmapped && handle->gpuaddr) { - // Unmap this gpuaddr - LINK_c2dUnMapAddr( (void*) handle->gpuaddr); - handle->gpuaddr = 0; - } -} -static int blit_to_target( uint32 surfaceId, const struct copybit_image_t *rhs) +static int finish_copybit(struct copybit_device_t *dev) { - struct private_handle_t* handle = (struct private_handle_t*)rhs->handle; - uint32 cformat = get_format(rhs->format); - C2D_SURFACE_TYPE surfaceType; - uint32 memoryMapped = 0; - int status = COPYBIT_SUCCESS; + struct copybit_context_t* ctx = (struct copybit_context_t*)dev; + if (!ctx) + return COPYBIT_FAILURE; - if (!handle->gpuaddr) { - handle->gpuaddr = c2d_get_gpuaddr(handle); - if(!handle->gpuaddr) - return COPYBIT_FAILURE; + int status = msm_copybit(ctx, ctx->dst[ctx->dst_surface_type]); - memoryMapped = 1; + if(LINK_c2dFinish(ctx->dst[ctx->dst_surface_type])) { + ALOGE("%s: LINK_c2dFinish ERROR", __FUNCTION__); + return COPYBIT_FAILURE; } - /* create C2D surface */ - - if(cformat) { - /* RGB */ - C2D_RGB_SURFACE_DEF surfaceDef; - memset(&surfaceDef, 0, sizeof(surfaceDef)); - - surfaceDef.buffer = (void*) handle->base; - surfaceDef.phys = (void*) handle->gpuaddr; - - surfaceType = C2D_SURFACE_RGB_HOST; - surfaceDef.format = get_format(rhs->format); - surfaceDef.width = rhs->w; - surfaceDef.height = rhs->h; - surfaceDef.stride = ALIGN(((surfaceDef.width * c2diGetBpp(surfaceDef.format))>>3), 32); - - if(LINK_c2dReadSurface(surfaceId, surfaceType, (void*)&surfaceDef, 0, 0)) { - ALOGE("%s: LINK_c2dReadSurface ERROR", __func__); - status = COPYBIT_FAILURE; - goto done; + // Unmap any mapped addresses. + for (int i = 0; i < MAX_SURFACES; i++) { + if (ctx->mapped_gpu_addr[i]) { + LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[i]); + ctx->mapped_gpu_addr[i] = 0; } } - else { - /* YUV */ - /* TODO */ - } -done: - if (memoryMapped) { - LINK_c2dUnMapAddr( (void*) handle->gpuaddr); - handle->gpuaddr = 0; - } + // Reset the counts after the draw. + ctx->blit_rgb_count = 0; + ctx->blit_yuv_2_plane_count = 0; + ctx->blit_yuv_3_plane_count = 0; + ctx->blit_count = 0; return status; } @@ -696,24 +638,6 @@ static void set_rects(struct copybit_context_t *ctx, c2dObject->config_mask |= C2D_SCISSOR_RECT_BIT; } -/** copy the bits */ -static int msm_copybit(struct copybit_context_t *dev, blitlist *list, uint32 target) -{ - unsigned int objects; - - for(objects = 0; objects < list->count; objects++) { - list->blitObjects[objects].next = &(list->blitObjects[objects+1]); - } - - if(LINK_c2dDraw(target,dev->trg_transform, 0x0, 0, 0, list->blitObjects, - list->count)) { - ALOGE("%s: LINK_c2dDraw ERROR", __FUNCTION__); - return COPYBIT_FAILURE; - } - - return COPYBIT_SUCCESS; -} - /*****************************************************************************/ /** Set a parameter to value */ @@ -729,67 +653,79 @@ static int set_parameter_copybit( } switch(name) { - case COPYBIT_ROTATION_DEG: - ctx->blitState.rotation = value<<16; - /* SRC rotation */ - if(!value) - ctx->blitState.config_mask &=~C2D_ROTATE_BIT;; - break; case COPYBIT_PLANE_ALPHA: + { if (value < 0) value = 0; if (value >= 256) value = 255; - ctx->blitState.global_alpha = value; - - if(ctx->blitState.global_alpha<255) - ctx->blitState.config_mask |= C2D_GLOBAL_ALPHA_BIT; + ctx->src_global_alpha = value; + if (value < 255) + ctx->config_mask |= C2D_GLOBAL_ALPHA_BIT; else - ctx->blitState.config_mask &=~C2D_GLOBAL_ALPHA_BIT; - break; - case COPYBIT_DITHER: - /* TODO */ - break; - case COPYBIT_BLUR: - /* TODO */ - break; + ctx->config_mask &= ~C2D_GLOBAL_ALPHA_BIT; + } + break; + case COPYBIT_BLEND_MODE: + { + if (value == COPYBIT_BLENDING_NONE) { + ctx->config_mask |= C2D_ALPHA_BLEND_NONE; + ctx->is_premultiplied_alpha = true; + } else if (value == COPYBIT_BLENDING_PREMULT) { + ctx->is_premultiplied_alpha = true; + } else { + ctx->config_mask &= ~C2D_ALPHA_BLEND_NONE; + } + } + break; case COPYBIT_TRANSFORM: - ctx->blitState.config_mask &=~C2D_ROTATE_BIT; - ctx->blitState.config_mask &=~C2D_MIRROR_H_BIT; - ctx->blitState.config_mask &=~C2D_MIRROR_V_BIT; - ctx->trg_transform = C2D_TARGET_ROTATE_0; - - if((value&0x7) == COPYBIT_TRANSFORM_ROT_180) - ctx->trg_transform = C2D_TARGET_ROTATE_180; - else if((value&0x7) == COPYBIT_TRANSFORM_ROT_270) - ctx->trg_transform = C2D_TARGET_ROTATE_90; - else { - if(value©BIT_TRANSFORM_FLIP_H) - ctx->blitState.config_mask |= C2D_MIRROR_H_BIT; - if(value©BIT_TRANSFORM_FLIP_V) - ctx->blitState.config_mask |= C2D_MIRROR_V_BIT; - if(value©BIT_TRANSFORM_ROT_90) - ctx->trg_transform = C2D_TARGET_ROTATE_270; + { + unsigned int transform = 0; + uint32 config_mask = 0; + config_mask |= C2D_OVERRIDE_GLOBAL_TARGET_ROTATE_CONFIG; + if((value & 0x7) == COPYBIT_TRANSFORM_ROT_180) { + transform = C2D_TARGET_ROTATE_180; + config_mask |= C2D_OVERRIDE_TARGET_ROTATE_180; + } else if((value & 0x7) == COPYBIT_TRANSFORM_ROT_270) { + transform = C2D_TARGET_ROTATE_90; + config_mask |= C2D_OVERRIDE_TARGET_ROTATE_90; + } else if(value == COPYBIT_TRANSFORM_ROT_90) { + transform = C2D_TARGET_ROTATE_270; + config_mask |= C2D_OVERRIDE_TARGET_ROTATE_270; + } else { + config_mask |= C2D_OVERRIDE_TARGET_ROTATE_0; + if(value & COPYBIT_TRANSFORM_FLIP_H) { + config_mask |= C2D_MIRROR_H_BIT; + } else if(value & COPYBIT_TRANSFORM_FLIP_V) { + config_mask |= C2D_MIRROR_V_BIT; + } } - break; - case COPYBIT_PREMULTIPLIED_ALPHA: - (value == COPYBIT_ENABLE) ? ctx->isPremultipliedAlpha = true : - ctx->isPremultipliedAlpha = false; - break; + + if (transform != ctx->trg_transform) { + if (ctx->c2d_driver_info.capabilities_mask & + C2D_DRIVER_SUPPORTS_OVERRIDE_TARGET_ROTATE_OP) { + ctx->config_mask |= config_mask; + } else { + // The transform for this surface does not match the current + // target transform. Draw all previous surfaces. This will be + // changed once we have a new mechanism to send different + // target rotations to c2d. + finish_copybit(dev); + } + } + ctx->trg_transform = transform; + } + break; case COPYBIT_FRAMEBUFFER_WIDTH: ctx->fb_width = value; break; case COPYBIT_FRAMEBUFFER_HEIGHT: ctx->fb_height = value; break; + case COPYBIT_ROTATION_DEG: + case COPYBIT_DITHER: + case COPYBIT_BLUR: case COPYBIT_BLIT_TO_FRAMEBUFFER: - if (COPYBIT_ENABLE == value) { - ctx->mBlitToFB = value; - } else if (COPYBIT_DISABLE == value) { - ctx->mBlitToFB = value; - } else { - ALOGE ("%s:Invalid input for COPYBIT_BLIT_TO_FRAMEBUFFER : %d", - __FUNCTION__, value); - } + // Do nothing break; default: ALOGE("%s: default case param=0x%x", __FUNCTION__, name); @@ -898,14 +834,14 @@ static size_t get_size(const bufferInfo& info) { // Chroma for this format is aligned to 2K. size = ALIGN((aligned_w*h), 2048) + - ALIGN(w/2, 32) * h/2 *2; + ALIGN(aligned_w/2, 32) * (h/2) *2; size = ALIGN(size, 4096); } break; case HAL_PIXEL_FORMAT_YCbCr_420_SP: case HAL_PIXEL_FORMAT_YCrCb_420_SP: { - size = aligned_w*h + - ALIGN(w/2, 32) * h/2 *2; + size = aligned_w * h + + ALIGN(aligned_w/2, 32) * (h/2) * 2; size = ALIGN(size, 4096); } break; default: break; @@ -998,6 +934,19 @@ static void delete_handle(private_handle_t *handle) handle = 0; } } + +static bool need_to_execute_draw(struct copybit_context_t* ctx, + eC2DFlags flags) +{ + if (flags & FLAGS_TEMP_SRC_DST) { + return true; + } + if (flags & FLAGS_YUV_DESTINATION) { + return true; + } + return false; +} + /** do a stretch blit type operation */ static int stretch_copybit_internal( struct copybit_device_t *dev, @@ -1010,14 +959,10 @@ static int stretch_copybit_internal( { struct copybit_context_t* ctx = (struct copybit_context_t*)dev; int status = COPYBIT_SUCCESS; - uint32 maxCount; - uint32 src_mapped = 0, trg_mapped = 0; - blitlist list; - C2D_OBJECT *req; - memset(&list, 0, sizeof(list)); - int cformat; - c2d_ts_handle timestamp; - uint32 src_surface_index = 0, dst_surface_index = 0; + int flags = 0; + int src_surface_type; + int mapped_src_idx = -1, mapped_dst_idx = -1; + C2D_OBJECT_STR src_surface; if (!ctx) { ALOGE("%s: null context error", __FUNCTION__); @@ -1030,40 +975,54 @@ static int stretch_copybit_internal( } if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) { - ALOGE("%s : dst dimension error dst w %d h %d", __FUNCTION__, dst->w, dst->h); + ALOGE("%s : dst dimension error dst w %d h %d", __FUNCTION__, dst->w, + dst->h); return -EINVAL; } - maxCount = sizeof(list.blitObjects)/sizeof(C2D_OBJECT); - - struct copybit_rect_t clip; - list.count = 0; - if (is_valid_destination_format(dst->format) == COPYBIT_FAILURE) { - ALOGE("%s: Invalid destination format format = 0x%x", __FUNCTION__, dst->format); + ALOGE("%s: Invalid destination format format = 0x%x", __FUNCTION__, + dst->format); return COPYBIT_FAILURE; } - bool isYUVDestination = false; + int dst_surface_type; if (is_supported_rgb_format(dst->format) == COPYBIT_SUCCESS) { - dst_surface_index = RGB_SURFACE; + dst_surface_type = RGB_SURFACE; + flags |= FLAGS_PREMULTIPLIED_ALPHA; } else if (is_supported_yuv_format(dst->format) == COPYBIT_SUCCESS) { - isYUVDestination = true; int num_planes = get_num_planes(dst->format); + flags |= FLAGS_YUV_DESTINATION; if (num_planes == 2) { - dst_surface_index = YUV_SURFACE_2_PLANES; + dst_surface_type = YUV_SURFACE_2_PLANES; } else if (num_planes == 3) { - dst_surface_index = YUV_SURFACE_3_PLANES; + dst_surface_type = YUV_SURFACE_3_PLANES; } else { ALOGE("%s: dst number of YUV planes is invalid dst format = 0x%x", __FUNCTION__, dst->format); return COPYBIT_FAILURE; } } else { - ALOGE("%s: Invalid dst surface format 0x%x", __FUNCTION__, dst->format); + ALOGE("%s: Invalid dst surface format 0x%x", __FUNCTION__, + dst->format); return COPYBIT_FAILURE; } + if (ctx->blit_rgb_count == MAX_RGB_SURFACES || + ctx->blit_yuv_2_plane_count == MAX_YUV_2_PLANE_SURFACES || + ctx->blit_yuv_3_plane_count == MAX_YUV_2_PLANE_SURFACES || + ctx->blit_count == MAX_BLIT_OBJECT_COUNT || + ctx->dst_surface_type != dst_surface_type) { + // we have reached the max. limits of our internal structures or + // changed the target. + // Draw the remaining surfaces. We need to do the finish here since + // we need to free up the surface templates. + finish_copybit(dev); + } + + ctx->dst_surface_type = dst_surface_type; + + // Update the destination copybit_image_t dst_image; dst_image.w = dst->w; dst_image.h = dst->h; @@ -1072,7 +1031,7 @@ static int stretch_copybit_internal( // Check if we need a temp. copy for the destination. We'd need this the destination // width is not aligned to 32. This case occurs for YUV formats. RGB formats are // aligned to 32. - bool needTempDestination = need_temp_buffer(dst); + bool need_temp_dst = need_temp_buffer(dst); bufferInfo dst_info; populate_buffer_info(dst, dst_info); private_handle_t* dst_hnd = new private_handle_t(-1, 0, 0, 0, dst_info.format, @@ -1081,7 +1040,7 @@ static int stretch_copybit_internal( ALOGE("%s: dst_hnd is null", __FUNCTION__); return COPYBIT_FAILURE; } - if (needTempDestination) { + if (need_temp_dst) { if (get_size(dst_info) != ctx->temp_dst_buffer.size) { free_temp_buffer(ctx->temp_dst_buffer); // Create a temp buffer and set that as the destination. @@ -1100,35 +1059,40 @@ static int stretch_copybit_internal( dst_image.handle = dst_hnd; } - int flags = 0; - flags |= (ctx->isPremultipliedAlpha) ? FLAGS_PREMULTIPLIED_ALPHA : 0; - flags |= (isYUVDestination) ? FLAGS_YUV_DESTINATION : 0; - - status = set_image( ctx->dst[dst_surface_index], &dst_image, - &cformat, &trg_mapped, (eC2DFlags)flags); + status = set_image(ctx, ctx->dst[ctx->dst_surface_type], &dst_image, + (eC2DFlags)flags, mapped_dst_idx); if(status) { ALOGE("%s: dst: set_image error", __FUNCTION__); delete_handle(dst_hnd); + unmap_gpuaddr(ctx, mapped_dst_idx); return COPYBIT_FAILURE; } + // Update the source + flags = 0; if(is_supported_rgb_format(src->format) == COPYBIT_SUCCESS) { - src_surface_index = RGB_SURFACE; + src_surface_type = RGB_SURFACE; + src_surface = ctx->blit_rgb_object[ctx->blit_rgb_count]; } else if (is_supported_yuv_format(src->format) == COPYBIT_SUCCESS) { int num_planes = get_num_planes(src->format); if (num_planes == 2) { - src_surface_index = YUV_SURFACE_2_PLANES; + src_surface_type = YUV_SURFACE_2_PLANES; + src_surface = ctx->blit_yuv_2_plane_object[ctx->blit_yuv_2_plane_count]; } else if (num_planes == 3) { - src_surface_index = YUV_SURFACE_3_PLANES; + src_surface_type = YUV_SURFACE_3_PLANES; + src_surface = ctx->blit_yuv_3_plane_object[ctx->blit_yuv_2_plane_count]; } else { ALOGE("%s: src number of YUV planes is invalid src format = 0x%x", __FUNCTION__, src->format); delete_handle(dst_hnd); + unmap_gpuaddr(ctx, mapped_dst_idx); return -EINVAL; } } else { - ALOGE("%s: Invalid source surface format 0x%x", __FUNCTION__, src->format); + ALOGE("%s: Invalid source surface format 0x%x", __FUNCTION__, + src->format); delete_handle(dst_hnd); + unmap_gpuaddr(ctx, mapped_dst_idx); return -EINVAL; } @@ -1138,24 +1102,27 @@ static int stretch_copybit_internal( src_image.format = src->format; src_image.handle = src->handle; - bool needTempSource = need_temp_buffer(src); + bool need_temp_src = need_temp_buffer(src); bufferInfo src_info; populate_buffer_info(src, src_info); private_handle_t* src_hnd = new private_handle_t(-1, 0, 0, 0, src_info.format, - src_info.width, src_info.height); + src_info.width, src_info.height); if (NULL == src_hnd) { ALOGE("%s: src_hnd is null", __FUNCTION__); delete_handle(dst_hnd); + unmap_gpuaddr(ctx, mapped_dst_idx); return COPYBIT_FAILURE; } - if (needTempSource) { + if (need_temp_src) { if (get_size(src_info) != ctx->temp_src_buffer.size) { free_temp_buffer(ctx->temp_src_buffer); // Create a temp buffer and set that as the destination. - if (COPYBIT_SUCCESS != get_temp_buffer(src_info, ctx->temp_src_buffer)) { + if (COPYBIT_SUCCESS != get_temp_buffer(src_info, + ctx->temp_src_buffer)) { ALOGE("%s: get_temp_buffer(src) failed", __FUNCTION__); delete_handle(dst_hnd); delete_handle(src_hnd); + unmap_gpuaddr(ctx, mapped_dst_idx); return COPYBIT_FAILURE; } } @@ -1168,7 +1135,15 @@ static int stretch_copybit_internal( src_image.handle = src_hnd; // Copy the source. - copy_image((private_handle_t *)src->handle, &src_image, CONVERT_TO_C2D_FORMAT); + status = copy_image((private_handle_t *)src->handle, &src_image, + CONVERT_TO_C2D_FORMAT); + if (status == COPYBIT_FAILURE) { + ALOGE("%s:copy_image failed in temp source",__FUNCTION__); + delete_handle(dst_hnd); + delete_handle(src_hnd); + unmap_gpuaddr(ctx, mapped_dst_idx); + return status; + } // Flush the cache IMemAlloc* memalloc = sAlloc->getAllocator(src_hnd->flags); @@ -1177,70 +1152,90 @@ static int stretch_copybit_internal( ALOGE("%s: clean_buffer failed", __FUNCTION__); delete_handle(dst_hnd); delete_handle(src_hnd); + unmap_gpuaddr(ctx, mapped_dst_idx); return COPYBIT_FAILURE; } } - status = set_image( ctx->src[src_surface_index], &src_image, - &cformat, &src_mapped, (eC2DFlags)flags); + flags |= (ctx->is_premultiplied_alpha) ? FLAGS_PREMULTIPLIED_ALPHA : 0; + flags |= (ctx->dst_surface_type != RGB_SURFACE) ? FLAGS_YUV_DESTINATION : 0; + status = set_image(ctx, src_surface.surface_id, &src_image, + (eC2DFlags)flags, mapped_src_idx); if(status) { - ALOGE("%s: set_src_image error", __FUNCTION__); + ALOGE("%s: set_image (src) error", __FUNCTION__); delete_handle(dst_hnd); delete_handle(src_hnd); + unmap_gpuaddr(ctx, mapped_dst_idx); + unmap_gpuaddr(ctx, mapped_src_idx); return COPYBIT_FAILURE; } + src_surface.config_mask = C2D_NO_BILINEAR_BIT | C2D_NO_ANTIALIASING_BIT | + ctx->config_mask; + src_surface.global_alpha = ctx->src_global_alpha; if (enableBlend) { - if(ctx->blitState.config_mask & C2D_GLOBAL_ALPHA_BIT) { - ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE; - if(!(ctx->blitState.global_alpha)) { + if(src_surface.config_mask & C2D_GLOBAL_ALPHA_BIT) { + src_surface.config_mask &= ~C2D_ALPHA_BLEND_NONE; + if(!(src_surface.global_alpha)) { // src alpha is zero - unset_image( ctx->src[src_surface_index], - &src_image, src_mapped); - unset_image( ctx->dst[dst_surface_index], - &dst_image, trg_mapped); delete_handle(dst_hnd); delete_handle(src_hnd); - return status; + unmap_gpuaddr(ctx, mapped_dst_idx); + unmap_gpuaddr(ctx, mapped_src_idx); + return COPYBIT_FAILURE; } } else { - if(is_alpha(cformat)) - ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE; + int c2d_format = get_format(src->format); + if(is_alpha(c2d_format)) + src_surface.config_mask &= ~C2D_ALPHA_BLEND_NONE; else - ctx->blitState.config_mask |= C2D_ALPHA_BLEND_NONE; + src_surface.config_mask |= C2D_ALPHA_BLEND_NONE; } } else { - ctx->blitState.config_mask |= C2D_ALPHA_BLEND_NONE; + src_surface.config_mask |= C2D_ALPHA_BLEND_NONE; } - ctx->blitState.surface_id = ctx->src[src_surface_index]; + if (src_surface_type == RGB_SURFACE) { + ctx->blit_rgb_object[ctx->blit_rgb_count] = src_surface; + ctx->blit_rgb_count++; + } else if (src_surface_type == YUV_SURFACE_2_PLANES) { + ctx->blit_yuv_2_plane_object[ctx->blit_yuv_2_plane_count] = src_surface; + ctx->blit_yuv_2_plane_count++; + } else { + ctx->blit_yuv_3_plane_object[ctx->blit_yuv_3_plane_count] = src_surface; + ctx->blit_yuv_3_plane_count++; + } + struct copybit_rect_t clip; while ((status == 0) && region->next(region, &clip)) { - req = &(list.blitObjects[list.count]); - memcpy(req,&ctx->blitState,sizeof(C2D_OBJECT)); - - set_rects(ctx, req, dst_rect, src_rect, &clip); - - if (++list.count == maxCount) { - status = msm_copybit(ctx, &list, ctx->dst[dst_surface_index]); - list.count = 0; + set_rects(ctx, &(src_surface), dst_rect, src_rect, &clip); + if (ctx->blit_count == MAX_BLIT_OBJECT_COUNT) { + ALOGW("Reached end of blit count"); + finish_copybit(dev);; } - } - if ((status == 0) && list.count) { - status = msm_copybit(ctx, &list, ctx->dst[dst_surface_index]); + ctx->blit_list[ctx->blit_count] = src_surface; + ctx->blit_count++; } - if(LINK_c2dFinish(ctx->dst[dst_surface_index])) { - ALOGE("%s: LINK_c2dFinish ERROR", __FUNCTION__); + // Check if we need to perform an early draw-finish. + flags |= (need_temp_dst || need_temp_src) ? FLAGS_TEMP_SRC_DST : 0; + if (need_to_execute_draw(ctx, (eC2DFlags)flags)) + { + finish_copybit(dev); } - unset_image( ctx->src[src_surface_index], &src_image, - src_mapped); - unset_image( ctx->dst[dst_surface_index], &dst_image, - trg_mapped); - if (needTempDestination) { - // copy the temp. destination without the alignment to the actual destination. - copy_image(dst_hnd, dst, CONVERT_TO_ANDROID_FORMAT); + if (need_temp_dst) { + // copy the temp. destination without the alignment to the actual + // destination. + status = copy_image(dst_hnd, dst, CONVERT_TO_ANDROID_FORMAT); + if (status == COPYBIT_FAILURE) { + ALOGE("%s:copy_image failed in temp Dest",__FUNCTION__); + delete_handle(dst_hnd); + delete_handle(src_hnd); + unmap_gpuaddr(ctx, mapped_dst_idx); + unmap_gpuaddr(ctx, mapped_src_idx); + return status; + } // Invalidate the cache. IMemAlloc* memalloc = sAlloc->getAllocator(dst_hnd->flags); memalloc->clean_buffer((void *)(dst_hnd->base), dst_hnd->size, @@ -1248,12 +1243,15 @@ static int stretch_copybit_internal( } delete_handle(dst_hnd); delete_handle(src_hnd); - ctx->isPremultipliedAlpha = false; + + ctx->is_premultiplied_alpha = false; ctx->fb_width = 0; ctx->fb_height = 0; + ctx->config_mask = 0; return status; } + static int stretch_copybit( struct copybit_device_t *dev, struct copybit_image_t const *dst, @@ -1263,7 +1261,7 @@ static int stretch_copybit( struct copybit_region_t const *region) { struct copybit_context_t* ctx = (struct copybit_context_t*)dev; - bool needsBlending = (ctx->blitState.global_alpha != 0); + bool needsBlending = (ctx->src_global_alpha != 0); return stretch_copybit_internal(dev, dst, src, dst_rect, src_rect, region, needsBlending); } @@ -1282,26 +1280,48 @@ static int blit_copybit( /*****************************************************************************/ +static void clean_up(copybit_context_t* ctx) +{ + if (!ctx) + return; + + for (int i = 0; i < NUM_SURFACE_TYPES; i++) { + if (ctx->dst[i]) + LINK_c2dDestroySurface(ctx->dst[i]); + } + + for (int i = 0; i < MAX_RGB_SURFACES; i++) { + if (ctx->blit_rgb_object[i].surface_id) + LINK_c2dDestroySurface(ctx->blit_rgb_object[i].surface_id); + } + + for (int i = 0; i < MAX_YUV_2_PLANE_SURFACES; i++) { + if (ctx->blit_yuv_2_plane_object[i].surface_id) + LINK_c2dDestroySurface(ctx->blit_yuv_2_plane_object[i].surface_id); + } + + for (int i = 0; i < MAX_YUV_3_PLANE_SURFACES; i++) { + if (ctx->blit_yuv_3_plane_object[i].surface_id) + LINK_c2dDestroySurface(ctx->blit_yuv_3_plane_object[i].surface_id); + } + + if (ctx->libc2d2) { + ::dlclose(ctx->libc2d2); + ALOGV("dlclose(libc2d2)"); + } + + free(ctx); +} + /** Close the copybit device */ static int close_copybit(struct hw_device_t *dev) { struct copybit_context_t* ctx = (struct copybit_context_t*)dev; if (ctx) { - for(int i = 0; i dst[i]); - LINK_c2dDestroySurface(ctx->src[i]); - } - - if (ctx->libc2d2) { - ::dlclose(ctx->libc2d2); - ALOGV("dlclose(libc2d2)"); - } - free_temp_buffer(ctx->temp_src_buffer); free_temp_buffer(ctx->temp_dst_buffer); - free(ctx); } - + clean_up(ctx); return 0; } @@ -1323,16 +1343,13 @@ static int open_copybit(const struct hw_module_t* module, const char* name, /* 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) { ALOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror()); - goto error; + clean_up(ctx); + status = COPYBIT_FAILURE; + *device = NULL; + return status; } *(void **)&LINK_c2dCreateSurface = ::dlsym(ctx->libc2d2, "c2dCreateSurface"); @@ -1351,12 +1368,18 @@ static int open_copybit(const struct hw_module_t* module, const char* name, "c2dMapAddr"); *(void **)&LINK_c2dUnMapAddr = ::dlsym(ctx->libc2d2, "c2dUnMapAddr"); + *(void **)&LINK_c2dGetDriverCapabilities = ::dlsym(ctx->libc2d2, + "c2dGetDriverCapabilities"); if (!LINK_c2dCreateSurface || !LINK_c2dUpdateSurface || !LINK_c2dReadSurface - || !LINK_c2dDraw || !LINK_c2dFlush || !LINK_c2dWaitTimestamp || !LINK_c2dFinish - || !LINK_c2dDestroySurface) { + || !LINK_c2dDraw || !LINK_c2dFlush || !LINK_c2dWaitTimestamp || + !LINK_c2dFinish || !LINK_c2dDestroySurface || + !LINK_c2dGetDriverCapabilities) { ALOGE("%s: dlsym ERROR", __FUNCTION__); - goto error; + clean_up(ctx); + status = COPYBIT_FAILURE; + *device = NULL; + return status; } ctx->device.common.tag = HARDWARE_DEVICE_TAG; @@ -1367,8 +1390,7 @@ static int open_copybit(const struct hw_module_t* module, const char* name, ctx->device.get = get; ctx->device.blit = blit_copybit; ctx->device.stretch = stretch_copybit; - ctx->blitState.config_mask = C2D_NO_BILINEAR_BIT | C2D_NO_ANTIALIASING_BIT; - ctx->trg_transform = C2D_TARGET_ROTATE_0; + ctx->device.finish = finish_copybit; /* Create RGB Surface */ surfDefinition.buffer = (void*)0xdddddddd; @@ -1379,24 +1401,45 @@ static int open_copybit(const struct hw_module_t* module, const char* name, surfDefinition.format = C2D_COLOR_FORMAT_8888_ARGB; if (LINK_c2dCreateSurface(&(ctx->dst[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE, (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | - C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY ), &surfDefinition)) { - ALOGE("%s: create ctx->dst[RGB_SURFACE] failed", __FUNCTION__); - ctx->dst[RGB_SURFACE] = -1; - goto error; + C2D_SURFACE_WITH_PHYS | + C2D_SURFACE_WITH_PHYS_DUMMY ), + &surfDefinition)) { + ALOGE("%s: create ctx->dst_surface[RGB_SURFACE] failed", __FUNCTION__); + ctx->dst[RGB_SURFACE] = 0; + clean_up(ctx); + status = COPYBIT_FAILURE; + *device = NULL; + return status; } - - if (LINK_c2dCreateSurface(&(ctx->src[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE, + unsigned int surface_id = 0; + for (int i = 0; i < MAX_RGB_SURFACES; i++) + { + if (LINK_c2dCreateSurface(&surface_id, C2D_TARGET | C2D_SOURCE, (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST | - C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY), &surfDefinition)) { - ALOGE("%s: create ctx->src[RGB_SURFACE] failed", __FUNCTION__); - ctx->src[RGB_SURFACE] = -1; - goto error; + C2D_SURFACE_WITH_PHYS | + C2D_SURFACE_WITH_PHYS_DUMMY ), + &surfDefinition)) { + ALOGE("%s: create RGB source surface %d failed", __FUNCTION__, i); + ctx->blit_rgb_object[i].surface_id = 0; + status = COPYBIT_FAILURE; + break; + } else { + ctx->blit_rgb_object[i].surface_id = surface_id; + ALOGW("%s i = %d surface_id=%d", __FUNCTION__, i, + ctx->blit_rgb_object[i].surface_id); + } } - /* Create YUV source surface */ - yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_NV12; + if (status == COPYBIT_FAILURE) { + clean_up(ctx); + status = COPYBIT_FAILURE; + *device = NULL; + return status; + } + // Create 2 plane YUV surfaces + yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_NV12; yuvSurfaceDef.width = 4; yuvSurfaceDef.height = 4; yuvSurfaceDef.plane0 = (void*)0xaaaaaaaa; @@ -1406,48 +1449,101 @@ static int open_copybit(const struct hw_module_t* module, const char* name, yuvSurfaceDef.plane1 = (void*)0xaaaaaaaa; yuvSurfaceDef.phys1 = (void*) 0xaaaaaaaa; yuvSurfaceDef.stride1 = 4; - - if (LINK_c2dCreateSurface(&(ctx->src[YUV_SURFACE_2_PLANES]), + if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_2_PLANES]), C2D_TARGET | C2D_SOURCE, - (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST|C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY), + (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | + C2D_SURFACE_WITH_PHYS | + C2D_SURFACE_WITH_PHYS_DUMMY), &yuvSurfaceDef)) { - ALOGE("%s: create ctx->src[YUV_SURFACE_2_PLANES] failed", __FUNCTION__); - ctx->src[YUV_SURFACE_2_PLANES] = -1; - goto error; + ALOGE("%s: create ctx->dst[YUV_SURFACE_2_PLANES] failed", __FUNCTION__); + ctx->dst[YUV_SURFACE_2_PLANES] = 0; + clean_up(ctx); + status = COPYBIT_FAILURE; + *device = NULL; + return status; } - if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_2_PLANES]), - C2D_TARGET | C2D_SOURCE, - (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY), + for (int i=0; i < MAX_YUV_2_PLANE_SURFACES; i++) + { + if (LINK_c2dCreateSurface(&surface_id, C2D_TARGET | C2D_SOURCE, + (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | + C2D_SURFACE_WITH_PHYS | + C2D_SURFACE_WITH_PHYS_DUMMY ), &yuvSurfaceDef)) { - ALOGE("%s: create ctx->dst[YUV_SURFACE_2_PLANES] failed", __FUNCTION__); - ctx->dst[YUV_SURFACE_2_PLANES] = -1; - goto error; + ALOGE("%s: create YUV source %d failed", __FUNCTION__, i); + ctx->blit_yuv_2_plane_object[i].surface_id = 0; + status = COPYBIT_FAILURE; + break; + } else { + ctx->blit_yuv_2_plane_object[i].surface_id = surface_id; + ALOGW("%s: 2 Plane YUV i=%d surface_id=%d", __FUNCTION__, i, + ctx->blit_yuv_2_plane_object[i].surface_id); + } + } + + if (status == COPYBIT_FAILURE) { + clean_up(ctx); + status = COPYBIT_FAILURE; + *device = NULL; + return status; } + // Create YUV 3 plane surfaces 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]), + if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_3_PLANES]), C2D_TARGET | C2D_SOURCE, - (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY), + (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | + C2D_SURFACE_WITH_PHYS | + C2D_SURFACE_WITH_PHYS_DUMMY), &yuvSurfaceDef)) { - ALOGE("%s: create ctx->src[YUV_SURFACE_3_PLANES] failed", __FUNCTION__); - ctx->src[YUV_SURFACE_3_PLANES] = -1; - goto error; + ALOGE("%s: create ctx->dst[YUV_SURFACE_3_PLANES] failed", __FUNCTION__); + ctx->dst[YUV_SURFACE_3_PLANES] = 0; + clean_up(ctx); + status = COPYBIT_FAILURE; + *device = NULL; + return status; } - if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_3_PLANES]), + for (int i=0; i < MAX_YUV_3_PLANE_SURFACES; i++) + { + if (LINK_c2dCreateSurface(&(surface_id), C2D_TARGET | C2D_SOURCE, - (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY), + (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | + C2D_SURFACE_WITH_PHYS | + C2D_SURFACE_WITH_PHYS_DUMMY), &yuvSurfaceDef)) { - ALOGE("%s: create ctx->dst[YUV_SURFACE_3_PLANES] failed", __FUNCTION__); - ctx->dst[YUV_SURFACE_3_PLANES] = -1; - goto error; + ALOGE("%s: create 3 plane YUV surface %d failed", __FUNCTION__, i); + ctx->blit_yuv_3_plane_object[i].surface_id = 0; + status = COPYBIT_FAILURE; + break; + } else { + ctx->blit_yuv_3_plane_object[i].surface_id = surface_id; + ALOGW("%s: 3 Plane YUV i=%d surface_id=%d", __FUNCTION__, i, + ctx->blit_yuv_3_plane_object[i].surface_id); + } } + if (status == COPYBIT_FAILURE) { + clean_up(ctx); + status = COPYBIT_FAILURE; + *device = NULL; + return status; + } + + if (LINK_c2dGetDriverCapabilities(&(ctx->c2d_driver_info))) { + ALOGE("%s: LINK_c2dGetDriverCapabilities failed", __FUNCTION__); + clean_up(ctx); + status = COPYBIT_FAILURE; + *device = NULL; + return status; + } + // Initialize context variables. + ctx->trg_transform = C2D_TARGET_ROTATE_0; + ctx->temp_src_buffer.fd = -1; ctx->temp_src_buffer.base = 0; ctx->temp_src_buffer.size = 0; @@ -1458,28 +1554,12 @@ static int open_copybit(const struct hw_module_t* module, const char* name, ctx->fb_width = 0; ctx->fb_height = 0; - ctx->isPremultipliedAlpha = false; - *device = &ctx->device.common; - return status; - -error: - 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->libc2d2) - ::dlclose(ctx->libc2d2); - if (ctx) - free(ctx); - status = COPYBIT_FAILURE; - *device = NULL; + ctx->blit_rgb_count = 0; + ctx->blit_yuv_2_plane_count = 0; + ctx->blit_yuv_3_plane_count = 0; + ctx->blit_count = 0; + *device = &ctx->device.common; return status; } -- cgit v1.2.3