hwc: Add support for clearing with c2d
When blending translucent layers or transitioning with c2d,
sometimes the frame is blended with stale framebuffer content.
Clear the frame with C2D fill surface before drawing.
CRs-fixed: 462461
Change-Id: I1dca477fe88d77f4f0fa4846b155404f348e911d
diff --git a/libcopybit/copybit.h b/libcopybit/copybit.h
index d57b84d..07593f3 100644
--- a/libcopybit/copybit.h
+++ b/libcopybit/copybit.h
@@ -250,6 +250,11 @@
* @return 0 if successful
*/
int (*flush_get_fence)(struct copybit_device_t *dev, int* fd);
+
+ /* Clears the buffer
+ */
+ int (*clear)(struct copybit_device_t *dev, struct copybit_image_t const *buf,
+ struct copybit_rect_t *rect);
};
diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp
index c186242..dfbbf76 100644
--- a/libcopybit/copybit_c2d.cpp
+++ b/libcopybit/copybit_c2d.cpp
@@ -90,6 +90,10 @@
/* create a fence fd for the timestamp */
C2D_STATUS (*LINK_c2dCreateFenceFD) ( uint32 target_id, c2d_ts_handle timestamp,
int32 *fd);
+
+C2D_STATUS (*LINK_c2dFillSurface) ( uint32 surface_id, uint32 fill_color,
+ C2D_RECT * fill_rect);
+
/******************************************************************************/
#if defined(COPYBIT_Z180)
@@ -674,6 +678,28 @@
return status;
}
+static int clear_copybit(struct copybit_device_t *dev,
+ struct copybit_image_t const *buf,
+ struct copybit_rect_t *rect)
+{
+ int ret = 0;
+ int flags = FLAGS_PREMULTIPLIED_ALPHA;
+ int mapped_dst_idx = -1;
+ struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+ C2D_RECT c2drect = {rect->l, rect->t, rect->r - rect->l, rect->b - rect->t};
+ ret = set_image(ctx, ctx->dst[RGB_SURFACE], buf,
+ (eC2DFlags)flags, mapped_dst_idx);
+ if(ret) {
+ ALOGE("%s: set_image error", __FUNCTION__);
+ unmap_gpuaddr(ctx, mapped_dst_idx);
+ return COPYBIT_FAILURE;
+ }
+
+ ret = LINK_c2dFillSurface(ctx->dst[RGB_SURFACE], 0x0, &c2drect);
+ return ret;
+}
+
+
/** setup rectangles */
static void set_rects(struct copybit_context_t *ctx,
C2D_OBJECT *c2dObject,
@@ -1476,11 +1502,14 @@
"c2dGetDriverCapabilities");
*(void **)&LINK_c2dCreateFenceFD = ::dlsym(ctx->libc2d2,
"c2dCreateFenceFD");
+ *(void **)&LINK_c2dFillSurface = ::dlsym(ctx->libc2d2,
+ "c2dFillSurface");
if (!LINK_c2dCreateSurface || !LINK_c2dUpdateSurface || !LINK_c2dReadSurface
|| !LINK_c2dDraw || !LINK_c2dFlush || !LINK_c2dWaitTimestamp ||
!LINK_c2dFinish || !LINK_c2dDestroySurface ||
- !LINK_c2dGetDriverCapabilities || !LINK_c2dCreateFenceFD) {
+ !LINK_c2dGetDriverCapabilities || !LINK_c2dCreateFenceFD ||
+ !LINK_c2dFillSurface) {
ALOGE("%s: dlsym ERROR", __FUNCTION__);
clean_up(ctx);
status = COPYBIT_FAILURE;
@@ -1498,6 +1527,7 @@
ctx->device.stretch = stretch_copybit;
ctx->device.finish = finish_copybit;
ctx->device.flush_get_fence = flush_get_fence_copybit;
+ ctx->device.clear = clear_copybit;
/* Create RGB Surface */
surfDefinition.buffer = (void*)0xdddddddd;
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 4549dcf..aa05aa9 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -201,6 +201,25 @@
return true;
}
+int CopyBit::clear (private_handle_t* hnd, hwc_rect_t& rect)
+{
+ int ret = 0;
+ copybit_rect_t clear_rect = {rect.left, rect.top,
+ rect.right,
+ rect.bottom};
+
+ copybit_image_t buf;
+ buf.w = ALIGN(hnd->width,32);
+ buf.h = hnd->height;
+ buf.format = hnd->format;
+ buf.base = (void *)hnd->base;
+ buf.handle = (native_handle_t *)hnd;
+
+ copybit_device_t *copybit = mEngine;
+ ret = copybit->clear(copybit, &buf, &clear_rect);
+ return ret;
+}
+
bool CopyBit::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
int dpy, int32_t *fd) {
// draw layers marked for COPYBIT
@@ -224,6 +243,12 @@
close(mRelFd[0]);
mRelFd[0] = -1;
}
+
+ //Clear the visible region on the render buffer
+ //XXX: Do this only when needed.
+ hwc_rect_t clearRegion;
+ getNonWormholeRegion(list, clearRegion);
+ clear(renderBuffer, clearRegion);
// numAppLayers-1, as we iterate from 0th layer index with HWC_COPYBIT flag
for (int i = 0; i <= (ctx->listStats[dpy].numAppLayers-1); i++) {
hwc_layer_1_t *layer = &list->hwLayers[i];
diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h
index 45d254a..bc3f263 100644
--- a/libhwcomposer/hwc_copybit.h
+++ b/libhwcomposer/hwc_copybit.h
@@ -70,6 +70,8 @@
void freeRenderBuffers();
+ int clear (private_handle_t* hnd, hwc_rect_t& rect);
+
private_handle_t* mRenderBuffer[NUM_RENDER_BUFFERS];
// Index of the current intermediate render buffer