From 48f7bb38a79175987fe5cc2f7d576469708b4364 Mon Sep 17 00:00:00 2001 From: Kinjal Bhavsar Date: Fri, 11 Feb 2011 18:05:39 -0800 Subject: [PATCH] liboverlay: Add support for 3D panel Detect and use 3D panel for 3D content. Use the virtual framebuffer for 3D panel. Set position for overlay channels accordingly. Use 3D ioctl for line interleaving. Add state machine for Overlay. Change-Id: I28dc7ed99aed7ca2c53c93722c44279d9c7de9fc Conflicts: liboverlay/overlayLib.cpp --- liboverlay/overlay.cpp | 2061 +++++++++++++++++------------------ liboverlay/overlayLib.cpp | 481 +++++--- liboverlay/overlayLib.h | 23 +- liboverlay/overlayState.cpp | 1109 +++++++++++++++++++ 4 files changed, 2467 insertions(+), 1207 deletions(-) create mode 100644 liboverlay/overlayState.cpp diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp index 9f9075f..aa2828b 100644 --- a/liboverlay/overlay.cpp +++ b/liboverlay/overlay.cpp @@ -31,88 +31,177 @@ using android::Mutex; #define EVEN_OUT(x) if (x & 0x0001) {x--;} #define SHARED_MEMORY_REGION_NAME "overlay_shared_memory" + +#define OVERLAY_HDMI_ENABLE 8 + /*****************************************************************************/ + using namespace overlay; 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 - unsigned int state; - unsigned int orientation; - overlay_rect posPanel; + struct overlay_control_device_t device; + void *sharedMemBase; + unsigned int format3D; //input and output 3D format, zero means no 3D + unsigned int state; + unsigned int orientation; + overlay_rect posPanel; }; struct overlay_data_context_t { - struct overlay_data_device_t device; - OverlayDataChannel* pobjDataChannel[2]; - unsigned int format3D; - 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; + struct overlay_data_device_t device; + OverlayDataChannel* pobjDataChannel[2]; + unsigned int format3D; + 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; }; +/////////////////////////////////////////////////////////////////////////////////// + +/* Overlay State func FIXME move to a separate module */ +class overlay_object; +int setParameterHandleState(overlay_control_context_t *ctx, + overlay_object *obj, + int param, int value); +int createOverlayHandleState(overlay_control_context_t *ctx, bool noRot, + overlay_object* overlay, int fd); +int setPositionHandleState(overlay_control_context_t *ctx, + overlay_object *obj, overlay_rect& rect, + int x, int y, uint32_t w, uint32_t h); +int configPipes_OV_2D_VIDEO_ON_PANEL(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect); + +int configPipes_OV_3D_VIDEO_2D_PANEL(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect); + +int configPipes_OV_3D_VIDEO_3D_PANEL(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect); + +int configPipes_OV_2D_VIDEO_ON_TV(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect); + +int configPipes_OV_3D_VIDEO_2D_TV(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect); + +int configPipes_OV_3D_VIDEO_3D_TV(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect); + +/* queue buffer */ +int queueBuffer_OV_2D_VIDEO_ON_PANEL(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot); + +int queueBuffer_OV_3D_VIDEO_2D_PANEL(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot); + + +int queueBuffer_OV_3D_VIDEO_3D_PANEL(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot); + +int queueBuffer_OV_2D_VIDEO_ON_TV(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot); + +int queueBuffer_OV_3D_VIDEO_2D_TV(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot); + +int queueBuffer_OV_3D_VIDEO_3D_TV(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot); + +/////////////////////////////////////////////////////////////////////////////////// + + static int overlay_device_open(const struct hw_module_t* module, const char* name, - struct hw_device_t** device); + struct hw_device_t** device); static struct hw_module_methods_t overlay_module_methods = { - open: overlay_device_open +open: overlay_device_open }; struct private_overlay_module_t { - overlay_module_t base; - Mutex *pobjMutex; + overlay_module_t base; + Mutex *pobjMutex; }; struct private_overlay_module_t HAL_MODULE_INFO_SYM = { - base: { - common: { - tag: HARDWARE_MODULE_TAG, - version_major: 1, - version_minor: 0, - id: OVERLAY_HARDWARE_MODULE_ID, - name: "QCT MSM OVERLAY module", - author: "QuIC, Inc.", - methods: &overlay_module_methods, - } - }, - pobjMutex: NULL, +base: { +common: { +tag: HARDWARE_MODULE_TAG, + version_major: 1, + version_minor: 0, + id: OVERLAY_HARDWARE_MODULE_ID, + name: "QCT MSM OVERLAY module", + author: "QuIC, Inc.", + methods: &overlay_module_methods, + } + }, +pobjMutex: NULL, }; struct handle_t : public native_handle { - int sharedMemoryFd; - int ovid[2]; - int rotid[2]; - int size; - int w; - int h; - int format; - unsigned int format3D; - OverlayControlChannel *pobjControlChannel[2]; + int sharedMemoryFd; + int ovid[2]; + int rotid[2]; + int size; + int w; + int h; + int format; + unsigned int format3D; + OverlayControlChannel *pobjControlChannel[2]; }; static int handle_get_ovId(const overlay_handle_t overlay, int index = 0) { - return static_cast(overlay)->ovid[index]; + return static_cast(overlay)->ovid[index]; } static int handle_get_rotId(const overlay_handle_t overlay, int index = 0) { - return static_cast(overlay)->rotid[index]; + return static_cast(overlay)->rotid[index]; } static int handle_get_size(const overlay_handle_t overlay) { - return static_cast(overlay)->size; + return static_cast(overlay)->size; +} + +static int handle_get_width(const overlay_handle_t overlay) { + return static_cast(overlay)->w; +} + +static int handle_get_height(const overlay_handle_t overlay) { + return static_cast(overlay)->h; } static int handle_get_shared_fd(const overlay_handle_t overlay) { - return static_cast(overlay)->sharedMemoryFd; + return static_cast(overlay)->sharedMemoryFd; } static int handle_get_format3D(const overlay_handle_t overlay) { - return static_cast(overlay)->format3D; + return static_cast(overlay)->format3D; } /* @@ -122,1083 +211,987 @@ static int handle_get_format3D(const overlay_handle_t overlay) { * HAL modules (for instance video decode modules). */ class overlay_object : public overlay_t { - handle_t mHandle; + handle_t mHandle; - static overlay_handle_t getHandleRef(struct overlay_t* overlay) { - /* returns a reference to the handle, caller doesn't take ownership */ - return &(static_cast(overlay)->mHandle); - } + static overlay_handle_t getHandleRef(struct overlay_t* overlay) { + /* returns a reference to the handle, caller doesn't take ownership */ + return &(static_cast(overlay)->mHandle); + } -public: - overlay_object(int w, int h, int format, int fd, unsigned int format3D = 0) { - this->overlay_t::getHandleRef = getHandleRef; - mHandle.version = sizeof(native_handle); - mHandle.sharedMemoryFd = fd; - mHandle.numFds = 1; - mHandle.numInts = (sizeof(mHandle) - sizeof(native_handle)) / 4; - mHandle.ovid[0] = -1; - mHandle.ovid[1] = -1; - mHandle.rotid[0] = -1; - mHandle.rotid[1] = -1; - mHandle.size = -1; - mHandle.w = w; - mHandle.h = h; - mHandle.format = format; - mHandle.format3D = format3D; - mHandle.pobjControlChannel[0] = 0; - mHandle.pobjControlChannel[1] = 0; - } + public: + overlay_object(int w, int h, int format, int fd, unsigned int format3D = 0) { + this->overlay_t::getHandleRef = getHandleRef; + this->overlay_t::w = w; + this->overlay_t::h = h; + mHandle.version = sizeof(native_handle); + mHandle.sharedMemoryFd = fd; + mHandle.numFds = 1; + mHandle.numInts = (sizeof(mHandle) - sizeof(native_handle)) / 4; + mHandle.ovid[0] = -1; + mHandle.ovid[1] = -1; + mHandle.rotid[0] = -1; + mHandle.rotid[1] = -1; + mHandle.size = -1; + mHandle.w = w; + mHandle.h = h; + mHandle.format = format; + mHandle.format3D = format3D; + mHandle.pobjControlChannel[0] = 0; + mHandle.pobjControlChannel[1] = 0; + } - ~overlay_object() { - destroy_overlay(); - } + ~overlay_object() { + destroy_overlay(); + } - int getHwOvId(int index = 0) { return mHandle.ovid[index]; } - int getRotSessionId(int index = 0) { return mHandle.rotid[index]; } - int getSharedMemoryFD() {return mHandle.sharedMemoryFd;} + int getHwOvId(int index = 0) { return mHandle.ovid[index]; } + int getRotSessionId(int index = 0) { return mHandle.rotid[index]; } + int getSharedMemoryFD() {return mHandle.sharedMemoryFd;} - bool startControlChannel(int fbnum, bool norot = false, int zorder = 0) { - int index = fbnum; - if (mHandle.format3D) - index = zorder; - if (!mHandle.pobjControlChannel[index]) - mHandle.pobjControlChannel[index] = new OverlayControlChannel(); - else { - mHandle.pobjControlChannel[index]->closeControlChannel(); - mHandle.pobjControlChannel[index] = new OverlayControlChannel(); - } - bool ret = mHandle.pobjControlChannel[index]->startControlChannel( - mHandle.w, mHandle.h, mHandle.format, fbnum, norot, false, - mHandle.format3D, zorder, true); - if (ret) { - if (!(mHandle.pobjControlChannel[index]-> - getOvSessionID(mHandle.ovid[index]) && - mHandle.pobjControlChannel[index]-> - getRotSessionID(mHandle.rotid[index]) && - mHandle.pobjControlChannel[index]-> - getSize(mHandle.size))) - ret = false; - } + bool startControlChannel(int fbnum, bool norot = false, int zorder = 0) { + int index = fbnum; + if (mHandle.format3D) + index = zorder; + if (!mHandle.pobjControlChannel[index]) + mHandle.pobjControlChannel[index] = new OverlayControlChannel(); + else { + mHandle.pobjControlChannel[index]->closeControlChannel(); + mHandle.pobjControlChannel[index] = new OverlayControlChannel(); + } + bool ret = mHandle.pobjControlChannel[index]->startControlChannel( + mHandle.w, mHandle.h, mHandle.format, fbnum, norot, false, + mHandle.format3D, zorder, true); + if (ret) { + if (!(mHandle.pobjControlChannel[index]-> + getOvSessionID(mHandle.ovid[index]) && + mHandle.pobjControlChannel[index]-> + getRotSessionID(mHandle.rotid[index]) && + mHandle.pobjControlChannel[index]-> + getSize(mHandle.size))) + ret = false; + } - if (!ret) { - closeControlChannel(index); - } + if (!ret) { + closeControlChannel(index); + } - return ret; - } + return ret; + } - bool setPosition(int x, int y, uint32_t w, uint32_t h, int channel) { - if (!mHandle.pobjControlChannel[channel]) - return false; - return mHandle.pobjControlChannel[channel]->setPosition( - x, y, w, h); - } + bool setPosition(int x, int y, uint32_t w, uint32_t h, int channel) { + if (!mHandle.pobjControlChannel[channel]) + return false; + return mHandle.pobjControlChannel[channel]->setPosition( + x, y, w, h); + } - bool getAspectRatioPosition(overlay_rect *rect, int channel) { - if (!mHandle.pobjControlChannel[channel]) - return false; - return mHandle.pobjControlChannel[channel]->getAspectRatioPosition(mHandle.w, - mHandle.h, rect); - } + bool getAspectRatioPosition(overlay_rect *rect, int channel) { + if (!mHandle.pobjControlChannel[channel]) + return false; + return mHandle.pobjControlChannel[channel]->getAspectRatioPosition(mHandle.w, + mHandle.h, rect); + } - bool setParameter(int param, int value, int channel) { - if (!mHandle.pobjControlChannel[channel]) - return false; - return mHandle.pobjControlChannel[channel]->setParameter( - param, value); - } + bool setParameter(int param, int value, int channel) { + if (!mHandle.pobjControlChannel[channel]) + return false; + return mHandle.pobjControlChannel[channel]->setParameter( + param, value); + } - bool closeControlChannel(int channel) { - if (!mHandle.pobjControlChannel[channel]) - return true; - bool ret = mHandle.pobjControlChannel[channel]-> - closeControlChannel(); - delete mHandle.pobjControlChannel[channel]; - mHandle.pobjControlChannel[channel] = 0; - return ret; - } + bool closeControlChannel(int channel) { + if (!mHandle.pobjControlChannel[channel]) + return true; + bool ret = mHandle.pobjControlChannel[channel]-> + closeControlChannel(); + delete mHandle.pobjControlChannel[channel]; + mHandle.pobjControlChannel[channel] = 0; + return ret; + } - bool getPositionS3D(overlay_rect *rect, int channel) { - if (!mHandle.pobjControlChannel[channel]) { - LOGE("%s:Failed got channel %d", __func__, channel); - return false; - } + bool getPositionS3D(overlay_rect *rect, int channel, bool useVFB = false) { + if (!mHandle.pobjControlChannel[channel]) { + LOGE("%s:Failed got channel %d", __func__, channel); + return false; + } + int format = useVFB ? HAL_3D_OUT_SIDE_BY_SIDE_MASK : mHandle.format3D; + return mHandle.pobjControlChannel[channel]->getPositionS3D( + channel, format, rect); + } - 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; + return mHandle.pobjControlChannel[channel]->getPosition( + *x, *y, *w, *h); + } - bool getPosition(int *x, int *y, uint32_t *w, uint32_t *h, int channel) { - if (!mHandle.pobjControlChannel[channel]) - return false; - return mHandle.pobjControlChannel[channel]->getPosition( - *x, *y, *w, *h); - } + bool getOrientation(int *orientation, int channel) { + if (!mHandle.pobjControlChannel[channel]) + return false; + return mHandle.pobjControlChannel[channel]->getOrientation( + *orientation); + } - bool getOrientation(int *orientation, int channel) { - if (!mHandle.pobjControlChannel[channel]) - return false; - return mHandle.pobjControlChannel[channel]->getOrientation( - *orientation); - } + void destroy_overlay() { + close(mHandle.sharedMemoryFd); + closeControlChannel(VG1_PIPE); + closeControlChannel(VG0_PIPE); + if(mHandle.format3D) { + send3DInfoPacket (0); + enableBarrier(0); + } + } - void destroy_overlay() { - close(mHandle.sharedMemoryFd); - closeControlChannel(0); - closeControlChannel(1); - send3DInfoPacket (0); - } + int getFBWidth(int channel) { + if (!mHandle.pobjControlChannel[channel]) + return false; + return mHandle.pobjControlChannel[channel]->getFBWidth(); + } - int getFBWidth(int channel) { - if (!mHandle.pobjControlChannel[channel]) - return false; - return mHandle.pobjControlChannel[channel]->getFBWidth(); - } + int getFBHeight(int channel) { + if (!mHandle.pobjControlChannel[channel]) + return false; + return mHandle.pobjControlChannel[channel]->getFBHeight(); + } - int getFBHeight(int channel) { - if (!mHandle.pobjControlChannel[channel]) - return false; - return mHandle.pobjControlChannel[channel]->getFBHeight(); - } + inline void setFormat3D(unsigned int format3D) { + mHandle.format3D = format3D; + } - inline void setFormat3D(unsigned int format3D) { - mHandle.format3D = format3D; - } + inline bool useVirtualFB(int channel) { + if (!mHandle.pobjControlChannel[channel]) + return false; + return mHandle.pobjControlChannel[channel]->useVirtualFB(); + } }; // **************************************************************************** // Control module // **************************************************************************** - static int overlay_get(struct overlay_control_device_t *dev, int name) { - int result = -1; - switch (name) { - case OVERLAY_MINIFICATION_LIMIT: - result = HW_OVERLAY_MINIFICATION_LIMIT; - break; - case OVERLAY_MAGNIFICATION_LIMIT: - result = HW_OVERLAY_MAGNIFICATION_LIMIT; - break; - case OVERLAY_SCALING_FRAC_BITS: - result = 32; - break; - case OVERLAY_ROTATION_STEP_DEG: - result = 90; // 90 rotation steps (for instance) - break; - case OVERLAY_HORIZONTAL_ALIGNMENT: - result = 1; // 1-pixel alignment - break; - case OVERLAY_VERTICAL_ALIGNMENT: - result = 1; // 1-pixel alignment - break; - case OVERLAY_WIDTH_ALIGNMENT: - result = 1; // 1-pixel alignment - break; - case OVERLAY_HEIGHT_ALIGNMENT: - result = 1; // 1-pixel alignment - break; - } - return result; - } +static int overlay_get(struct overlay_control_device_t *dev, int name) { + int result = -1; + switch (name) { + case OVERLAY_MINIFICATION_LIMIT: + result = HW_OVERLAY_MINIFICATION_LIMIT; + break; + case OVERLAY_MAGNIFICATION_LIMIT: + result = HW_OVERLAY_MAGNIFICATION_LIMIT; + break; + case OVERLAY_SCALING_FRAC_BITS: + result = 32; + break; + case OVERLAY_ROTATION_STEP_DEG: + result = 90; // 90 rotation steps (for instance) + break; + case OVERLAY_HORIZONTAL_ALIGNMENT: + result = 1; // 1-pixel alignment + break; + case OVERLAY_VERTICAL_ALIGNMENT: + result = 1; // 1-pixel alignment + break; + case OVERLAY_WIDTH_ALIGNMENT: + result = 1; // 1-pixel alignment + break; + case OVERLAY_HEIGHT_ALIGNMENT: + result = 1; // 1-pixel alignment + break; + } + 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 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; - overlay_control_context_t *ctx = (overlay_control_context_t *)dev; - private_overlay_module_t* m = reinterpret_cast( - dev->common.module); - Mutex::Autolock objLock(m->pobjMutex); +static overlay_t* overlay_createOverlay(struct overlay_control_device_t *dev, + uint32_t w, uint32_t h, int32_t format) { + overlay_object *overlay = NULL; + overlay_control_context_t *ctx = (overlay_control_context_t *)dev; + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + Mutex::Autolock objLock(m->pobjMutex); - // Open shared memory to store shared data - int size = sizeof(overlay_shared_data); - void *base; - int fd = ashmem_create_region(SHARED_MEMORY_REGION_NAME, - size); - if(fd < 0) { - LOGE("%s: create shared memory failed", __func__); - return NULL; - } - if (ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE) < 0) { - LOGE("ashmem_set_prot_region(fd=%d, failed (%s)", - fd, strerror(-errno)); - close(fd); - fd = -1; - return NULL; - } else { - base = mmap(0, size, PROT_READ | PROT_WRITE, - MAP_SHARED|MAP_POPULATE, fd, 0); - if (base == MAP_FAILED) { - LOGE("alloc mmap(fd=%d, size=%d) failed (%s)", - fd, size, strerror(-errno)); - close(fd); - fd = -1; - return NULL; - } - } + // Open shared memory to store shared data + int size = sizeof(overlay_shared_data); + void *base; + int fd = ashmem_create_region(SHARED_MEMORY_REGION_NAME, + size); + if(fd < 0) { + LOGE("%s: create shared memory failed", __func__); + return NULL; + } + if (ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE) < 0) { + LOGE("ashmem_set_prot_region(fd=%d, failed (%s)", + fd, strerror(-errno)); + close(fd); + fd = -1; + return NULL; + } else { + base = mmap(0, size, PROT_READ | PROT_WRITE, + MAP_SHARED|MAP_POPULATE, fd, 0); + if (base == MAP_FAILED) { + LOGE("alloc mmap(fd=%d, size=%d) failed (%s)", + fd, size, strerror(-errno)); + close(fd); + fd = -1; + return NULL; + } + } - // Separate the color format from the 3D format. - // If there is 3D content; the effective format passed by the client is: - // effectiveFormat = 3D_IN | 3D_OUT | ColorFormat - unsigned int format3D = FORMAT_3D(format); - format = COLOR_FORMAT(format); - int fIn3D = FORMAT_3D_INPUT(format3D); // MSB 2 bytes are input format - int fOut3D = FORMAT_3D_OUTPUT(format3D); // LSB 2 bytes are output format - format3D = fIn3D | fOut3D; - // Use the same in/out format if not mentioned - if (!fIn3D) { - format3D |= fOut3D << SHIFT_3D; //Set the input format - } - if(!fOut3D) { - switch (fIn3D) { - 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_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); + // Separate the color format from the 3D format. + // If there is 3D content; the effective format passed by the client is: + // effectiveFormat = 3D_IN | 3D_OUT | ColorFormat + unsigned int format3D = FORMAT_3D(format); + format = COLOR_FORMAT(format); + int fIn3D = FORMAT_3D_INPUT(format3D); // MSB 2 bytes are input format + int fOut3D = FORMAT_3D_OUTPUT(format3D); // LSB 2 bytes are output format + format3D = fIn3D | fOut3D; + // Use the same in/out format if not mentioned + if (!fIn3D) { + format3D |= fOut3D << SHIFT_3D; //Set the input format + } + if(!fOut3D) { + switch (fIn3D) { + 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_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; + } + LOGW("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)) { - munmap(ctx->sharedMemBase, size); - ctx->sharedMemBase = MAP_FAILED; - } - if(fd > 0) - close(fd); - return NULL; - } - bool noRot; + /* 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)) { + munmap(ctx->sharedMemBase, size); + ctx->sharedMemBase = MAP_FAILED; + } + if(fd > 0) + close(fd); + return NULL; + } + bool noRot; #ifdef USE_MSM_ROTATOR - noRot = false; + noRot = false; #else - noRot = true; + 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; - } - 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 (!overlay->startControlChannel(FRAMEBUFFER_1, true, VG1_PIPE)) { - error_cleanup_control(ctx, overlay, fd, VG1_PIPE); - return NULL; - } - 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; - } + if(-1 == createOverlayHandleState(ctx, noRot, overlay, fd)) + return 0;// NULL + 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, - overlay_t* overlay) - { - overlay_control_context_t *ctx = (overlay_control_context_t *)dev; - overlay_object * obj = static_cast(overlay); - private_overlay_module_t* m = reinterpret_cast( - dev->common.module); - Mutex::Autolock objLock(m->pobjMutex); - if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { - munmap(ctx->sharedMemBase, sizeof(overlay_shared_data)); - ctx->sharedMemBase = MAP_FAILED; - } - obj->destroy_overlay(); - delete overlay; - } +static void overlay_destroyOverlay(struct overlay_control_device_t *dev, + overlay_t* overlay) +{ + overlay_control_context_t *ctx = (overlay_control_context_t *)dev; + overlay_object * obj = static_cast(overlay); + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + Mutex::Autolock objLock(m->pobjMutex); + if(ctx && (ctx->sharedMemBase != MAP_FAILED)) { + munmap(ctx->sharedMemBase, sizeof(overlay_shared_data)); + ctx->sharedMemBase = MAP_FAILED; + } + // ~overlay_object calls destroy_overlay + delete obj; +} - static int overlay_setPosition(struct overlay_control_device_t *dev, - overlay_t* overlay, - int x, int y, uint32_t w, uint32_t h) { - /* set this overlay's position (talk to the h/w) */ - overlay_control_context_t *ctx = (overlay_control_context_t *)dev; - overlay_object * obj = static_cast(overlay); - private_overlay_module_t* m = reinterpret_cast( - dev->common.module); - Mutex::Autolock objLock(m->pobjMutex); - bool 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; +static int overlay_setPosition(struct overlay_control_device_t *dev, + overlay_t* overlay, + int x, int y, uint32_t w, uint32_t h) { + /* set this overlay's position (talk to the h/w) */ + overlay_control_context_t *ctx = (overlay_control_context_t *)dev; + overlay_object * obj = static_cast(overlay); + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + Mutex::Autolock objLock(m->pobjMutex); + bool 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; - } + if(-1 == setPositionHandleState(ctx, obj, rect, x, y, w, h)) + return -1; - static int overlay_commit(struct overlay_control_device_t *dev, - overlay_t* overlay) - { - overlay_control_context_t *ctx = (overlay_control_context_t *)dev; - overlay_object *obj = static_cast(overlay); - private_overlay_module_t* m = reinterpret_cast( - dev->common.module); + return 0; +} - Mutex::Autolock objLock(m->pobjMutex); - if (obj && (obj->getSharedMemoryFD() > 0) && - (ctx->sharedMemBase != MAP_FAILED)) { - overlay_shared_data data; - data.readyToQueue = 1; - memcpy(ctx->sharedMemBase, (void*)&data, sizeof(overlay_shared_data)); - } - return 0; - } +static int overlay_commit(struct overlay_control_device_t *dev, + overlay_t* overlay) +{ + overlay_control_context_t *ctx = (overlay_control_context_t *)dev; + overlay_object *obj = static_cast(overlay); + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); - static int overlay_getPosition(struct overlay_control_device_t *dev, - overlay_t* overlay, - int* x, int* y, uint32_t* w, uint32_t* h) { + Mutex::Autolock objLock(m->pobjMutex); + if (obj && (obj->getSharedMemoryFD() > 0) && + (ctx->sharedMemBase != MAP_FAILED)) { + overlay_shared_data* data = static_cast(ctx->sharedMemBase); + data->isControlSetup = true; + } + return 0; +} - /* get this overlay's position */ - private_overlay_module_t* m = reinterpret_cast( - dev->common.module); - Mutex::Autolock objLock(m->pobjMutex); - overlay_object * obj = static_cast(overlay); - 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; +static int overlay_getPosition(struct overlay_control_device_t *dev, + overlay_t* overlay, + int* x, int* y, uint32_t* w, uint32_t* h) { + + /* get this overlay's position */ + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + Mutex::Autolock objLock(m->pobjMutex); + overlay_object * obj = static_cast(overlay); + return obj->getPosition(x, y, w, h, 0) ? 0 : -1; +} + +static bool overlay_configPipes(overlay_control_context_t *ctx, + overlay_object *obj, int enable, + unsigned int newState) { + bool noRot = true; + overlay_rect rect; #ifdef USE_MSM_ROTATOR - noRot = false; + noRot = false; #else - noRot = true; + 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) { + switch (ctx->state) + { + case OV_2D_VIDEO_ON_PANEL: + if(-1 == configPipes_OV_2D_VIDEO_ON_PANEL(ctx, + obj, + newState, + enable, noRot, rect)) + return false; + break; + case OV_3D_VIDEO_2D_PANEL: + if(-1 == configPipes_OV_3D_VIDEO_2D_PANEL(ctx, + obj, + newState, + enable, noRot, rect)) + return false; + break; + case OV_3D_VIDEO_3D_PANEL: + if(-1 == configPipes_OV_3D_VIDEO_3D_PANEL(ctx, + obj, + newState, + enable, noRot, rect)) + return false; + break; + case OV_2D_VIDEO_ON_TV: + if(-1 == configPipes_OV_2D_VIDEO_ON_TV(ctx, + obj, + newState, + enable, noRot, rect)) + return false; + break; + case OV_3D_VIDEO_2D_TV: + if(-1 == configPipes_OV_3D_VIDEO_2D_TV(ctx, + obj, + newState, + enable, noRot, rect)) + return false; + break; + case OV_3D_VIDEO_3D_TV: + if(-1 == configPipes_OV_3D_VIDEO_3D_TV(ctx, + obj, + newState, + enable, noRot, rect)) + return false; + break; + default: + LOGE("Unknown state in configPipes"); + abort(); + } + //update the context's state + ctx->state = newState; + return true; +} - overlay_control_context_t *ctx = (overlay_control_context_t *)dev; - overlay_object *obj = static_cast(overlay); - private_overlay_module_t* m = reinterpret_cast( - dev->common.module); - Mutex::Autolock objLock(m->pobjMutex); +static int overlay_setParameter(struct overlay_control_device_t *dev, + overlay_t* overlay, int param, int value) { - if (obj && (obj->getSharedMemoryFD() > 0) && - (ctx->sharedMemBase != MAP_FAILED)) { - 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 - } -// 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; - } + overlay_control_context_t *ctx = (overlay_control_context_t *)dev; + overlay_object *obj = static_cast(overlay); + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + Mutex::Autolock objLock(m->pobjMutex); - static int overlay_control_close(struct hw_device_t *dev) - { - struct overlay_control_context_t* ctx = (struct overlay_control_context_t*)dev; - if (ctx) { - /* free all resources associated with this device here - * in particular the overlay_handle_t, outstanding overlay_t, etc... - */ - free(ctx); - } - return 0; - } + if (obj && (obj->getSharedMemoryFD() > 0) && + (ctx->sharedMemBase != MAP_FAILED)) { + overlay_shared_data* data = static_cast(ctx->sharedMemBase); + data->isControlSetup = false; + /* 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, false, value); + 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); + } + } + } + } + } + if(param != OVERLAY_HDMI_ENABLE) { + //Save the panel orientation + if (param == OVERLAY_TRANSFORM) { + ctx->orientation = value; + if(ctx->state == OV_3D_VIDEO_3D_PANEL) { + int barrier = 0; + switch(ctx->orientation) { + case HAL_TRANSFORM_ROT_90: + case HAL_TRANSFORM_ROT_270: + barrier = BARRIER_LANDSCAPE; + break; + default: + barrier = BARRIER_PORTRAIT; + break; + } + if(!enableBarrier(barrier)) + LOGE("%s:failed to enable barriers for 3D video", __func__); + } + } + if (-1 == setParameterHandleState(ctx, obj, param, value)) + return -1; + } + return 0; +} + +static int overlay_control_close(struct hw_device_t *dev) +{ + struct overlay_control_context_t* ctx = (struct overlay_control_context_t*)dev; + if (ctx) { + /* free all resources associated with this device here + * in particular the overlay_handle_t, outstanding overlay_t, etc... + */ + free(ctx); + } + 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; - } - } +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) - { - /* - * overlay_handle_t should contain all the information to "inflate" this - * overlay. Typically it'll have a file descriptor, informations about - * how many buffers are there, etc... - * It is also the place to mmap all buffers associated with this overlay - * (see getBufferAddress). - * - * NOTE: this function doesn't take ownership of overlay_handle_t - * - */ +int overlay_initialize(struct overlay_data_device_t *dev, + overlay_handle_t handle) +{ + /* + * overlay_handle_t should contain all the information to "inflate" this + * overlay. Typically it'll have a file descriptor, informations about + * how many buffers are there, etc... + * It is also the place to mmap all buffers associated with this overlay + * (see getBufferAddress). + * + * NOTE: this function doesn't take ownership of overlay_handle_t + * + */ - struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; - int ovid = handle_get_ovId(handle); - int rotid = handle_get_rotId(handle); - int size = handle_get_size(handle); - int sharedFd = handle_get_shared_fd(handle); - unsigned int format3D = handle_get_format3D(handle); - private_overlay_module_t* m = reinterpret_cast( - dev->common.module); - Mutex::Autolock objLock(m->pobjMutex); - bool noRot = true; + struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; + int ovid = handle_get_ovId(handle); + int rotid = handle_get_rotId(handle); + int size = handle_get_size(handle); + int sharedFd = handle_get_shared_fd(handle); + unsigned int format3D = handle_get_format3D(handle); + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + Mutex::Autolock objLock(m->pobjMutex); + bool noRot = true; #ifdef USE_MSM_ROTATOR - noRot = false; + noRot = false; #else - noRot = true; + 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; + //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); - if(sharedFd > 0) { - void *base = mmap(0, sizeof(overlay_shared_data), PROT_READ, - MAP_SHARED|MAP_POPULATE, sharedFd, 0); - if(base == MAP_FAILED) { - LOGE("%s: map region failed %d", __func__, -errno); - return -1; - } - ctx->sharedMemBase = base; - } else { - LOGE("Received invalid shared memory fd"); - return -1; - } - 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; - } - //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__); - } - 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; - } + ctx->sharedMemBase = MAP_FAILED; + ctx->format3D = format3D; + //Store the size, needed for HDMI mirroring + ctx->size = size; - int overlay_dequeueBuffer(struct overlay_data_device_t *dev, - overlay_buffer_t* buf) - { - /* blocks until a buffer is available and return an opaque structure - * representing this buffer. - */ + if(sharedFd > 0) { + void *base = mmap(0, sizeof(overlay_shared_data), PROT_READ, + MAP_SHARED|MAP_POPULATE, sharedFd, 0); + if(base == MAP_FAILED) { + LOGE("%s: map region failed %d", __func__, -errno); + return -1; + } + ctx->sharedMemBase = base; + } else { + LOGE("Received invalid shared memory fd"); + return -1; + } + 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; + } + break; + case OV_3D_VIDEO_3D_PANEL: + 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_0, noRot)) { + error_cleanup_data(ctx, i); + return -1; + } + } + 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 (FRAMEBUFFER_1 == i) + noRot = true; + if (!ctx->pobjDataChannel[i]->startDataChannel(ovid, rotid, size, i, noRot)) { + error_cleanup_data(ctx, i); + return -1; + } + } + break; + case OV_3D_VIDEO_3D_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, FRAMEBUFFER_1, true)) { + error_cleanup_data(ctx, 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; +} - /* no internal overlay buffer to dequeue */ - LOGE("%s: no buffer to dequeue ...\n", __FUNCTION__); +int overlay_dequeueBuffer(struct overlay_data_device_t *dev, + overlay_buffer_t* buf) +{ + /* blocks until a buffer is available and return an opaque structure + * representing this buffer. + */ - return 0; - } + /* no internal overlay buffer to dequeue */ + LOGE("%s: no buffer to dequeue ...\n", __FUNCTION__); - int overlay_queueBuffer(struct overlay_data_device_t *dev, - overlay_buffer_t buffer) - { - /* Mark this buffer for posting and recycle or free overlay_buffer_t. */ - struct overlay_data_context_t *ctx = (struct overlay_data_context_t*)dev; - private_overlay_module_t* m = reinterpret_cast( - dev->common.module); - Mutex::Autolock objLock(m->pobjMutex); - bool noRot = true; + return 0; +} + +//Called with Mutex::Autolock objLock(m->pobjMutex); already held +int overlay_queueBufferCheckStateChange(struct overlay_data_device_t *dev, + overlay_buffer_t buffer) +{ + /* Mark this buffer for posting and recycle or free overlay_buffer_t. */ + struct overlay_data_context_t *ctx = (struct overlay_data_context_t*)dev; + overlay_shared_data* data = 0; + if(ctx->sharedMemBase != MAP_FAILED) { + data = static_cast(ctx->sharedMemBase); + if(0 == data){ + LOGE("ctx->sharedMemBase is NULL"); + return false; + } + } + else{ + LOGE("ctx->sharedMemBase == MAP_FAILED"); + return false; + } + + bool noRot = true; #ifdef USE_MSM_ROTATOR - noRot = false; + noRot = false; #else - noRot = true; + noRot = true; #endif - // Check if readyToQueue is enabled. - overlay_shared_data data; - if(ctx->sharedMemBase != MAP_FAILED) - memcpy(&data, ctx->sharedMemBase, sizeof(data)); - else - return false; - if(!data.readyToQueue) { - LOGE("Overlay is not ready to queue buffers"); - return -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; - } - } - //update the context's state - ctx->state = data->state; - } -#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; - } - 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; - } + unsigned int newState = data->state; - return -1; - } + switch (ctx->state) + { + case OV_2D_VIDEO_ON_PANEL: + if(-1 == queueBuffer_OV_2D_VIDEO_ON_PANEL(ctx, data, + newState, + noRot)) + return -1; + break; + case OV_3D_VIDEO_2D_PANEL: + if(-1 == queueBuffer_OV_3D_VIDEO_2D_PANEL(ctx, data, + newState, + noRot)) + return -1; + break; + case OV_3D_VIDEO_3D_PANEL: + if(-1 == queueBuffer_OV_3D_VIDEO_3D_PANEL(ctx, data, + newState, + noRot)) + return -1; + break; + case OV_2D_VIDEO_ON_TV: + if(-1 == queueBuffer_OV_2D_VIDEO_ON_TV(ctx, data, + newState, + noRot)) + return -1; + break; + case OV_3D_VIDEO_2D_TV: + if(-1 == queueBuffer_OV_3D_VIDEO_2D_TV(ctx, data, + newState, + noRot)) + return -1; + break; + case OV_3D_VIDEO_3D_TV: + if(-1 == queueBuffer_OV_3D_VIDEO_3D_TV(ctx, data, + newState, + noRot)) + return -1; + break; + default: + LOGE("Unknown state in configPipes"); + abort(); + } + //update the context's state + ctx->state = newState; + return 0; +} - int overlay_setFd(struct overlay_data_device_t *dev, int fd) - { - private_overlay_module_t* m = reinterpret_cast( - dev->common.module); - struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; - Mutex::Autolock objLock(m->pobjMutex); - 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; - } - 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; - } - } - break; - default: - break; - } - return 0; - } +int overlay_queueBuffer(struct overlay_data_device_t *dev, + overlay_buffer_t buffer) +{ + struct overlay_data_context_t *ctx = (struct overlay_data_context_t*)dev; + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + Mutex::Autolock objLock(m->pobjMutex); - static int overlay_setCrop(struct overlay_data_device_t *dev, uint32_t x, - uint32_t y, uint32_t w, uint32_t h) - { - private_overlay_module_t* m = reinterpret_cast( - dev->common.module); - struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; - Mutex::Autolock objLock(m->pobjMutex); - overlay_rect rect; - ctx->cropRect.x = x; - ctx->cropRect.y = y; - ctx->cropRect.w = w; - ctx->cropRect.h = h; - 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; - } + // Check if control channel is setup. + overlay_shared_data* data = NULL; + if(ctx->sharedMemBase != MAP_FAILED) { + data = static_cast(ctx->sharedMemBase); + if(data == NULL) + return false; + } + else + return false; - void *overlay_getBufferAddress(struct overlay_data_device_t *dev, - overlay_buffer_t buffer) - { - /* overlay buffers are coming from client */ - return( NULL ); - } + if(false == data->isControlSetup) { + LOGE("Overlay Control Channel is not fully setup yet"); + return -1; + } - int overlay_getBufferCount(struct overlay_data_device_t *dev) - { - return 0; - } + // check any state-changing related events + if(-1 == overlay_queueBufferCheckStateChange(dev, buffer)){ + return -1; + } + 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; + } + 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_3D_VIDEO_3D_PANEL: + 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 0; +} + +int overlay_setFd(struct overlay_data_device_t *dev, int fd) +{ + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; + Mutex::Autolock objLock(m->pobjMutex); + 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; + } + break; + case OV_3D_VIDEO_3D_PANEL: + 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; + } + } + break; + default: + break; + } + return 0; +} + +static int overlay_setCrop(struct overlay_data_device_t *dev, uint32_t x, + uint32_t y, uint32_t w, uint32_t h) +{ + private_overlay_module_t* m = reinterpret_cast( + dev->common.module); + struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; + overlay_shared_data* data = static_cast(ctx->sharedMemBase); + //Yield processor until control channel is fully set up i.e commit happens. + while(false == data->isControlSetup) { + sched_yield(); + } + Mutex::Autolock objLock(m->pobjMutex); + overlay_rect rect; + ctx->cropRect.x = x; + ctx->cropRect.y = y; + ctx->cropRect.w = w; + ctx->cropRect.h = h; + 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_3D_PANEL: + 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; +} + +void *overlay_getBufferAddress(struct overlay_data_device_t *dev, + overlay_buffer_t buffer) +{ + /* overlay buffers are coming from client */ + return( NULL ); +} + +int overlay_getBufferCount(struct overlay_data_device_t *dev) +{ + return 0; +} - static int overlay_data_close(struct hw_device_t *dev) - { - struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; - if (ctx) { - /* free all resources associated with this device here - * in particular all pending overlay_buffer_t if needed. - * - * NOTE: overlay_handle_t passed in initialize() is NOT freed and - * its file descriptors are not closed (this is the responsibility - * of the caller). - */ +static int overlay_data_close(struct hw_device_t *dev) +{ + struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; + if (ctx) { + /* free all resources associated with this device here + * in particular all pending overlay_buffer_t if needed. + * + * NOTE: overlay_handle_t passed in initialize() is NOT freed and + * its file descriptors are not closed (this is the responsibility + * of the caller). + */ - if (ctx->pobjDataChannel[0]) { - ctx->pobjDataChannel[0]->closeDataChannel(); - delete ctx->pobjDataChannel[0]; - ctx->pobjDataChannel[0] = 0; - } + if (ctx->pobjDataChannel[0]) { + ctx->pobjDataChannel[0]->closeDataChannel(); + delete ctx->pobjDataChannel[0]; + ctx->pobjDataChannel[0] = 0; + } - if (ctx->pobjDataChannel[1]) { - ctx->pobjDataChannel[1]->closeDataChannel(); - delete ctx->pobjDataChannel[1]; - ctx->pobjDataChannel[1] = 0; - } + if (ctx->pobjDataChannel[1]) { + ctx->pobjDataChannel[1]->closeDataChannel(); + delete ctx->pobjDataChannel[1]; + ctx->pobjDataChannel[1] = 0; + } - if(ctx->sharedMemBase != MAP_FAILED) { - munmap(ctx->sharedMemBase, sizeof(overlay_shared_data)); - ctx->sharedMemBase = MAP_FAILED; - } + if(ctx->sharedMemBase != MAP_FAILED) { + munmap(ctx->sharedMemBase, sizeof(overlay_shared_data)); + ctx->sharedMemBase = MAP_FAILED; + } - free(ctx); - } - return 0; - } + free(ctx); + } + return 0; +} /*****************************************************************************/ - static int overlay_device_open(const struct hw_module_t* module, const char* name, - struct hw_device_t** device) - { - int status = -EINVAL; +static int overlay_device_open(const struct hw_module_t* module, const char* name, + struct hw_device_t** device) +{ + int status = -EINVAL; - private_overlay_module_t* m = reinterpret_cast - (const_cast(module)); - if (!m->pobjMutex) - m->pobjMutex = new Mutex(); + private_overlay_module_t* m = reinterpret_cast + (const_cast(module)); + if (!m->pobjMutex) + m->pobjMutex = new Mutex(); - if (!strcmp(name, OVERLAY_HARDWARE_CONTROL)) { - struct overlay_control_context_t *dev; - dev = (overlay_control_context_t*)malloc(sizeof(*dev)); + if (!strcmp(name, OVERLAY_HARDWARE_CONTROL)) { + struct overlay_control_context_t *dev; + dev = (overlay_control_context_t*)malloc(sizeof(*dev)); - if (!dev) - return status; + if (!dev) + return status; - /* initialize our state here */ - memset(dev, 0, sizeof(*dev)); + /* initialize our state here */ + memset(dev, 0, sizeof(*dev)); - /* initialize the procs */ - dev->device.common.tag = HARDWARE_DEVICE_TAG; - dev->device.common.version = 0; - dev->device.common.module = const_cast(module); - dev->device.common.close = overlay_control_close; + /* initialize the procs */ + dev->device.common.tag = HARDWARE_DEVICE_TAG; + dev->device.common.version = 0; + dev->device.common.module = const_cast(module); + dev->device.common.close = overlay_control_close; - dev->device.get = overlay_get; - dev->device.createOverlay = overlay_createOverlay; - dev->device.destroyOverlay = overlay_destroyOverlay; - dev->device.setPosition = overlay_setPosition; - dev->device.getPosition = overlay_getPosition; - dev->device.setParameter = overlay_setParameter; - dev->device.commit = overlay_commit; + dev->device.get = overlay_get; + dev->device.createOverlay = overlay_createOverlay; + dev->device.destroyOverlay = overlay_destroyOverlay; + dev->device.setPosition = overlay_setPosition; + dev->device.getPosition = overlay_getPosition; + dev->device.setParameter = overlay_setParameter; + dev->device.commit = overlay_commit; - *device = &dev->device.common; - status = 0; - } else if (!strcmp(name, OVERLAY_HARDWARE_DATA)) { - struct overlay_data_context_t *dev; - dev = (overlay_data_context_t*)malloc(sizeof(*dev)); + *device = &dev->device.common; + status = 0; + } else if (!strcmp(name, OVERLAY_HARDWARE_DATA)) { + struct overlay_data_context_t *dev; + dev = (overlay_data_context_t*)malloc(sizeof(*dev)); - if (!dev) - return status; + if (!dev) + return status; - /* initialize our state here */ - memset(dev, 0, sizeof(*dev)); + /* initialize our state here */ + memset(dev, 0, sizeof(*dev)); - /* initialize the procs */ - dev->device.common.tag = HARDWARE_DEVICE_TAG; - dev->device.common.version = 0; - dev->device.common.module = const_cast(module); - dev->device.common.close = overlay_data_close; + /* initialize the procs */ + dev->device.common.tag = HARDWARE_DEVICE_TAG; + dev->device.common.version = 0; + dev->device.common.module = const_cast(module); + dev->device.common.close = overlay_data_close; - dev->device.initialize = overlay_initialize; - dev->device.setCrop = overlay_setCrop; - dev->device.dequeueBuffer = overlay_dequeueBuffer; - dev->device.queueBuffer = overlay_queueBuffer; - dev->device.setFd = overlay_setFd; - dev->device.getBufferAddress = overlay_getBufferAddress; - dev->device.getBufferCount = overlay_getBufferCount; + dev->device.initialize = overlay_initialize; + dev->device.setCrop = overlay_setCrop; + dev->device.dequeueBuffer = overlay_dequeueBuffer; + dev->device.queueBuffer = overlay_queueBuffer; + dev->device.setFd = overlay_setFd; + dev->device.getBufferAddress = overlay_getBufferAddress; + dev->device.getBufferCount = overlay_getBufferCount; - *device = &dev->device.common; - status = 0; - } - return status; - } + *device = &dev->device.common; + status = 0; + } + return status; +} + +#include "overlayState.cpp" diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp index 0dfa814..7a97063 100644 --- a/liboverlay/overlayLib.cpp +++ b/liboverlay/overlayLib.cpp @@ -163,6 +163,32 @@ bool overlay::is3DTV() { return (is3DTV == '0') ? false : true; } +bool overlay::isPanel3D() { + int fd = open("/dev/graphics/fb0", O_RDWR, 0); + if (fd < 0) { + reportError("Can't open framebuffer 0"); + return false; + } + fb_fix_screeninfo finfo; + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) { + reportError("FBIOGET_FSCREENINFO on fb0 failed"); + close(fd); + fd = -1; + return false; + } + close(fd); + return (FB_TYPE_3D_PANEL == finfo.type) ? true : false; +} + +bool overlay::usePanel3D() { + if(!isPanel3D()) + return false; + char value[PROPERTY_VALUE_MAX]; + property_get("persist.user.panel3D", value, "0"); + int usePanel3D = atoi(value); + return usePanel3D ? true : false; +} + bool overlay::send3DInfoPacket (unsigned int format3D) { FILE *fp = fopen(FORMAT_3D_FILE, "wb"); if (fp) { @@ -171,28 +197,45 @@ bool overlay::send3DInfoPacket (unsigned int format3D) { fp = NULL; return true; } - LOGE("%s:no sysfs entry for setting 3d mode!", __func__); + LOGE("%s:no sysfs entry for setting 3d mode!", __FUNCTION__); return false; } -unsigned int overlay::getOverlayConfig (unsigned int format3D) { - bool isTV3D = false, isHDMI = false; +bool overlay::enableBarrier (unsigned int orientation) { + FILE *fp = fopen(BARRIER_FILE, "wb"); + if (fp) { + fprintf(fp, "%d", orientation); + fclose(fp); + fp = NULL; + return true; + } + LOGE("%s:no sysfs entry for enabling barriers on 3D panel!", __FUNCTION__); + return false; +} + +unsigned int overlay::getOverlayConfig (unsigned int format3D, bool poll, + bool isHDMI) { + bool isTV3D = false; unsigned int curState = 0; - isHDMI = overlay::isHDMIConnected(); + if (poll) + isHDMI = isHDMIConnected(); if (isHDMI) { - LOGD("%s: HDMI connected... checking the TV type", __func__); - isTV3D = overlay::is3DTV(); + LOGD("%s: HDMI connected... checking the TV type", __FUNCTION__); if (format3D) { - if (isTV3D) + if (is3DTV()) 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; + LOGD("%s: HDMI not connected...", __FUNCTION__); + if(format3D) { + if (usePanel3D()) + curState = OV_3D_VIDEO_3D_PANEL; + else + curState = OV_3D_VIDEO_2D_PANEL; + } else curState = OV_2D_VIDEO_ON_PANEL; } @@ -201,7 +244,7 @@ unsigned int overlay::getOverlayConfig (unsigned int format3D) { Overlay::Overlay() : mChannelUP(false), mHDMIConnected(false), mS3DFormat(0), mCroppedSrcWidth(0), - mCroppedSrcHeight(0) { + mCroppedSrcHeight(0), mState(-1) { mOVBufferInfo.width = mOVBufferInfo.height = 0; mOVBufferInfo.format = mOVBufferInfo.size = 0; } @@ -228,6 +271,9 @@ bool Overlay::startChannel(const overlay_buffer_info& info, int fbnum, mCroppedSrcHeight = info.height; if (format3D) zorder = channel; + if (mState == -1) + mState = OV_UI_MIRROR_TV; + mChannelUP = objOvCtrlChannel[channel].startControlChannel(info.width, info.height, format, fbnum, norot, uichannel, @@ -241,39 +287,16 @@ bool Overlay::startChannel(const overlay_buffer_info& info, int fbnum, norot, uichannel, num_buffers); } -bool Overlay::startChannelHDMI(const overlay_buffer_info& info, bool norot) { - - bool ret = startChannel(info, FRAMEBUFFER_0, norot); - if(ret) { - ret = startChannel(info, FRAMEBUFFER_1, true, 0, 0, VG1_PIPE); - } - return ret; -} - -bool Overlay::startChannelS3D(const overlay_buffer_info& info, bool norot) { - bool ret = false; - // Start both the channels for the S3D content - if (mS3DFormat & HAL_3D_OUT_MONOSCOPIC_MASK) - ret = startChannel(info, FRAMEBUFFER_0, norot, 0, mS3DFormat, VG0_PIPE); - else - ret = startChannel(info, FRAMEBUFFER_1, norot, 0, mS3DFormat, VG0_PIPE); - if (ret) { - ret = startChannel(info, FRAMEBUFFER_1, norot, 0, mS3DFormat, VG1_PIPE); - } - if (!ret) { - closeChannel(); - } else if (!(mS3DFormat & HAL_3D_OUT_MONOSCOPIC_MASK)) - ret = overlay::send3DInfoPacket(mS3DFormat & OUTPUT_MASK_3D); - return ret; -} - bool Overlay::closeChannel() { if (!mChannelUP) return true; if(mS3DFormat) { - overlay::send3DInfoPacket(0); + if (mHDMIConnected) + overlay::send3DInfoPacket(0); + else if (mState == OV_3D_VIDEO_3D_PANEL) + enableBarrier(0); } for (int i = 0; i < NUM_CHANNELS; i++) { objOvCtrlChannel[i].closeControlChannel(); @@ -285,6 +308,7 @@ bool Overlay::closeChannel() { mOVBufferInfo.height = 0; mOVBufferInfo.format = 0; mOVBufferInfo.size = 0; + mState = -1; return true; } @@ -297,40 +321,58 @@ bool Overlay::getOrientation(int& orientation, int channel) const { } bool Overlay::setPosition(int x, int y, uint32_t w, uint32_t h) { - if(mHDMIConnected) { - if(mS3DFormat) { - return setPositionS3D(x, y, w, h); - } else { - overlay_rect rect; + bool ret = false; + overlay_rect rect; + switch (mState) { + case OV_UI_MIRROR_TV: + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + return setChannelPosition(x, y, w, h, VG0_PIPE); + break; + case OV_2D_VIDEO_ON_TV: objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(mCroppedSrcWidth, mCroppedSrcHeight, &rect); setChannelPosition(rect.x, rect.y, rect.w, rect.h, VG1_PIPE); - } + return setChannelPosition(x, y, w, h, VG0_PIPE); + break; + case OV_3D_VIDEO_3D_PANEL: + for (int i = 0; i < NUM_CHANNELS; i++) { + if (!objOvCtrlChannel[i].useVirtualFB()) { + LOGE("%s: failed virtual fb for channel %d", __FUNCTION__, i); + return false; + } + objOvCtrlChannel[i].getPositionS3D(i, 0x1, &rect); + if(!setChannelPosition(rect.x, rect.y, rect.w, rect.h, i)) { + LOGE("%s: failed for channel %d", __FUNCTION__, i); + return false; + } + } + break; + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + for (int i = 0; i < NUM_CHANNELS; i++) { + ret = objOvCtrlChannel[i].getPositionS3D(i, mS3DFormat, &rect); + 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", __FUNCTION__, i); + return ret; + } + } + break; + default: + LOGE("%s:Unknown state %d", __FUNCTION__, mState); + break; } - return setChannelPosition(x, y, w, h, VG0_PIPE); + return true; } bool Overlay::setChannelPosition(int x, int y, uint32_t w, uint32_t h, int channel) { return objOvCtrlChannel[channel].setPosition(x, y, w, h); } -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) - 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; -} - bool Overlay::updateOverlaySource(const overlay_buffer_info& info, int orientation) { if (hasHDMIStatusChanged()) { return setSource(info, orientation, mHDMIConnected); @@ -343,8 +385,19 @@ bool Overlay::updateOverlaySource(const overlay_buffer_info& info, int orientati return true; } - // Disable rotation for the HDMI channel + // Disable rotation for the HDMI channels int orient[2] = {orientation, 0}; + switch(mState) { + case OV_3D_VIDEO_3D_PANEL: + orient[1] = orientation; + break; + case OV_3D_VIDEO_3D_TV: + orient[0] = 0; + break; + default: + break; + } + // Set the overlay source info for (int i = 0; i < NUM_CHANNELS; i++) { if (objOvCtrlChannel[i].isChannelUP()) { @@ -405,80 +458,116 @@ bool Overlay::setSource(const overlay_buffer_info& info, int orientation, // Separate the color format from the 3D format. // If there is 3D content; the effective format passed by the client is: // effectiveFormat = 3D_IN | 3D_OUT | ColorFormat + int newState = mState; + bool stateChange = false, ret = true; unsigned int format3D = getS3DFormat(info.format); int colorFormat = getColorFormat(info.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; - - if (format3D != mS3DFormat) - s3dChanged = 0x10; - - stateChanged = s3dChanged|hasHDMIStatusChanged(); - if (stateChanged || !objOvCtrlChannel[0].setSource(info.width, info.height, colorFormat, orientation, ignoreFB)) { + newState = getOverlayConfig (format3D, false, hdmiConnected); + stateChange = (mState == newState) ? false : true; + // Check if the orientation of the primary channel changed + if (mState != OV_3D_VIDEO_3D_TV) + if (mChannelUP) + ret = objOvCtrlChannel[0].setSource(info.width, info.height, + colorFormat, orientation, ignoreFB); + if (stateChange || !ret) { closeChannel(); + mHDMIConnected = hdmiConnected; + mState = newState; mS3DFormat = format3D; - - mOVBufferInfo = info; - if (mHDMIConnected) { - if (mS3DFormat) { - // Start both the VG pipes - return startChannelS3D(info, !orientation); - } else { - return startChannelHDMI(info, !orientation); - } - } else { - return startChannel(info, 0, !orientation, - false, 0, VG0_PIPE, ignoreFB, num_buffers); + if (mState == OV_3D_VIDEO_2D_PANEL || mState == OV_3D_VIDEO_2D_TV) { + LOGI("3D content on 2D display: set the output format as monoscopic"); + mS3DFormat = FORMAT_3D_INPUT(format3D) | HAL_3D_OUT_MONOSCOPIC_MASK; + } + bool noRot = !orientation; + switch(mState) { + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + return startChannel(info, FRAMEBUFFER_0, noRot, false, + mS3DFormat, VG0_PIPE, ignoreFB, num_buffers); + break; + case OV_3D_VIDEO_3D_PANEL: + for (int i=0; ioffset; const int fd = hnd->fd; - bool ret = true; - - if (mHDMIConnected) { - // Queue the buffer on VG1 pipe - ret = queueBuffer(fd, offset, VG1_PIPE); + switch (mState) { + case OV_UI_MIRROR_TV: + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + if(!queueBuffer(fd, offset, VG0_PIPE)) { + LOGE("%s:failed for channel 0", __FUNCTION__); + return false; + } + break; + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_3D_PANEL: + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + for (int i=0; i> SHIFT_OUTPUT_3D) #define HAL_3D_OUT_MONOSCOPIC_MASK (HAL_3D_OUT_MONOSCOPIC >> SHIFT_OUTPUT_3D) +// 3D panel barrier orientation +#define BARRIER_LANDSCAPE 1 +#define BARRIER_PORTRAIT 2 + #define FORMAT_3D_FILE "/sys/class/graphics/fb1/format_3d" #define EDID_3D_INFO_FILE "/sys/class/graphics/fb1/3d_present" +#define BARRIER_FILE "/sys/devices/platform/mipi_novatek.0/enable_3d_barrier" /* -------------------------- end 3D defines ----------------------------------------*/ // Struct to hold the buffer info: geometry and size @@ -101,7 +106,8 @@ struct overlay_buffer_info { namespace overlay { enum { - OV_2D_VIDEO_ON_PANEL = 0, + OV_UI_MIRROR_TV = 0, + OV_2D_VIDEO_ON_PANEL, OV_2D_VIDEO_ON_TV, OV_3D_VIDEO_2D_PANEL, OV_3D_VIDEO_2D_TV, @@ -110,8 +116,12 @@ enum { }; bool isHDMIConnected(); bool is3DTV(); +bool isPanel3D(); +bool usePanel3D(); bool send3DInfoPacket(unsigned int format3D); -unsigned int getOverlayConfig (unsigned int format3D); +bool enableBarrier(unsigned int orientation); +unsigned int getOverlayConfig (unsigned int format3D, bool poll = true, + bool isHDMI = false); int get_mdp_format(int format); int get_size(int format, int w, int h); @@ -143,6 +153,7 @@ class OverlayControlChannel { bool mUIChannel; mdp_overlay mOVInfo; msm_rotator_img_info mRotInfo; + msmfb_overlay_3d m3DOVInfo; bool openDevices(int fbnum = -1); bool setOverlayInformation(const overlay_buffer_info& info, int flags, int orientation, int zorder = 0, bool ignoreFB = false, @@ -177,6 +188,7 @@ public: bool getPositionS3D(int channel, int format, overlay_rect *rect); bool updateOverlaySource(const overlay_buffer_info& info, int orientation); bool getFormat() const { return mFormat; } + bool useVirtualFB (); }; class OverlayDataChannel { @@ -231,6 +243,7 @@ class Overlay { int mCroppedSrcWidth; int mCroppedSrcHeight; overlay_buffer_info mOVBufferInfo; + int mState; OverlayControlChannel objOvCtrlChannel[2]; OverlayDataChannel objOvDataChannel[2]; @@ -263,10 +276,6 @@ public: bool updateOverlaySource(const overlay_buffer_info& info, int orientation); private: - bool startChannelHDMI(const overlay_buffer_info& info, bool norot); - bool startChannelS3D(const overlay_buffer_info& info, 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); bool setChannelCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h, int channel); bool queueBuffer(int fd, uint32_t offset, int channel); @@ -277,7 +286,7 @@ private: }; struct overlay_shared_data { - int readyToQueue; + volatile bool isControlSetup; unsigned int state; int rotid[2]; int ovid[2]; diff --git a/liboverlay/overlayState.cpp b/liboverlay/overlayState.cpp new file mode 100644 index 0000000..f4398d4 --- /dev/null +++ b/liboverlay/overlayState.cpp @@ -0,0 +1,1109 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * Copyright (c) 2009 - 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +int setParameterHandleState(overlay_control_context_t *ctx, + overlay_object *obj, + int param, int 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: + case OV_3D_VIDEO_3D_PANEL: + for (int i=0; isetParameter(param, value, i)) { + LOGE("%s: Failed for channel %d", __func__, i); + return -1; + } + } + break; + default: + LOGE("Unknown state in setParameter"); + abort(); + break; + } + return 0; +} + +int createOverlayHandleState(overlay_control_context_t *ctx, bool noRot, + overlay_object* overlay, int fd) +{ + 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 -1; + } + break; + case OV_3D_VIDEO_3D_PANEL: + for (int i=0; istartControlChannel(FRAMEBUFFER_0, noRot, i)) { + error_cleanup_control(ctx, overlay, fd, i); + return -1; + } + } + 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 -1; + } + if (!overlay->startControlChannel(FRAMEBUFFER_1, true, VG1_PIPE)) { + error_cleanup_control(ctx, overlay, fd, VG1_PIPE); + return -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 -1; + } + } + break; + default: + break; + } + return 0; +} + +int setPositionHandleState(overlay_control_context_t *ctx, + overlay_object *obj, overlay_rect& rect, + int x, int y, uint32_t w, uint32_t h) +{ + int ret = 0; + 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_3D_VIDEO_3D_PANEL: + for (int i = 0; i < NUM_CHANNELS; i++) { + if (!obj->useVirtualFB(i)) { + LOGE("can't use the virtual fb for line interleaving!"); + } + obj->getPositionS3D(&rect, i, true); + if(!obj->setPosition(rect.x, rect.y, rect.w, rect.h, i)) { + LOGE("%s:Failed for channel %d", __func__, i); + return -1; + } + } + break; + case OV_2D_VIDEO_ON_TV: + 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__); + } + if(!obj->setPosition(x, y, w, h, VG0_PIPE)) { + LOGE("%s:Failed for channel 0", __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 ret; +} + +//////////////////////// configPipes /////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////////////// + +bool TV2Dconn(overlay_control_context_t *ctx, + overlay_object *obj, bool noRot, + overlay_rect& rect) +{ + 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(VG1_PIPE); + 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; + } + return true; +} + +bool TV3Dconn(overlay_control_context_t *ctx, + overlay_object *obj, bool noRot, + overlay_rect& rect) +{ + 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(VG0_PIPE); + //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; + } + } + return true; +} + +bool TV3DSetup(overlay_control_context_t *ctx, overlay_object *obj, int i, + int fbnum, overlay_rect& rect) +{ + bool noRot = fbnum ? true : false; + if (!obj->startControlChannel(fbnum, noRot, i)) { + LOGE("%s:Failed to open control channel for pipe %d", __func__, i); + return false; + } + bool ret=true; + if (!obj->getPositionS3D(&rect, i)) + ret = obj->setPosition(ctx->posPanel.x, ctx->posPanel.y, + ctx->posPanel.w, ctx->posPanel.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 false; + } + return true; +} + +int configPipes_OV_2D_VIDEO_ON_PANEL_to_OV_2D_VIDEO_ON_TV (overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + if(enable) // HDMI connected + { + if(!TV2Dconn(ctx, obj, noRot, rect)) + return -1; + return 0; + } + LOGE("%s Error cannot disconnect HDMI in that state", __func__); + abort(); + return -1; +} + +int configPipes_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_2D_TV (overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + // same as OV_2D_VIDEO_ON_PANEL_to_OV_2D_VIDEO_ON_TV + return configPipes_OV_2D_VIDEO_ON_PANEL_to_OV_2D_VIDEO_ON_TV(ctx, + obj, + newState, + enable, noRot, rect); +} + +int configPipes_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_3D_TV (overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + if(enable) // HDMI connected + { + if(!TV3Dconn(ctx, obj, noRot, rect)) + return -1; + return 0; + } + // HDMI disconnected + LOGE("%s Error cannot disconnect HDMI in that state", __func__); + abort(); + return -1; +} + +int configPipes_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_2D_TV (overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + if(!enable){ // HDMI disconnect + LOGE("%s Error cannot disconnect HDMI in that state", __func__); + abort(); + return -1; + } + obj->closeControlChannel(VG1_PIPE); + obj->closeControlChannel(VG0_PIPE); + //disable the panel barriers + enableBarrier(0); + //now open both the channels + //update the output from stereoscopic to monoscopic + ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | HAL_3D_OUT_MONOSCOPIC_MASK; + obj->setFormat3D(ctx->format3D); + LOGI("Control: new S3D format : 0x%x", ctx->format3D); + int fbnum = 0; + bool ret = true; + //now open both the channels + for (int i = 0; i < NUM_CHANNELS; i++) { + fbnum = i; + if(!TV3DSetup(ctx, obj, i, fbnum, rect)) + return -1; + } + return 0; +} + +int configPipes_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_3D_TV (overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + if(!enable){ // HDMI disconnect + LOGE("%s Error cannot disconnect HDMI in that state", __func__); + abort(); + return -1; + } + obj->closeControlChannel(VG1_PIPE); + obj->closeControlChannel(VG0_PIPE); + //disable the panel barrier + enableBarrier(0); + //now open both the channels + for (int i = 0; i < NUM_CHANNELS; i++) { + if(!TV3DSetup(ctx, obj, i, FRAMEBUFFER_1, rect)) + return -1; + } + return 0; +} + + +///// HDMI Disconnect //// +int configPipes_OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL (overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + if(enable) // HDMI connected + { + LOGE("%s Error cannot connect HDMI in that state", __func__); + abort(); + return -1; + } + LOGI("2D TV disconnected, close the control channel."); + obj->closeControlChannel(VG1_PIPE); + return 0; +} + +int configPipes_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_2D_PANEL (overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + // same as OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL + return configPipes_OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL(ctx, + obj, + newState, + enable, noRot, rect); +} + +int configPipes_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_2D_PANEL(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + if(enable) // HDMI connected + { + LOGE("%s Error cannot connect HDMI in that state", __func__); + abort(); + return -1; + } + LOGI("3D TV disconnected, close the control channels & open one for panel."); + // Close both the pipes' control channel + obj->closeControlChannel(VG1_PIPE); + obj->closeControlChannel(VG0_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 orientation for channel 0", __func__); + return -1; + } + return 0; +} + +int TVto3DPanel(overlay_control_context_t *ctx, overlay_object *obj, + bool noRot, overlay_rect& rect) +{ + for (int i = 0; i < NUM_CHANNELS; i++) { + if (!obj->startControlChannel(FRAMEBUFFER_0, noRot, i)) { + LOGE("%s:Failed to open control channel for pipe %d", __func__, i); + return false; + } + if (!obj->useVirtualFB(i)) { + LOGE("can't use the virtual fb for line interleaving!"); + } + 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 -1; + } + if (!obj->setParameter(OVERLAY_TRANSFORM, ctx->orientation, i)) { + LOGE("%s: Failed to set orientation for channel 0", __func__); + return -1; + } + } + return 0; +} + +int configPipes_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_3D_PANEL(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + if(enable) { // HDMI connect + LOGE("%s Error cannot connect HDMI in that state", __func__); + abort(); + return -1; + } + // disconnect TV + // Close both the pipes' control channel + obj->closeControlChannel(VG0_PIPE); + obj->closeControlChannel(VG1_PIPE); + //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); + return TVto3DPanel(ctx, obj, noRot, rect); +} + +int configPipes_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_3D_PANEL(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + if(enable) { // HDMI connect + LOGE("%s Error cannot connect HDMI in that state", __func__); + abort(); + return -1; + } + + // disconnect TV + // Close both the pipes' control channel + obj->closeControlChannel(VG0_PIPE); + obj->closeControlChannel(VG1_PIPE); + return TVto3DPanel(ctx, obj, noRot, rect); +} + + +//// On Panel //// + +int configPipes_OV_2D_VIDEO_ON_PANEL(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + switch(newState){ + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + case OV_3D_VIDEO_3D_PANEL: + case OV_3D_VIDEO_3D_TV: + case OV_3D_VIDEO_2D_TV: + LOGE("ctl: Error in handling OV_2D_VIDEO_ON_PANEL newstate=%d", newState); + abort(); + return -1; + break; + case OV_2D_VIDEO_ON_TV: + LOGI("TV connected: open a new VG control channel"); + if(-1 == configPipes_OV_2D_VIDEO_ON_PANEL_to_OV_2D_VIDEO_ON_TV(ctx, + obj, + newState, + enable, noRot, rect)) + return -1; + break; + default: + LOGE("%s Unknown state in configPipes %d", __func__, newState); + abort(); + break; + } + return 0; +} + +int configPipes_OV_3D_VIDEO_2D_PANEL(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + switch(newState){ + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + case OV_3D_VIDEO_3D_PANEL: + case OV_2D_VIDEO_ON_TV: + LOGE("Error in handling OV_3D_VIDEO_2D_PANEL newstate=%d", newState); + abort(); + return -1; + case OV_3D_VIDEO_2D_TV: + if(-1 == configPipes_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_2D_TV(ctx, + obj, + newState, + enable, noRot, rect)) + return -1; + break; + case OV_3D_VIDEO_3D_TV: + if(-1 == configPipes_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_3D_TV(ctx, + obj, + newState, + enable, noRot, rect)) + return -1; + break; + default: + LOGE("%s Unknown state in configPipes %d", __func__, newState); + abort(); + } + return 0; +} + +int configPipes_OV_3D_VIDEO_3D_PANEL(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + switch(newState){ + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + case OV_3D_VIDEO_3D_PANEL: + case OV_2D_VIDEO_ON_TV: + LOGE("Error in handling OV_3D_VIDEO_3D_PANEL newstate=%d", newState); + abort(); + return -1; + case OV_3D_VIDEO_2D_TV: + if(-1 == configPipes_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_2D_TV(ctx, + obj, + newState, + enable, noRot, rect)) + return -1; + break; + case OV_3D_VIDEO_3D_TV: + if(-1 == configPipes_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_3D_TV(ctx, + obj, + newState, + enable, noRot, rect)) + return -1; + break; + default: + LOGE("%s Unknown state in configPipes %d", __func__, newState); + abort(); + } + return 0; +} + +/// OV on TV //// + +int configPipes_OV_2D_VIDEO_ON_TV(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + switch(newState){ + case OV_2D_VIDEO_ON_PANEL: + if(-1 == configPipes_OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL(ctx, + obj, + newState, + enable, noRot, rect)) + return -1; + break; + case OV_3D_VIDEO_3D_PANEL: + case OV_3D_VIDEO_2D_PANEL: + case OV_3D_VIDEO_3D_TV: + case OV_3D_VIDEO_2D_TV: + case OV_2D_VIDEO_ON_TV: + LOGE("Error in handling OV_2D_VIDEO_ON_TV newstate=%d", newState); + abort(); + return -1; + default: + LOGE("%s Unknown state in configPipes %d", __func__, newState); + abort(); + } + return 0; +} + +int configPipes_OV_3D_VIDEO_2D_TV(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + switch(newState){ + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_3D_TV: + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_2D_TV: + LOGE("Error in handling OV_3D_VIDEO_2D_TV newstate=%d", newState); + abort(); + return -1; + case OV_3D_VIDEO_3D_PANEL: + if(-1 == configPipes_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_3D_PANEL(ctx, + obj, + newState, + enable, noRot, rect)) + break; + case OV_3D_VIDEO_2D_PANEL: + if(-1 == configPipes_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_2D_PANEL(ctx, + obj, + newState, + enable, noRot, rect)) + return -1; + break; + default: + LOGE("%s Unknown state in configPipes %d", __func__, newState); + abort(); + } + return 0; +} + +int configPipes_OV_3D_VIDEO_3D_TV(overlay_control_context_t *ctx, + overlay_object *obj, + unsigned int newState, + int enable, bool noRot, + overlay_rect& rect) +{ + switch(newState){ + case OV_3D_VIDEO_2D_PANEL: + if(-1 == configPipes_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_2D_PANEL(ctx, + obj, + newState, + enable, noRot, rect)) + return -1; + break; + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_3D_TV: + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_2D_TV: + LOGE("Error in handling OV_3D_VIDEO_2D_TV newstate=%d", newState); + abort(); + return -1; + case OV_3D_VIDEO_3D_PANEL: + if(-1 == configPipes_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_3D_PANEL(ctx, + obj, + newState, + enable, noRot, rect)) + return -1; + break; + default: + LOGE("%s Unknown state in configPipes %d", __func__, newState); + abort(); + } + return 0; +} + + +//////////////////////////////////// Queue Buffer /////////////////////////////////// + +///////////////////////// Helper func /////////////////////////////// + +int queueBuffer_OV_2D_VIDEO_ON_PANEL_to_OV_2D_VIDEO_ON_TV(overlay_data_context_t *ctx, + overlay_shared_data* data) +{ + 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; + } + 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; + } + return 0; +} + +int queueBuffer_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_2D_TV(overlay_data_context_t *ctx, + overlay_shared_data* data) +{ + 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; + } + 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__); + return -1; + } + //setting the srcFD + if (!ctx->pobjDataChannel[VG1_PIPE]->setFd(ctx->srcFD)) { + LOGE("%s: Failed to set fd for pipe 1", __func__); + return -1; + } + return 0; +} + +int queueBuffer_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_3D_TV(overlay_data_context_t *ctx, + overlay_shared_data* data) +{ + //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); + return 0; +} +int queueBuffer_3D_to_2D_TV_common(overlay_data_context_t *ctx, + overlay_shared_data* data, + overlay_rect& rect, + int i, int fbnum) +{ + bool noRot = fbnum ? true : false; + ctx->pobjDataChannel[i] = new OverlayDataChannel(); + if (!ctx->pobjDataChannel[i]->startDataChannel( + data->ovid[i], data->rotid[i], ctx->size, fbnum, noRot)) { + 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; + } + return 0; +} + +int queueBuffer_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_2D_TV(overlay_data_context_t *ctx, + overlay_shared_data* data) +{ + // 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; + } + //now open both the channels + overlay_rect rect; + for (int i = 0; i < NUM_CHANNELS; i++) { + int fbnum = i; + //update the output from stereoscopic to monoscopic + ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | HAL_3D_OUT_MONOSCOPIC_MASK; + LOGI("Data: New S3D format : 0x%x", ctx->format3D); + if(-1 == queueBuffer_3D_to_2D_TV_common(ctx, data, rect, i, fbnum)) + return -1; + } + return 0; +} + +int queueBuffer_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_3D_TV(overlay_data_context_t *ctx, + overlay_shared_data* data) +{ + // 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; + } + //now open both the channels + overlay_rect rect; + int fbnum = 1; + for (int i = 0; i < NUM_CHANNELS; i++) { + if(-1 == queueBuffer_3D_to_2D_TV_common(ctx, data, rect, i, fbnum)) + return -1; + } + send3DInfoPacket(ctx->format3D & OUTPUT_MASK_3D); + return 0; +} + +void queueBuffer_OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL(overlay_data_context_t *ctx) +{ + 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; +} + +void queueBuffer_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_2D_PANEL(overlay_data_context_t *ctx) +{ + // same as queueBuffer_OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL + queueBuffer_OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL(ctx); +} + +int queueBuffer_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_2D_PANEL(overlay_data_context_t *ctx, + overlay_shared_data* data, bool noRot) +{ + 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; + } + return 0; +} + +void queueBuffer_3D_Panel_common_pre(overlay_data_context_t *ctx) +{ + // 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); +} + + +int queueBuffer_3D_Panel_common_post(overlay_data_context_t *ctx, + overlay_shared_data* data, + bool noRot) +{ + 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_0, noRot)) { + 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; + } + } + return 0; +} + +int queueBuffer_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_3D_PANEL(overlay_data_context_t *ctx, + overlay_shared_data* data, + bool noRot) +{ + queueBuffer_3D_Panel_common_pre(ctx); + + if(-1 == queueBuffer_3D_Panel_common_post(ctx, data, noRot)) + return -1; + + return 0; +} + +int queueBuffer_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_3D_PANEL(overlay_data_context_t *ctx, + overlay_shared_data* data, + bool noRot) +{ + queueBuffer_3D_Panel_common_pre(ctx); + ctx->format3D = FORMAT_3D_INPUT(ctx->format3D) | + ctx->format3D >> SHIFT_3D; + if(-1 == queueBuffer_3D_Panel_common_post(ctx, data, noRot)) + return -1; + + return 0; +} + +////////////////// Queue buffer state machine handling ///////////////////// + +int queueBuffer_OV_2D_VIDEO_ON_PANEL(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot) +{ + switch(newState){ + case OV_2D_VIDEO_ON_PANEL: + // nothing to do here + break; + case OV_2D_VIDEO_ON_TV: + LOGI("TV connected, open a new data channel"); + if(-1 == queueBuffer_OV_2D_VIDEO_ON_PANEL_to_OV_2D_VIDEO_ON_TV(ctx, data)) + return -1; + break; + case OV_3D_VIDEO_2D_PANEL: + case OV_3D_VIDEO_3D_PANEL: + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + LOGE("data: Error in handling OV_2D_VIDEO_ON_PANEL newstate=%d", newState); + abort(); + return -1; + default: + LOGE("%s Unknown state in queueBuffer %d", __func__, newState); + abort(); + } + + return 0; +} + +int queueBuffer_OV_3D_VIDEO_2D_PANEL(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot) +{ + switch(newState){ + case OV_3D_VIDEO_2D_PANEL: + // nothing to do here + break; + case OV_3D_VIDEO_2D_TV: + if(-1 == queueBuffer_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_2D_TV(ctx, data)) + return -1; + break; + case OV_3D_VIDEO_3D_TV: + if(-1 == queueBuffer_OV_3D_VIDEO_2D_PANEL_to_OV_3D_VIDEO_3D_TV(ctx, data)) + return -1; + break; + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_3D_PANEL: + case OV_2D_VIDEO_ON_TV: + LOGE("Error in handling OV_3D_VIDEO_2D_PANEL newstate=%d", newState); + abort(); + return -1; + default: + LOGE("%s Unknown state in queueBuffer %d", __func__, newState); + abort(); + } + + return 0; +} + +int queueBuffer_OV_3D_VIDEO_3D_PANEL(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot) +{ + switch(newState){ + case OV_3D_VIDEO_3D_PANEL: + // nothing to do here + break; + case OV_2D_VIDEO_ON_PANEL: + case OV_3D_VIDEO_2D_PANEL: + case OV_2D_VIDEO_ON_TV: + LOGE("Error in handling OV_3D_VIDEO_3D_PANEL newstate=%d", newState); + abort(); + return -1; + case OV_3D_VIDEO_2D_TV: + if(-1 == queueBuffer_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_2D_TV(ctx, data)) + return -1; + break; + case OV_3D_VIDEO_3D_TV: + if(-1 == queueBuffer_OV_3D_VIDEO_3D_PANEL_to_OV_3D_VIDEO_3D_TV(ctx, data)) + return -1; + break; + default: + LOGE("%s Unknown state in queueBuffer %d", __func__, newState); + abort(); + } + + return 0; +} + +int queueBuffer_OV_2D_VIDEO_ON_TV(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot) +{ + switch(newState){ + case OV_2D_VIDEO_ON_TV: + // nothing to see here + break; + case OV_2D_VIDEO_ON_PANEL: + queueBuffer_OV_2D_VIDEO_ON_TV_to_OV_2D_VIDEO_ON_PANEL(ctx); + break; + case OV_3D_VIDEO_2D_PANEL: + case OV_3D_VIDEO_3D_PANEL: + case OV_3D_VIDEO_2D_TV: + case OV_3D_VIDEO_3D_TV: + LOGE("Error in handling OV_2D_VIDEO_ON_TV newstate=%d", newState); + abort(); + return -1; + default: + LOGE("%s Unknown state in queueBuffer %d", __func__, newState); + abort(); + } + + return 0; +} + +int queueBuffer_OV_3D_VIDEO_2D_TV(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot) +{ + switch(newState){ + case OV_3D_VIDEO_2D_TV: + // nothing to see here + break; + case OV_3D_VIDEO_2D_PANEL: + queueBuffer_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_2D_PANEL(ctx); + break; + case OV_3D_VIDEO_3D_PANEL: + if(-1 == queueBuffer_OV_3D_VIDEO_2D_TV_to_OV_3D_VIDEO_3D_PANEL(ctx, data, noRot)) + return -1; + break; + case OV_2D_VIDEO_ON_PANEL: + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_3D_TV: + LOGE("Error in handling OV_3D_VIDEO_2D_TV newstate=%d", newState); + abort(); + return -1; + default: + LOGE("%s Unknown state in queueBuffer %d", __func__, newState); + abort(); + } + + return 0; +} + +int queueBuffer_OV_3D_VIDEO_3D_TV(overlay_data_context_t *ctx, + overlay_shared_data* data, + unsigned int newState, bool noRot) +{ + switch(newState){ + case OV_3D_VIDEO_3D_TV: + // nothing to see here + break; + case OV_3D_VIDEO_2D_PANEL: + if(-1 == queueBuffer_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_2D_PANEL(ctx, data, noRot)) + return -1; + break; + case OV_3D_VIDEO_3D_PANEL: + if(-1 == queueBuffer_OV_3D_VIDEO_3D_TV_to_OV_3D_VIDEO_3D_PANEL(ctx, data, noRot)) + return -1; + break; + case OV_2D_VIDEO_ON_PANEL: + case OV_2D_VIDEO_ON_TV: + case OV_3D_VIDEO_2D_TV: + LOGE("Error in handling OV_3D_VIDEO_3D_TV newstate=%d", newState); + abort(); + return -1; + default: + LOGE("%s Unknown state in queueBuffer %d", __func__, newState); + abort(); + } + + return 0; +} + + +///////////////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////////////// +