diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h index 39b488e..228b6be 100755 --- a/libgralloc-qsd8k/gralloc_priv.h +++ b/libgralloc-qsd8k/gralloc_priv.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2008 The Android Open Source Project - * Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -154,15 +154,15 @@ enum { /* possible formats for 3D content*/ enum { - HAL_NO_3D = 0x00, - HAL_3D_IN_SIDE_BY_SIDE_HALF_L_R = 0x10000, + HAL_NO_3D = 0x0000, + HAL_3D_IN_SIDE_BY_SIDE_L_R = 0x10000, HAL_3D_IN_TOP_BOTTOM = 0x20000, HAL_3D_IN_INTERLEAVE = 0x40000, - HAL_3D_IN_SIDE_BY_SIDE_FULL = 0x80000, - HAL_3D_IN_SIDE_BY_SIDE_HALF_R_L = 0xC0000, - HAL_3D_OUT_SIDE_BY_SIDE = 0x1000, - HAL_3D_OUT_TOP_BOTTOM = 0x2000, - HAL_3D_OUT_INTERLEAVE = 0x4000, + HAL_3D_IN_SIDE_BY_SIDE_R_L = 0x80000, + HAL_3D_OUT_SIDE_BY_SIDE = 0x1000, + HAL_3D_OUT_TOP_BOTTOM = 0x2000, + HAL_3D_OUT_INTERLEAVE = 0x4000, + HAL_3D_OUT_MONOSCOPIC = 0x8000 }; enum { diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp index aa2b524..db8468b 100644 --- a/liboverlay/overlay.cpp +++ b/liboverlay/overlay.cpp @@ -39,21 +39,20 @@ struct overlay_control_context_t { struct overlay_control_device_t device; void *sharedMemBase; unsigned int format3D; //input and output 3D format, zero means no 3D -}; - -struct ov_crop_rect_t { - int x; - int y; - int w; - int h; + unsigned int state; + unsigned int orientation; + overlay_rect posPanel; }; struct overlay_data_context_t { struct overlay_data_device_t device; OverlayDataChannel* pobjDataChannel[2]; - int setCrop; unsigned int format3D; - struct ov_crop_rect_t cropRect; + unsigned int state; + bool setCrop; + overlay_rect cropRect; + int srcFD; //store the FD as it will needed for fb1 + int size; //size of the overlay created void *sharedMemBase; }; @@ -65,7 +64,7 @@ static struct hw_module_methods_t overlay_module_methods = { }; struct private_overlay_module_t { - overlay_module_t base; + overlay_module_t base; Mutex *pobjMutex; }; @@ -104,7 +103,6 @@ static int handle_get_rotId(const overlay_handle_t overlay, int index = 0) { return static_cast(overlay)->rotid[index]; } - static int handle_get_size(const overlay_handle_t overlay) { return static_cast(overlay)->size; } @@ -159,13 +157,10 @@ public: int getRotSessionId(int index = 0) { return mHandle.rotid[index]; } int getSharedMemoryFD() {return mHandle.sharedMemoryFd;} - bool startControlChannel(int fbnum, bool norot = false, - unsigned int format3D = 0, int zorder = 0) { - int index = 0; - if (format3D) + bool startControlChannel(int fbnum, bool norot = false, int zorder = 0) { + int index = fbnum; + if (mHandle.format3D) index = zorder; - else - index = fbnum; if (!mHandle.pobjControlChannel[index]) mHandle.pobjControlChannel[index] = new OverlayControlChannel(); else { @@ -174,7 +169,7 @@ public: } bool ret = mHandle.pobjControlChannel[index]->startControlChannel( mHandle.w, mHandle.h, mHandle.format, fbnum, norot, false, - format3D, zorder, true); + mHandle.format3D, zorder, true); if (ret) { if (!(mHandle.pobjControlChannel[index]-> getOvSessionID(mHandle.ovid[index]) && @@ -223,6 +218,16 @@ public: return ret; } + bool getPositionS3D(overlay_rect *rect, int channel) { + if (!mHandle.pobjControlChannel[channel]) { + LOGE("%s:Failed got channel %d", __func__, channel); + return false; + } + + return mHandle.pobjControlChannel[channel]->getPositionS3D( + channel, mHandle.format3D, rect); + } + bool getPosition(int *x, int *y, uint32_t *w, uint32_t *h, int channel) { if (!mHandle.pobjControlChannel[channel]) return false; @@ -241,12 +246,7 @@ public: close(mHandle.sharedMemoryFd); closeControlChannel(0); closeControlChannel(1); - FILE *fp = NULL; - fp = fopen(FORMAT_3D_FILE, "wb"); - if(fp) { - fprintf(fp, "0"); //Sending hdmi info packet(2D) - fclose(fp); - } + send3DInfoPacket (0); } int getFBWidth(int channel) { @@ -260,6 +260,10 @@ public: return false; return mHandle.pobjControlChannel[channel]->getFBHeight(); } + + inline void setFormat3D(unsigned int format3D) { + mHandle.format3D = format3D; + } }; // **************************************************************************** @@ -297,6 +301,19 @@ public: return result; } + static void error_cleanup_control(overlay_control_context_t *ctx, overlay_object *overlay, int fd, int index) { + LOGE("Failed to start control channel %d", index); + for (int i = 0; i < index; i++) + overlay->closeControlChannel(i); + if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { + munmap(ctx->sharedMemBase, sizeof(overlay_shared_data)); + ctx->sharedMemBase = MAP_FAILED; + } + if(fd > 0) + close(fd); + delete overlay; + } + static overlay_t* overlay_createOverlay(struct overlay_control_device_t *dev, uint32_t w, uint32_t h, int32_t format) { overlay_object *overlay = NULL; @@ -307,10 +324,9 @@ public: // Open shared memory to store shared data int size = sizeof(overlay_shared_data); - void *base; + void *base; int fd = ashmem_create_region(SHARED_MEMORY_REGION_NAME, size); - if(fd < 0) { LOGE("%s: create shared memory failed", __func__); return NULL; @@ -347,26 +363,30 @@ public: } if(!fOut3D) { switch (fIn3D) { - case HAL_3D_IN_SIDE_BY_SIDE_HALF_L_R: - case HAL_3D_IN_SIDE_BY_SIDE_HALF_R_L: - case HAL_3D_IN_SIDE_BY_SIDE_FULL: + case HAL_3D_IN_SIDE_BY_SIDE_L_R: + case HAL_3D_IN_SIDE_BY_SIDE_R_L: // For all side by side formats, set the output // format as Side-by-Side i.e 0x1 - format3D |= HAL_3D_IN_SIDE_BY_SIDE_HALF_L_R >> SHIFT_3D; + format3D |= HAL_3D_IN_SIDE_BY_SIDE_L_R >> SHIFT_3D; break; default: format3D |= fIn3D >> SHIFT_3D; //Set the output format break; } } - + unsigned int curState = overlay::getOverlayConfig(format3D); + if (curState == OV_3D_VIDEO_2D_PANEL || curState == OV_3D_VIDEO_2D_TV) { + LOGI("3D content on 2D display: set the output format as monoscopic"); + format3D = FORMAT_3D_INPUT(format3D) | HAL_3D_OUT_MONOSCOPIC_MASK; + } + LOGD("createOverlay: creating overlay with format3D: 0x%x, curState: %d", format3D, curState); ctx->sharedMemBase = base; ctx->format3D = format3D; + ctx->state = curState; memset(ctx->sharedMemBase, 0, size); /* number of buffer is not being used as overlay buffers are coming from client */ overlay = new overlay_object(w, h, format, fd, format3D); - if (overlay == NULL) { LOGE("%s: can't create overlay object!", __FUNCTION__); if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { @@ -377,81 +397,49 @@ public: close(fd); return NULL; } - - if (format3D) { - bool res1, res2; - if (format3D & HAL_3D_IN_SIDE_BY_SIDE_HALF_R_L) { - // For R-L formats, set the Zorder of the second channel as 0 - res1 = overlay->startControlChannel(1, false, format3D, 1); - res2 = overlay->startControlChannel(1, false, format3D, 0); - } else { - res1 = overlay->startControlChannel(1, false, format3D, 0); - res2 = overlay->startControlChannel(1, false, format3D, 1); - } - if (!res1 || !res2) { - LOGE("Failed to start control channel for VG pipe 0 or 1"); - overlay->closeControlChannel(0); - overlay->closeControlChannel(1); - if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { - munmap(ctx->sharedMemBase, size); - ctx->sharedMemBase = MAP_FAILED; - } - if(fd > 0) - close(fd); - - delete overlay; + bool noRot; +#ifdef USE_MSM_ROTATOR + noRot = false; +#else + noRot = true; +#endif + switch (ctx->state) { + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + if (!overlay->startControlChannel(FRAMEBUFFER_0, noRot)) { + error_cleanup_control(ctx, overlay, fd, FRAMEBUFFER_0); return NULL; } - return overlay; - } -#ifdef USE_MSM_ROTATOR - if (!overlay->startControlChannel(0)) { -#else - if (!overlay->startControlChannel(0, true)) { -#endif - LOGE("Failed to start control channel for framebuffer 0"); - overlay->closeControlChannel(0); - if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { - munmap(ctx->sharedMemBase, size); - ctx->sharedMemBase = MAP_FAILED; + break; + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_2D_TV: + if (!overlay->startControlChannel(FRAMEBUFFER_0, noRot, VG0_PIPE)) { + error_cleanup_control(ctx, overlay, fd, VG0_PIPE); + return NULL; } - if(fd > 0) - close(fd); - - delete overlay; - return NULL; - } - - char value[PROPERTY_VALUE_MAX]; - property_get("hw.hdmiON", value, "0"); - if (!atoi(value)) { - return overlay; - } - - if (!overlay->startControlChannel(1, true)) { - LOGE("Failed to start control channel for framebuffer 1"); - overlay->closeControlChannel(1); - if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { - munmap(ctx->sharedMemBase, size); - ctx->sharedMemBase = MAP_FAILED; + if (!overlay->startControlChannel(FRAMEBUFFER_1, true, VG1_PIPE)) { + error_cleanup_control(ctx, overlay, fd, VG1_PIPE); + return NULL; } - if(fd > 0) - close(fd); - - delete overlay; - return NULL; - } - else { - overlay_rect rect; - if(overlay->getAspectRatioPosition(&rect, 1)) { - if (!overlay->setPosition(rect.x, rect.y, rect.width, rect.height, 1)) { - LOGE("Failed to upscale for framebuffer 1"); + break; + case OV_3D_VIDEO_3D_TV: + for (int i=0; istartControlChannel(FRAMEBUFFER_1, true, i)) { + error_cleanup_control(ctx, overlay, fd, i); + return NULL; } } + break; + default: + break; + } + overlay_shared_data* data = static_cast(ctx->sharedMemBase); + data->state = ctx->state; + for (int i=0; iovid[i] = overlay->getHwOvId(i); + data->rotid[i] = overlay->getRotSessionId(i); } - return overlay; - } static void overlay_destroyOverlay(struct overlay_control_device_t *dev, @@ -480,37 +468,47 @@ public: dev->common.module); Mutex::Autolock objLock(m->pobjMutex); bool ret; - if(ctx->format3D){ - int wHDMI = obj->getFBWidth(1); - int hHDMI = obj->getFBHeight(1); - if(ctx->format3D & HAL_3D_OUT_SIDE_BY_SIDE_HALF_MASK) { - ret = obj->setPosition(0, 0, wHDMI/2, hHDMI, 0); - if (!ret) - return -1; - ret = obj->setPosition(wHDMI/2, 0, wHDMI/2, hHDMI, 1); - if (!ret) - return -1; - } - else if (ctx->format3D & HAL_3D_OUT_TOP_BOTTOM_MASK) { - ret = obj->setPosition(0, 0, wHDMI, hHDMI/2, 0); - if (!ret) - return -1; - ret = obj->setPosition(0, hHDMI/2, wHDMI, hHDMI/2, 1); - if (!ret) - return -1; - } - else if (ctx->format3D & HAL_3D_OUT_INTERLEAVE_MASK) { - //TBD - } else if (ctx->format3D & HAL_3D_OUT_SIDE_BY_SIDE_FULL_MASK) { - //TBD - } else { - LOGE("%s: Unsupported 3D output format!!!", __func__); - } - } - else { - ret = obj->setPosition(x, y, w, h, 0); - if (!ret) + overlay_rect rect; + // saving the position for the disconnection event + ctx->posPanel.x = x; + ctx->posPanel.y = y; + ctx->posPanel.w = w; + ctx->posPanel.h = h; + + switch (ctx->state) { + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + if(!obj->setPosition(x, y, w, h, VG0_PIPE)) { + LOGE("%s:Failed for channel 0", __func__); return -1; + } + break; + case OV_2D_VIDEO_ON_TV: + if(!obj->setPosition(x, y, w, h, VG0_PIPE)) { + LOGE("%s:Failed for channel 0", __func__); + return -1; + } + obj->getAspectRatioPosition(&rect, VG1_PIPE); + if(!obj->setPosition(rect.x, rect.y, rect.w, rect.h, VG1_PIPE)) { + LOGE("%s:Failed for channel 1", __func__); + return -1; + } + break; + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + for (int i = 0; i < NUM_CHANNELS; i++) { + if (!obj->getPositionS3D(&rect, i)) + ret = obj->setPosition(x, y, w, h, i); + else + ret = obj->setPosition(rect.x, rect.y, rect.w, rect.h, i); + if (!ret) { + LOGE("%s:Failed for channel %d", __func__, i); + return -1; + } + } + break; + default: + break; } return 0; } @@ -530,7 +528,7 @@ public: data.readyToQueue = 1; memcpy(ctx->sharedMemBase, (void*)&data, sizeof(overlay_shared_data)); } -return 0; + return 0; } static int overlay_getPosition(struct overlay_control_device_t *dev, @@ -542,12 +540,91 @@ return 0; dev->common.module); Mutex::Autolock objLock(m->pobjMutex); overlay_object * obj = static_cast(overlay); - bool ret = obj->getPosition(x, y, w, h, 0); - if (!ret) - return -1; - return 0; + return obj->getPosition(x, y, w, h, 0) ? 0 : -1; } - +#if 0 + static bool overlay_configPipes(overlay_control_context_t *ctx, + overlay_object *obj, int enable, + unsigned int curState) { + bool noRot = true; + overlay_rect rect; +#ifdef USE_MSM_ROTATOR + noRot = false; +#else + noRot = true; +#endif + if(enable) { + if( (ctx->state == OV_2D_VIDEO_ON_PANEL) || + (ctx->state == OV_3D_VIDEO_2D_PANEL && curState == OV_3D_VIDEO_2D_TV) ) { + LOGI("2D TV connected, Open a new control channel for TV."); + //Start a new channel for mirroring on HDMI + if (!obj->startControlChannel(FRAMEBUFFER_1, true, VG1_PIPE)) { + obj->closeControlChannel(FRAMEBUFFER_1); + return false; + } + if (ctx->format3D) + obj->getPositionS3D(&rect, FRAMEBUFFER_1); + else + obj->getAspectRatioPosition(&rect, FRAMEBUFFER_1); + if(!obj->setPosition(rect.x, rect.y, rect.w, rect.h, FRAMEBUFFER_1)) { + LOGE("%s:Failed to set position for framebuffer 1", __func__); + return false; + } + } else if( (ctx->state == OV_3D_VIDEO_2D_PANEL && curState == OV_3D_VIDEO_3D_TV) ) { + LOGI("3D TV connected, close old ctl channel and open two ctl channels for 3DTV."); + //close the channel 0 as it is configured for panel + obj->closeControlChannel(FRAMEBUFFER_0); + //update the output from monoscopic to stereoscopic + ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | ctx->format3D >> SHIFT_3D; + obj->setFormat3D(ctx->format3D); + LOGI("Control: new S3D format : 0x%x", ctx->format3D); + //now open both the channels + for (int i = 0; i < NUM_CHANNELS; i++) { + if (!obj->startControlChannel(FRAMEBUFFER_1, true, i)) { + LOGE("%s:Failed to open control channel for pipe %d", __func__, i); + return false; + } + obj->getPositionS3D(&rect, i); + if(!obj->setPosition(rect.x, rect.y, rect.w, rect.h, i)) { + LOGE("%s: failed for channel %d", __func__, i); + return false; + } + } + } + } else { + if ( (ctx->state == OV_2D_VIDEO_ON_TV) || + (ctx->state == OV_3D_VIDEO_2D_TV && curState == OV_3D_VIDEO_2D_PANEL) ) { + LOGI("2D TV disconnected, close the control channel."); + obj->closeControlChannel(VG1_PIPE); + } else if (ctx->state == OV_3D_VIDEO_3D_TV && curState == OV_3D_VIDEO_2D_PANEL) { + LOGI("3D TV disconnected, close the control channels & open one for panel."); + // Close both the pipes' control channel + obj->closeControlChannel(VG0_PIPE); + obj->closeControlChannel(VG1_PIPE); + //update the format3D as monoscopic + ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | HAL_3D_OUT_MONOSCOPIC_MASK; + obj->setFormat3D(ctx->format3D); + LOGI("Control: New format3D: 0x%x", ctx->format3D); + //now open the channel 0 + if (!obj->startControlChannel(FRAMEBUFFER_0, noRot)) { + LOGE("%s:Failed to open control channel for pipe 0", __func__); + return false; + } + if(!obj->setPosition(ctx->posPanel.x, ctx->posPanel.y, ctx->posPanel.w, ctx->posPanel.h, FRAMEBUFFER_0)) { + LOGE("%s:Failed to set position for framebuffer 0", __func__); + return false; + } + if (!obj->setParameter(OVERLAY_TRANSFORM, ctx->orientation, VG0_PIPE)) { + LOGE("%s: Failed to set orienatation for channel 0", __func__); + return -1; + } + } + } + //update the context's state + ctx->state = curState; + return true; + } +#endif static int overlay_setParameter(struct overlay_control_device_t *dev, overlay_t* overlay, int param, int value) { @@ -555,28 +632,60 @@ return 0; overlay_object *obj = static_cast(overlay); private_overlay_module_t* m = reinterpret_cast( dev->common.module); - Mutex::Autolock objLock(m->pobjMutex); if (obj && (obj->getSharedMemoryFD() > 0) && (ctx->sharedMemBase != MAP_FAILED)) { - overlay_shared_data data; - data.readyToQueue = 0; - memcpy(ctx->sharedMemBase, (void*)&data, sizeof(data)); + overlay_shared_data* data = static_cast(ctx->sharedMemBase); + data->readyToQueue = 0; +#if 0 + /* SF will inform Overlay HAL the HDMI cable connection. + This avoids polling on the system property hw.hdmiON */ + if(param == OVERLAY_HDMI_ENABLE) { + unsigned int curState = getOverlayConfig(ctx->format3D); + if(ctx->state != curState) { + LOGI("Overlay Configured for : %d Current state: %d", ctx->state, curState); + if(!overlay_configPipes(ctx, obj, value, curState)) { + LOGE("In overlay_setParameter: reconfiguring of Overlay failed !!"); + return -1; + } + else { + data->state = ctx->state; + for (int i=0; iovid[i] = obj->getHwOvId(i); + data->rotid[i] = obj->getRotSessionId(i); + } + } + } + } +#endif } - bool ret; - if (ctx->format3D) { - ret = obj->setParameter(param, value, 0); - if (!ret) - return -1; - ret = obj->setParameter(param, value, 1); - if (!ret) - return -1; - } - else { - ret = obj->setParameter(param, value, 0); - if (!ret) - return -1; +// if(param != OVERLAY_HDMI_ENABLE) + { + //Save the panel orientation + if (param == OVERLAY_TRANSFORM) + ctx->orientation = value; + switch (ctx->state) { + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + if(!obj->setParameter(param, value, VG0_PIPE)) { + LOGE("%s: Failed for channel 0", __func__); + return -1; + } + break; + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + for (int i=0; isetParameter(param, value, i)) { + LOGE("%s: Failed for channel %d", __func__, i); + return -1; + } + } + break; + default: + break; + } } return 0; } @@ -597,6 +706,15 @@ return 0; // Data module // **************************************************************************** + static void error_cleanup_data(struct overlay_data_context_t* ctx, int index) + { + LOGE("Couldn't start data channel %d", index); + for (int i = 0; ipobjDataChannel[i]; + ctx->pobjDataChannel[i] = NULL; + } + } + int overlay_initialize(struct overlay_data_device_t *dev, overlay_handle_t handle) { @@ -617,11 +735,20 @@ return 0; int size = handle_get_size(handle); int sharedFd = handle_get_shared_fd(handle); unsigned int format3D = handle_get_format3D(handle); - FILE *fp = NULL; private_overlay_module_t* m = reinterpret_cast( dev->common.module); Mutex::Autolock objLock(m->pobjMutex); - + bool noRot = true; +#ifdef USE_MSM_ROTATOR + noRot = false; +#else + noRot = true; +#endif + //default: set crop info to src size. + ctx->cropRect.x = 0; + ctx->cropRect.y = 0; + //ctx->cropRect.w = handle_get_width(handle); + //ctx->cropRect.h = handle_get_height(handle); ctx->sharedMemBase = MAP_FAILED; ctx->format3D = format3D; @@ -637,64 +764,67 @@ return 0; LOGE("Received invalid shared memory fd"); return -1; } - - if (ctx->format3D) { - bool res1, res2; - ctx->pobjDataChannel[0] = new OverlayDataChannel(); - ctx->pobjDataChannel[1] = new OverlayDataChannel(); - res1 = - ctx->pobjDataChannel[0]->startDataChannel(ovid, rotid, size, 1); - ovid = handle_get_ovId(handle, 1); - rotid = handle_get_rotId(handle, 1); - res2 = - ctx->pobjDataChannel[1]->startDataChannel(ovid, rotid, size, 1); - if (!res1 || !res2) { - LOGE("Couldnt start data channel for VG pipe 0 or 1"); - delete ctx->pobjDataChannel[0]; - ctx->pobjDataChannel[0] = 0; - delete ctx->pobjDataChannel[1]; - ctx->pobjDataChannel[1] = 0; + overlay_shared_data* data = static_cast + (ctx->sharedMemBase); + if (data == NULL){ + LOGE("%s:Shared data is NULL!!", __func__); + return -1; + } + ctx->state = data->state; + switch (ctx->state) { + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + ctx->pobjDataChannel[VG0_PIPE] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[VG0_PIPE]->startDataChannel(ovid, rotid, size, FRAMEBUFFER_0, noRot)) { + error_cleanup_data(ctx, VG0_PIPE); return -1; } - //Sending hdmi info packet(3D output format) - fp = fopen(FORMAT_3D_FILE, "wb"); - if (fp) { - fprintf(fp, "%d", format3D & OUTPUT_MASK_3D); - fclose(fp); - fp = NULL; + //setting the crop value + if(!ctx->pobjDataChannel[VG0_PIPE]->setCrop( + ctx->cropRect.x,ctx->cropRect.y, + ctx->cropRect.w,ctx->cropRect.h)) { + LOGE("%s:failed to crop pipe 0", __func__); } - return 0; - } - ctx->pobjDataChannel[0] = new OverlayDataChannel(); - if (!ctx->pobjDataChannel[0]->startDataChannel(ovid, rotid, - size, 0)) { - LOGE("Couldnt start data channel for framebuffer 0"); - delete ctx->pobjDataChannel[0]; - ctx->pobjDataChannel[0] = 0; - return -1; - } - - char value[PROPERTY_VALUE_MAX]; - property_get("hw.hdmiON", value, "0"); - if (!atoi(value)) { - ctx->pobjDataChannel[1] = 0; - return 0; - } - - ovid = handle_get_ovId(handle, 1); - rotid = handle_get_rotId(handle, 1); - ctx->pobjDataChannel[1] = new OverlayDataChannel(); - if (!ctx->pobjDataChannel[1]->startDataChannel(ovid, rotid, - size, 1, true)) { - LOGE("Couldnt start data channel for framebuffer 1"); - delete ctx->pobjDataChannel[1]; - ctx->pobjDataChannel[1] = 0; - } - fp = fopen(FORMAT_3D_FILE, "wb"); - if (fp) { - fprintf(fp, "0"); //Sending hdmi info packet(2D) - fclose(fp); - fp = NULL; + break; + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_2D_TV: + for (int i = 0; i < NUM_CHANNELS; i++) { + ovid = handle_get_ovId(handle, i); + rotid = handle_get_rotId(handle, i); + ctx->pobjDataChannel[i] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[i]->startDataChannel(ovid, rotid, size, i, true)) { + error_cleanup_data(ctx, i); + return -1; + } + //setting the crop value + if(!ctx->pobjDataChannel[i]->setCrop( + ctx->cropRect.x,ctx->cropRect.y, + ctx->cropRect.w,ctx->cropRect.h)) { + LOGE("%s:failed to crop pipe %d", __func__, i); + } + } + break; + case OV_3D_VIDEO_3D_TV: + overlay_rect rect; + for (int i = 0; i < NUM_CHANNELS; i++) { + ovid = handle_get_ovId(handle, i); + rotid = handle_get_rotId(handle, i); + ctx->pobjDataChannel[i] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[i]->startDataChannel(ovid, rotid, size, FRAMEBUFFER_1, true)) { + error_cleanup_data(ctx, i); + return -1; + } + ctx->pobjDataChannel[i]->getCropS3D(&ctx->cropRect, i, ctx->format3D, &rect); + if (!ctx->pobjDataChannel[i]->setCrop(rect.x, rect.y, rect.w, rect.h)) { + LOGE("%s: Failed to crop channel %d", __func__, i); + //return -1; + } + } + if(!send3DInfoPacket(ctx->format3D & OUTPUT_MASK_3D)) + LOGI("%s:Error setting the 3D mode for TV", __func__); + break; + default: + break; } return 0; } @@ -706,7 +836,7 @@ return 0; * representing this buffer. */ - /* no interal overlay buffer to dequeue */ + /* no internal overlay buffer to dequeue */ LOGE("%s: no buffer to dequeue ...\n", __FUNCTION__); return 0; @@ -720,7 +850,12 @@ return 0; private_overlay_module_t* m = reinterpret_cast( dev->common.module); Mutex::Autolock objLock(m->pobjMutex); - + bool noRot = true; +#ifdef USE_MSM_ROTATOR + noRot = false; +#else + noRot = true; +#endif // Check if readyToQueue is enabled. overlay_shared_data data; if(ctx->sharedMemBase != MAP_FAILED) @@ -732,60 +867,150 @@ return 0; LOGE("Overlay is not ready to queue buffers"); return -1; } - - bool result; - if (ctx->format3D) { - if ( (ctx->format3D & HAL_3D_OUT_SIDE_BY_SIDE_HALF_MASK) || - (ctx->format3D & HAL_3D_OUT_TOP_BOTTOM_MASK) ) { - result = (ctx->pobjDataChannel[0] && - ctx->pobjDataChannel[0]-> - queueBuffer((uint32_t) buffer)); - if (!result) - LOGE("Queuebuffer failed for VG pipe 0"); - result = (ctx->pobjDataChannel[1] && - ctx->pobjDataChannel[1]-> - queueBuffer((uint32_t) buffer)); - if (!result) - LOGE("Queuebuffer failed for VG pipe 1"); +#if 0 + if(data->state != ctx->state) { + LOGI("Data: State has changed from %d to %d", ctx->state, data->state); + if( (ctx->state == OV_2D_VIDEO_ON_PANEL) || + (ctx->state == OV_3D_VIDEO_2D_PANEL && data->state == OV_3D_VIDEO_2D_TV) ) { + LOGI("2D TV connected, Open a new data channel for TV."); + //Start a new channel for mirroring on HDMI + ctx->pobjDataChannel[VG1_PIPE] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[VG1_PIPE]->startDataChannel( + data->ovid[VG1_PIPE], data->rotid[VG1_PIPE], ctx->size, + FRAMEBUFFER_1, true)) { + delete ctx->pobjDataChannel[VG1_PIPE]; + ctx->pobjDataChannel[VG1_PIPE] = NULL; + return -1; + } + //setting the crop value + if(ctx->format3D) { + overlay_rect rect; + ctx->pobjDataChannel[VG1_PIPE]->getCropS3D(&ctx->cropRect, VG1_PIPE, ctx->format3D, &rect); + if (!ctx->pobjDataChannel[VG1_PIPE]->setCrop(rect.x, rect.y, rect.w, rect.h)) { + LOGE("%s: Failed to crop pipe 1", __func__); + } + } else { + if(!ctx->pobjDataChannel[VG1_PIPE]->setCrop( + ctx->cropRect.x,ctx->cropRect.y, + ctx->cropRect.w,ctx->cropRect.h)) { + LOGE("%s:failed to crop pipe 1", __func__); + } + } + //setting the srcFD + if (!ctx->pobjDataChannel[VG1_PIPE]->setFd(ctx->srcFD)) { + LOGE("%s: Failed to set fd for pipe 1", __func__); + return -1; + } + } else if( (ctx->state == OV_3D_VIDEO_2D_PANEL && data->state == OV_3D_VIDEO_3D_TV) ) { + LOGI("3D TV connected, close data channel and open both data channels for 3DTV."); + //close the channel 0 as it is configured for panel + ctx->pobjDataChannel[VG0_PIPE]->closeDataChannel(); + delete ctx->pobjDataChannel[VG0_PIPE]; + ctx->pobjDataChannel[VG0_PIPE] = NULL; + //update the output from monoscopic to stereoscopic + ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | ctx->format3D >> SHIFT_3D; + LOGI("Data: New S3D format : 0x%x", ctx->format3D); + //now open both the channels + overlay_rect rect; + for (int i = 0; i < NUM_CHANNELS; i++) { + ctx->pobjDataChannel[i] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[i]->startDataChannel( + data->ovid[i], data->rotid[i], ctx->size, + FRAMEBUFFER_1, true)) { + error_cleanup_data(ctx, i); + return -1; + } + ctx->pobjDataChannel[i]->getCropS3D(&ctx->cropRect, i, ctx->format3D, &rect); + if (!ctx->pobjDataChannel[i]->setCrop(rect.x, rect.y, rect.w, rect.h)) { + LOGE("%s: Failed to crop pipe %d", __func__, i); + return -1; + } + if (!ctx->pobjDataChannel[i]->setFd(ctx->srcFD)) { + LOGE("%s: Failed to set fd for pipe %d", __func__, i); + return -1; + } + } + send3DInfoPacket(ctx->format3D & OUTPUT_MASK_3D); + } else if( (ctx->state == OV_2D_VIDEO_ON_TV) || + (ctx->state == OV_3D_VIDEO_2D_TV && data->state == OV_3D_VIDEO_2D_PANEL) ) { + LOGI("2D TV disconnected, close the data channel for TV."); + ctx->pobjDataChannel[VG1_PIPE]->closeDataChannel(); + delete ctx->pobjDataChannel[VG1_PIPE]; + ctx->pobjDataChannel[VG1_PIPE] = NULL; + } else if (ctx->state == OV_3D_VIDEO_3D_TV && data->state == OV_3D_VIDEO_2D_PANEL) { + LOGI("3D TV disconnected, close the data channels for 3DTV and open one for panel."); + // Close both the pipes' data channel + for (int i = 0; i < NUM_CHANNELS; i++) { + ctx->pobjDataChannel[i]->closeDataChannel(); + delete ctx->pobjDataChannel[i]; + ctx->pobjDataChannel[i] = NULL; + } + send3DInfoPacket(0); + //update the format3D as monoscopic + ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | HAL_3D_OUT_MONOSCOPIC_MASK; + //now open the channel 0 + ctx->pobjDataChannel[VG0_PIPE] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[VG0_PIPE]->startDataChannel( + data->ovid[VG0_PIPE], data->rotid[VG0_PIPE], ctx->size, + FRAMEBUFFER_0, noRot)) { + error_cleanup_data(ctx, VG0_PIPE); + return -1; + } + overlay_rect rect; + ctx->pobjDataChannel[VG0_PIPE]->getCropS3D(&ctx->cropRect, VG0_PIPE, ctx->format3D, &rect); + //setting the crop value + if(!ctx->pobjDataChannel[VG0_PIPE]->setCrop( rect.x, rect.y,rect.w, rect.h)) { + LOGE("%s:failed to crop pipe 0", __func__); + } + //setting the srcFD + if (!ctx->pobjDataChannel[VG0_PIPE]->setFd(ctx->srcFD)) { + LOGE("%s: Failed set fd for pipe 0", __func__); + return -1; + } } - else if (ctx->format3D & HAL_3D_OUT_INTERLEAVE_MASK) { - //TBD - } else if (ctx->format3D & HAL_3D_OUT_SIDE_BY_SIDE_FULL_MASK) { - //TBD - } else { - LOGE("%s:Unknown 3D Format...", __func__); - } - return 0; + //update the context's state + ctx->state = data->state; } - if(ctx->setCrop) { - bool result = (ctx->pobjDataChannel[0] && - ctx->pobjDataChannel[0]-> - setCrop(ctx->cropRect.x,ctx->cropRect.y,ctx->cropRect.w,ctx->cropRect.h)); - ctx->setCrop = 0; - if (!result) { - LOGE("set crop failed for framebuffer 0"); +#endif + switch (ctx->state) { + case OV_2D_VIDEO_ON_PANEL: + if (ctx->setCrop) { + if(!ctx->pobjDataChannel[VG0_PIPE]->setCrop(ctx->cropRect.x, ctx->cropRect.y, ctx->cropRect.w, ctx->cropRect.h)) { + LOGE("%s: failed for pipe 0", __func__); + } + ctx->setCrop = false; + } + if(!ctx->pobjDataChannel[VG0_PIPE]->queueBuffer((uint32_t) buffer)) { + LOGE("%s: failed for VG pipe 0", __func__); return -1; } - } - - result = (ctx->pobjDataChannel[0] && - ctx->pobjDataChannel[0]-> - queueBuffer((uint32_t) buffer)); - if (!result) - LOGE("Queuebuffer failed for framebuffer 0"); - else { - char value[PROPERTY_VALUE_MAX]; - property_get("hw.hdmiON", value, "0"); - if (!atoi(value)) { - return 0; - } - result = (ctx->pobjDataChannel[1] && - ctx->pobjDataChannel[1]-> - queueBuffer((uint32_t) buffer)); - if (!result) { - LOGE("QueueBuffer failed for framebuffer 1"); - return -1; - } + break; + case OV_3D_VIDEO_2D_PANEL: + if (ctx->setCrop) { + overlay_rect rect; + ctx->pobjDataChannel[VG0_PIPE]->getCropS3D(&ctx->cropRect, VG0_PIPE, ctx->format3D, &rect); + if(!ctx->pobjDataChannel[VG0_PIPE]->setCrop(rect.x, rect.y, rect.w, rect.h)) { + LOGE("%s: failed for pipe 0", __func__); + } + ctx->setCrop = false; + } + if(!ctx->pobjDataChannel[VG0_PIPE]->queueBuffer((uint32_t) buffer)) { + LOGE("%s: failed for VG pipe 0", __func__); + return -1; + } + break; + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + for (int i=0; ipobjDataChannel[i]->queueBuffer((uint32_t) buffer)) { + LOGE("%s: failed for VG pipe %d", __func__, i); + return -1; + } + } + break; + default: + break; } return -1; @@ -797,41 +1022,28 @@ return 0; dev->common.module); struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; Mutex::Autolock objLock(m->pobjMutex); - bool ret; - if (ctx->format3D) { - ret = (ctx->pobjDataChannel[0] && - ctx->pobjDataChannel[0]->setFd(fd)); - if (!ret) { - LOGE("set fd failed for VG pipe 0"); + ctx->srcFD = fd; + switch (ctx->state) { + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + if(!ctx->pobjDataChannel[VG0_PIPE]->setFd(fd)) { + LOGE("%s: failed for VG pipe 0", __func__); return -1; } - ret = (ctx->pobjDataChannel[1] && - ctx->pobjDataChannel[1]->setFd(fd)); - if (!ret) { - LOGE("set fd failed for VG pipe 1"); - return -1; + break; + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + for (int i=0; ipobjDataChannel[i]->setFd(fd)) { + LOGE("%s: failed for pipe %d", __func__, i); + return -1; + } } - return 0; + break; + default: + break; } - ret = (ctx->pobjDataChannel[0] && - ctx->pobjDataChannel[0]->setFd(fd)); - if (!ret) { - LOGE("set fd failed for framebuffer 0"); - return -1; - } - - char value[PROPERTY_VALUE_MAX]; - property_get("hw.hdmiON", value, "0"); - if (!atoi(value)) { - return 0; - } - - ret = (ctx->pobjDataChannel[1] && - ctx->pobjDataChannel[1]->setFd(fd)); - if (!ret) { - LOGE("set fd failed for framebuffer 1"); - } - return 0; } @@ -842,68 +1054,36 @@ return 0; dev->common.module); struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; Mutex::Autolock objLock(m->pobjMutex); - bool ret = false; - // for the 3D usecase extract L and R channels from a frame - if(ctx->format3D) { - if ((ctx->format3D & HAL_3D_IN_SIDE_BY_SIDE_HALF_L_R) || - (ctx->format3D & HAL_3D_IN_SIDE_BY_SIDE_HALF_R_L)) { - ret = (ctx->pobjDataChannel[0] && - ctx->pobjDataChannel[0]-> - setCrop(0, 0, w/2, h)); - if (!ret) { - LOGE("set crop failed for VG pipe 0"); - return -1; - } - ret = (ctx->pobjDataChannel[1] && - ctx->pobjDataChannel[1]-> - setCrop(w/2, 0, w/2, h)); - if (!ret) { - LOGE("set crop failed for VG pipe 1"); - return -1; - } - } - else if (ctx->format3D & HAL_3D_IN_TOP_BOTTOM) { - ret = (ctx->pobjDataChannel[0] && - ctx->pobjDataChannel[0]-> - setCrop(0, 0, w, h/2)); - if (!ret) { - LOGE("set crop failed for VG pipe 0"); - return -1; - } - ret = (ctx->pobjDataChannel[1] && - ctx->pobjDataChannel[1]-> - setCrop(0, h/2, w, h/2)); - if (!ret) { - LOGE("set crop failed for VG pipe 1"); - return -1; - } - } - else if (ctx->format3D & HAL_3D_IN_INTERLEAVE) { - //TBD - } else if (ctx->format3D & HAL_3D_IN_SIDE_BY_SIDE_FULL) { - //TBD - } - return 0; - } - //For primary set Crop - ctx->setCrop = 1; + overlay_rect rect; ctx->cropRect.x = x; ctx->cropRect.y = y; ctx->cropRect.w = w; ctx->cropRect.h = h; - - char value[PROPERTY_VALUE_MAX]; - property_get("hw.hdmiON", value, "0"); - if (!atoi(value)) { - return 0; - } - - ret = (ctx->pobjDataChannel[1] && - ctx->pobjDataChannel[1]-> - setCrop(x, y, w, h)); - if (!ret) { - LOGE("set crop failed for framebuffer 1"); - return -1; + switch (ctx->state) { + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + ctx->setCrop = true; + break; + case OV_2D_VIDEO_ON_TV: + for (int i=0; ipobjDataChannel[i]->setCrop(x, y, w, h)) { + LOGE("%s: failed for pipe %d", __func__, i); + return -1; + } + } + break; + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + for (int i=0; ipobjDataChannel[i]->getCropS3D(&ctx->cropRect, i, ctx->format3D, &rect); + if(!ctx->pobjDataChannel[i]->setCrop(rect.x, rect.y, rect.w, rect.h)) { + LOGE("%s: failed for pipe %d", __func__, i); + return -1; + } + } + break; + default: + break; } return 0; } @@ -917,7 +1097,7 @@ return 0; int overlay_getBufferCount(struct overlay_data_device_t *dev) { - return( 0 ); + return 0; } @@ -1010,7 +1190,7 @@ return 0; dev->device.common.close = overlay_data_close; dev->device.initialize = overlay_initialize; - dev->device.setCrop = overlay_setCrop; + dev->device.setCrop = overlay_setCrop; dev->device.dequeueBuffer = overlay_dequeueBuffer; dev->device.queueBuffer = overlay_queueBuffer; dev->device.setFd = overlay_setFd; diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 33dd458..ba35210 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -139,6 +139,60 @@ static void reportError(const char* message) { using namespace overlay; +bool overlay::isHDMIConnected () { + char value[PROPERTY_VALUE_MAX]; + property_get("hw.hdmiON", value, "0"); + int isHDMI = atoi(value); + return isHDMI ? true : false; +} + +bool overlay::is3DTV() { + char is3DTV = '0'; + FILE *fp = fopen(EDID_3D_INFO_FILE, "r"); + if (fp) { + fread(&is3DTV, 1, 1, fp); + fclose(fp); + } + LOGI("3DTV EDID flag: %d", is3DTV); + return (is3DTV == '0') ? false : true; +} + +bool overlay::send3DInfoPacket (unsigned int format3D) { + FILE *fp = fopen(FORMAT_3D_FILE, "wb"); + if (fp) { + fprintf(fp, "%d", format3D); + fclose(fp); + fp = NULL; + return true; + } + LOGE("%s:no sysfs entry for setting 3d mode!", __func__); + return false; +} + +unsigned int overlay::getOverlayConfig (unsigned int format3D) { + bool isTV3D = false, isHDMI = false; + unsigned int curState = 0; + isHDMI = overlay::isHDMIConnected(); + if (isHDMI) { + LOGD("%s: HDMI connected... checking the TV type", __func__); + isTV3D = overlay::is3DTV(); + if (format3D) { + if (isTV3D) + curState = OV_3D_VIDEO_3D_TV; + else + curState = OV_3D_VIDEO_2D_TV; + } else + curState = OV_2D_VIDEO_ON_TV; + } else { + LOGD("%s: HDMI not connected...", __func__); + if(format3D) + curState = OV_3D_VIDEO_2D_PANEL; + else + curState = OV_2D_VIDEO_ON_PANEL; + } + return curState; +} + Overlay::Overlay() : mChannelUP(false), mHDMIConnected(false), mCloseChannel(false), mS3DFormat(0) { } @@ -160,7 +214,6 @@ bool Overlay::startChannel(int w, int h, int format, int fbnum, unsigned int format3D, int channel, bool ignoreFB, int num_buffers) { int zorder = 0; - if (format3D) zorder = channel; mChannelUP = objOvCtrlChannel[channel].startControlChannel(w, h, format, fbnum, @@ -180,7 +233,7 @@ bool Overlay::startChannelHDMI(int w, int h, int format, bool norot) { ret = startChannel(w, h, format, FRAMEBUFFER_1, true, 0, 0, VG1_PIPE); overlay_rect rect; if(ret && objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(w, h, format, &rect)) { - if(!setChannelPosition(rect.x, rect.y, rect.width, rect.height, VG1_PIPE)) { + if(!setChannelPosition(rect.x, rect.y, rect.w, rect.h, VG1_PIPE)) { LOGE("Failed to upscale for framebuffer 1"); return false; } @@ -189,29 +242,20 @@ bool Overlay::startChannelHDMI(int w, int h, int format, bool norot) { return ret; } -bool Overlay::startChannelS3D(int w, int h, int format, bool norot, int s3DFormat) { - - if (!mHDMIConnected) { - // S3D without HDMI is not supported yet - return true; - } +bool Overlay::startChannelS3D(int w, int h, int format, bool norot) { + bool ret = false; // Start both the channels for the S3D content - bool ret = startChannel(w, h, format, FRAMEBUFFER_1, norot, 0, mS3DFormat, VG0_PIPE); + if (mS3DFormat & HAL_3D_OUT_MONOSCOPIC_MASK) + ret = startChannel(w, h, format, FRAMEBUFFER_0, norot, 0, mS3DFormat, VG0_PIPE); + else + ret = startChannel(w, h, format, FRAMEBUFFER_1, norot, 0, mS3DFormat, VG0_PIPE); if (ret) { ret = startChannel(w, h, format, FRAMEBUFFER_1, norot, 0, mS3DFormat, VG1_PIPE); } - if (ret) { - FILE *fp = fopen(FORMAT_3D_FILE, "wb"); - if (fp) { - fprintf(fp, "%d", mS3DFormat & OUTPUT_MASK_3D); - fclose(fp); - fp = NULL; - } - } - if (!ret) { closeChannel(); - } + } else if (!(mS3DFormat & HAL_3D_OUT_MONOSCOPIC_MASK)) + ret = overlay::send3DInfoPacket(mS3DFormat & OUTPUT_MASK_3D); return ret; } @@ -221,12 +265,7 @@ bool Overlay::closeChannel() { return true; if(mS3DFormat) { - FILE *fp = fopen(FORMAT_3D_FILE, "wb"); - if (fp) { - fprintf(fp, "0"); - fclose(fp); - fp = NULL; - } + overlay::send3DInfoPacket(0); } for (int i = 0; i < NUM_CHANNELS; i++) { objOvCtrlChannel[i].closeControlChannel(); @@ -260,12 +299,16 @@ bool Overlay::setChannelPosition(int x, int y, uint32_t w, uint32_t h, int chann bool Overlay::setPositionS3D(int x, int y, uint32_t w, uint32_t h) { bool ret = false; - for (int i = 0; i < NUM_CHANNELS; i++) { overlay_rect rect; ret = objOvCtrlChannel[i].getPositionS3D(i, mS3DFormat, &rect); - if (ret) { - setChannelPosition(rect.x, rect.y, rect.width, rect.height, i); + if (!ret) + ret = setChannelPosition(x, y, w, h, i); + else + ret = setChannelPosition(rect.x, rect.y, rect.w, rect.h, i); + if (!ret) { + LOGE("%s: failed for channel %d", __func__, i); + return ret; } } return ret; @@ -322,7 +365,15 @@ bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation, if (!fOut3D) { format3D |= fIn3D >> SHIFT_3D; //Set the output format } - + if (format3D) { + bool isTV3D = false; + if (hdmiConnected) + isTV3D = overlay::is3DTV(); + if (!isTV3D) { + LOGD("Set the output format as monoscopic"); + format3D = FORMAT_3D_INPUT(format3D) | HAL_3D_OUT_MONOSCOPIC_MASK; + } + } int stateChanged = 0; int hw_format = get_mdp_format(colorFormat); int s3dChanged =0, hdmiChanged = 0; @@ -340,9 +391,9 @@ bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation, mS3DFormat = format3D; if (mHDMIConnected) { - if (format3D) { + if (mS3DFormat) { // Start both the VG pipes - return startChannelS3D(w, h, colorFormat, !orientation, format3D); + return startChannelS3D(w, h, colorFormat, !orientation); } else { return startChannelHDMI(w, h, colorFormat, !orientation); } @@ -359,22 +410,31 @@ bool Overlay::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) { if (!mChannelUP) return false; bool ret; + overlay_rect rect, inRect; + inRect.x = x; inRect.y = y; inRect.w = w; inRect.h = h; if (mHDMIConnected) { if (mS3DFormat) { - overlay_rect rect; - overlay_rect inRect; - inRect.x = x; inRect.y = y; inRect.width = w; inRect.height = h; - // Set the crop for both VG pipes for (int i = 0; i < NUM_CHANNELS; i++) { objOvDataChannel[i].getCropS3D(&inRect, i, mS3DFormat, &rect); - ret = setChannelCrop(rect.x, rect.y, rect.width, rect.height, i); + ret = setChannelCrop(rect.x, rect.y, rect.w, rect.h, i); + if (!ret) { + LOGE("%s: Failure for channel %d", __func__, i); + return ret; + } } return ret; } else { - setChannelCrop(x, y, w, h, VG1_PIPE); + ret = setChannelCrop(x, y, w, h, VG1_PIPE); + if (!ret) { + LOGE("%s: Failure for channel 1", __func__); + return ret; + } } + } else if (mS3DFormat & HAL_3D_OUT_MONOSCOPIC_MASK) { + objOvDataChannel[VG0_PIPE].getCropS3D(&inRect, VG0_PIPE, mS3DFormat, &rect); + return setChannelCrop(rect.x, rect.y, rect.w, rect.h, VG0_PIPE); } return setChannelCrop(x, y, w, h, VG0_PIPE); } @@ -423,15 +483,8 @@ bool Overlay::queueBuffer(buffer_handle_t buffer) { bool ret = true; if (mHDMIConnected) { - if (mS3DFormat) { - // Queue the buffer on VG1 pipe - if ((mS3DFormat & HAL_3D_OUT_SIDE_BY_SIDE_HALF_MASK) || - (mS3DFormat & HAL_3D_OUT_TOP_BOTTOM_MASK)) { - ret = queueBuffer(fd, offset, VG1_PIPE); - } - } else { - ret = queueBuffer(fd, offset, VG1_PIPE); - } + // Queue the buffer on VG1 pipe + ret = queueBuffer(fd, offset, VG1_PIPE); } if (ret && setFd(fd)) { return queueBuffer(offset); @@ -467,8 +520,8 @@ OverlayControlChannel::~OverlayControlChannel() { bool OverlayControlChannel::getAspectRatioPosition(int w, int h, int format, overlay_rect *rect) { int width = w, height = h, x, y; - int fbWidthHDMI = getFBWidth(); - int fbHeightHDMI = getFBHeight(); + int fbWidth = getFBWidth(); + int fbHeight = getFBHeight(); // width and height for YUV TILE format int tempWidth = w, tempHeight = h; /* Calculate the width and height if it is YUV TILE format*/ @@ -476,17 +529,17 @@ bool OverlayControlChannel::getAspectRatioPosition(int w, int h, int format, ove tempWidth = w - ( (((w-1)/64 +1)*64) - w); tempHeight = h - ((((h-1)/32 +1)*32) - h); } - if (width * fbHeightHDMI > fbWidthHDMI * height) { - height = fbWidthHDMI * height / width; + if (width * fbHeight > fbWidth * height) { + height = fbWidth * height / width; EVEN_OUT(height); - width = fbWidthHDMI; - } else if (width * fbHeightHDMI < fbWidthHDMI * height) { - width = fbHeightHDMI * width / height; + width = fbWidth; + } else if (width * fbHeight < fbWidth * height) { + width = fbHeight * width / height; EVEN_OUT(width); - height = fbHeightHDMI; + height = fbHeight; } else { - width = fbWidthHDMI; - height = fbHeightHDMI; + width = fbWidth; + height = fbHeight; } /* Scaling of upto a max of 8 times supported */ if(width >(tempWidth * HW_OVERLAY_MAGNIFICATION_LIMIT)){ @@ -495,54 +548,66 @@ bool OverlayControlChannel::getAspectRatioPosition(int w, int h, int format, ove if(height >(tempHeight*HW_OVERLAY_MAGNIFICATION_LIMIT)) { height = HW_OVERLAY_MAGNIFICATION_LIMIT * tempHeight; } - if (width > fbWidthHDMI) width = fbWidthHDMI; - if (height > fbHeightHDMI) height = fbHeightHDMI; - x = (fbWidthHDMI - width) / 2; - y = (fbHeightHDMI - height) / 2; + if (width > fbWidth) width = fbWidth; + if (height > fbHeight) height = fbHeight; + x = (fbWidth - width) / 2; + y = (fbHeight - height) / 2; rect->x = x; rect->y = y; - rect->width = width; - rect->height = height; + rect->w = width; + rect->h = height; return true; } bool OverlayControlChannel::getPositionS3D(int channel, int format, overlay_rect *rect) { - int wHDMI = getFBWidth(); - int hHDMI = getFBHeight(); - - if (format & HAL_3D_OUT_SIDE_BY_SIDE_HALF_MASK) { + int wDisp = getFBWidth(); + int hDisp = getFBHeight(); + switch (format & OUTPUT_MASK_3D) { + case HAL_3D_OUT_SIDE_BY_SIDE_MASK: if (channel == VG0_PIPE) { rect->x = 0; rect->y = 0; - rect->width = wHDMI/2; - rect->height = hHDMI; + rect->w = wDisp/2; + rect->h = hDisp; } else { - rect->x = wHDMI/2; + rect->x = wDisp/2; rect->y = 0; - rect->width = wHDMI/2; - rect->height = hHDMI; + rect->w = wDisp/2; + rect->h = hDisp; } - } else if (format & HAL_3D_OUT_TOP_BOTTOM_MASK) { + break; + case HAL_3D_OUT_TOP_BOTTOM_MASK: if (channel == VG0_PIPE) { rect->x = 0; rect->y = 0; - rect->width = wHDMI; - rect->height = hHDMI/2; + rect->w = wDisp; + rect->h = hDisp/2; } else { rect->x = 0; - rect->y = hHDMI/2; - rect->width = wHDMI; - rect->height = hHDMI/2; + rect->y = hDisp/2; + rect->w = wDisp; + rect->h = hDisp/2; } - } else if (format & HAL_3D_OUT_INTERLEAVE_MASK) { - //TBD - } else if (format & HAL_3D_OUT_SIDE_BY_SIDE_FULL_MASK) { - //TBD - } else { - reportError("Unsupported 3D output format"); + break; + case HAL_3D_OUT_MONOSCOPIC_MASK: + if (channel == VG1_PIPE) { + rect->x = 0; + rect->y = 0; + rect->w = wDisp; + rect->h = hDisp; + } + else + return false; + break; + case HAL_3D_OUT_INTERLEAVE_MASK: + break; + default: + reportError("Unsupported 3D output format"); + break; } return true; } + bool OverlayControlChannel::openDevices(int fbnum) { if (fbnum < 0) return false; @@ -675,11 +740,11 @@ bool OverlayControlChannel::startOVRotatorSessions(int w, int h, if(mUIChannel) mRotInfo.enable = 1; mRotInfo.session_id = 0; - int result = ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo); - if (result) { + int result = ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo); + if (result) { reportError("Rotator session failed"); - ret = false; - } + ret = false; + } } if (!mNoRot && isRGBType(format) && mOrientation && mOVInfo.is_fg) { @@ -807,12 +872,12 @@ bool OverlayControlChannel::startControlChannel(int w, int h, } hw_format = get_mdp_format(colorFormat); if (hw_format < 0) { - reportError("Unsupported format"); + reportError("Unsupported format"); return false; } mFormat3D = format3D; - if (!mFormat3D) { + if ( !mFormat3D || (mFormat3D && HAL_3D_OUT_MONOSCOPIC_MASK) ) { // Set the share bit for sharing the VG pipe flags |= MDP_OV_PIPE_SHARE; } @@ -920,7 +985,7 @@ bool OverlayControlChannel::setPosition(int x, int y, uint32_t w, uint32_t h) { if (ioctl(mFD, MSMFB_OVERLAY_SET, &ov)) { reportError("setPosition, Overlay SET failed"); - return false; + return false; } mOVInfo = ov; @@ -958,7 +1023,7 @@ bool OverlayControlChannel::setParameter(int param, int value, bool fetch) { case OVERLAY_TRANSFORM: { int val = mOVInfo.user_data[0]; - if (value && mNoRot) + if (mNoRot) return true; int rot = value; @@ -1152,7 +1217,7 @@ bool OverlayDataChannel::startDataChannel( memset(&mRotData, 0, sizeof(mRotData)); if (objOvCtrlChannel.getOvSessionID(ovid) && objOvCtrlChannel.getRotSessionID(rotid) && - objOvCtrlChannel.getSize(size)) { + objOvCtrlChannel.getSize(size)) { return startDataChannel(ovid, rotid, size, fbnum, norot, uichannel, num_buffers); } @@ -1277,7 +1342,7 @@ bool OverlayDataChannel::setFd(int fd) { bool OverlayDataChannel::queueBuffer(uint32_t offset) { if ((!isChannelUP()) || mOvData.data.memory_id < 0) { reportError("QueueBuffer failed, either channel is not set or no file descriptor to read from"); - return false; + return false; } msmfb_overlay_data *odPtr; @@ -1296,7 +1361,7 @@ bool OverlayDataChannel::queueBuffer(uint32_t offset) { if (!result) { mOvDataRot.data.offset = (uint32_t) mRotData.dst.offset; - odPtr = &mOvDataRot; + odPtr = &mOvDataRot; } else if (max_num_buffers == mNumBuffers) { reportError("Rotator failed.."); @@ -1306,7 +1371,7 @@ bool OverlayDataChannel::queueBuffer(uint32_t offset) { if (ioctl(mFD, MSMFB_OVERLAY_PLAY, odPtr)) { reportError("overlay play failed."); - return false; + return false; } return true; @@ -1314,51 +1379,67 @@ bool OverlayDataChannel::queueBuffer(uint32_t offset) { bool OverlayDataChannel::getCropS3D(overlay_rect *inRect, int channel, int format, overlay_rect *rect) { - - bool ret; - // for the 3D usecase extract L and R channels from a frame - if ( (format & HAL_3D_IN_SIDE_BY_SIDE_HALF_L_R) || - (format & HAL_3D_IN_SIDE_BY_SIDE_HALF_R_L) ) { + // for the 3D usecase extract channels from a frame + switch (format & INPUT_MASK_3D) { + case HAL_3D_IN_SIDE_BY_SIDE_L_R: if(channel == 0) { rect->x = 0; rect->y = 0; - rect->width = inRect->width/2; - rect->height = inRect->height; + rect->w = inRect->w/2; + rect->h = inRect->h; } else { - rect->x = inRect->width/2; + rect->x = inRect->w/2; rect->y = 0; - rect->width = inRect->width/2; - rect->height = inRect->height; + rect->w = inRect->w/2; + rect->h = inRect->h; } - } else if (format & HAL_3D_IN_TOP_BOTTOM) { + break; + case HAL_3D_IN_SIDE_BY_SIDE_R_L: + if(channel == 1) { + rect->x = 0; + rect->y = 0; + rect->w = inRect->w/2; + rect->h = inRect->h; + } else { + rect->x = inRect->w/2; + rect->y = 0; + rect->w = inRect->w/2; + rect->h = inRect->h; + } + break; + case HAL_3D_IN_TOP_BOTTOM: if(channel == 0) { rect->x = 0; rect->y = 0; - rect->width = inRect->width; - rect->height = inRect->height/2; + rect->w = inRect->w; + rect->h = inRect->h/2; } else { rect->x = 0; - rect->y = inRect->height/2; - rect->width = inRect->width; - rect->height = inRect->height/2; + rect->y = inRect->h/2; + rect->w = inRect->w; + rect->h = inRect->h/2; } - } else if (format & HAL_3D_IN_INTERLEAVE) { - //TBD + break; + case HAL_3D_IN_INTERLEAVE: + break; + default: + reportError("Unsupported 3D format..."); + break; } return true; } bool OverlayDataChannel::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) { if (!isChannelUP()) { - reportError("Channel not set"); - return false; + reportError("Channel not set"); + return false; } mdp_overlay ov; ov.id = mOvData.id; if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) { reportError("setCrop, overlay GET failed"); - return false; + return false; } if ((ov.user_data[0] == MDP_ROT_90) || diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h index 55af19f..c7ac671 100644 --- a/liboverlay/overlayLib.h +++ b/liboverlay/overlayLib.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2008 The Android Open Source Project - * Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -69,29 +69,41 @@ enum { #define COLOR_FORMAT(x) (x & 0xFFF) // in the final 3D format, the MSB 2Bytes are the input format and the // LSB 2bytes are the output format. Shift the output byte 12 bits. -#define FORMAT_3D_OUTPUT(x) ((x & 0xF000) >> 12) -#define FORMAT_3D_INPUT(x) (x & 0xF0000) -#define INPUT_MASK_3D 0xFFFF0000 -#define OUTPUT_MASK_3D 0x0000FFFF -#define SHIFT_3D 16 +#define SHIFT_OUTPUT_3D 12 +#define FORMAT_3D_OUTPUT(x) ((x & 0xF000) >> SHIFT_OUTPUT_3D) +#define FORMAT_3D_INPUT(x) (x & 0xF0000) +#define INPUT_MASK_3D 0xFFFF0000 +#define OUTPUT_MASK_3D 0x0000FFFF +#define SHIFT_3D 16 // The output format is the 2MSB bytes. Shift the format by 12 to reflect this -#define HAL_3D_OUT_SIDE_BY_SIDE_HALF_MASK ((HAL_3D_IN_SIDE_BY_SIDE_HALF_L_R|HAL_3D_IN_SIDE_BY_SIDE_HALF_R_L) >> SHIFT_3D) -#define HAL_3D_OUT_SIDE_BY_SIDE_FULL_MASK (HAL_3D_IN_SIDE_BY_SIDE_FULL >> SHIFT_3D) -#define HAL_3D_OUT_TOP_BOTTOM_MASK (HAL_3D_OUT_TOP_BOTTOM >> 12) -#define HAL_3D_OUT_INTERLEAVE_MASK (HAL_3D_OUT_INTERLEAVE >> 12) +#define HAL_3D_OUT_SIDE_BY_SIDE_MASK (HAL_3D_OUT_SIDE_BY_SIDE >> SHIFT_OUTPUT_3D) +#define HAL_3D_OUT_TOP_BOTTOM_MASK (HAL_3D_OUT_TOP_BOTTOM >> SHIFT_OUTPUT_3D) +#define HAL_3D_OUT_INTERLEAVE_MASK (HAL_3D_OUT_INTERLEAVE >> SHIFT_OUTPUT_3D) +#define HAL_3D_OUT_MONOSCOPIC_MASK (HAL_3D_OUT_MONOSCOPIC >> SHIFT_OUTPUT_3D) + #define FORMAT_3D_FILE "/sys/class/graphics/fb1/format_3d" +#define EDID_3D_INFO_FILE "/sys/class/graphics/fb1/3d_present" /* -------------------------- end 3D defines ----------------------------------------*/ namespace overlay { -const int max_num_buffers = 3; -struct overlay_rect { - int x; - int y; - int width; - int height; +enum { + OV_2D_VIDEO_ON_PANEL = 0, + OV_2D_VIDEO_ON_TV, + OV_3D_VIDEO_2D_PANEL, + OV_3D_VIDEO_2D_TV, + OV_3D_VIDEO_3D_PANEL, + OV_3D_VIDEO_3D_TV }; +bool isHDMIConnected(); +bool is3DTV(); +bool send3DInfoPacket(unsigned int format3D); +unsigned int getOverlayConfig (unsigned int format3D); + +const int max_num_buffers = 3; +typedef struct mdp_rect overlay_rect; + class OverlayControlChannel { bool mNoRot; @@ -184,8 +196,8 @@ class Overlay { bool mChannelUP; bool mHDMIConnected; - int mS3DFormat; bool mCloseChannel; + unsigned int mS3DFormat; OverlayControlChannel objOvCtrlChannel[2]; OverlayDataChannel objOvDataChannel[2]; @@ -221,7 +233,7 @@ public: private: bool startChannelHDMI(int w, int h, int format, bool norot); - bool startChannelS3D(int w, int h, int format, bool norot, int s3DFormat); + bool startChannelS3D(int w, int h, int format, bool norot); bool setPositionS3D(int x, int y, uint32_t w, uint32_t h); bool setParameterS3D(int param, int value); bool setChannelPosition(int x, int y, uint32_t w, uint32_t h, int channel = 0); @@ -232,6 +244,9 @@ private: struct overlay_shared_data { int readyToQueue; + unsigned int state; + int rotid[2]; + int ovid[2]; }; }; #endif