summaryrefslogtreecommitdiff
path: root/libcopybit/copybit_c2d.cpp
diff options
context:
space:
mode:
authorArun Kumar K.R <akumarkr@codeaurora.org>2012-11-27 17:18:45 -0800
committerArun Kumar K.R <akumarkr@codeaurora.org>2013-01-09 13:56:38 -0800
commit6b353bd3d634042ad3129755c513f47159f8ff4e (patch)
tree6b5ed87f35565549e7769b2aecf4d7a172450f51 /libcopybit/copybit_c2d.cpp
parent6e044717788c5e97d43fd3b14d3d274790eebe29 (diff)
downloaddisplay-6b353bd3d634042ad3129755c513f47159f8ff4e.tar.gz
libcopybit: Merge copybit HAL from jb
Single commit having all the following commits commit f39e512ad6f51cf35ab00995e52a39f31e76e77f Author: Naomi Luis <nluis@codeaurora.org> 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 <nluis@codeaurora.org> 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 <nluis@codeaurora.org> 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 <nluis@codeaurora.org> 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 <nluis@codeaurora.org> 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 <ramaka@codeaurora.org> 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 <pavaku@codeaurora.org> 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 <lnxbuild@localhost> Date: Sat Sep 1 13:36:47 2012 -0700 Merge "Display ::Use proper ion heap id" into jb commit ab25cb4818d9b87886678972f2861bacc93c580a Author: Ramakant Singh <ramaka@codeaurora.org> 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 <pkandula@codeaurora.org> 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 <sravank1@codeaurora.org> Date: Thu Aug 2 14:37:37 2012 +0530 copybit : Add support for NV12_ENCODABLE format Change-Id: I7087dcad2238a3c35cc15c28d75b76a9e3ca6718 Change-Id: I748bffb4215d27f609beec209af0a5047858a314
Diffstat (limited to 'libcopybit/copybit_c2d.cpp')
-rw-r--r--libcopybit/copybit_c2d.cpp886
1 files changed, 483 insertions, 403 deletions
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&COPYBIT_TRANSFORM_FLIP_H)
- ctx->blitState.config_mask |= C2D_MIRROR_H_BIT;
- if(value&COPYBIT_TRANSFORM_FLIP_V)
- ctx->blitState.config_mask |= C2D_MIRROR_V_BIT;
- if(value&COPYBIT_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 <NUM_SURFACES; i++) {
- LINK_c2dDestroySurface(ctx->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; i<NUM_SURFACES; i++) {
- if (-1 != (ctx->src[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;
}