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; +} + + +///////////////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////////////// +