copybit: Enable copy bit to use sync pt
Since mdp composition is now an async call, the waiting for fences
is now no longer needed inside copybit. In addition, how
composition ioctl is called is slightly different as a result
needing to pass in aquire fences device performing compsition
Change-Id: Ia12dfb2960ba2fc78b14e776984ffe0c3fe45fdb
diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp
index 43b90d1..d787828 100644
--- a/libcopybit/copybit.cpp
+++ b/libcopybit/copybit.cpp
@@ -46,6 +46,11 @@
#define MAX_DIMENSION (4096)
/******************************************************************************/
+struct blitReq{
+ struct mdp_buf_sync sync;
+ uint32_t count;
+ struct mdp_blit_req req[10];
+};
/** State information for each device instance */
struct copybit_context_t {
@@ -54,6 +59,10 @@
uint8_t mAlpha;
int mFlags;
bool mBlitToFB;
+ int acqFence[MDP_MAX_FENCE_FD];
+ int relFence;
+ struct mdp_buf_sync sync;
+ struct blitReq list;
};
/**
@@ -219,15 +228,15 @@
/** copy the bits */
static int msm_copybit(struct copybit_context_t *dev, void const *list)
{
- int err = ioctl(dev->mFD, MSMFB_BLIT,
- (struct mdp_blit_req_list const*)list);
+ int err = ioctl(dev->mFD, MSMFB_ASYNC_BLIT,
+ (struct mdp_async_blit_req_list const*)list);
ALOGE_IF(err<0, "copyBits failed (%s)", strerror(errno));
if (err == 0) {
return 0;
} else {
#if DEBUG_MDP_ERRORS
- struct mdp_blit_req_list const* l =
- (struct mdp_blit_req_list const*)list;
+ struct mdp_async_blit_req_list const* l =
+ (struct mdp_async_blit_req_list const*)list;
for (unsigned int i=0 ; i<l->count ; i++) {
ALOGE("%d: src={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n"
" dst={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n"
@@ -369,6 +378,33 @@
return value;
}
+static int set_sync_copybit(struct copybit_device_t *dev,
+ int acquireFenceFd)
+{
+ struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+ if (acquireFenceFd != -1) {
+ if (ctx->sync.acq_fen_fd_cnt < (MDP_MAX_FENCE_FD - 1)) {
+ ctx->acqFence[ctx->sync.acq_fen_fd_cnt++] = acquireFenceFd;
+ } else {
+ int ret = -EINVAL;
+ struct blitReq *list = &ctx->list;
+
+ // Since fence is full kick off what is already in the list
+ ret = msm_copybit(ctx, list);
+ if (ret < 0) {
+ ALOGE("%s: Blit call failed", __FUNCTION__);
+ return -EINVAL;
+ }
+ list->count = 0;
+ ctx->sync.acq_fen_fd_cnt = 0;
+ ctx->acqFence[ctx->sync.acq_fen_fd_cnt++] = ctx->relFence;
+ ctx->acqFence[ctx->sync.acq_fen_fd_cnt++] = acquireFenceFd;
+ ctx->relFence = -1;
+ }
+ }
+ return 0;
+}
+
/** do a stretch blit type operation */
static int stretch_copybit(
struct copybit_device_t *dev,
@@ -379,15 +415,13 @@
struct copybit_region_t const *region)
{
struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+ struct blitReq *list;
int status = 0;
private_handle_t *yv12_handle = NULL;
- if (ctx) {
- struct {
- uint32_t count;
- struct mdp_blit_req req[12];
- } list;
- memset(&list, 0, sizeof(list));
+ if (ctx) {
+ list = &ctx->list;
+
if (ctx->mAlpha < 255) {
switch (src->format) {
// we don't support plane alpha with RGBA formats
@@ -445,14 +479,13 @@
return -EINVAL;
}
}
- const uint32_t maxCount = sizeof(list.req)/sizeof(list.req[0]);
+ const uint32_t maxCount = sizeof(list->req)/sizeof(list->req[0]);
const struct copybit_rect_t bounds = { 0, 0, dst->w, dst->h };
struct copybit_rect_t clip;
- list.count = 0;
status = 0;
while ((status == 0) && region->next(region, &clip)) {
intersect(&clip, &bounds, &clip);
- mdp_blit_req* req = &list.req[list.count];
+ mdp_blit_req* req = &list->req[list->count];
int flags = 0;
private_handle_t* src_hnd = (private_handle_t*)src->handle;
@@ -471,14 +504,17 @@
if (req->dst_rect.w<=0 || req->dst_rect.h<=0)
continue;
- if (++list.count == maxCount) {
- status = msm_copybit(ctx, &list);
- list.count = 0;
+ if (++list->count == maxCount) {
+ status = msm_copybit(ctx, list);
+ if (ctx->relFence != -1) {
+ ctx->sync.acq_fen_fd_cnt = 1;
+ ctx->sync.acq_fen_fd[0] = ctx->relFence;
+ } else {
+ ctx->sync.acq_fen_fd_cnt = 0;
+ }
+ list->count = 0;
}
}
- if ((status == 0) && list.count) {
- status = msm_copybit(ctx, &list);
- }
} else {
ALOGE ("%s : Invalid COPYBIT context", __FUNCTION__);
status = -EINVAL;
@@ -521,7 +557,20 @@
static int flush_get_fence(struct copybit_device_t *dev, int* fd)
{
- return -1;
+ struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+ struct blitReq *list = &ctx->list;
+ int ret = -EINVAL;
+
+ if (list->count) {
+ ret = msm_copybit(ctx, list);
+ if (ret < 0)
+ ALOGE("%s: Blit call failed", __FUNCTION__);
+ list->count = 0;
+ ctx->sync.acq_fen_fd_cnt = 0;
+ }
+ *fd = ctx->relFence;
+ ctx->relFence = -1;
+ return ret;
}
/** Open a new instance of a copybit device using name */
@@ -540,11 +589,19 @@
ctx->device.set_parameter = set_parameter_copybit;
ctx->device.get = get;
ctx->device.blit = blit_copybit;
+ ctx->device.set_sync = set_sync_copybit;
ctx->device.stretch = stretch_copybit;
ctx->device.finish = finish_copybit;
ctx->device.flush_get_fence = flush_get_fence;
ctx->mAlpha = MDP_ALPHA_NOP;
ctx->mFlags = 0;
+ ctx->sync.flags = 0;
+ ctx->sync.acq_fen_fd_cnt = 0;
+ ctx->sync.acq_fen_fd = ctx->acqFence;
+ ctx->sync.rel_fen_fd = &ctx->relFence;
+ ctx->list.count = 0;
+ ctx->list.sync.rel_fen_fd = ctx->sync.rel_fen_fd;
+ ctx->list.sync.acq_fen_fd = ctx->sync.acq_fen_fd;
ctx->mFD = open("/dev/graphics/fb0", O_RDWR, 0);
if (ctx->mFD < 0) {
status = errno;
diff --git a/libcopybit/copybit.h b/libcopybit/copybit.h
index 07593f3..0f4332f 100644
--- a/libcopybit/copybit.h
+++ b/libcopybit/copybit.h
@@ -213,6 +213,18 @@
struct copybit_region_t const *region);
/**
+ * Give acquire fence to copybit to be used in upcoming stretch
+ * call
+ *
+ * @param dev from open
+ * @param acquireFenceFd is the acquire fence
+ *
+ * @return 0 if successful
+ */
+ int (*set_sync)(struct copybit_device_t *dev,
+ int acquireFenceFd);
+
+ /**
* Execute the stretch bit blit copy operation
*
* @param dev from open
diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp
index 6973704..193d067 100644
--- a/libcopybit/copybit_c2d.cpp
+++ b/libcopybit/copybit_c2d.cpp
@@ -1388,6 +1388,11 @@
return status;
}
+static int set_sync_copybit(struct copybit_device_t *dev,
+ int acquireFenceFd)
+{
+ return 0;
+}
static int stretch_copybit(
struct copybit_device_t *dev,
@@ -1552,6 +1557,7 @@
ctx->device.set_parameter = set_parameter_copybit;
ctx->device.get = get;
ctx->device.blit = blit_copybit;
+ ctx->device.set_sync = set_sync_copybit;
ctx->device.stretch = stretch_copybit;
ctx->device.finish = finish_copybit;
ctx->device.flush_get_fence = flush_get_fence_copybit;
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 8589204..d402e0c 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -267,7 +267,8 @@
continue;
}
int ret = -1;
- if (list->hwLayers[i].acquireFenceFd != -1 ) {
+ if (list->hwLayers[i].acquireFenceFd != -1
+ && ctx->mMDP.version >= qdutils::MDP_V4_0) {
// Wait for acquire Fence on the App buffers.
ret = sync_wait(list->hwLayers[i].acquireFenceFd, 1000);
if(ret < 0) {
@@ -297,7 +298,7 @@
private_handle_t *renderBuffer, int dpy)
{
hwc_context_t* ctx = (hwc_context_t*)(dev);
- int err = 0;
+ int err = 0, acquireFd;
if(!ctx) {
ALOGE("%s: null context ", __FUNCTION__);
return -1;
@@ -391,6 +392,7 @@
scaleLimitMax,1/scaleLimitMin);
return -1;
}
+ acquireFd = layer->acquireFenceFd;
if(dsdx > copybitsMaxScale ||
dtdy > copybitsMaxScale ||
dsdx < 1/copybitsMinScale ||
@@ -446,6 +448,7 @@
copybit->set_parameter(copybit,COPYBIT_TRANSFORM,0);
//TODO: once, we are able to read layer alpha, update this
copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255);
+ copybit->set_sync(copybit, acquireFd);
err = copybit->stretch(copybit,&tmp_dst, &src, &tmp_rect,
&srcRect, &tmp_it);
if(err < 0){
@@ -455,6 +458,9 @@
free_buffer(tmpHnd);
return err;
}
+ // use release fence as aquire fd for next stretch
+ if (ctx->mMDP.version < qdutils::MDP_V4_0)
+ copybit->flush_get_fence(copybit, &acquireFd);
// copy new src and src rect crop
src = tmp_dst;
srcRect = tmp_rect;
@@ -479,13 +485,26 @@
COPYBIT_ENABLE : COPYBIT_DISABLE);
copybit->set_parameter(copybit, COPYBIT_BLIT_TO_FRAMEBUFFER,
COPYBIT_ENABLE);
+ copybit->set_sync(copybit, acquireFd);
err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect,
©bitRegion);
copybit->set_parameter(copybit, COPYBIT_BLIT_TO_FRAMEBUFFER,
COPYBIT_DISABLE);
- if(tmpHnd)
+ if(tmpHnd) {
+ if (ctx->mMDP.version < qdutils::MDP_V4_0){
+ int ret = -1, releaseFd;
+ // we need to wait for the buffer before freeing
+ copybit->flush_get_fence(copybit, &releaseFd);
+ ret = sync_wait(releaseFd, 1000);
+ if(ret < 0) {
+ ALOGE("%s: sync_wait error!! error no = %d err str = %s",
+ __FUNCTION__, errno, strerror(errno));
+ }
+ close(releaseFd);
+ }
free_buffer(tmpHnd);
+ }
if(err < 0)
ALOGE("%s: copybit stretch failed",__FUNCTION__);