libhwcomposer: Lock/unlock bypass buffers using genlock

Use genlock to lock the bypass buffers before they are queued to the
overlay. After all the bypass buffers are queued, use genlock to
unlock the previously locked bypass buffers.

Change-Id: Ifdd7921f0c9f5d5744c899a0257a4b954274334b
This commit is contained in:
Naomi Luis 2011-11-29 19:12:53 -08:00
parent e2de425bc4
commit b0e7470e4f

View File

@ -83,6 +83,11 @@ enum {
MAX_BYPASS_LAYERS = 2,
ANIM_FRAME_COUNT = 30,
};
enum BypassBufferLockState {
BYPASS_BUFFER_UNLOCKED,
BYPASS_BUFFER_LOCKED,
};
#endif
enum eHWCOverlayStatus {
@ -98,6 +103,8 @@ struct hwc_context_t {
native_handle_t *previousOverlayHandle;
#ifdef COMPOSITION_BYPASS
overlay::OverlayUI* mOvUI[MAX_BYPASS_LAYERS];
native_handle_t* previousBypassHandle[MAX_BYPASS_LAYERS];
BypassBufferLockState bypassBufferLockState[MAX_BYPASS_LAYERS];
int animCount;
BypassState bypassState;
#endif
@ -229,14 +236,30 @@ static int hwc_closeOverlayChannels(hwc_context_t* ctx) {
#ifdef COMPOSITION_BYPASS
// To-do: Merge this with other blocks & move them to a separate file.
void unlockPreviousBypassBuffers(hwc_context_t* ctx) {
// Unlock the previous bypass buffers. We can blindly unlock the buffers here,
// because buffers will be in this list only if the lock was successfully acquired.
for(int i = 0; i < MAX_BYPASS_LAYERS; i++) {
if (ctx->previousBypassHandle[i]) {
private_handle_t *hnd = (private_handle_t*) ctx->previousBypassHandle[i];
if (GENLOCK_FAILURE == genlock_unlock_buffer(ctx->previousBypassHandle[i])) {
LOGE("%s: genlock_unlock_buffer failed", __FUNCTION__);
} else {
ctx->previousBypassHandle[i] = NULL;
}
}
}
}
void closeBypass(hwc_context_t* ctx) {
for (int index = 0 ; index < MAX_BYPASS_LAYERS; index++) {
ctx->mOvUI[index]->closeChannel();
unlockPreviousBypassBuffers(ctx);
for (int index = 0 ; index < MAX_BYPASS_LAYERS; index++) {
ctx->mOvUI[index]->closeChannel();
}
#ifdef DEBUG
LOGE("%s", __FUNCTION__);
#endif
}
}
#endif
/*
@ -461,9 +484,20 @@ static int drawLayerUsingBypass(hwc_context_t *ctx, hwc_layer_t *layer,
overlay::OverlayUI *ovUI = ctx->mOvUI[index];
int ret = 0;
private_handle_t *hnd = (private_handle_t *)layer->handle;
if (GENLOCK_FAILURE == genlock_lock_buffer(hnd, GENLOCK_READ_LOCK,
GENLOCK_MAX_TIMEOUT)) {
LOGE("%s: genlock_lock_buffer(READ) failed", __FUNCTION__);
return -1;
}
ctx->bypassBufferLockState[index] = BYPASS_BUFFER_LOCKED;
ret = ovUI->queueBuffer(hnd);
if (ret) {
LOGE("drawLayerUsingBypass queueBuffer failed");
// Unlock the locked buffer
if (GENLOCK_FAILURE == genlock_unlock_buffer(hnd)) {
LOGE("%s: genlock_unlock_buffer failed", __FUNCTION__);
}
ctx->bypassBufferLockState[index] = BYPASS_BUFFER_UNLOCKED;
return -1;
}
}
@ -572,6 +606,24 @@ void unsetBypassLayerFlags(hwc_layer_list_t* list) {
}
}
void unsetBypassBufferLockState(hwc_context_t* ctx) {
for (int i=0; i< MAX_BYPASS_LAYERS; i++) {
ctx->bypassBufferLockState[i] = BYPASS_BUFFER_UNLOCKED;
}
}
void storeLockedBypassHandle(hwc_layer_list_t* list, hwc_context_t* ctx) {
for (int index = 0 ; index < list->numHwLayers; index++) {
// Store the current bypass handle.
if (list->hwLayers[index].flags == HWC_COMP_BYPASS) {
private_handle_t *hnd = (private_handle_t*)list->hwLayers[index].handle;
if (ctx->bypassBufferLockState[index] == BYPASS_BUFFER_LOCKED)
ctx->previousBypassHandle[index] = (native_handle_t*)list->hwLayers[index].handle;
else
ctx->previousBypassHandle[index] = NULL;
}
}
}
#endif //COMPOSITION_BYPASS
@ -835,7 +887,9 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) {
ctx->bypassState = BYPASS_ON;
}
} else {
unlockPreviousBypassBuffers(ctx);
unsetBypassLayerFlags(list);
unsetBypassBufferLockState(ctx);
if(ctx->bypassState == BYPASS_ON) {
ctx->bypassState = BYPASS_OFF_PENDING;
}
@ -1056,6 +1110,12 @@ static int hwc_set(hwc_composer_device_t *dev,
}
}
#ifdef COMPOSITION_BYPASS
unlockPreviousBypassBuffers(ctx);
storeLockedBypassHandle(list, ctx);
// We have stored the handles, unset the current lock states in the context.
unsetBypassBufferLockState(ctx);
#endif
// Do not call eglSwapBuffers if we the skip composition flag is set on the list.
if (!(list->flags & HWC_SKIP_COMPOSITION)) {
EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur);
@ -1114,9 +1174,11 @@ static int hwc_device_close(struct hw_device_t *dev)
delete ctx->mOverlayLibObject;
ctx->mOverlayLibObject = NULL;
#ifdef COMPOSITION_BYPASS
for(int i = 0; i < MAX_BYPASS_LAYERS; i++) {
delete ctx->mOvUI[i];
}
for(int i = 0; i < MAX_BYPASS_LAYERS; i++) {
delete ctx->mOvUI[i];
}
unlockPreviousBypassBuffers(ctx);
unsetBypassBufferLockState(ctx);
#endif
free(ctx);
}
@ -1193,7 +1255,9 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name,
#ifdef COMPOSITION_BYPASS
for(int i = 0; i < MAX_BYPASS_LAYERS; i++) {
dev->mOvUI[i] = new overlay::OverlayUI();
dev->previousBypassHandle[i] = NULL;
}
unsetBypassBufferLockState(dev);
dev->animCount = 0;
dev->bypassState = BYPASS_OFF;
#endif