diff --git a/common.mk b/common.mk new file mode 100644 index 0000000..0bc64a3 --- /dev/null +++ b/common.mk @@ -0,0 +1,31 @@ +#Common headers +common_includes := hardware/qcom/display/libgralloc +common_includes += hardware/qcom/display/libgenlock +common_includes += hardware/qcom/display/liboverlay +common_includes += hardware/qcom/display/libcopybit +common_includes += hardware/qcom/display/libqdutils + +ifeq ($(TARGET_USES_POST_PROCESSING),true) + common_flags += -DUSES_POST_PROCESSING + common_includes += $(TARGET_OUT_HEADERS)/pp/inc +endif + + +#Common libraries external to display HAL +common_libs := liblog libutils libcutils libhardware + +#Common C flags +common_flags := -DUSE_ION -DDEBUG_CALC_FPS -Wno-missing-field-initializers +ifeq ($(ARCH_ARM_HAVE_NEON),true) + common_flags += -D__ARM_HAVE_NEON +endif + +common_deps := +kernel_includes := +#Kernel includes +ifeq ($(call is-vendor-board-platform,QCOM),true) + common_deps += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr + kernel_includes += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include +endif + + diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk index abb5eca..b02927f 100644 --- a/libcopybit/Android.mk +++ b/libcopybit/Android.mk @@ -12,59 +12,31 @@ # See the License for the specific language governing permissions and # limitations under the License. - LOCAL_PATH:= $(call my-dir) -# HAL module implemenation, not prelinked and stored in -# hw/..so +include $(LOCAL_PATH)/../common.mk +include $(CLEAR_VARS) +LOCAL_MODULE := copybit.$(TARGET_BOARD_PLATFORM) +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_MODULE_TAGS := optional +LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes) +LOCAL_SHARED_LIBRARIES := $(common_libs) libdl libmemalloc +LOCAL_CFLAGS := $(common_flags) +LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) + ifeq ($(TARGET_USES_C2D_COMPOSITION),true) - include $(CLEAR_VARS) - LOCAL_PRELINK_MODULE := false - LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw - LOCAL_SHARED_LIBRARIES := liblog libdl libcutils libmemalloc libutils - LOCAL_SRC_FILES := copybit_c2d.cpp software_converter.cpp - LOCAL_MODULE := copybit.$(TARGET_BOARD_PLATFORM) - LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc LOCAL_CFLAGS += -DCOPYBIT_Z180=1 -DC2D_SUPPORT_DISPLAY=1 - LOCAL_MODULE_TAGS := optional + LOCAL_SRC_FILES := copybit_c2d.cpp software_converter.cpp include $(BUILD_SHARED_LIBRARY) else ifneq ($(TARGET_BOARD_PLATFORM),msm7x30) ifeq ($(TARGET_BOARD_PLATFORM),qsd8k) - include $(CLEAR_VARS) - LOCAL_PRELINK_MODULE := false - LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw - LOCAL_SHARED_LIBRARIES := liblog libmemalloc - LOCAL_SRC_FILES := software_converter.cpp copybit.cpp - LOCAL_MODULE := copybit.$(TARGET_BOARD_PLATFORM) - LOCAL_MODULE_TAGS := optional - LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc - LOCAL_CFLAGS += -D__ARM_HAVE_NEON -DCOPYBIT_QSD8K=1 + LOCAL_CFLAGS += -DCOPYBIT_QSD8K=1 -DDEBUG_MDP_ERRORS + LOCAL_SRC_FILES := software_converter.cpp copybit.cpp include $(BUILD_SHARED_LIBRARY) else - include $(CLEAR_VARS) - ifeq ($(ARCH_ARM_HAVE_NEON),true) - LOCAL_CFLAGS += -D__ARM_HAVE_NEON - endif - ifeq ($(TARGET_BOARD_PLATFORM),msm7x27a),true) - LOCAL_CFLAGS += -DTARGET_7x27A - endif - ifeq ($(TARGET_GRALLOC_USES_ASHMEM),true) - LOCAL_CFLAGS += -DUSE_ASHMEM - ifeq ($(TARGET_BOARD_PLATFORM),msm7k),true) - LOCAL_CFLAGS += -DTARGET_7x27 - endif - endif - - LOCAL_PRELINK_MODULE := false - LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw - LOCAL_SHARED_LIBRARIES := liblog libmemalloc - LOCAL_SRC_FILES := software_converter.cpp copybit.cpp - LOCAL_MODULE := copybit.$(TARGET_BOARD_PLATFORM) - LOCAL_MODULE_TAGS := optional - LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc - LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/qcom/display/libgralloc LOCAL_CFLAGS += -DCOPYBIT_MSM7K=1 + LOCAL_SRC_FILES := software_converter.cpp copybit.cpp include $(BUILD_SHARED_LIBRARY) endif endif diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index 886d12b..ee8c12e 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -60,6 +60,7 @@ struct copybit_context_t { int mFD; uint8_t mAlpha; int mFlags; + bool mBlitToFB; }; /** @@ -212,6 +213,10 @@ static void set_infos(struct copybit_context_t *dev, req->alpha = dev->mAlpha; req->transp_mask = MDP_TRANSP_NOP; req->flags = dev->mFlags | flags; + // check if we are blitting to f/b + if (COPYBIT_ENABLE == dev->mBlitToFB) { + req->flags |= MDP_MEMORY_ID_TYPE_FB; + } #if defined(COPYBIT_QSD8K) req->flags |= MDP_BLEND_FG_PREMULT; #endif @@ -229,10 +234,10 @@ static int msm_copybit(struct copybit_context_t *dev, void const *list) #if DEBUG_MDP_ERRORS struct mdp_blit_req_list const* l = (struct mdp_blit_req_list const*)list; - for (int i=0 ; icount ; i++) { + for (unsigned int i=0 ; icount ; i++) { ALOGE("%d: src={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n" " dst={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n" - " flags=%08lx" + " flags=%08x" , i, l->req[i].src.width, @@ -322,6 +327,16 @@ static int set_parameter_copybit( ctx->mFlags &= ~0x7; ctx->mFlags |= value & 0x7; break; + case COPYBIT_BLIT_TO_FRAMEBUFFER: + if (COPYBIT_ENABLE == value) { + ctx->mBlitToFB = value; + } else if (COPYBIT_DISABLE == value) { + ctx->mBlitToFB = value; + } else { + ALOGE ("%s:Invalid input for COPYBIT_BLIT_TO_FRAMEBUFFER : %d", + __FUNCTION__, value); + } + break; default: status = -EINVAL; break; @@ -391,8 +406,8 @@ static int stretch_copybit( } } - if (src_rect->l < 0 || src_rect->r > src->w || - src_rect->t < 0 || src_rect->b > src->h) { + if (src_rect->l < 0 || (uint32_t)src_rect->r > src->w || + src_rect->t < 0 || (uint32_t)src_rect->b > src->h) { // this is always invalid ALOGE ("%s : Invalid source rectangle : src_rect l %d t %d r %d b %d",\ __FUNCTION__, src_rect->l, src_rect->t, src_rect->r, src_rect->b); diff --git a/libcopybit/copybit.h b/libcopybit/copybit.h index 6384dfe..c14af74 100644 --- a/libcopybit/copybit.h +++ b/libcopybit/copybit.h @@ -52,6 +52,10 @@ enum { /* name for copybit_set_parameter */ enum { + /* Default blit destination is offline buffer */ + /* clients to set this to '1', if blitting to framebuffer */ + /* and reset to '0', after calling blit/stretch */ + COPYBIT_BLIT_TO_FRAMEBUFFER = 0, /* rotation of the source image in degrees (0 to 359) */ COPYBIT_ROTATION_DEG = 1, /* plane alpha value */ diff --git a/libgenlock/Android.mk b/libgenlock/Android.mk index 6ae8909..92ac227 100644 --- a/libgenlock/Android.mk +++ b/libgenlock/Android.mk @@ -1,14 +1,13 @@ LOCAL_PATH := $(call my-dir) - +include $(LOCAL_PATH)/../common.mk include $(CLEAR_VARS) -LOCAL_PRELINK_MODULE := false -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES) -LOCAL_SHARED_LIBRARIES := liblog libcutils -LOCAL_C_INCLUDES := hardware/qcom/display/libgralloc -LOCAL_ADDITIONAL_DEPENDENCIES := -LOCAL_SRC_FILES := genlock.cpp -LOCAL_CFLAGS:= -DLOG_TAG=\"libgenlock\" -LOCAL_MODULE_TAGS := optional -LOCAL_MODULE := libgenlock + +LOCAL_MODULE := libgenlock +LOCAL_MODULE_TAGS := optional +LOCAL_C_INCLUDES := $(common_includes) +LOCAL_SHARED_LIBRARIES := liblog libcutils +LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"libgenlock\" +LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) +LOCAL_SRC_FILES := genlock.cpp include $(BUILD_SHARED_LIBRARY) diff --git a/libgralloc/Android.mk b/libgralloc/Android.mk index 9d9c1b5..016fcbc 100644 --- a/libgralloc/Android.mk +++ b/libgralloc/Android.mk @@ -11,49 +11,31 @@ # 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. + +#gralloc module LOCAL_PATH := $(call my-dir) - -# HAL module implemenation, not prelinked and stored in -# hw/..so +include $(LOCAL_PATH)/../common.mk include $(CLEAR_VARS) -LOCAL_PRELINK_MODULE := false -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw -LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libmemalloc -LOCAL_SHARED_LIBRARIES += libgenlock libqdutils libGLESv1_CM -LOCAL_C_INCLUDES := hardware/qcom/display/liboverlay/ -LOCAL_C_INCLUDES += hardware/qcom/display/libgenlock -LOCAL_C_INCLUDES += hardware/qcom/display/libqdutils -LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM) -LOCAL_MODULE_TAGS := optional -LOCAL_CFLAGS := -DLOG_TAG=\"gralloc\" \ - -DDEBUG_CALC_FPS -Wno-missing-field-initializers -LOCAL_SRC_FILES := gpu.cpp gralloc.cpp framebuffer.cpp mapper.cpp -ifeq ($(TARGET_USES_POST_PROCESSING),true) - LOCAL_CFLAGS += -DUSES_POST_PROCESSING - LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/pp/inc -endif - -ifeq ($(TARGET_USES_MDP3), true) - LOCAL_CFLAGS += -DUSE_MDP3 -endif - -ifeq ($(TARGET_HAVE_HDMI_OUT),true) - LOCAL_CFLAGS += -DHDMI_DUAL_DISPLAY - LOCAL_SHARED_LIBRARIES += liboverlay -endif +LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM) +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_MODULE_TAGS := optional +LOCAL_C_INCLUDES := $(common_includes) +LOCAL_SHARED_LIBRARIES := $(common_libs) libmemalloc libgenlock +LOCAL_SHARED_LIBRARIES += libqdutils libGLESv1_CM +LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"gralloc\" +LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) +LOCAL_SRC_FILES := gpu.cpp gralloc.cpp framebuffer.cpp mapper.cpp include $(BUILD_SHARED_LIBRARY) #MemAlloc Library include $(CLEAR_VARS) -LOCAL_PRELINK_MODULE := false -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES) -LOCAL_C_INCLUDES := hardware/qcom/display/libqdutils -LOCAL_SHARED_LIBRARIES := liblog libcutils libutils -LOCAL_SRC_FILES := alloc_controller.cpp -LOCAL_CFLAGS:= -DLOG_TAG=\"memalloc\" -LOCAL_MODULE := libmemalloc -LOCAL_MODULE_TAGS := optional +LOCAL_MODULE := libmemalloc +LOCAL_MODULE_TAGS := optional +LOCAL_C_INCLUDES := $(common_includes) +LOCAL_SHARED_LIBRARIES := $(common_libs) libgenlock +LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"memalloc\" +LOCAL_SRC_FILES := alloc_controller.cpp ifeq ($(TARGET_USES_PMEM),true) LOCAL_SRC_FILES += pmemalloc.cpp \ ashmemalloc.cpp \ diff --git a/libgralloc/fb_priv.h b/libgralloc/fb_priv.h index 83b941a..48e5669 100644 --- a/libgralloc/fb_priv.h +++ b/libgralloc/fb_priv.h @@ -25,11 +25,6 @@ #define NO_SURFACEFLINGER_SWAPINTERVAL #define COLOR_FORMAT(x) (x & 0xFFF) // Max range for colorFormats is 0 - FFF -enum hdmi_mirroring_state { - HDMI_NO_MIRRORING, - HDMI_UI_MIRRORING, -}; - struct private_handle_t; enum { @@ -54,21 +49,11 @@ struct private_module_t { float ydpi; float fps; uint32_t swapInterval; -#if defined(__cplusplus) && defined(HDMI_DUAL_DISPLAY) - int orientation; - int videoOverlay; // VIDEO_OVERLAY - 2D or 3D - int secureVideoOverlay; // VideoOverlay is secure uint32_t currentOffset; - int enableHDMIOutput; // holds the type of external display - bool trueMirrorSupport; - bool exitHDMIUILoop; - float actionsafeWidthRatio; - float actionsafeHeightRatio; - bool hdmiStateChanged; - hdmi_mirroring_state hdmiMirroringState; - pthread_mutex_t overlayLock; - pthread_cond_t overlayPost; -#endif + bool fbPostDone; + pthread_mutex_t fbPostLock; + //Condition to inform HWC that fb_post called + pthread_cond_t fbPostCond; }; diff --git a/libgralloc/framebuffer.cpp b/libgralloc/framebuffer.cpp index 8cf5b45..9d974b4 100644 --- a/libgralloc/framebuffer.cpp +++ b/libgralloc/framebuffer.cpp @@ -43,9 +43,6 @@ #include #include -#include "overlay.h" -namespace ovutils = overlay::utils; - #define EVEN_OUT(x) if (x & 0x0001) {x--;} /** min of int a, b */ static inline int min(int a, int b) { @@ -101,403 +98,6 @@ static int fb_setUpdateRect(struct framebuffer_device_t* dev, return 0; } -#if defined(HDMI_DUAL_DISPLAY) -static int closeHDMIChannel(private_module_t* m) -{ - // XXX - when enabling HDMI -#if 0 - Overlay* pTemp = m->pobjOverlay; - if(pTemp != NULL) - pTemp->closeChannel(); -#endif - return 0; -} - -// XXX - Complete when enabling HDMI -#if 0 -static void getSecondaryDisplayDestinationInfo(private_module_t* m, overlay_rect& - rect, int& orientation) -{ - Overlay* pTemp = m->pobjOverlay; - int width = pTemp->getFBWidth(); - int height = pTemp->getFBHeight(); - int fbwidth = m->info.xres, fbheight = m->info.yres; - rect.x = 0; rect.y = 0; - rect.w = width; rect.h = height; - int rot = m->orientation; - switch(rot) { - // ROT_0 - case 0: - // ROT_180 - case HAL_TRANSFORM_ROT_180: - pTemp->getAspectRatioPosition(fbwidth, fbheight, - &rect); - if(rot == HAL_TRANSFORM_ROT_180) - orientation = HAL_TRANSFORM_ROT_180; - else - orientation = 0; - break; - // ROT_90 - case HAL_TRANSFORM_ROT_90: - // ROT_270 - case HAL_TRANSFORM_ROT_270: - //Calculate the Aspectratio for the UI - //in the landscape mode - //Width and height will be swapped as there - //is rotation - pTemp->getAspectRatioPosition(fbheight, fbwidth, - &rect); - - if(rot == HAL_TRANSFORM_ROT_90) - orientation = HAL_TRANSFORM_ROT_270; - else if(rot == HAL_TRANSFORM_ROT_270) - orientation = HAL_TRANSFORM_ROT_90; - break; - } - return; -} -#endif - -/* Determine overlay state based on whether hardware supports true UI - mirroring and whether video is playing or not */ -static ovutils::eOverlayState getOverlayState(struct private_module_t* module) -{ - overlay2::Overlay& ov = *(Overlay::getInstance()); - - // Default to existing state - ovutils::eOverlayState state = ov.getState(); - - // Sanity check - if (!module) { - ALOGE("%s: NULL module", __FUNCTION__); - return state; - } - - // Check if video is playing or not - if (module->videoOverlay) { - // Video is playing, check if hardware supports true UI mirroring - if (module->trueMirrorSupport) { - // True UI mirroring is supported by hardware - if (ov.getState() == ovutils::OV_2D_VIDEO_ON_PANEL) { - // Currently playing 2D video - state = ovutils::OV_2D_TRUE_UI_MIRROR; - } else if (ov.getState() == ovutils::OV_3D_VIDEO_ON_2D_PANEL) { - // Currently playing M3D video - // FIXME: Support M3D true UI mirroring - state = ovutils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV; - } - } else { - // True UI mirroring is not supported by hardware - if (ov.getState() == ovutils::OV_2D_VIDEO_ON_PANEL) { - // Currently playing 2D video - state = ovutils::OV_2D_VIDEO_ON_PANEL_TV; - } else if (ov.getState() == ovutils::OV_3D_VIDEO_ON_2D_PANEL) { - // Currently playing M3D video - state = ovutils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV; - } - } - } else { - // Video is not playing, true UI mirroring support is irrelevant - state = ovutils::OV_UI_MIRROR; - } - - return state; -} - -/* Set overlay state */ -static void setOverlayState(ovutils::eOverlayState state) -{ - overlay2::Overlay& ov = *(Overlay::getInstance()); - ov.setState(state); -} - -static void *hdmi_ui_loop(void *ptr) -{ - private_module_t* m = reinterpret_cast(ptr); - while (1) { - pthread_mutex_lock(&m->overlayLock); - while(!(m->hdmiStateChanged)) - pthread_cond_wait(&(m->overlayPost), &(m->overlayLock)); - - m->hdmiStateChanged = false; - if (m->exitHDMIUILoop) { - pthread_mutex_unlock(&m->overlayLock); - return NULL; - } - - // No need to mirror UI if HDMI is not on - if (!m->enableHDMIOutput) { - ALOGE_IF(FB_DEBUG, "%s: hdmi not ON", __FUNCTION__); - pthread_mutex_unlock(&m->overlayLock); - continue; - } - - overlay2::OverlayMgr* ovMgr = - overlay2::OverlayMgrSingleton::getOverlayMgr(); - overlay2::Overlay& ov = ovMgr->ov(); - - // Set overlay state - ovutils::eOverlayState state = getOverlayState(m); - setOverlayState(state); - - // Determine the RGB pipe for UI depending on the state - ovutils::eDest dest = ovutils::OV_PIPE_ALL; - if (state == ovutils::OV_2D_TRUE_UI_MIRROR) { - // True UI mirroring state: external RGB pipe is OV_PIPE2 - dest = ovutils::OV_PIPE2; - } else if (state == ovutils::OV_UI_MIRROR) { - // UI-only mirroring state: external RGB pipe is OV_PIPE0 - dest = ovutils::OV_PIPE0; - } else { - // No UI in this case - pthread_mutex_unlock(&m->overlayLock); - continue; - } - - if (m->hdmiMirroringState == HDMI_UI_MIRRORING) { - int alignedW = ALIGN(m->info.xres, 32); - - private_handle_t const* hnd = - reinterpret_cast(m->framebuffer); - unsigned int width = alignedW; - unsigned int height = hnd->height; - unsigned int format = hnd->format; - unsigned int size = hnd->size/m->numBuffers; - - ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE; - // External display connected during secure video playback - // Open secure UI session - // NOTE: when external display is already connected and then secure - // playback is started, we dont have to do anything - if (m->secureVideoOverlay) { - ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_SECURE_OVERLAY_SESSION); - } - - ovutils::Whf whf(width, height, format, size); - ovutils::PipeArgs parg(mdpFlags, - ovutils::OVERLAY_TRANSFORM_0, - whf, - ovutils::WAIT, - ovutils::ZORDER_0, - ovutils::IS_FG_OFF, - ovutils::ROT_FLAG_ENABLED); - ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg }; - bool ret = ov.setSource(pargs, dest); - if (!ret) { - ALOGE("%s setSource failed", __FUNCTION__); - } - - // we need to communicate m->orientation that will get some - // modifications within setParameter func. - // FIXME that is ugly. - const ovutils::Params prms (ovutils::OVERLAY_TRANSFORM_UI, - m->orientation); - ov.setParameter(prms, dest); - if (!ret) { - ALOGE("%s setParameter failed transform", __FUNCTION__); - } - - // x,y,w,h - ovutils::Dim dcrop(0, 0, m->info.xres, m->info.yres); - ov.setMemoryId(m->framebuffer->fd, dest); - ret = ov.setCrop(dcrop, dest); - if (!ret) { - ALOGE("%s setCrop failed", __FUNCTION__); - } - - ovutils::Dim pdim (m->info.xres, - m->info.yres, - 0, - 0, - m->orientation); - ret = ov.setPosition(pdim, dest); - if (!ret) { - ALOGE("%s setPosition failed", __FUNCTION__); - } - - if (!ov.commit(dest)) { - ALOGE("%s commit fails", __FUNCTION__); - } - - ret = ov.queueBuffer(m->currentOffset, dest); - if (!ret) { - ALOGE("%s queueBuffer failed", __FUNCTION__); - } - } else { - setOverlayState(ovutils::OV_CLOSED); - } - pthread_mutex_unlock(&m->overlayLock); - } - return NULL; -} - -static int fb_videoOverlayStarted(struct framebuffer_device_t* dev, int started) -{ - ALOGE_IF(FB_DEBUG, "%s started=%d", __FUNCTION__, started); - private_module_t* m = reinterpret_cast( - dev->common.module); - pthread_mutex_lock(&m->overlayLock); - if(started != m->videoOverlay) { - m->videoOverlay = started; - m->hdmiStateChanged = true; - if (!m->trueMirrorSupport) { - if (started) { - m->hdmiMirroringState = HDMI_NO_MIRRORING; - ovutils::eOverlayState state = getOverlayState(m); - setOverlayState(state); - } else if (m->enableHDMIOutput) - m->hdmiMirroringState = HDMI_UI_MIRRORING; - } else { - if (m->videoOverlay == VIDEO_3D_OVERLAY_STARTED) { - ALOGE_IF(FB_DEBUG, "3D Video Started, stop mirroring!"); - m->hdmiMirroringState = HDMI_NO_MIRRORING; - ovutils::eOverlayState state = getOverlayState(m); - setOverlayState(state); - } - else if (m->enableHDMIOutput) { - m->hdmiMirroringState = HDMI_UI_MIRRORING; - } - } - } - pthread_mutex_unlock(&m->overlayLock); - return 0; -} - -static int fb_enableHDMIOutput(struct framebuffer_device_t* dev, int externaltype) -{ - ALOGE_IF(FB_DEBUG, "%s externaltype=%d", __FUNCTION__, externaltype); - private_module_t* m = reinterpret_cast( - dev->common.module); - pthread_mutex_lock(&m->overlayLock); - //Check if true mirroring can be supported - m->trueMirrorSupport = ovutils::FrameBufferInfo::getInstance()->supportTrueMirroring(); - m->enableHDMIOutput = externaltype; - if(externaltype) { - if (m->trueMirrorSupport) { - m->hdmiMirroringState = HDMI_UI_MIRRORING; - } else { - if(!m->videoOverlay) - m->hdmiMirroringState = HDMI_UI_MIRRORING; - } - } else if (!externaltype) { - // Either HDMI is disconnected or suspend occurred - m->hdmiMirroringState = HDMI_NO_MIRRORING; - ovutils::eOverlayState state = getOverlayState(m); - setOverlayState(state); - } - m->hdmiStateChanged = true; - pthread_cond_signal(&(m->overlayPost)); - pthread_mutex_unlock(&m->overlayLock); - return 0; -} - -static int fb_orientationChanged(struct framebuffer_device_t* dev, int orientation) -{ - private_module_t* m = reinterpret_cast( - dev->common.module); - pthread_mutex_lock(&m->overlayLock); - neworientation = orientation; - pthread_mutex_unlock(&m->overlayLock); - return 0; -} - -static int handle_open_secure_start(private_module_t* m) { - pthread_mutex_lock(&m->overlayLock); - m->hdmiMirroringState = HDMI_NO_MIRRORING; - m->secureVideoOverlay = true; - pthread_mutex_unlock(&m->overlayLock); - return 0; -} - -static int handle_open_secure_end(private_module_t* m) { - pthread_mutex_lock(&m->overlayLock); - if (m->enableHDMIOutput) { - if (m->trueMirrorSupport) { - m->hdmiMirroringState = HDMI_UI_MIRRORING; - } else if(!m->videoOverlay) { - m->hdmiMirroringState = HDMI_UI_MIRRORING; - } - m->hdmiStateChanged = true; - pthread_cond_signal(&(m->overlayPost)); - } - pthread_mutex_unlock(&m->overlayLock); - return 0; -} - -static int handle_close_secure_start(private_module_t* m) { - pthread_mutex_lock(&m->overlayLock); - m->hdmiMirroringState = HDMI_NO_MIRRORING; - m->secureVideoOverlay = false; - pthread_mutex_unlock(&m->overlayLock); - return 0; -} - -static int handle_close_secure_end(private_module_t* m) { - pthread_mutex_lock(&m->overlayLock); - if (m->enableHDMIOutput) { - if (m->trueMirrorSupport) { - m->hdmiMirroringState = HDMI_UI_MIRRORING; - } else if(!m->videoOverlay) { - m->hdmiMirroringState = HDMI_UI_MIRRORING; - } - m->hdmiStateChanged = true; - pthread_cond_signal(&(m->overlayPost)); - } - pthread_mutex_unlock(&m->overlayLock); - return 0; -} -#endif - - - -/* fb_perform - used to add custom event and handle them in fb HAL - * Used for external display related functions as of now - */ -static int fb_perform(struct framebuffer_device_t* dev, int event, int value) -{ - private_module_t* m = reinterpret_cast( - dev->common.module); - switch(event) { -#if defined(HDMI_DUAL_DISPLAY) - case EVENT_EXTERNAL_DISPLAY: - fb_enableHDMIOutput(dev, value); - break; - case EVENT_VIDEO_OVERLAY: - fb_videoOverlayStarted(dev, value); - break; - case EVENT_ORIENTATION_CHANGE: - fb_orientationChanged(dev, value); - break; - case EVENT_OVERLAY_STATE_CHANGE: - if (value == OVERLAY_STATE_CHANGE_START) { - // When state change starts, get a lock on overlay - pthread_mutex_lock(&m->overlayLock); - } else if (value == OVERLAY_STATE_CHANGE_END) { - // When state change is complete, unlock overlay - pthread_mutex_unlock(&m->overlayLock); - } - break; - case EVENT_OPEN_SECURE_START: - handle_open_secure_start(m); - break; - case EVENT_OPEN_SECURE_END: - handle_open_secure_end(m); - break; - case EVENT_CLOSE_SECURE_START: - handle_close_secure_start(m); - break; - case EVENT_CLOSE_SECURE_END: - handle_close_secure_end(m); - break; -#endif - default: - ALOGE("In %s: UNKNOWN Event = %d!!!", __FUNCTION__, event); - break; - } - return 0; -} - - static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) { if (private_handle_t::validate(buffer) < 0) @@ -511,6 +111,7 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) private_module_t* m = reinterpret_cast(dev->common.module); + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { genlock_lock_buffer(hnd, GENLOCK_READ_LOCK, GENLOCK_MAX_TIMEOUT); @@ -520,6 +121,14 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) } const size_t offset = hnd->base - m->framebuffer->base; + // frame ready to be posted, signal so that hwc can update External + // display + pthread_mutex_lock(&m->fbPostLock); + m->currentOffset = offset; + m->fbPostDone = true; + pthread_cond_signal(&m->fbPostCond); + pthread_mutex_unlock(&m->fbPostLock); + m->info.activate = FB_ACTIVATE_VBL; m->info.yoffset = offset / m->finfo.line_length; if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) { @@ -580,11 +189,12 @@ int mapFrameBufferLocked(struct private_module_t* module) info.yoffset = 0; info.activate = FB_ACTIVATE_NOW; - /* Interpretation of offset for color fields: All offsets are from the right, - * inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you - * can use the offset as right argument to <<). A pixel afterwards is a bit - * stream and is written to video memory as that unmodified. This implies - * big-endian byte order if bits_per_pixel is greater than 8. + /* Interpretation of offset for color fields: All offsets are from the + * right, inside a "pixel" value, which is exactly 'bits_per_pixel' wide + * (means: you can use the offset as right argument to <<). A pixel + * afterwards is a bit stream and is written to video memory as that + * unmodified. This implies big-endian byte order if bits_per_pixel is + * greater than 8. */ if(info.bits_per_pixel == 32) { @@ -601,10 +211,11 @@ int mapFrameBufferLocked(struct private_module_t* module) info.transp.offset = 0; info.transp.length = 8; - /* Note: the GL driver does not have a r=8 g=8 b=8 a=0 config, so if we do - * not use the MDP for composition (i.e. hw composition == 0), ask for - * RGBA instead of RGBX. */ - if (property_get("debug.sf.hw", property, NULL) > 0 && atoi(property) == 0) + /* Note: the GL driver does not have a r=8 g=8 b=8 a=0 config, so if we + * do not use the MDP for composition (i.e. hw composition == 0), ask + * for RGBA instead of RGBX. */ + if (property_get("debug.sf.hw", property, NULL) > 0 && + atoi(property) == 0) module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888; else if(property_get("debug.composition.type", property, NULL) > 0 && (strncmp(property, "mdp", 3) == 0)) @@ -628,7 +239,8 @@ int mapFrameBufferLocked(struct private_module_t* module) } //adreno needs 4k aligned offsets. Max hole size is 4096-1 - int size = roundUpToPageSize(info.yres * info.xres * (info.bits_per_pixel/8)); + int size = roundUpToPageSize(info.yres * info.xres * + (info.bits_per_pixel/8)); /* * Request NUM_BUFFERS screens (at least 2 for page flipping) @@ -739,9 +351,9 @@ int mapFrameBufferLocked(struct private_module_t* module) size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres)* module->numBuffers; module->framebuffer = new private_handle_t(fd, fbSize, - private_handle_t::PRIV_FLAGS_USES_PMEM, - BUFFER_TYPE_UI, - module->fbFormat, info.xres, info.yres); + private_handle_t::PRIV_FLAGS_USES_PMEM, + BUFFER_TYPE_UI, + module->fbFormat, info.xres, info.yres); void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (vaddr == MAP_FAILED) { ALOGE("Error mapping the framebuffer (%s)", strerror(errno)); @@ -749,20 +361,10 @@ int mapFrameBufferLocked(struct private_module_t* module) } module->framebuffer->base = intptr_t(vaddr); memset(vaddr, 0, fbSize); - -#if defined(HDMI_DUAL_DISPLAY) - /* Overlay for HDMI*/ - pthread_mutex_init(&(module->overlayLock), NULL); - pthread_cond_init(&(module->overlayPost), NULL); module->currentOffset = 0; - module->exitHDMIUILoop = false; - module->hdmiStateChanged = false; - pthread_t hdmiUIThread; - pthread_create(&hdmiUIThread, NULL, &hdmi_ui_loop, (void *) module); - module->hdmiMirroringState = HDMI_NO_MIRRORING; - module->trueMirrorSupport = false; -#endif - + module->fbPostDone = false; + pthread_mutex_init(&(module->fbPostLock), NULL); + pthread_cond_init(&(module->fbPostCond), NULL); return 0; } @@ -779,14 +381,6 @@ static int mapFrameBuffer(struct private_module_t* module) static int fb_close(struct hw_device_t *dev) { fb_context_t* ctx = (fb_context_t*)dev; -#if defined(HDMI_DUAL_DISPLAY) - private_module_t* m = reinterpret_cast( - ctx->device.common.module); - pthread_mutex_lock(&m->overlayLock); - m->exitHDMIUILoop = true; - pthread_cond_signal(&(m->overlayPost)); - pthread_mutex_unlock(&m->overlayLock); -#endif if (ctx) { free(ctx); } @@ -829,8 +423,10 @@ int fb_device_open(hw_module_t const* module, const char* name, const_cast(dev->device.xdpi) = m->xdpi; const_cast(dev->device.ydpi) = m->ydpi; const_cast(dev->device.fps) = m->fps; - const_cast(dev->device.minSwapInterval) = PRIV_MIN_SWAP_INTERVAL; - const_cast(dev->device.maxSwapInterval) = PRIV_MAX_SWAP_INTERVAL; + const_cast(dev->device.minSwapInterval) = + PRIV_MIN_SWAP_INTERVAL; + const_cast(dev->device.maxSwapInterval) = + PRIV_MAX_SWAP_INTERVAL; const_cast(dev->device.numFramebuffers) = m->numBuffers; if (m->finfo.reserved[0] == 0x5444 && m->finfo.reserved[1] == 0x5055) { diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h index 7c530fa..9dfcd32 100644 --- a/libgralloc/gralloc_priv.h +++ b/libgralloc/gralloc_priv.h @@ -112,7 +112,7 @@ enum { HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED = 0x7FA30C03, #endif HAL_PIXEL_FORMAT_YCbCr_420_SP = 0x109, - HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO = 0x10A, + HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO = 0x7FA30C01, HAL_PIXEL_FORMAT_YCrCb_422_SP = 0x10B, HAL_PIXEL_FORMAT_R_8 = 0x10D, HAL_PIXEL_FORMAT_RG_88 = 0x10E, diff --git a/libgralloc/ionalloc.cpp b/libgralloc/ionalloc.cpp index 7c8fbf4..80f448f 100644 --- a/libgralloc/ionalloc.cpp +++ b/libgralloc/ionalloc.cpp @@ -85,8 +85,7 @@ int IonAlloc::alloc_buffer(alloc_data& data) if(data.uncached) { // Use the sync FD to alloc and map // when we need uncached memory - // XXX: Change O_SYNC to O_DSYNC when available in bionic - ionSyncFd = open(ION_DEVICE, O_RDONLY|O_SYNC); + ionSyncFd = open(ION_DEVICE, O_RDONLY|O_DSYNC); if(ionSyncFd < 0) { ALOGE("%s: Failed to open ion device - %s", __FUNCTION__, strerror(errno)); diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk index 018de6c..5067a2a 100644 --- a/libhwcomposer/Android.mk +++ b/libhwcomposer/Android.mk @@ -1,18 +1,15 @@ LOCAL_PATH := $(call my-dir) +include $(LOCAL_PATH)/../common.mk include $(CLEAR_VARS) -LOCAL_PRELINK_MODULE := false -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw -LOCAL_SHARED_LIBRARIES := liblog libcutils libhardware libutils -LOCAL_SHARED_LIBRARIES += libEGL liboverlay libgenlock libqdutils -LOCAL_SRC_FILES := hwc.cpp \ - hwc_overlay.cpp \ - hwc_utils.cpp -LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM) -LOCAL_C_INCLUDES := hardware/qcom/display/libgralloc -LOCAL_C_INCLUDES += hardware/qcom/display/libgenlock -LOCAL_C_INCLUDES += hardware/qcom/display/liboverlay -LOCAL_C_INCLUDES += hardware/qcom/display/libqdutils -LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).hwcomposer\" - -LOCAL_MODULE_TAGS := optional +LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM) +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_MODULE_TAGS := optional +LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes) +LOCAL_SHARED_LIBRARIES := $(common_libs) libEGL liboverlay libgenlock \ + libqdutils libhardware_legacy libdl libmemalloc +LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"hwcomposer\" +LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) +LOCAL_SRC_FILES := hwc.cpp hwc_video.cpp hwc_utils.cpp \ + hwc_uimirror.cpp hwc_ext_observer.cpp \ + hwc_copybit.cpp include $(BUILD_SHARED_LIBRARY) diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp index a5e31ef..34972b7 100644 --- a/libhwcomposer/hwc.cpp +++ b/libhwcomposer/hwc.cpp @@ -20,9 +20,11 @@ #include #include -#include #include "hwc_utils.h" +#include "hwc_video.h" +#include "hwc_uimirror.h" +#include "hwc_copybit.h" using namespace qhwc; @@ -65,21 +67,28 @@ static void hwc_registerProcs(struct hwc_composer_device* dev, static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) { hwc_context_t* ctx = (hwc_context_t*)(dev); + ctx->overlayInUse = false; + + //Prepare is called after a vsync, so unlock previous buffers here. + ctx->qbuf->unlockAllPrevious(); + if (LIKELY(list)) { getLayerStats(ctx, list); - cleanOverlays(ctx); - for (int i=list->numHwLayers-1; i >= 0 ; i--) { - private_handle_t *hnd = - (private_handle_t *)list->hwLayers[i].handle; - if (isSkipLayer(&list->hwLayers[i])) { - break; - } else if(isYuvBuffer(hnd)) { - handleYUV(ctx,&list->hwLayers[i]); - } else { - list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; - } + if(VideoOverlay::prepare(ctx, list)) { + ctx->overlayInUse = true; + //Nothing here + } else if(UIMirrorOverlay::prepare(ctx, list)) { + ctx->overlayInUse = true; + } else if (0) { + //Other features + ctx->overlayInUse = true; + } else { // Else set this flag to false, otherwise video cases + // fail in non-overlay targets. + ctx->overlayInUse = false; } + CopyBit::prepare(ctx, list); } + return 0; } @@ -91,21 +100,18 @@ static int hwc_set(hwc_composer_device_t *dev, int ret = 0; hwc_context_t* ctx = (hwc_context_t*)(dev); if (LIKELY(list)) { - for (size_t i=0; inumHwLayers; i++) { - if (list->hwLayers[i].flags & HWC_SKIP_LAYER) { - continue; - } else if (list->hwLayers[i].compositionType == HWC_OVERLAY) { - drawLayerUsingOverlay(ctx, &(list->hwLayers[i])); - } - } - //XXX: Handle vsync with FBIO_WAITFORVSYNC ioctl - //All other operations (including pan display) should be NOWAIT + VideoOverlay::draw(ctx, list); + CopyBit::draw(ctx, list, (EGLDisplay)dpy, (EGLSurface)sur); EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur); + UIMirrorOverlay::draw(ctx); } else { - //XXX: put in a wrapper for non overlay targets - setOverlayState(ctx, ovutils::OV_CLOSED); + ctx->mOverlay->setState(ovutils::OV_CLOSED); + ctx->qbuf->unlockAllPrevious(); } - ctx->qbuf->unlockAllPrevious(); + + if(!ctx->overlayInUse) + ctx->mOverlay->setState(ovutils::OV_CLOSED); + return ret; } diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp new file mode 100644 index 0000000..adcd4dc --- /dev/null +++ b/libhwcomposer/hwc_copybit.cpp @@ -0,0 +1,453 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2012, Code Aurora Forum. All rights reserved. + * + * Not a Contribution, Apache license notifications and license are retained + * for attribution purposes only. + * + * 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. + */ + +#include "hwc_copybit.h" +#include "hwc_copybitEngine.h" + +namespace qhwc { + + +struct range { + int current; + int end; +}; +struct region_iterator : public copybit_region_t { + + region_iterator(hwc_region_t region) { + mRegion = region; + r.end = region.numRects; + r.current = 0; + this->next = iterate; + } + +private: + static int iterate(copybit_region_t const * self, copybit_rect_t* rect){ + if (!self || !rect) { + ALOGE("iterate invalid parameters"); + return 0; + } + + region_iterator const* me = + static_cast(self); + if (me->r.current != me->r.end) { + rect->l = me->mRegion.rects[me->r.current].left; + rect->t = me->mRegion.rects[me->r.current].top; + rect->r = me->mRegion.rects[me->r.current].right; + rect->b = me->mRegion.rects[me->r.current].bottom; + me->r.current++; + return 1; + } + return 0; + } + + hwc_region_t mRegion; + mutable range r; +}; + +// Initialize CopyBit Class Static Mmembers. +functype_eglGetRenderBufferANDROID CopyBit::LINK_eglGetRenderBufferANDROID + = NULL; +functype_eglGetCurrentSurface CopyBit::LINK_eglGetCurrentSurface = NULL; +int CopyBit::sYuvCount = 0; +int CopyBit::sYuvLayerIndex = -1; +bool CopyBit::sIsModeOn = false; +bool CopyBit::sIsLayerSkip = false; +void* CopyBit::egl_lib = NULL; + +void CopyBit::updateEglHandles(void* egl_lib) +{ + if(egl_lib != NULL) { + *(void **)&CopyBit::LINK_eglGetRenderBufferANDROID = + ::dlsym(egl_lib, "eglGetRenderBufferANDROID"); + *(void **)&CopyBit::LINK_eglGetCurrentSurface = + ::dlsym(egl_lib, "eglGetCurrentSurface"); + }else { + LINK_eglGetCurrentSurface = NULL; + LINK_eglGetCurrentSurface = NULL; + } +} + +bool CopyBit::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) { + for (int i=list->numHwLayers-1; i >= 0 ; i--) { + private_handle_t *hnd = + (private_handle_t *)list->hwLayers[i].handle; + if (isSkipLayer(&list->hwLayers[i])) { + break; + } else if(canUseCopybit(ctx, list, getYuvCount()) + && !ctx->overlayInUse){ + list->hwLayers[i].compositionType = HWC_USE_COPYBIT; + } else { + list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; + } + } + return true; +} +bool CopyBit::draw(hwc_context_t *ctx, hwc_layer_list_t *list, EGLDisplay dpy, + EGLSurface sur){ + for (size_t i=0; inumHwLayers; i++) { + if (list->hwLayers[i].flags & HWC_SKIP_LAYER) { + continue; + } else if (list->hwLayers[i].compositionType == HWC_USE_COPYBIT) { + drawLayerUsingCopybit(ctx, &(list->hwLayers[i]), + (EGLDisplay)dpy, + (EGLSurface)sur, + LINK_eglGetRenderBufferANDROID, + LINK_eglGetCurrentSurface); + } + } + return true; +} + +int CopyBit::drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_t *layer, + EGLDisplay dpy, + EGLSurface surface, + functype_eglGetRenderBufferANDROID& LINK_eglGetRenderBufferANDROID, + functype_eglGetCurrentSurface LINK_eglGetCurrentSurface) +{ + hwc_context_t* ctx = (hwc_context_t*)(dev); + if(!ctx) { + ALOGE("%s: null context ", __FUNCTION__); + return -1; + } + + private_handle_t *hnd = (private_handle_t *)layer->handle; + if(!hnd) { + ALOGE("%s: invalid handle", __FUNCTION__); + return -1; + } + + // Lock this buffer for read. + genlock_lock_type lockType = GENLOCK_READ_LOCK; + int err = genlock_lock_buffer(hnd, lockType, GENLOCK_MAX_TIMEOUT); + if (GENLOCK_FAILURE == err) { + ALOGE("%s: genlock_lock_buffer(READ) failed", __FUNCTION__); + return -1; + } + //render buffer + EGLSurface eglSurface = LINK_eglGetCurrentSurface(EGL_DRAW); + android_native_buffer_t *renderBuffer = + (android_native_buffer_t *)LINK_eglGetRenderBufferANDROID(dpy, eglSurface); + if (!renderBuffer) { + ALOGE("%s: eglGetRenderBuffer returned NULL buffer", __FUNCTION__); + genlock_unlock_buffer(hnd); + return -1; + } + private_handle_t *fbHandle = (private_handle_t *)renderBuffer->handle; + if(!fbHandle) { + ALOGE("%s: Framebuffer handle is NULL", __FUNCTION__); + genlock_unlock_buffer(hnd); + return -1; + } + + // Set the copybit source: + copybit_image_t src; + src.w = hnd->width; + src.h = hnd->height; + src.format = hnd->format; + src.base = (void *)hnd->base; + src.handle = (native_handle_t *)layer->handle; + src.horiz_padding = src.w - hnd->width; + // Initialize vertical padding to zero for now, + // this needs to change to accomodate vertical stride + // if needed in the future + src.vert_padding = 0; + // Remove the srcBufferTransform if any + layer->transform = (layer->transform & FINAL_TRANSFORM_MASK); + + // Copybit source rect + hwc_rect_t sourceCrop = layer->sourceCrop; + copybit_rect_t srcRect = {sourceCrop.left, sourceCrop.top, + sourceCrop.right, + sourceCrop.bottom}; + + // Copybit destination rect + hwc_rect_t displayFrame = layer->displayFrame; + copybit_rect_t dstRect = {displayFrame.left, displayFrame.top, + displayFrame.right, + displayFrame.bottom}; + + // Copybit dst + copybit_image_t dst; + dst.w = ALIGN(fbHandle->width,32); + dst.h = fbHandle->height; + dst.format = fbHandle->format; + dst.base = (void *)fbHandle->base; + dst.handle = (native_handle_t *)renderBuffer->handle; + + copybit_device_t *copybit = ctx->mCopybitEngine->getEngine(); + + int32_t screen_w = displayFrame.right - displayFrame.left; + int32_t screen_h = displayFrame.bottom - displayFrame.top; + int32_t src_crop_width = sourceCrop.right - sourceCrop.left; + int32_t src_crop_height = sourceCrop.bottom -sourceCrop.top; + + // Copybit dst + float copybitsMaxScale = + (float)copybit->get(copybit,COPYBIT_MAGNIFICATION_LIMIT); + float copybitsMinScale = + (float)copybit->get(copybit,COPYBIT_MINIFICATION_LIMIT); + + if((layer->transform == HWC_TRANSFORM_ROT_90) || + (layer->transform == HWC_TRANSFORM_ROT_270)) { + //swap screen width and height + int tmp = screen_w; + screen_w = screen_h; + screen_h = tmp; + } + private_handle_t *tmpHnd = NULL; + + if(screen_w <=0 || screen_h<=0 ||src_crop_width<=0 || src_crop_height<=0 ) { + ALOGE("%s: wrong params for display screen_w=%d src_crop_width=%d \ + screen_w=%d src_crop_width=%d", __FUNCTION__, screen_w, + src_crop_width,screen_w,src_crop_width); + genlock_unlock_buffer(hnd); + return -1; + } + + float dsdx = (float)screen_w/src_crop_width; + float dtdy = (float)screen_h/src_crop_height; + + float scaleLimitMax = copybitsMaxScale * copybitsMaxScale; + float scaleLimitMin = copybitsMinScale * copybitsMinScale; + if(dsdx > scaleLimitMax || + dtdy > scaleLimitMax || + dsdx < 1/scaleLimitMin || + dtdy < 1/scaleLimitMin) { + ALOGE("%s: greater than max supported size dsdx=%f dtdy=%f \ + scaleLimitMax=%f scaleLimitMin=%f", __FUNCTION__,dsdx,dtdy, + scaleLimitMax,1/scaleLimitMin); + genlock_unlock_buffer(hnd); + return -1; + } + if(dsdx > copybitsMaxScale || + dtdy > copybitsMaxScale || + dsdx < 1/copybitsMinScale || + dtdy < 1/copybitsMinScale){ + // The requested scale is out of the range the hardware + // can support. + ALOGE("%s:%d::Need to scale twice dsdx=%f, dtdy=%f,copybitsMaxScale=%f,\ + copybitsMinScale=%f,screen_w=%d,screen_h=%d \ + src_crop_width=%d src_crop_height=%d",__FUNCTION__,__LINE__, + dsdx,dtdy,copybitsMaxScale,1/copybitsMinScale,screen_w,screen_h, + src_crop_width,src_crop_height); + + //Driver makes width and height as even + //that may cause wrong calculation of the ratio + //in display and crop.Hence we make + //crop width and height as even. + src_crop_width = (src_crop_width/2)*2; + src_crop_height = (src_crop_height/2)*2; + + int tmp_w = src_crop_width; + int tmp_h = src_crop_height; + + if (dsdx > copybitsMaxScale || dtdy > copybitsMaxScale ){ + tmp_w = src_crop_width*copybitsMaxScale; + tmp_h = src_crop_height*copybitsMaxScale; + }else if (dsdx < 1/copybitsMinScale ||dtdy < 1/copybitsMinScale ){ + tmp_w = src_crop_width/copybitsMinScale; + tmp_h = src_crop_height/copybitsMinScale; + tmp_w = (tmp_w/2)*2; + tmp_h = (tmp_h/2)*2; + } + ALOGE("%s:%d::tmp_w = %d,tmp_h = %d",__FUNCTION__,__LINE__,tmp_w,tmp_h); + + int usage = GRALLOC_USAGE_PRIVATE_MM_HEAP; + + if (0 == alloc_buffer(&tmpHnd, tmp_w, tmp_h, fbHandle->format, usage)){ + copybit_image_t tmp_dst; + copybit_rect_t tmp_rect; + tmp_dst.w = tmp_w; + tmp_dst.h = tmp_h; + tmp_dst.format = tmpHnd->format; + tmp_dst.handle = tmpHnd; + tmp_dst.horiz_padding = src.horiz_padding; + tmp_dst.vert_padding = src.vert_padding; + tmp_rect.l = 0; + tmp_rect.t = 0; + tmp_rect.r = tmp_dst.w; + tmp_rect.b = tmp_dst.h; + //create one clip region + hwc_rect tmp_hwc_rect = {0,0,tmp_rect.r,tmp_rect.b}; + hwc_region_t tmp_hwc_reg = {1,(hwc_rect_t const*)&tmp_hwc_rect}; + region_iterator tmp_it(tmp_hwc_reg); + copybit->set_parameter(copybit,COPYBIT_TRANSFORM,0); + // TODO : alpha not defined , fix this + // copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, + // (layer->blending == HWC_BLENDING_NONE) ? -1 : layer->alpha); + err = copybit->stretch(copybit,&tmp_dst, &src, &tmp_rect, + &srcRect, &tmp_it); + if(err < 0){ + ALOGE("%s:%d::tmp copybit stretch failed",__FUNCTION__, + __LINE__); + if(tmpHnd) + free_buffer(tmpHnd); + genlock_unlock_buffer(hnd); + return err; + } + // copy new src and src rect crop + src = tmp_dst; + srcRect = tmp_rect; + } + } + // Copybit region + hwc_region_t region = layer->visibleRegionScreen; + region_iterator copybitRegion(region); + + copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_WIDTH, + renderBuffer->width); + copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_HEIGHT, + renderBuffer->height); + copybit->set_parameter(copybit, COPYBIT_TRANSFORM, + layer->transform); + // TODO : alpha not defined , fix this + // copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, + // (layer->blending == HWC_BLENDING_NONE) ? -1 : layer->alpha); + copybit->set_parameter(copybit, COPYBIT_PREMULTIPLIED_ALPHA, + (layer->blending == HWC_BLENDING_PREMULT)? + COPYBIT_ENABLE : COPYBIT_DISABLE); + copybit->set_parameter(copybit, COPYBIT_DITHER, + (dst.format == HAL_PIXEL_FORMAT_RGB_565)? + COPYBIT_ENABLE : COPYBIT_DISABLE); + copybit->set_parameter(copybit, COPYBIT_BLIT_TO_FRAMEBUFFER, + COPYBIT_ENABLE); + err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect, + ©bitRegion); + copybit->set_parameter(copybit, COPYBIT_BLIT_TO_FRAMEBUFFER, + COPYBIT_DISABLE); + + if(tmpHnd) + free_buffer(tmpHnd); + + if(err < 0) + ALOGE("%s: copybit stretch failed",__FUNCTION__); + + // Unlock this buffer since copybit is done with it. + err = genlock_unlock_buffer(hnd); + if (GENLOCK_FAILURE == err) { + ALOGE("%s: genlock_unlock_buffer failed", __FUNCTION__); + } + + return err; +} + +void CopyBit::getLayerResolution(const hwc_layer_t* layer, int& width, + int& height) +{ + hwc_rect_t displayFrame = layer->displayFrame; + + width = displayFrame.right - displayFrame.left; + height = displayFrame.bottom - displayFrame.top; +} + +bool CopyBit::canUseCopybit(hwc_context_t *ctx, const hwc_layer_list_t* list, + const int numYUVBuffers) +{ + // XXX : TODO , currently returning false for MDP4 targets, + // This has to be modified after adding C2D support. + if(ctx->hasOverlay) + return false; + + framebuffer_device_t* fbDev = ctx->mFbDevice->getFb(); + if(!fbDev) { + ALOGE("ERROR: canUseCopybit : fb device is invalid"); + return false; + } + + if (!list) + return false; + + // If , couldnt link to adreno library return false. + if(LINK_eglGetRenderBufferANDROID == NULL || + LINK_eglGetCurrentSurface == NULL ) + return false; + + if(!ctx->hasOverlay) { + if (numYUVBuffers) + return true; + } + + int fb_w = fbDev->width; + int fb_h = fbDev->height; + + /* + * Use copybit only when we need to blit + * max 2 full screen sized regions + */ + + unsigned int renderArea = 0; + + for(unsigned int i = 0; i < list->numHwLayers; i++ ) { + int w, h; + getLayerResolution(&list->hwLayers[i], w, h); + renderArea += w*h; + } + + return (renderArea <= (2 * fb_w * fb_h)); +} +void CopyBit::openEglLibAndGethandle() +{ + egl_lib = ::dlopen("libEGL_adreno200.so", RTLD_GLOBAL | RTLD_LAZY); + if (!egl_lib) { + return; + } + updateEglHandles(egl_lib); +} +void CopyBit::closeEglLib() +{ + if(egl_lib) + ::dlclose(egl_lib); + + egl_lib = NULL; + updateEglHandles(NULL); +} + + + +//CopybitEngine Class functions +CopybitEngine* CopybitEngine::sInstance = 0;; + +struct copybit_device_t* CopybitEngine::getEngine() { + return sEngine; +} +CopybitEngine* CopybitEngine::getInstance() { + if(sInstance == NULL) + sInstance = new CopybitEngine(); + return sInstance; +} + +CopybitEngine::CopybitEngine(){ + hw_module_t const *module; + if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) { + copybit_open(module, &sEngine); + } else { + ALOGE("FATAL ERROR: copybit open failed."); + } +} +CopybitEngine::~CopybitEngine() +{ + if(sEngine) + { + copybit_close(sEngine); + sEngine = NULL; + } +} + +}; //namespace qhwc diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h new file mode 100644 index 0000000..adf088b --- /dev/null +++ b/libhwcomposer/hwc_copybit.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2012, Code Aurora Forum. All rights reserved. + * + * Not a Contribution, Apache license notifications and license are retained + * for attribution purposes only. + * + * 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. + */ +#ifndef HWC_COPYBIT_H +#define HWC_COPYBIT_H +#include "hwc_utils.h" +#include +#include +#include +#include +#include + +#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) +#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) + +namespace qhwc { +//Feature for using Copybit to display RGB layers. +class CopyBit { +public: + //Sets up members and prepares copybit if conditions are met + static bool prepare(hwc_context_t *ctx, hwc_layer_list_t *list); + //Draws layer if the layer is set for copybit in prepare + static bool draw(hwc_context_t *ctx, hwc_layer_list_t *list, EGLDisplay dpy, + EGLSurface sur); + //Receives data from hwc + static void setStats(int yuvCount, int yuvLayerIndex, bool isYuvLayerSkip); + + static void updateEglHandles(void*); + static int drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_t *layer, + EGLDisplay dpy, EGLSurface surface, + functype_eglGetRenderBufferANDROID& LINK_eglGetRenderBufferANDROID, + functype_eglGetCurrentSurface LINK_eglGetCurrentSurface); + static bool canUseCopybit(hwc_context_t* ctx, const hwc_layer_list_t* list, + const int numYUVBuffers); + static void closeEglLib(); + static void openEglLibAndGethandle(); +private: + //Marks layer flags if this feature is used + static void markFlags(hwc_layer_t *layer); + //returns yuv count + static int getYuvCount(); + + //Number of yuv layers in this drawing round + static int sYuvCount; + //Index of YUV layer, relevant only if count is 1 + static int sYuvLayerIndex; + //Flags if a yuv layer is animating or below something that is animating + static bool sIsLayerSkip; + //Flags if this feature is on. + static bool sIsModeOn; + //handle for adreno lib + static void* egl_lib; + + static functype_eglGetRenderBufferANDROID LINK_eglGetRenderBufferANDROID; + static functype_eglGetCurrentSurface LINK_eglGetCurrentSurface; + + static void getLayerResolution(const hwc_layer_t* layer, int& width, + int& height); + +}; + +inline void CopyBit::setStats(int yuvCount, int yuvLayerIndex, + bool isYuvLayerSkip) { + sYuvCount = yuvCount; + sYuvLayerIndex = yuvLayerIndex; + sIsLayerSkip = isYuvLayerSkip; +} + +inline int CopyBit::getYuvCount() { return sYuvCount; } + + +}; //namespace qhwc + +#endif //HWC_COPYBIT_H diff --git a/libhwcomposer/hwc_copybitEngine.h b/libhwcomposer/hwc_copybitEngine.h new file mode 100644 index 0000000..d627e44 --- /dev/null +++ b/libhwcomposer/hwc_copybitEngine.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2012, Code Aurora Forum. All rights reserved. + * + * Not a Contribution, Apache license notifications and license are retained + * for attribution purposes only. + * + * 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. + */ +#ifndef HWC_COPYBIT_ENGINE_H +#define HWC_COPYBIT_ENGINE_H + +namespace qhwc { +class CopybitEngine { +public: + ~CopybitEngine(); + // API to get copybit engine(non static) + struct copybit_device_t *getEngine(); + // API to get singleton + static CopybitEngine* getInstance(); + +private: + CopybitEngine(); + struct copybit_device_t *sEngine; + static CopybitEngine* sInstance; // singleton +}; + +}; //namespace qhwc + +#endif //HWC_COPYBIT_ENGINE_H diff --git a/libhwcomposer/hwc_ext_observer.cpp b/libhwcomposer/hwc_ext_observer.cpp new file mode 100644 index 0000000..d79e2f3 --- /dev/null +++ b/libhwcomposer/hwc_ext_observer.cpp @@ -0,0 +1,446 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2012, Code Aurora Forum. All rights reserved. + * + * Not a Contribution, Apache license notifications and license are + * retained for attribution purposes only. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include "hwc_utils.h" +#include "hwc_ext_observer.h" + +namespace qhwc { + +#define EXT_OBSERVER_DEBUG 1 + +#define DEVICE_ROOT "/sys/devices/virtual/graphics" +#define DEVICE_NODE "fb1" + +#define SYSFS_CONNECTED DEVICE_ROOT "/" DEVICE_NODE "/connected" +#define SYSFS_EDID_MODES DEVICE_ROOT "/" DEVICE_NODE "/edid_modes" +#define SYSFS_HPD DEVICE_ROOT "/" DEVICE_NODE "/hpd" + + +android::sp ExtDisplayObserver:: + sExtDisplayObserverInstance(0); + +ExtDisplayObserver::ExtDisplayObserver() : Thread(false), + fd(-1), mCurrentID(-1), mHwcContext(NULL) +{ + //Enable HPD for HDMI + writeHPDOption(1); +} + +ExtDisplayObserver::~ExtDisplayObserver() { + if (fd > 0) + close(fd); +} + +ExtDisplayObserver *ExtDisplayObserver::getInstance() { + ALOGD_IF(EXT_OBSERVER_DEBUG, "%s ", __FUNCTION__); + if(sExtDisplayObserverInstance.get() == NULL) + sExtDisplayObserverInstance = new ExtDisplayObserver(); + return sExtDisplayObserverInstance.get(); +} + +void ExtDisplayObserver::setHwcContext(hwc_context_t* hwcCtx) { + ALOGD_IF(EXT_OBSERVER_DEBUG, "%s", __FUNCTION__); + if(hwcCtx) { + mHwcContext = hwcCtx; + } + return; +} +void ExtDisplayObserver::onFirstRef() { + ALOGD_IF(EXT_OBSERVER_DEBUG, "%s", __FUNCTION__); + run("ExtDisplayObserver", ANDROID_PRIORITY_DISPLAY); +} + +int ExtDisplayObserver::readyToRun() { + //Initialize the uevent + uevent_init(); + ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: success", __FUNCTION__); + return android::NO_ERROR; +} + +void ExtDisplayObserver::handleUEvent(char* str){ + int connected = 0; + // TODO: check for fb2(WFD) driver also + if(!strcasestr(str, DEVICE_NODE)) + { + ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: Not Ext Disp Event ", __FUNCTION__); + return; + } + // Event will be of the form: + // change@/devices/virtual/graphics/fb1 ACTION=change + // DEVPATH=/devices/virtual/graphics/fb1 + // SUBSYSTEM=graphics HDCP_STATE=FAIL MAJOR=29 + // for now just parse the online or offline are important for us. + if(!(strncmp(str,"online@",strlen("online@")))) { + ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: external disp online", __FUNCTION__); + connected = 1; + readResolution(); + //Get the best mode and set + // TODO: DO NOT call this for WFD + setResolution(getBestMode()); + } else if(!(strncmp(str,"offline@",strlen("offline@")))) { + ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: external disp online", __FUNCTION__); + connected = 0; + close(fd); + } + setExternalDisplayStatus(connected); +} + +bool ExtDisplayObserver::threadLoop() +{ + static char uEventString[1024]; + memset(uEventString, 0, sizeof(uEventString)); + int count = uevent_next_event(uEventString, sizeof(uEventString)); + if(count) { + ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: UeventString: %s len = %d", + __FUNCTION__, uEventString, count); + handleUEvent(uEventString); + } + return true; +} + +struct disp_mode_timing_type { + int video_format; + + int active_h; + int active_v; + + int front_porch_h; + int pulse_width_h; + int back_porch_h; + + int front_porch_v; + int pulse_width_v; + int back_porch_v; + + int pixel_freq; + bool interlaced; + + void set_info(struct fb_var_screeninfo &info) const; +}; + +void disp_mode_timing_type::set_info(struct fb_var_screeninfo &info) const +{ + info.reserved[0] = 0; + info.reserved[1] = 0; + info.reserved[2] = 0; + info.reserved[3] = video_format; + + info.xoffset = 0; + info.yoffset = 0; + info.xres = active_h; + info.yres = active_v; + + info.pixclock = pixel_freq*1000; + info.vmode = interlaced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED; + + info.right_margin = front_porch_h; + info.hsync_len = pulse_width_h; + info.left_margin = back_porch_h; + info.lower_margin = front_porch_v; + info.vsync_len = pulse_width_v; + info.upper_margin = back_porch_v; +} + +/* Video formates supported by the HDMI Standard */ +/* Indicates the resolution, pix clock and the aspect ratio */ +#define m640x480p60_4_3 1 +#define m720x480p60_4_3 2 +#define m720x480p60_16_9 3 +#define m1280x720p60_16_9 4 +#define m1920x1080i60_16_9 5 +#define m1440x480i60_4_3 6 +#define m1440x480i60_16_9 7 +#define m1920x1080p60_16_9 16 +#define m720x576p50_4_3 17 +#define m720x576p50_16_9 18 +#define m1280x720p50_16_9 19 +#define m1440x576i50_4_3 21 +#define m1440x576i50_16_9 22 +#define m1920x1080p50_16_9 31 +#define m1920x1080p24_16_9 32 +#define m1920x1080p25_16_9 33 +#define m1920x1080p30_16_9 34 + +static struct disp_mode_timing_type supported_video_mode_lut[] = { + {m640x480p60_4_3, 640, 480, 16, 96, 48, 10, 2, 33, 25200, false}, + {m720x480p60_4_3, 720, 480, 16, 62, 60, 9, 6, 30, 27030, false}, + {m720x480p60_16_9, 720, 480, 16, 62, 60, 9, 6, 30, 27030, false}, + {m1280x720p60_16_9, 1280, 720, 110, 40, 220, 5, 5, 20, 74250, false}, + {m1920x1080i60_16_9, 1920, 540, 88, 44, 148, 2, 5, 5, 74250, false}, + {m1440x480i60_4_3, 1440, 240, 38, 124, 114, 4, 3, 15, 27000, true}, + {m1440x480i60_16_9, 1440, 240, 38, 124, 114, 4, 3, 15, 27000, true}, + {m1920x1080p60_16_9, 1920, 1080, 88, 44, 148, 4, 5, 36, 148500, false}, + {m720x576p50_4_3, 720, 576, 12, 64, 68, 5, 5, 39, 27000, false}, + {m720x576p50_16_9, 720, 576, 12, 64, 68, 5, 5, 39, 27000, false}, + {m1280x720p50_16_9, 1280, 720, 440, 40, 220, 5, 5, 20, 74250, false}, + {m1440x576i50_4_3, 1440, 288, 24, 126, 138, 2, 3, 19, 27000, true}, + {m1440x576i50_16_9, 1440, 288, 24, 126, 138, 2, 3, 19, 27000, true}, + {m1920x1080p50_16_9, 1920, 1080, 528, 44, 148, 4, 5, 36, 148500, false}, + {m1920x1080p24_16_9, 1920, 1080, 638, 44, 148, 4, 5, 36, 74250, false}, + {m1920x1080p25_16_9, 1920, 1080, 528, 44, 148, 4, 5, 36, 74250, false}, + {m1920x1080p30_16_9, 1920, 1080, 88, 44, 148, 4, 5, 36, 74250, false}, +}; +int ExtDisplayObserver::parseResolution(char* edidStr, int* edidModes, int len) +{ + char delim = ','; + int count = 0; + char *start, *end; + // EDIDs are string delimited by ',' + // Ex: 16,4,5,3,32,34,1 + // Parse this string to get mode(int) + start = (char*) edidStr; + for(int i=0; i 1 && isspace(mEDIDs[len-1])) + --len; + mEDIDs[len] = 0; + } + } + close(hdmiEDIDFile); + if(len > 0) { + // GEt EDID modes from the EDID strings + mModeCount = parseResolution(mEDIDs, mEDIDModes, len); + ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: mModeCount = %d", __FUNCTION__, + mModeCount); + } + + return (strlen(mEDIDs) > 0); +} + +bool ExtDisplayObserver::openFramebuffer() +{ + if (fd == -1) { + fd = open("/dev/graphics/fb1", O_RDWR); + if (fd < 0) + ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: /dev/graphics/fb1 not available" + "\n", __FUNCTION__); + } + return (fd > 0); +} + + +int ExtDisplayObserver::getModeOrder(int mode) +{ + switch (mode) { + default: + case m1440x480i60_4_3: + return 1; // 480i 4:3 + case m1440x480i60_16_9: + return 2; // 480i 16:9 + case m1440x576i50_4_3: + return 3; // i576i 4:3 + case m1440x576i50_16_9: + return 4; // 576i 16:9 + case m640x480p60_4_3: + return 5; // 640x480 4:3 + case m720x480p60_4_3: + return 6; // 480p 4:3 + case m720x480p60_16_9: + return 7; // 480p 16:9 + case m720x576p50_4_3: + return 8; // 576p 4:3 + case m720x576p50_16_9: + return 9; // 576p 16:9 + case m1920x1080i60_16_9: + return 10; // 1080i 16:9 + case m1280x720p50_16_9: + return 11; // 720p@50Hz + case m1280x720p60_16_9: + return 12; // 720p@60Hz + case m1920x1080p24_16_9: + return 13; //1080p@24Hz + case m1920x1080p25_16_9: + return 14; //108-p@25Hz + case m1920x1080p30_16_9: + return 15; //1080p@30Hz + case m1920x1080p50_16_9: + return 16; //1080p@50Hz + case m1920x1080p60_16_9: + return 17; //1080p@60Hz + } +} + +// Get the best mode for the current HD TV +int ExtDisplayObserver::getBestMode() { + int bestOrder = 0; + int bestMode = m640x480p60_4_3; + + // for all the edid read, get the best mode + for(int i = 0; i < mModeCount; i++) { + int mode = mEDIDModes[i]; + int order = getModeOrder(mode); + if (order > bestOrder) { + bestOrder = order; + bestMode = mode; + } + } + return bestMode; + } + +inline bool ExtDisplayObserver::isValidMode(int ID) +{ + return ((ID >= m640x480p60_4_3) && (ID <= m1920x1080p30_16_9)); +} + +void ExtDisplayObserver::setResolution(int ID) +{ + struct fb_var_screeninfo info; + if (!openFramebuffer()) + return; + //If its a valid mode and its a new ID - update var_screeninfo + if ((isValidMode(ID)) && mCurrentID != ID) { + const struct disp_mode_timing_type *mode = + &supported_video_mode_lut[0]; + unsigned count = sizeof(supported_video_mode_lut)/sizeof + (*supported_video_mode_lut); + for (unsigned int i = 0; i < count; ++i) { + const struct disp_mode_timing_type *cur = + &supported_video_mode_lut[i]; + if (cur->video_format == ID) + mode = cur; + } + ioctl(fd, FBIOGET_VSCREENINFO, &info); + ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: GET Info", __FUNCTION__, + info.reserved[3], info.xres, info.yres, + info.right_margin, info.hsync_len, info.left_margin, + info.lower_margin, info.vsync_len, info.upper_margin, + info.pixclock/1000/1000); + mode->set_info(info); + ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: SET Info Info", __FUNCTION__, ID, + info.reserved[3], info.xres, info.yres, + info.right_margin, info.hsync_len, info.left_margin, + info.lower_margin, info.vsync_len, info.upper_margin, + info.pixclock/1000/1000); + info.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL | FB_ACTIVATE_FORCE; + ioctl(fd, FBIOPUT_VSCREENINFO, &info); + mCurrentID = ID; + } + //Powerup + ioctl(fd, FBIOBLANK, FB_BLANK_UNBLANK); + ioctl(fd, FBIOGET_VSCREENINFO, &info); + //Pan_Display + ioctl(fd, FBIOPAN_DISPLAY, &info); + property_set("hw.hdmiON", "1"); +} + + +int ExtDisplayObserver::getExternalDisplay() const +{ + return mExternalDisplay; +} + +void ExtDisplayObserver::setExternalDisplayStatus(int connected) +{ + + hwc_context_t* ctx = mHwcContext; + if(ctx) { + ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: status = %d", __FUNCTION__, + connected); + // Store the external display + mExternalDisplay = connected;//(external_display_type)value; + //Invalidate + hwc_procs* proc = (hwc_procs*)ctx->device.reserved_proc[0]; + if(!proc) { + ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: HWC proc not registered", + __FUNCTION__); + } else { + /* Trigger redraw */ + ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: Invalidate !!", __FUNCTION__); + proc->invalidate(proc); + } + } + return; +} + +bool ExtDisplayObserver::writeHPDOption(int userOption) const +{ + bool ret = true; + int hdmiHPDFile = open(SYSFS_HPD,O_RDWR, 0); + if (hdmiHPDFile < 0) { + ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: state file '%s' not found : ret%d" + "err str: %s", __FUNCTION__, SYSFS_HPD, hdmiHPDFile, strerror(errno)); + ret = false; + } else { + int err = -1; + ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: option = %d", __FUNCTION__, + userOption); + if(userOption) + err = write(hdmiHPDFile, "1", 2); + else + err = write(hdmiHPDFile, "0" , 2); + if (err <= 0) { + ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: file write failed '%s'", + __FUNCTION__, SYSFS_HPD); + ret = false; + } + close(hdmiHPDFile); + } + return ret; +} +}; + diff --git a/libhwcomposer/hwc_ext_observer.h b/libhwcomposer/hwc_ext_observer.h new file mode 100644 index 0000000..e7cb890 --- /dev/null +++ b/libhwcomposer/hwc_ext_observer.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2012, Code Aurora Forum. All rights reserved. + * + * Not a Contribution, Apache license notifications and license are + * retained for attribution purposes only. + + * 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. + */ + +#ifndef HWC_EXT_OBSERVER_H +#define HWC_EXT_OBSERVER_H + +#include + +struct hwc_context_t; + +namespace qhwc { + +class ExtDisplayObserver : public android::Thread +{ + //Type of external display - OFF, HDMI, WFD + enum external_display_type { + EXT_TYPE_NONE, + EXT_TYPE_HDMI, + EXT_TYPE_WIFI + }; + + // Mirroring state + enum external_mirroring_state { + EXT_MIRRORING_OFF, + EXT_MIRRORING_ON, + }; + public: + /*Overrides*/ + virtual bool threadLoop(); + virtual int readyToRun(); + virtual void onFirstRef(); + + virtual ~ExtDisplayObserver(); + static ExtDisplayObserver *getInstance(); + int getExternalDisplay() const; + void setHwcContext(hwc_context_t* hwcCtx); + + private: + ExtDisplayObserver(); + void setExternalDisplayStatus(int connected); + bool readResolution(); + int parseResolution(char* edidStr, int* edidModes, int len); + void setResolution(int ID); + bool openFramebuffer(); + bool writeHPDOption(int userOption) const; + bool isValidMode(int ID); + void handleUEvent(char* str); + int getModeOrder(int mode); + int getBestMode(); + + int fd; + int mExternalDisplay; + int mCurrentID; + char mEDIDs[128]; + int mEDIDModes[64]; + int mModeCount; + hwc_context_t *mHwcContext; + static android::sp sExtDisplayObserverInstance; +}; + +}; //qhwc +// --------------------------------------------------------------------------- +#endif //HWC_EXT_OBSERVER_H diff --git a/libhwcomposer/hwc_overlay.cpp b/libhwcomposer/hwc_overlay.cpp deleted file mode 100644 index 77402cc..0000000 --- a/libhwcomposer/hwc_overlay.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * Copyright (C) 2012, 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. - */ - -#include "hwc_utils.h" -#define FINAL_TRANSFORM_MASK 0x000F - -namespace qhwc { -// Determine overlay state based on decoded video info -static ovutils::eOverlayState determineOverlayState(hwc_context_t* ctx, - uint32_t bypassLayer, - uint32_t format) -{ - ovutils::eOverlayState state = ovutils::OV_CLOSED; - - // Sanity check - if (!ctx) { - ALOGE("%s: NULL ctx", __FUNCTION__); - return state; - } - - overlay::Overlay& ov = *(ctx->mOverlay); - state = ov.getState(); - - // If there are any bypassLayers, state is based on number of layers - if ((bypassLayer > 0) && (ctx->hdmiEnabled == EXT_TYPE_NONE)) { - if (bypassLayer == 1) { - state = ovutils::OV_BYPASS_1_LAYER; - } else if (bypassLayer == 2) { - state = ovutils::OV_BYPASS_2_LAYER; - } else if (bypassLayer == 3) { - state = ovutils::OV_BYPASS_3_LAYER; - } - return state; - } - - // RGB is ambiguous for determining overlay state - if (ovutils::isRgb(ovutils::getMdpFormat(format))) { - return state; - } - - // Content type is either 2D or 3D - uint32_t fmt3D = 0;//XXX: 3D - ovutils::getS3DFormat(format); - - // Determine state based on the external display, content type, and hw type - if (ctx->hdmiEnabled == EXT_TYPE_HDMI) { - // External display is HDMI - if (fmt3D) { - // Content type is 3D - if (ovutils::is3DTV()) { - // TV panel type is 3D - state = ovutils::OV_3D_VIDEO_ON_3D_TV; - } else { - // TV panel type is 2D - state = ovutils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV; - } - } else { - // Content type is 2D - if (ovutils::FrameBufferInfo::getInstance()->supportTrueMirroring()) { - // True UI mirroring is supported - state = ovutils::OV_2D_TRUE_UI_MIRROR; - } else { - // True UI mirroring is not supported - state = ovutils::OV_2D_VIDEO_ON_PANEL_TV; - } - } - } else if (ctx->hdmiEnabled == EXT_TYPE_WIFI) { - // External display is Wifi (currently unsupported) - ALOGE("%s: WIFI external display is unsupported", __FUNCTION__); - return state; - } else { - // No external display (primary panel only) - if (fmt3D) { - // Content type is 3D - if (ovutils::usePanel3D()) { - // Primary panel type is 3D - state = ovutils::OV_3D_VIDEO_ON_3D_PANEL; - } else { - // Primary panel type is 2D - state = ovutils::OV_3D_VIDEO_ON_2D_PANEL; - } - } else { - // Content type is 2D - state = ovutils::OV_2D_VIDEO_ON_PANEL; - } - } - - return state; -} - -void setOverlayState(hwc_context_t *ctx, ovutils::eOverlayState state) -{ - if (!ctx) { - ALOGE("%s: NULL ctx", __FUNCTION__); - return; - } - - overlay::Overlay *ov = ctx->mOverlay; - if (!ov) { - ALOGE("%s: NULL OV object", __FUNCTION__); - return; - } - ov->setState(state); -} - -bool prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer) -{ - bool ret = false; - if (LIKELY(ctx->mOverlay)) { - private_handle_t *hnd = (private_handle_t *)layer->handle; - overlay::Overlay& ov = *(ctx->mOverlay); - ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size); - - // Set overlay state - ovutils::eOverlayState state = determineOverlayState(ctx, 0, info.format); - setOverlayState(ctx, state); - - ovutils::eDest dest = ovutils::OV_PIPE_ALL; - - // In the true UI mirroring case, video needs to go to OV_PIPE0 (for - // primary) and OV_PIPE1 (for external) - if (state == ovutils::OV_2D_TRUE_UI_MIRROR) { - dest = static_cast( - ovutils::OV_PIPE0 | ovutils::OV_PIPE1); - } - - // Order order order - // setSource - just setting source - // setParameter - changes src w/h/f accordingly - // setCrop - ROI - that is src_rect - // setPosition - need to do scaling - // commit - commit changes to mdp driver - // queueBuffer - not here, happens when draw is called - - ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE; - if (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) { - ovutils::setMdpFlags(mdpFlags, - ovutils::OV_MDP_SECURE_OVERLAY_SESSION); - } - - // FIXME: Use source orientation for TV when source is portrait - int transform = layer->transform & FINAL_TRANSFORM_MASK; - ovutils::eTransform orient = - static_cast(transform); - - ovutils::eWait waitFlag = ovutils::NO_WAIT; - if (ctx->skipComposition == true) { - waitFlag = ovutils::WAIT; - } - - ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF; - if (ctx->numHwLayers == 1) { - isFgFlag = ovutils::IS_FG_SET; - } - - ovutils::PipeArgs parg(mdpFlags, - orient, - info, - waitFlag, - ovutils::ZORDER_0, - isFgFlag, - ovutils::ROT_FLAG_DISABLED); - ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg }; - ret = ov.setSource(pargs, dest); - if (!ret) { - ALOGE("%s: setSource failed", __FUNCTION__); - return ret; - } - - const ovutils::Params prms (ovutils::OVERLAY_TRANSFORM, orient); - ret = ov.setParameter(prms, dest); - if (!ret) { - ALOGE("%s: setParameter failed transform %x", __FUNCTION__, orient); - return ret; - } - - hwc_rect_t sourceCrop = layer->sourceCrop; - // x,y,w,h - ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top, // x, y - sourceCrop.right - sourceCrop.left, // w - sourceCrop.bottom - sourceCrop.top);// h - ret = ov.setCrop(dcrop, dest); - if (!ret) { - ALOGE("%s: setCrop failed", __FUNCTION__); - return ret; - } - - int orientation = 0; - ovutils::Dim dim; - hwc_rect_t displayFrame = layer->displayFrame; - dim.x = displayFrame.left; - dim.y = displayFrame.top; - dim.w = (displayFrame.right - displayFrame.left); - dim.h = (displayFrame.bottom - displayFrame.top); - dim.o = orientation; - - ret = ov.setPosition(dim, dest); - if (!ret) { - ALOGE("%s: setPosition failed", __FUNCTION__); - return ret; - } - if (!ov.commit(dest)) { - ALOGE("%s: commit fails", __FUNCTION__); - return false; - } - } - return true; -} - -bool drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer) -{ - private_handle_t *hnd = (private_handle_t *)layer->handle; - - // Lock this buffer for read. - ctx->qbuf->lockAndAdd(hnd); - bool ret = true; - overlay::Overlay& ov = *(ctx->mOverlay); - ovutils::eOverlayState state = ov.getState(); - - // Differentiate between states that need to wait for vsync - switch (state) { - case ovutils::OV_2D_VIDEO_ON_PANEL_TV: - case ovutils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - case ovutils::OV_2D_TRUE_UI_MIRROR: - // If displaying on both primary and external, must play each - // pipe individually since wait for vsync needs to be done at - // the end. Do the following: - // - Play external - // - Play primary - // - Wait for external vsync to be done - // NOTE: In these states - // - primary VG = OV_PIPE0 - // - external VG = OV_PIPE1 - // - external RGB = OV_PIPE2 - // - Only in true UI mirroring case, played by fb - - // Same FD for both primary and external VG pipes - ov.setMemoryId(hnd->fd, static_cast( - ovutils::OV_PIPE0 | ovutils::OV_PIPE1)); - - // Play external - if (!ov.queueBuffer(hnd->offset, ovutils::OV_PIPE1)) { - ALOGE("%s: queueBuffer failed for external", __FUNCTION__); - ret = false; - } - - // Play primary - if (!ov.queueBuffer(hnd->offset, ovutils::OV_PIPE0)) { - ALOGE("%s: queueBuffer failed for primary", __FUNCTION__); - ret = false; - } - - // Wait for external vsync to be done - if (!ov.waitForVsync(ovutils::OV_PIPE1)) { - ALOGE("%s: waitForVsync failed for external", __FUNCTION__); - ret = false; - } - break; - default: - // In most cases, displaying only to one (primary or external) - // so use OV_PIPE_ALL since overlay will ignore NullPipes - ov.setMemoryId(hnd->fd, ovutils::OV_PIPE_ALL); - if (!ov.queueBuffer(hnd->offset, ovutils::OV_PIPE_ALL)) { - ALOGE("%s: queueBuffer failed", __FUNCTION__); - ret = false; - } - break; - } - - if (!ret) { - ALOGE("%s: failed", __FUNCTION__); - } - return ret; -} - -void cleanOverlays(hwc_context_t *ctx ) -{ - //XXX: handle for HDMI - if(0 == ctx->yuvBufferCount) - setOverlayState(ctx, ovutils::OV_CLOSED); -} -}; //namespace qhwc diff --git a/libhwcomposer/hwc_uimirror.cpp b/libhwcomposer/hwc_uimirror.cpp new file mode 100644 index 0000000..4540be8 --- /dev/null +++ b/libhwcomposer/hwc_uimirror.cpp @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2012, Code Aurora Forum. All rights reserved. + * + * Not a Contribution, Apache license notifications and license are + * retained for attribution purposes only. + * + * 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. + */ + +#include "hwc_uimirror.h" +#include "hwc_ext_observer.h" + +namespace qhwc { + +#define HWC_UI_MIRROR 0 + +// Function to get the primary device orientation +// Loops thru the hardware layers and returns the orientation of the max. +// number of layers +int getDeviceOrientation(hwc_context_t* ctx, hwc_layer_list_t *list) { + int orientation = list->hwLayers[0].transform; + if(!ctx) { + ALOGD_IF(HWC_UI_MIRROR, "In %s: ctx is NULL!!", __FUNCTION__); + return -1; + } + for(size_t i=0; i <= list->numHwLayers;i++ ) + { + for(size_t j=i+1; j <= list->numHwLayers; j++) + { + // Should we not check for the video layer orientation as it might + // source orientation(?) + if(list->hwLayers[i].transform == list->hwLayers[j].transform) + { + orientation = list->hwLayers[i].transform; + } + } + } + return orientation; +} + +//Static Members +ovutils::eOverlayState UIMirrorOverlay::sState = ovutils::OV_CLOSED; +bool UIMirrorOverlay::sIsUiMirroringOn = false; + + +//Prepare the overlay for the UI mirroring +bool UIMirrorOverlay::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) { + sState = ovutils::OV_CLOSED; + sIsUiMirroringOn = false; + // If external display is connected + if(ctx->mExtDisplayObserver->getExternalDisplay()) { + sState = ovutils::OV_UI_MIRROR; + configure(ctx, list); + } + return sIsUiMirroringOn; +} + +// Configure +bool UIMirrorOverlay::configure(hwc_context_t *ctx, hwc_layer_list_t *list) +{ + if (LIKELY(ctx->mOverlay)) { + overlay::Overlay& ov = *(ctx->mOverlay); + // Set overlay state + ov.setState(sState); + framebuffer_device_t *fbDev = ctx->mFbDevice->getFb(); + if(fbDev) { + private_module_t* m = reinterpret_cast( + fbDev->common.module); + int alignedW = ALIGN_TO(m->info.xres, 32); + + private_handle_t const* hnd = + reinterpret_cast(m->framebuffer); + unsigned int size = hnd->size/m->numBuffers; + ovutils::Whf info(alignedW, hnd->height, hnd->format, size); + // Determine the RGB pipe for UI depending on the state + ovutils::eDest dest = ovutils::OV_PIPE_ALL; + if (sState == ovutils::OV_2D_TRUE_UI_MIRROR) { + // True UI mirroring state: external RGB pipe is OV_PIPE2 + dest = ovutils::OV_PIPE2; + } else if (sState == ovutils::OV_UI_MIRROR) { + // UI-only mirroring state: external RGB pipe is OV_PIPE0 + dest = ovutils::OV_PIPE0; + } + + ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_MEMORY_ID_TYPE_FB; + /* - TODO: Secure content + if (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) { + ovutils::setMdpFlags(mdpFlags, + ovutils::OV_MDP_SECURE_OVERLAY_SESSION); + } + */ + + ovutils::PipeArgs parg(mdpFlags, + info, + ovutils::ZORDER_0, + ovutils::IS_FG_OFF, + ovutils::ROT_FLAG_ENABLED); + ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg }; + ov.setSource(pargs, dest); + + // x,y,w,h + ovutils::Dim dcrop(0, 0, m->info.xres, m->info.yres); + ov.setCrop(dcrop, dest); + //Get the current orientation on primary panel + int transform = getDeviceOrientation(ctx, list); + ovutils::eTransform orient = + static_cast(transform); + ov.setTransform(orient, dest); + + ovutils::Dim dim; + dim.x = 0; + dim.y = 0; + dim.w = m->info.xres; + dim.h = m->info.yres; + ov.setPosition(dim, dest); + if (!ov.commit(dest)) { + ALOGE("%s: commit fails", __FUNCTION__); + return false; + } + sIsUiMirroringOn = true; + } + } + return sIsUiMirroringOn; +} + +bool UIMirrorOverlay::draw(hwc_context_t *ctx) +{ + if(!sIsUiMirroringOn) { + return true; + } + bool ret = true; + overlay::Overlay& ov = *(ctx->mOverlay); + ovutils::eOverlayState state = ov.getState(); + ovutils::eDest dest = ovutils::OV_PIPE_ALL; + framebuffer_device_t *fbDev = ctx->mFbDevice->getFb(); + if(fbDev) { + private_module_t* m = reinterpret_cast( + fbDev->common.module); + //wait for the fb_post to be called + pthread_mutex_lock(&m->fbPostLock); + while(m->fbPostDone == false) { + pthread_cond_wait(&(m->fbPostCond), &(m->fbPostLock)); + } + pthread_mutex_unlock(&m->fbPostLock); + switch (state) { + case ovutils::OV_UI_MIRROR: + if (!ov.queueBuffer(m->framebuffer->fd, m->currentOffset, + ovutils::OV_PIPE0)) { + ALOGE("%s: queueBuffer failed for external", __FUNCTION__); + } + break; + case ovutils::OV_2D_TRUE_UI_MIRROR: + if (!ov.queueBuffer(m->framebuffer->fd, m->currentOffset, + ovutils::OV_PIPE2)) { + ALOGE("%s: queueBuffer failed for external", __FUNCTION__); + } + break; + + default: + break; + } + // TODO: + // Call PANDISPLAY ioctl here to kickoff + } + return ret; +} + +//--------------------------------------------------------------------- +}; //namespace qhwc diff --git a/libhwcomposer/hwc_uimirror.h b/libhwcomposer/hwc_uimirror.h new file mode 100644 index 0000000..af43848 --- /dev/null +++ b/libhwcomposer/hwc_uimirror.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2012, Code Aurora Forum. All rights reserved. + * + * Not a Contribution, Apache license notifications and license are + * retained for attribution purposes only. + * + * 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. + */ +#ifndef HWC_UIMIRROR_H +#define HWC_UIMIRROR_H +#include "hwc_utils.h" + +#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) +#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) + +namespace qhwc { +//Feature for Mirroring UI on the External display +class UIMirrorOverlay { + public: + // Sets up members and prepares overlay if conditions are met + static bool prepare(hwc_context_t *ctx, hwc_layer_list_t *list); + // Draws layer if this feature is on + static bool draw(hwc_context_t *ctx); + private: + //Configures overlay + static bool configure(hwc_context_t *ctx, hwc_layer_list_t *list); + //The chosen overlay state. + static ovutils::eOverlayState sState; + //Flags if this feature is on. + static bool sIsUiMirroringOn; +}; + +}; //namespace qhwc + +#endif //HWC_UIMIRROR_H diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp index 79e09f7..ae5c526 100644 --- a/libhwcomposer/hwc_utils.cpp +++ b/libhwcomposer/hwc_utils.cpp @@ -17,18 +17,24 @@ #include "hwc_utils.h" #include "mdp_version.h" - +#include "hwc_video.h" +#include "hwc_ext_observer.h" +#include "hwc_copybit.h" namespace qhwc { void initContext(hwc_context_t *ctx) { //XXX: target specific initializations here - openFramebufferDevice(ctx); ctx->mOverlay = overlay::Overlay::getInstance(); ctx->qbuf = new QueuedBufferStore(); ctx->mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion(); ctx->hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay(); ALOGI("MDP version: %d",ctx->mdpVersion); + ctx->mExtDisplayObserver = ExtDisplayObserver::getInstance(); + ctx->mExtDisplayObserver->setHwcContext(ctx); + ctx->mFbDevice = FbDevice::getInstance(); + ctx->mCopybitEngine = CopybitEngine::getInstance(); + CopyBit::openEglLibAndGethandle(); } void closeContext(hwc_context_t *ctx) @@ -37,23 +43,20 @@ void closeContext(hwc_context_t *ctx) delete ctx->mOverlay; ctx->mOverlay = NULL; } - if(ctx->fbDev) { - framebuffer_close(ctx->fbDev); - ctx->fbDev = NULL; - } + if(ctx->mCopybitEngine) { + delete ctx->mCopybitEngine; + ctx->mCopybitEngine = NULL; + } + if(ctx->mFbDevice) { + delete ctx->mFbDevice; + ctx->mFbDevice = NULL; + } if(ctx->qbuf) { delete ctx->qbuf; ctx->qbuf = NULL; } -} - -// Opens Framebuffer device -void openFramebufferDevice(hwc_context_t *ctx) { - hw_module_t const *module; - if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { - framebuffer_open(module, &(ctx->fbDev)); - } + CopyBit::closeEglLib(); } void dumpLayer(hwc_layer_t const* l) @@ -73,28 +76,120 @@ void dumpLayer(hwc_layer_t const* l) void getLayerStats(hwc_context_t *ctx, const hwc_layer_list_t *list) { - int yuvBufCount = 0; - int layersNotUpdatingCount = 0; - for (size_t i=0 ; inumHwLayers; i++) { - private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle; + //Video specific stats + int yuvCount = 0; + int yuvLayerIndex = -1; + bool isYuvLayerSkip = false; + + for (size_t i = 0; i < list->numHwLayers; i++) { + private_handle_t *hnd = + (private_handle_t *)list->hwLayers[i].handle; + if (isYuvBuffer(hnd)) { - yuvBufCount++; + yuvCount++; + yuvLayerIndex = i; + //Animating + if (isSkipLayer(&list->hwLayers[i])) { + isYuvLayerSkip = true; + } + } else if (isSkipLayer(&list->hwLayers[i])) { //Popups + //If video layer is below a skip layer + if(yuvLayerIndex != -1 && yuvLayerIndex < (ssize_t)i) { + isYuvLayerSkip = true; + } } } - // Number of video/camera layers drawable with overlay - ctx->yuvBufferCount = yuvBufCount; + + VideoOverlay::setStats(yuvCount, yuvLayerIndex, isYuvLayerSkip); + CopyBit::setStats(yuvCount, yuvLayerIndex, isYuvLayerSkip); + ctx->numHwLayers = list->numHwLayers; return; } -void handleYUV(hwc_context_t *ctx, hwc_layer_t *layer) -{ - private_handle_t *hnd = - (private_handle_t *)layer->handle; - //XXX: Handle targets not using overlay - if(prepareOverlay(ctx, layer)) { - layer->compositionType = HWC_OVERLAY; - layer->hints |= HWC_HINT_CLEAR_FB; +//Crops source buffer against destination and FB boundaries +void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst, + const int fbWidth, const int fbHeight) { + + int& crop_x = crop.left; + int& crop_y = crop.top; + int& crop_r = crop.right; + int& crop_b = crop.bottom; + int crop_w = crop.right - crop.left; + int crop_h = crop.bottom - crop.top; + + int& dst_x = dst.left; + int& dst_y = dst.top; + int& dst_r = dst.right; + int& dst_b = dst.bottom; + int dst_w = dst.right - dst.left; + int dst_h = dst.bottom - dst.top; + + if(dst_x < 0) { + float scale_x = crop_w * 1.0f / dst_w; + float diff_factor = (scale_x * abs(dst_x)); + crop_x = crop_x + (int)diff_factor; + crop_w = crop_r - crop_x; + + dst_x = 0; + dst_w = dst_r - dst_x;; + } + if(dst_r > fbWidth) { + float scale_x = crop_w * 1.0f / dst_w; + float diff_factor = scale_x * (dst_r - fbWidth); + crop_r = crop_r - diff_factor; + crop_w = crop_r - crop_x; + + dst_r = fbWidth; + dst_w = dst_r - dst_x; + } + if(dst_y < 0) { + float scale_y = crop_h * 1.0f / dst_h; + float diff_factor = scale_y * abs(dst_y); + crop_y = crop_y + diff_factor; + crop_h = crop_b - crop_y; + + dst_y = 0; + dst_h = dst_b - dst_y; + } + if(dst_b > fbHeight) { + float scale_y = crop_h * 1.0f / dst_h; + float diff_factor = scale_y * (dst_b - fbHeight); + crop_b = crop_b - diff_factor; + crop_h = crop_b - crop_y; + + dst_b = fbHeight; + dst_h = dst_b - dst_y; } } + +//FbDevice class functions +FbDevice* FbDevice::sInstance = 0;; +struct framebuffer_device_t* FbDevice::getFb() { + return sFb; +} + +FbDevice* FbDevice::getInstance() { + if(sInstance == NULL) + sInstance = new FbDevice(); + return sInstance; +} + +FbDevice::FbDevice(){ + hw_module_t const *module; + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { + framebuffer_open(module, &sFb); + } else { + ALOGE("FATAL ERROR: framebuffer open failed."); + } +} +FbDevice::~FbDevice() +{ + if(sFb) + { + framebuffer_close(sFb); + sFb = NULL; + } +} + };//namespace diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h index 94a4edb..0bf30c9 100644 --- a/libhwcomposer/hwc_utils.h +++ b/libhwcomposer/hwc_utils.h @@ -26,12 +26,16 @@ #include #include #include +#include +#include #include #include "hwc_qbuf.h" +#include -#define ALIGN(x, align) (((x) + ((align)-1)) & ~((align)-1)) +#define ALIGN_TO(x, align) (((x) + ((align)-1)) & ~((align)-1)) #define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) #define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) +#define FINAL_TRANSFORM_MASK 0x000F struct hwc_context_t; namespace qhwc { @@ -41,16 +45,24 @@ enum external_display_type { EXT_TYPE_HDMI, EXT_TYPE_WIFI }; +enum HWCCompositionType { + HWC_USE_GPU = HWC_FRAMEBUFFER, // This layer is to be handled by + // Surfaceflinger + HWC_USE_OVERLAY = HWC_OVERLAY, // This layer is to be handled by the overlay + HWC_USE_COPYBIT // This layer is to be handled by copybit +}; +class ExtDisplayObserver; // ----------------------------------------------------------------------------- // Utility functions - implemented in hwc_utils.cpp void dumpLayer(hwc_layer_t const* l); void getLayerStats(hwc_context_t *ctx, const hwc_layer_list_t *list); -void handleYUV(hwc_context_t *ctx, hwc_layer_t *layer); void initContext(hwc_context_t *ctx); void closeContext(hwc_context_t *ctx); -void openFramebufferDevice(hwc_context_t *ctx); +//Crops source buffer against destination and FB boundaries +void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst, + const int fbWidth, const int fbHeight); // Inline utility functions static inline bool isSkipLayer(const hwc_layer_t* l) { @@ -66,28 +78,30 @@ static inline bool isYuvBuffer(const private_handle_t* hnd) { static inline bool isBufferLocked(const private_handle_t* hnd) { return (hnd && (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags)); } +// ----------------------------------------------------------------------------- +// Copybit specific - inline or implemented in hwc_copybit.cpp +typedef EGLClientBuffer (*functype_eglGetRenderBufferANDROID) ( + EGLDisplay dpy, + EGLSurface draw); +typedef EGLSurface (*functype_eglGetCurrentSurface)(EGLint readdraw); // ----------------------------------------------------------------------------- -// Overlay specific functions - inline or implemented in hwc_overlay.cpp -bool prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer); -//XXX: Refine draw functions -bool drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer); -//XXX: Refine -void cleanOverlays(hwc_context_t *ctx ); -void setOverlayState(hwc_context_t* ctx, ovutils::eOverlayState state); +// Singleton for Framebuffer device +class FbDevice{ +public: + ~FbDevice(); + // API to get Fb device(non static) + struct framebuffer_device_t *getFb(); + // API to get singleton + static FbDevice* getInstance(); -// ----------------------------------------------------------------------------- -// Copybit specific functions - inline or implemented in hwc_copybit.cpp - - - -// ----------------------------------------------------------------------------- -// HDMI specific functions - inline or implemented in hwc_hdmi.cpp - - - -} //qhwc namespace +private: + FbDevice(); + struct framebuffer_device_t *sFb; + static FbDevice* sInstance; // singleton +}; +}; //qhwc namespace // ----------------------------------------------------------------------------- @@ -95,25 +109,25 @@ void setOverlayState(hwc_context_t* ctx, ovutils::eOverlayState state); // This structure contains overall state struct hwc_context_t { hwc_composer_device_t device; - // Layer variables - int yuvBufferCount; - int hdmiEnabled; int numHwLayers; int mdpVersion; bool hasOverlay; - bool skipComposition; + int overlayInUse; //Framebuffer device - framebuffer_device_t *fbDev; + qhwc::FbDevice* mFbDevice; + + //Copybit Engine + qhwc::CopybitEngine* mCopybitEngine; //Overlay object - NULL for non overlay devices overlay::Overlay *mOverlay; //QueuedBufferStore to hold buffers for overlay qhwc::QueuedBufferStore *qbuf; + + // External display related information + qhwc::ExtDisplayObserver*mExtDisplayObserver; }; - - - #endif //HWC_UTILS_H diff --git a/libhwcomposer/hwc_video.cpp b/libhwcomposer/hwc_video.cpp new file mode 100644 index 0000000..180ab86 --- /dev/null +++ b/libhwcomposer/hwc_video.cpp @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2012, 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. + */ + +#include "hwc_video.h" +#include "hwc_ext_observer.h" + +namespace qhwc { + +#define FINAL_TRANSFORM_MASK 0x000F +#define VIDEO_DEBUG 0 + +//Static Members +ovutils::eOverlayState VideoOverlay::sState = ovutils::OV_CLOSED; +int VideoOverlay::sYuvCount = 0; +int VideoOverlay::sYuvLayerIndex = -1; +bool VideoOverlay::sIsModeOn = false; +bool VideoOverlay::sIsLayerSkip = false; + +//Cache stats, figure out the state, config overlay +bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) { + sIsModeOn = false; + if(!ctx->hasOverlay) { + ALOGD_IF(VIDEO_DEBUG,"%s, this hw doesnt support overlay", __FUNCTION__); + return false; + } + chooseState(ctx); + //if the state chosen above is CLOSED, skip this block. + if(sState != ovutils::OV_CLOSED) { + if(configure(ctx, &list->hwLayers[sYuvLayerIndex])) { + markFlags(&list->hwLayers[sYuvLayerIndex]); + } + } + + ALOGD_IF(VIDEO_DEBUG, "%s: stats: yuvCount = %d, yuvIndex = %d," + "IsModeOn = %d, IsSkipLayer = %d", __FUNCTION__, sYuvCount, + sYuvLayerIndex, sIsModeOn, sIsLayerSkip); + + return sIsModeOn; +} + +void VideoOverlay::chooseState(hwc_context_t *ctx) { + ALOGD_IF(VIDEO_DEBUG, "%s: old state = %s", __FUNCTION__, + ovutils::getStateString(sState)); + + ovutils::eOverlayState newState = ovutils::OV_CLOSED; + //TODO check if device supports overlay and hdmi + + //Support 1 video layer + if(sYuvCount == 1) { + //Skip on primary, display on ext. + if(sIsLayerSkip && ctx->mExtDisplayObserver->getExternalDisplay()) { + //TODO + //VIDEO_ON_TV_ONLY + } else if(sIsLayerSkip) { //skip on primary, no ext + newState = ovutils::OV_CLOSED; + } else if(ctx->mExtDisplayObserver->getExternalDisplay()) { + //display on both + newState = ovutils::OV_2D_VIDEO_ON_PANEL_TV; + } else { //display on primary only + newState = ovutils::OV_2D_VIDEO_ON_PANEL; + } + } + sState = newState; + ALOGD_IF(VIDEO_DEBUG, "%s: new chosen state = %s", __FUNCTION__, + ovutils::getStateString(sState)); +} + +void VideoOverlay::markFlags(hwc_layer_t *layer) { + switch(sState) { + case ovutils::OV_2D_VIDEO_ON_PANEL: + case ovutils::OV_2D_VIDEO_ON_PANEL_TV: + layer->compositionType = HWC_OVERLAY; + layer->hints |= HWC_HINT_CLEAR_FB; + break; + //TODO + //case ovutils::OV_2D_VIDEO_ON_TV: + //just break, dont update flags. + default: + break; + } +} + +bool VideoOverlay::configure(hwc_context_t *ctx, hwc_layer_t *layer) +{ + if (LIKELY(ctx->mOverlay)) { + + overlay::Overlay& ov = *(ctx->mOverlay); + // Set overlay state + ov.setState(sState); + + private_handle_t *hnd = (private_handle_t *)layer->handle; + ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size); + + //TODO change this based on state. + ovutils::eDest dest = ovutils::OV_PIPE_ALL; + + ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE; + if (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) { + ovutils::setMdpFlags(mdpFlags, + ovutils::OV_MDP_SECURE_OVERLAY_SESSION); + } + + ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF; + if (ctx->numHwLayers == 1) { + isFgFlag = ovutils::IS_FG_SET; + } + + ovutils::PipeArgs parg(mdpFlags, + info, + ovutils::ZORDER_0, + isFgFlag, + ovutils::ROT_FLAG_DISABLED); + ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg }; + ov.setSource(pargs, dest); + + hwc_rect_t sourceCrop = layer->sourceCrop; + // x,y,w,h + ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top, + sourceCrop.right - sourceCrop.left, + sourceCrop.bottom - sourceCrop.top); + //Only for External + ov.setCrop(dcrop, ovutils::OV_PIPE1); + + // FIXME: Use source orientation for TV when source is portrait + //Only for External + ov.setTransform(0, dest); + + ovutils::Dim dpos; + hwc_rect_t displayFrame = layer->displayFrame; + dpos.x = displayFrame.left; + dpos.y = displayFrame.top; + dpos.w = (displayFrame.right - displayFrame.left); + dpos.h = (displayFrame.bottom - displayFrame.top); + + //Only for External + ov.setPosition(dpos, ovutils::OV_PIPE1); + + //Calculate the rect for primary based on whether the supplied position + //is within or outside bounds. + const int fbWidth = + ovutils::FrameBufferInfo::getInstance()->getWidth(); + const int fbHeight = + ovutils::FrameBufferInfo::getInstance()->getHeight(); + + if( displayFrame.left < 0 || + displayFrame.top < 0 || + displayFrame.right > fbWidth || + displayFrame.bottom > fbHeight) { + + calculate_crop_rects(sourceCrop, displayFrame, fbWidth, fbHeight); + + //Update calculated width and height + dcrop.w = sourceCrop.right - sourceCrop.left; + dcrop.h = sourceCrop.bottom - sourceCrop.top; + + dpos.w = displayFrame.right - displayFrame.left; + dpos.h = displayFrame.bottom - displayFrame.top; + } + + //Only for Primary + ov.setCrop(dcrop, ovutils::OV_PIPE0); + + int transform = layer->transform & FINAL_TRANSFORM_MASK; + ovutils::eTransform orient = + static_cast(transform); + ov.setTransform(orient, ovutils::OV_PIPE0); + + ov.setPosition(dpos, ovutils::OV_PIPE0); + + //Both prim and external + if (!ov.commit(dest)) { + ALOGE("%s: commit fails", __FUNCTION__); + return false; + } + + sIsModeOn = true; + } + return sIsModeOn; +} + +bool VideoOverlay::draw(hwc_context_t *ctx, hwc_layer_list_t *list) +{ + if(!sIsModeOn || sYuvLayerIndex == -1) { + return true; + } + + private_handle_t *hnd = + (private_handle_t *)list->hwLayers[sYuvLayerIndex].handle; + + // Lock this buffer for read. + ctx->qbuf->lockAndAdd(hnd); + bool ret = true; + overlay::Overlay& ov = *(ctx->mOverlay); + ovutils::eOverlayState state = ov.getState(); + + switch (state) { + case ovutils::OV_2D_VIDEO_ON_PANEL_TV: + case ovutils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: + // Play external + if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) { + ALOGE("%s: queueBuffer failed for external", __FUNCTION__); + ret = false; + } + + // Play primary + if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) { + ALOGE("%s: queueBuffer failed for primary", __FUNCTION__); + ret = false; + } + + // Wait for external vsync to be done + if (!ov.waitForVsync(ovutils::OV_PIPE1)) { + ALOGE("%s: waitForVsync failed for external", __FUNCTION__); + ret = false; + } + break; + default: + // In most cases, displaying only to one (primary or external) + // so use OV_PIPE_ALL since overlay will ignore NullPipes + if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE_ALL)) { + ALOGE("%s: queueBuffer failed", __FUNCTION__); + ret = false; + } + break; + } + + return ret; +} + + +}; //namespace qhwc diff --git a/libhwcomposer/hwc_video.h b/libhwcomposer/hwc_video.h new file mode 100644 index 0000000..c6c6c22 --- /dev/null +++ b/libhwcomposer/hwc_video.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2012, 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. + */ +#ifndef HWC_VIDEO_H +#define HWC_VIDEO_H +#include "hwc_utils.h" + +#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) +#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) + +namespace qhwc { +//Feature for using overlay to display videos. +class VideoOverlay { +public: + //Sets up members and prepares overlay if conditions are met + static bool prepare(hwc_context_t *ctx, hwc_layer_list_t *list); + //Draws layer if this feature is on + static bool draw(hwc_context_t *ctx, hwc_layer_list_t *list); + //Receives data from hwc + static void setStats(int yuvCount, int yuvLayerIndex, bool isYuvLayerSkip); +private: + //Choose an appropriate overlay state based on conditions + static void chooseState(hwc_context_t *ctx); + //Configures overlay + static bool configure(hwc_context_t *ctx, hwc_layer_t *layer); + //Marks layer flags if this feature is used + static void markFlags(hwc_layer_t *layer); + //returns yuv count + static int getYuvCount(); + + //The chosen overlay state. + static ovutils::eOverlayState sState; + //Number of yuv layers in this drawing round + static int sYuvCount; + //Index of YUV layer, relevant only if count is 1 + static int sYuvLayerIndex; + //Flags if a yuv layer is animating or below something that is animating + static bool sIsLayerSkip; + //Flags if this feature is on. + static bool sIsModeOn; +}; + +inline void VideoOverlay::setStats(int yuvCount, int yuvLayerIndex, + bool isYuvLayerSkip) { + sYuvCount = yuvCount; + sYuvLayerIndex = yuvLayerIndex; + sIsLayerSkip = isYuvLayerSkip; +} + +inline int VideoOverlay::getYuvCount() { return sYuvCount; } + +}; //namespace qhwc + +#endif //HWC_VIDEO_H diff --git a/liboverlay/Android.mk b/liboverlay/Android.mk index 63d7780..67bb85f 100644 --- a/liboverlay/Android.mk +++ b/liboverlay/Android.mk @@ -1,11 +1,13 @@ LOCAL_PATH := $(call my-dir) +include $(LOCAL_PATH)/../common.mk include $(CLEAR_VARS) -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES) -LOCAL_SHARED_LIBRARIES := liblog -LOCAL_SHARED_LIBRARIES += libcutils -LOCAL_SHARED_LIBRARIES += libutils -LOCAL_SHARED_LIBRARIES += libmemalloc -LOCAL_C_INCLUDES := hardware/qcom/display/libgralloc +LOCAL_MODULE := liboverlay +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES) +LOCAL_MODULE_TAGS := optional +LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes) +LOCAL_SHARED_LIBRARIES := $(common_libs) libmemalloc +LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"overlay\" +LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) LOCAL_SRC_FILES := \ overlay.cpp \ overlayCtrl.cpp \ @@ -14,7 +16,4 @@ LOCAL_SRC_FILES := \ overlayRotator.cpp \ overlayTransitions.cpp -LOCAL_CFLAGS:= -DLOG_TAG=\"overlay2\" -LOCAL_MODULE := liboverlay -LOCAL_MODULE_TAGS := optional include $(BUILD_SHARED_LIBRARY) diff --git a/liboverlay/mdpWrapper.h b/liboverlay/mdpWrapper.h index 4cfd3e0..8c5f624 100644 --- a/liboverlay/mdpWrapper.h +++ b/liboverlay/mdpWrapper.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. +* Copyright (c) 2011, Code Aurora Forum. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -76,7 +76,7 @@ bool getOverlay(int fd, mdp_overlay& ov); bool play(int fd, msmfb_overlay_data& od); /* MSMFB_OVERLAY_PLAY_WAIT */ -bool playWait(int fd, msmfb_overlay_data& od); +bool waitForVsync(int fd, msmfb_overlay_data& od); /* MSMFB_OVERLAY_3D */ bool set3D(int fd, msmfb_overlay_3d& ov); @@ -102,96 +102,108 @@ void dump(const char* const s, const fb_var_screeninfo& vinfo); //---------------Inlines ------------------------------------- inline bool getFScreenInfo(int fd, fb_fix_screeninfo& finfo) { - if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) { - ALOGE("Failed to call ioctl FBIOGET_FSCREENINFO err=%d", errno); + if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) < 0) { + ALOGE("Failed to call ioctl FBIOGET_FSCREENINFO err=%s", + strerror(errno)); return false; } return true; } inline bool getVScreenInfo(int fd, fb_var_screeninfo& vinfo) { - if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1) { - ALOGE("Failed to call ioctl FBIOGET_VSCREENINFO err=%d", errno); + if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0) { + ALOGE("Failed to call ioctl FBIOGET_VSCREENINFO err=%s", + strerror(errno)); return false; } return true; } inline bool setVScreenInfo(int fd, fb_var_screeninfo& vinfo) { - if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo) == -1) { - ALOGE("Failed to call ioctl FBIOPUT_VSCREENINFO err=%d", errno); + if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo) < 0) { + ALOGE("Failed to call ioctl FBIOPUT_VSCREENINFO err=%s", + strerror(errno)); return false; } return true; } inline bool startRotator(int fd, msm_rotator_img_info& rot) { - if (ioctl(fd, MSM_ROTATOR_IOCTL_START, &rot) == -1){ - ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_START err=%d", errno); + if (ioctl(fd, MSM_ROTATOR_IOCTL_START, &rot) < 0){ + ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_START err=%s", + strerror(errno)); return false; } return true; } inline bool rotate(int fd, msm_rotator_data_info& rot) { - if (ioctl(fd, MSM_ROTATOR_IOCTL_ROTATE, &rot) == -1) { - ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_ROTATE err=%d", errno); + if (ioctl(fd, MSM_ROTATOR_IOCTL_ROTATE, &rot) < 0) { + ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_ROTATE err=%s", + strerror(errno)); return false; } return true; } inline bool setOverlay(int fd, mdp_overlay& ov) { - if (ioctl(fd, MSMFB_OVERLAY_SET, &ov) == -1) { - ALOGE("Failed to call ioctl MSMFB_OVERLAY_SET err=%d", errno); + if (ioctl(fd, MSMFB_OVERLAY_SET, &ov) < 0) { + ALOGE("Failed to call ioctl MSMFB_OVERLAY_SET err=%s", + strerror(errno)); return false; } return true; } inline bool endRotator(int fd, int sessionId) { - if (ioctl(fd, MSM_ROTATOR_IOCTL_FINISH, &sessionId) == -1) { - ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_FINISH err=%d", errno); + if (ioctl(fd, MSM_ROTATOR_IOCTL_FINISH, &sessionId) < 0) { + ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_FINISH err=%s", + strerror(errno)); return false; } return true; } inline bool unsetOverlay(int fd, int ovId) { - if (ioctl(fd, MSMFB_OVERLAY_UNSET, &ovId) == -1) { - ALOGE("Failed to call ioctl MSMFB_OVERLAY_UNSET err=%d", errno); + if (ioctl(fd, MSMFB_OVERLAY_UNSET, &ovId) < 0) { + ALOGE("Failed to call ioctl MSMFB_OVERLAY_UNSET err=%s", + strerror(errno)); return false; } return true; } inline bool getOverlay(int fd, mdp_overlay& ov) { - if (ioctl(fd, MSMFB_OVERLAY_GET, &ov) == -1) { - ALOGE("Failed to call ioctl MSMFB_OVERLAY_GET err=%d", errno); + if (ioctl(fd, MSMFB_OVERLAY_GET, &ov) < 0) { + ALOGE("Failed to call ioctl MSMFB_OVERLAY_GET err=%s", + strerror(errno)); return false; } return true; } inline bool play(int fd, msmfb_overlay_data& od) { - if (ioctl(fd, MSMFB_OVERLAY_PLAY, &od) == -1) { - ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY err=%d", errno); + if (ioctl(fd, MSMFB_OVERLAY_PLAY, &od) < 0) { + ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY err=%s", + strerror(errno)); return false; } return true; } -inline bool playWait(int fd, msmfb_overlay_data& od) { - if (ioctl(fd, MSMFB_OVERLAY_PLAY_WAIT, &od) == -1) { - ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY_WAIT err=%d", errno); +inline bool waitForVsync(int fd, msmfb_overlay_data& od) { + if (ioctl(fd, MSMFB_OVERLAY_PLAY_WAIT, &od) < 0) { + ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY_WAIT err=%s", + strerror(errno)); return false; } return true; } inline bool set3D(int fd, msmfb_overlay_3d& ov) { - if (ioctl(fd, MSMFB_OVERLAY_3D, &ov) == -1) { - ALOGE("Failed to call ioctl MSMFB_OVERLAY_3D err=%d", errno); + if (ioctl(fd, MSMFB_OVERLAY_3D, &ov) < 0) { + ALOGE("Failed to call ioctl MSMFB_OVERLAY_3D err=%s", + strerror(errno)); return false; } return true; @@ -262,7 +274,6 @@ inline void dump(const char* const s, const fb_var_screeninfo& vinfo) { s, vinfo.xres, vinfo.yres); } - } // mdp_wrapper } // overlay diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp index ed968c1..a05a307 100644 --- a/liboverlay/overlay.cpp +++ b/liboverlay/overlay.cpp @@ -31,10 +31,8 @@ #include "overlayImpl.h" #include "overlay.h" -// MDP related FIXME move to state #include "overlayMdp.h" #include "overlayCtrlData.h" -#include "overlayRotator.h" namespace overlay { @@ -42,64 +40,16 @@ Overlay::Overlay(): mOv(0) { } Overlay::~Overlay() { - if(mState.state() == utils::OV_CLOSED) return; - close(); + mOv = mState.handleEvent(utils::OV_CLOSED, mOv); delete mOv; mOv = 0; } -bool Overlay::open() { - // We need an empty open to just open the bare minimum for business - return true; -} - -void Overlay::reset(){ - if(mOv && !mOv->close()) { - ALOGE("%s Overlay failed", __FUNCTION__); - } - - delete mOv; - mOv = 0; -} - -bool Overlay::close() -{ - OVASSERT(mOv, - "%s Overlay and Rotator should be init at this point", - __FUNCTION__); - // FIXME that one needs to move to the state machine class - utils::eOverlayState st = mState.state(); - switch (st) { - case utils::OV_CLOSED: - // try to close any partially opened items - break; - case utils::OV_2D_VIDEO_ON_PANEL: - case utils::OV_2D_VIDEO_ON_PANEL_TV: - case utils::OV_3D_VIDEO_ON_2D_PANEL: - case utils::OV_3D_VIDEO_ON_3D_PANEL: - case utils::OV_3D_VIDEO_ON_3D_TV: - case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - case utils::OV_UI_MIRROR: - case utils::OV_2D_TRUE_UI_MIRROR: - case utils::OV_BYPASS_1_LAYER: - case utils::OV_BYPASS_2_LAYER: - case utils::OV_BYPASS_3_LAYER: - mOv = mState.handleEvent(utils::OV_CLOSED, mOv); - this->reset(); - break; - default: - OVASSERT(false, "close Unknown state %d", st); - return false; - } - return true; -} - bool Overlay::commit(utils::eDest dest) { OVASSERT(mOv, "%s Overlay and Rotator should be init at this point", __FUNCTION__); - // FIXME that one needs to move to the state machine class utils::eOverlayState st = mState.state(); switch (st) { case utils::OV_2D_VIDEO_ON_PANEL: @@ -125,13 +75,12 @@ bool Overlay::commit(utils::eDest dest) return true; } -bool Overlay::queueBuffer(uint32_t offset, +bool Overlay::queueBuffer(int fd, uint32_t offset, utils::eDest dest) { OVASSERT(mOv, "%s Overlay and Rotator should be init at this point", __FUNCTION__); - // FIXME that one needs to move to the state machine class utils::eOverlayState st = mState.state(); switch (st) { case utils::OV_2D_VIDEO_ON_PANEL: @@ -145,39 +94,7 @@ bool Overlay::queueBuffer(uint32_t offset, case utils::OV_BYPASS_1_LAYER: case utils::OV_BYPASS_2_LAYER: case utils::OV_BYPASS_3_LAYER: - if(!mOv->queueBuffer(offset, dest)) { - ALOGE("Overlay %s failed", __FUNCTION__); - return false; - } - break; - default: - OVASSERT(false, "%s Unknown state %d", __FUNCTION__, st); - return false; - } - return true; -} - -bool Overlay::dequeueBuffer(void*& buf, - utils::eDest dest) -{ - OVASSERT(mOv, - "%s Overlay and Rotator should be init at this point", - __FUNCTION__); - // FIXME that one needs to move to the state machine class - utils::eOverlayState st = mState.state(); - switch (st) { - case utils::OV_2D_VIDEO_ON_PANEL: - case utils::OV_2D_VIDEO_ON_PANEL_TV: - case utils::OV_3D_VIDEO_ON_2D_PANEL: - case utils::OV_3D_VIDEO_ON_3D_PANEL: - case utils::OV_3D_VIDEO_ON_3D_TV: - case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - case utils::OV_UI_MIRROR: - case utils::OV_2D_TRUE_UI_MIRROR: - case utils::OV_BYPASS_1_LAYER: - case utils::OV_BYPASS_2_LAYER: - case utils::OV_BYPASS_3_LAYER: - if(!mOv->dequeueBuffer(buf, dest)) { + if(!mOv->queueBuffer(fd, offset, dest)) { ALOGE("Overlay %s failed", __FUNCTION__); return false; } @@ -194,7 +111,6 @@ bool Overlay::waitForVsync(utils::eDest dest) OVASSERT(mOv, "%s Overlay and Rotator should be init at this point", __FUNCTION__); - // FIXME that one needs to move to the state machine class utils::eOverlayState st = mState.state(); switch (st) { case utils::OV_2D_VIDEO_ON_PANEL: @@ -226,7 +142,6 @@ bool Overlay::setCrop(const utils::Dim& d, OVASSERT(mOv, "%s Overlay and Rotator should be init at this point", __FUNCTION__); - // FIXME that one needs to move to the state machine class utils::eOverlayState st = mState.state(); switch (st) { case utils::OV_2D_VIDEO_ON_PANEL: @@ -257,7 +172,6 @@ bool Overlay::setPosition(const utils::Dim& d, OVASSERT(mOv, "%s Overlay and Rotator should be init at this point", __FUNCTION__); - // FIXME that one needs to move to the state machine class utils::eOverlayState st = mState.state(); switch (st) { case utils::OV_2D_VIDEO_ON_PANEL: @@ -282,13 +196,13 @@ bool Overlay::setPosition(const utils::Dim& d, } return true; } -bool Overlay::setParameter(const utils::Params& param, + +bool Overlay::setTransform(const int orient, utils::eDest dest) { - OVASSERT(mOv, - "%s Overlay and Rotator should be init at this point", - __FUNCTION__); - // FIXME that one needs to move to the state machine class + utils::eTransform transform = + static_cast(orient); + utils::eOverlayState st = mState.state(); switch (st) { case utils::OV_2D_VIDEO_ON_PANEL: @@ -302,7 +216,7 @@ bool Overlay::setParameter(const utils::Params& param, case utils::OV_BYPASS_1_LAYER: case utils::OV_BYPASS_2_LAYER: case utils::OV_BYPASS_3_LAYER: - if(!mOv->setParameter(param, dest)) { + if(!mOv->setTransform(transform, dest)) { ALOGE("Overlay %s failed", __FUNCTION__); return false; } @@ -313,25 +227,19 @@ bool Overlay::setParameter(const utils::Params& param, } return true; } + bool Overlay::setSource(const utils::PipeArgs args[utils::MAX_PIPES], utils::eDest dest) { - // FIXME that one needs to move to the state machine class utils::PipeArgs margs[utils::MAX_PIPES] = { args[0], args[1], args[2] }; utils::eOverlayState st = mState.state(); switch (st) { case utils::OV_CLOSED: - // if we get setSource when we are closed, then - // we will assume tranistion to OV_2D_VIDEO_ON_PANEL - // returns overlay - mOv = mState.handle_closed(utils::OV_2D_VIDEO_ON_PANEL); - if (!mOv) { - ALOGE("Overlay %s failed", __FUNCTION__); - this->reset(); // cleanup - return false; - } + ALOGE("Overlay %s failed, state is OV_CLOSED, set state first", + __FUNCTION__); + return false; break; case utils::OV_2D_VIDEO_ON_PANEL: case utils::OV_3D_VIDEO_ON_2D_PANEL: @@ -339,25 +247,15 @@ bool Overlay::setSource(const utils::PipeArgs args[utils::MAX_PIPES], case utils::OV_BYPASS_1_LAYER: case utils::OV_BYPASS_2_LAYER: case utils::OV_BYPASS_3_LAYER: - // no tweaking break; case utils::OV_3D_VIDEO_ON_3D_PANEL: case utils::OV_3D_VIDEO_ON_3D_TV: - margs[utils::CHANNEL_1].zorder = utils::ZORDER_1; - break; + //TODO set zorder for channel 1 as 1 in 3D pipe case utils::OV_2D_VIDEO_ON_PANEL_TV: case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - // If displaying on both, external VG pipe set to be no wait - margs[utils::CHANNEL_1].wait = utils::NO_WAIT; break; case utils::OV_2D_TRUE_UI_MIRROR: - // Set zorder -- external VG pipe (video) gets 0, RGB pipe (UI) gets 1 - margs[utils::CHANNEL_1].zorder = utils::ZORDER_0; - margs[utils::CHANNEL_2].zorder = utils::ZORDER_1; - // External VG (video) and RGB (UI) pipe set to be no wait - margs[utils::CHANNEL_0].wait = utils::WAIT; - margs[utils::CHANNEL_1].wait = utils::NO_WAIT; - margs[utils::CHANNEL_2].wait = utils::NO_WAIT; + // TODO Set zorder, external VG pipe (video) gets 0, RGB pipe (UI) gets 1 break; default: OVASSERT(false, "%s Unknown state %d", __FUNCTION__, st); @@ -371,39 +269,12 @@ bool Overlay::setSource(const utils::PipeArgs args[utils::MAX_PIPES], return true; } -void Overlay::setMemoryId(int id, utils::eDest dest) -{ - OVASSERT(mOv, - "%s Overlay and Rotator should be init at this point", - __FUNCTION__); - // FIXME that one needs to move to the state machine class - utils::eOverlayState st = mState.state(); - switch (st) { - case utils::OV_2D_VIDEO_ON_PANEL: - case utils::OV_2D_VIDEO_ON_PANEL_TV: - case utils::OV_3D_VIDEO_ON_2D_PANEL: - case utils::OV_3D_VIDEO_ON_3D_PANEL: - case utils::OV_3D_VIDEO_ON_3D_TV: - case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - case utils::OV_UI_MIRROR: - case utils::OV_2D_TRUE_UI_MIRROR: - case utils::OV_BYPASS_1_LAYER: - case utils::OV_BYPASS_2_LAYER: - case utils::OV_BYPASS_3_LAYER: - mOv->setMemoryId(id, dest); - break; - default: - OVASSERT(false, "setMemId Unknown state %d", st); - } -} - void Overlay::dump() const { OVASSERT(mOv, "%s Overlay and Rotator should be init at this point", __FUNCTION__); - // FIXME dump tate object, factory ALOGE("== Dump Overlay start =="); mState.dump(); mOv->dump(); @@ -426,30 +297,4 @@ Overlay* Overlay::getInstance() { return sInstance; } -/**** NullPipe ****/ - -bool NullPipe::open(RotatorBase*) { - ALOGE_IF(DEBUG_OVERLAY, "NullPipe open"); - return true; -} -bool NullPipe::close() { return true; } -bool NullPipe::commit() { return true; } -bool NullPipe::start(const utils::PipeArgs&) { return true; } -bool NullPipe::setCrop(const utils::Dim&) { return true; } -bool NullPipe::setPosition(const utils::Dim&) { return true; } -bool NullPipe::setParameter(const utils::Params&) { return true; } -bool NullPipe::setSource(const utils::PipeArgs&) { return true; } -bool NullPipe::queueBuffer(uint32_t offset) { return true; } -bool NullPipe::dequeueBuffer(void*&) { return true; } -bool NullPipe::waitForVsync() { return true; } -void NullPipe::setMemoryId(int) {} -// NullPipe will return by val here as opposed to other Pipes. -utils::PipeArgs NullPipe::getArgs() const { return utils::PipeArgs(); } -utils::eOverlayPipeType NullPipe::getOvPipeType() const { - return utils::OV_PIPE_TYPE_NULL; -} -void NullPipe::dump() const { - ALOGE("== NullPipe (null) start/end =="); -} - } // overlay diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h index e2ee6cd..b3324eb 100644 --- a/liboverlay/overlay.h +++ b/liboverlay/overlay.h @@ -43,31 +43,22 @@ public: /* Overlay related func */ - /* We need an empty open to just open the bare minimum for - * business. */ - bool open(); - - /* close rotator, state, overlayimpl*/ - bool close(); - /* Following is the same as the pure virt interface in ov impl */ - bool commit(utils::eDest dest = utils::OV_PIPE_ALL); - - bool queueBuffer(uint32_t offset, + bool setSource(const utils::PipeArgs args[utils::MAX_PIPES], utils::eDest dest = utils::OV_PIPE_ALL); - bool dequeueBuffer(void*& buf, - utils::eDest dest = utils::OV_PIPE_ALL); - bool waitForVsync(utils::eDest dest = utils::OV_PIPE1); bool setCrop(const utils::Dim& d, utils::eDest dest = utils::OV_PIPE_ALL); + bool setTransform(const int orientation, + utils::eDest dest = utils::OV_PIPE_ALL); bool setPosition(const utils::Dim& dim, utils::eDest dest = utils::OV_PIPE_ALL); - bool setParameter(const utils::Params& param, + bool commit(utils::eDest dest = utils::OV_PIPE_ALL); + + bool queueBuffer(int fd, uint32_t offset, utils::eDest dest = utils::OV_PIPE_ALL); - bool setSource(const utils::PipeArgs args[utils::MAX_PIPES], - utils::eDest dest = utils::OV_PIPE_ALL); - void setMemoryId(int id, utils::eDest dest = utils::OV_PIPE_ALL); + bool waitForVsync(utils::eDest dest = utils::OV_PIPE1); + void dump() const; /* state related functions */ diff --git a/liboverlay/overlayCtrl.cpp b/liboverlay/overlayCtrl.cpp index 6f84d07..bb91529 100644 --- a/liboverlay/overlayCtrl.cpp +++ b/liboverlay/overlayCtrl.cpp @@ -18,14 +18,14 @@ #include #include "overlayCtrlData.h" #include "fb_priv.h" +#include "gralloc_priv.h" //for interlace namespace overlay{ -bool Ctrl::open(uint32_t fbnum, - RotatorBase* rot) { - // MDP/FD open - if(!mMdp.open(fbnum)) { - ALOGE("Ctrl failed to open fbnum=%d", fbnum); +bool Ctrl::init(uint32_t fbnum) { + // MDP/FD init + if(!mMdp.init(fbnum)) { + ALOGE("Ctrl failed to init fbnum=%d", fbnum); return false; } @@ -34,127 +34,12 @@ bool Ctrl::open(uint32_t fbnum, return false; } - OVASSERT(rot, "rot is null"); - mRot = rot; - // rot should be already opened - return true; } -bool Ctrl::start(const utils::PipeArgs& args) -{ - int colorFormat = utils::getColorFormat(args.whf.format); - utils::eMdpFlags flags = args.mdpFlags; - - //XXX: Support for interlaced content - if (0) { - - setMdpFlags(flags, utils::OV_MDP_DEINTERLACE); - - // Get the actual format - colorFormat = args.whf.format ^ HAL_PIXEL_FORMAT_INTERLACE; - } - utils::Whf hwwhf(args.whf); - int fmt = utils::getMdpFormat(colorFormat); - // FIXME format should probably be int and not uint - if (fmt < 0) { - ALOGE("Ctrl failed getMdpFormat unsopported " - "colorFormat=%d format=%d flags=%d", - colorFormat, fmt, flags); - return false; - } - hwwhf.format = fmt; - - // devices should be already opened - // (by calling open earlier in the flow) - - const utils::PipeArgs newargs(flags, // mdp flags - args.orientation, // trans - hwwhf, - args.wait, - args.zorder, - args.isFg, - args.rotFlags); - if (!setInfo(newargs)) { - ALOGE("Ctrl failed to setInfo mdpflags=%d wait=%d zorder=%d", - newargs.mdpFlags, newargs.wait, newargs.zorder); - hwwhf.dump(); - return false; - } - - // FIXME, can we remove that and have it in - // setSource only when source changed? - if(!mRot->start(newargs)) { - ALOGE("Ctrl failed to start Rotation session"); - return false; - } - - // if geom is different, we need to prepare a new rot buffers. - // remap on demand when the current orientation is 90,180, etc. - // and the prev orientation was 0. It means we go from orient - if(!mRot->remap(utils::ROT_NUM_BUFS, newargs)) { - ALOGE("%s Error in remapping", __FUNCTION__); - } - - if(!mMdp.set()) { - ALOGE("Ctrl start failed set overlay"); - return false; - } - - // cache the src to be the current mCrop vals - mCrop.w = hwwhf.w; - mCrop.h = hwwhf.h; - - return true; -} - -inline void Ctrl::updateSource(RotatorBase* r, - const utils::PipeArgs& args, - utils::ScreenInfo& info) -{ - mMdp.updateSource(r, args, info); -} - bool Ctrl::setSource(const utils::PipeArgs& args) { - mMdp.setWait(args.wait); - - utils::PipeArgs newargs(args); - utils::Whf whf(args.whf); - // check geom change - if(mOvBufInfo != whf) { - // whf.format is given as HAL, that is why it is - // needed to be MDP fmt. - whf.format = utils::getColorFormat(whf.format); - int fmt = utils::getMdpFormat(whf.format); - OVASSERT(-1 != fmt, "Ctrl setSource format is -1"); - whf.format = fmt; - newargs.whf = whf; - updateSource(mRot, newargs, mInfo); - mMdp.setUserData(0); - if(!mRot->start(newargs)) { - ALOGE("%s failed start rot", __FUNCTION__); - return false; - } - - // if geom is different, we need to prepare a new rot buffers. - // remap on demand when the current orientation is 90,180, etc. - // and the prev orientation was 0. It means we go from orient - if(!mRot->remap(utils::ROT_NUM_BUFS, newargs)) { - ALOGE("%s Error in remapping", __FUNCTION__); - } - } - - // needed for setSource - mOrient = args.orientation; - - // cache last whf from gralloc hnd - mOvBufInfo = args.whf; - - // orign impl is returning false here - // because they will close the overlay and reopen it. - // New design would not do that. - return true; + return mMdp.setSource(args); } bool Ctrl::setPosition(const utils::Dim& dim) @@ -172,41 +57,21 @@ bool Ctrl::setPosition(const utils::Dim& dim) return true; } -bool Ctrl::setParameter(const utils::Params& p) +bool Ctrl::setTransform(const utils::eTransform& orient, const bool& rotUsed) { - if (utils::OVERLAY_TRANSFORM == p.param && - p.value == mMdp.getUserData()) { - // nothing to do here - return true; - } - - utils::eTransform trns = static_cast(p.value); - switch (p.param) { - case utils::OVERLAY_DITHER: - // nothing here today - ALOGE("Ctrl setParameter OVERLAY_DITHER not impl"); - return true; - case utils::OVERLAY_TRANSFORM: - if(!mRot->overlayTransform(mMdp, trns)) { - ALOGE("Ctrl setParameter failed Rot overlayTransform"); - return false; - } - break; - default: - ALOGE("Ctrl setParameter unknown param %d", p.param); - return false; + if(!mMdp.setTransform(orient, rotUsed)) { + ALOGE("Ctrl setTransform failed for Mdp"); + return false; } return true; } bool Ctrl::setCrop(const utils::Dim& d) { - // FIXME check channel validity if(!mMdp.setCrop(d)) { ALOGE("Data setCrop failed in MDP setCrop"); return false; } - mCrop = d; return true; } @@ -224,11 +89,9 @@ utils::Dim Ctrl::getAspectRatio(const utils::Whf& whf) const } if (inWhf.w * fbHeight > fbWidth * inWhf.h) { inWhf.h = fbWidth * inWhf.h / inWhf.w; - utils::even_out(inWhf.h); inWhf.w = fbWidth; } else if (inWhf.w * fbHeight < fbWidth * inWhf.h) { inWhf.w = fbHeight * inWhf.w / inWhf.h; - utils::even_out(inWhf.w); inWhf.h = fbHeight; } else { inWhf.w = fbWidth; @@ -339,10 +202,8 @@ utils::Dim Ctrl::getAspectRatio(const utils::Dim& dim) const { void Ctrl::dump() const { ALOGE("== Dump Ctrl start =="); - ALOGE("orient=%d", mOrient); mInfo.dump("mInfo"); mMdp.dump(); - mRot->dump(); ALOGE("== Dump Ctrl end =="); } diff --git a/liboverlay/overlayCtrlData.h b/liboverlay/overlayCtrlData.h index fbd701a..1398ec4 100644 --- a/liboverlay/overlayCtrlData.h +++ b/liboverlay/overlayCtrlData.h @@ -38,65 +38,40 @@ namespace ovutils = overlay::utils; namespace overlay { -// FIXME make int to be uint32 whenever possible - -class RotatorBase; - /* -* FIXME do we want rot to be template parameter? -* It's already using inheritance... -* * Sequence to use: -* open +* init * start * setXXX * close -* -* Can call setRot anytime to replace rotator on-the-fly * */ class Ctrl : utils::NoCopy { public: /* ctor */ explicit Ctrl(); - /* dtor close */ ~Ctrl(); - - /* should open devices? or start()? */ - bool open(uint32_t fbnum, RotatorBase* rot); - + /* init fd etc*/ + bool init(uint32_t fbnum); /* close underlying mdp */ bool close(); - /* Invoke methods for opening underlying devices - * flags - PIPE SHARED - * wait - WAIT, NO_WAIT */ - bool start(const utils::PipeArgs& args); - - /* Dynamically set rotator*/ - void setRot(RotatorBase* rot); - - /* set mdp posision using dim */ - bool setPosition(const utils::Dim& dim); - - /* set param using Params (param,value pair) */ - bool setParameter(const utils::Params& p); - /* set source using whf, orient and wait flag */ bool setSource(const utils::PipeArgs& args); - /* set crop info and pass it down to mdp */ bool setCrop(const utils::Dim& d); - + /* set orientation */ + bool setTransform(const utils::eTransform& p, const bool&); + /* set mdp position using dim */ + bool setPosition(const utils::Dim& dim); /* mdp set overlay/commit changes */ bool commit(); /* ctrl id */ - int getId() const; + int getPipeId() const; /* ctrl fd */ int getFd() const; - bool getRotSessId(int& id) const; utils::Dim getAspectRatio(const utils::Whf& whf) const; utils::Dim getAspectRatio(const utils::Dim& dim) const; @@ -113,40 +88,14 @@ private: /* Retrieve screen info from underlying mdp */ bool getScreenInfo(utils::ScreenInfo& info); - /* calls underlying mdp set info */ - bool setInfo(const utils::PipeArgs& args); - - /* given whf, update src */ - void updateSource(RotatorBase* r, - const utils::PipeArgs& args, - utils::ScreenInfo& info); - // mdp ctrl struct(info e.g.) MdpCtrl mMdp; - // Rotator - RotatorBase* mRot; - - /* Cache cropped value */ - utils::Dim mCrop; - /* Screen info */ utils::ScreenInfo mInfo; - - /* orientation cache FIXME */ - utils::eTransform mOrient; - - /* Cache last known whfz. - * That would help us compare to a previous - * source that was submitted */ - utils::Whf mOvBufInfo; }; -/* -* MDP = DataMdp, ROT = CtrlMdp usually since Rotator<> -* is instansiated with Ctrl data structure. -* */ class Data : utils::NoCopy { public: /* init, reset */ @@ -155,44 +104,30 @@ public: /* calls close */ ~Data(); - /* should open devices? or start()? */ - bool open(uint32_t fbnum, RotatorBase* rot); + /* init fd etc */ + bool init(uint32_t fbnum); /* calls underlying mdp close */ bool close(); - /* set the rotator */ - void setRot(RotatorBase* rot); - - /* set memory id in the mdp struct */ - void setMemoryId(int id); - - /* set overlay id in the mdp struct */ - void setId(int id); + /* set overlay pipe id in the mdp struct */ + void setPipeId(int id); /* get overlay id in the mdp struct */ - int getId() const; + int getPipeId() const; /* queue buffer to the overlay */ - bool queueBuffer(uint32_t offset); + bool queueBuffer(int fd, uint32_t offset); /* wait for vsync to be done */ bool waitForVsync(); /* sump the state of the obj */ void dump() const; + private: - /* play wrapper */ - bool play(); - - /* playWait wrapper */ - bool playWait(); - // mdp data struct MdpData mMdp; - - // Rotator - RotatorBase* mRot; }; /* This class just creates a Ctrl Data pair to be used by a pipe. @@ -207,7 +142,7 @@ struct CtrlData { //-------------Inlines------------------------------- -inline Ctrl::Ctrl() : mRot(0), mOrient(utils::OVERLAY_TRANSFORM_0) { +inline Ctrl::Ctrl() { mMdp.reset(); } @@ -216,7 +151,6 @@ inline Ctrl::~Ctrl() { } inline bool Ctrl::close() { - // do not close the rotator if(!mMdp.close()) return false; return true; @@ -238,70 +172,37 @@ inline bool Ctrl::getScreenInfo(utils::ScreenInfo& info) { return true; } -inline bool Ctrl::setInfo(const utils::PipeArgs& args) -{ - // FIXME set flags, zorder and wait separtly - if(!mMdp.setInfo(mRot, args, mInfo)){ - ALOGE("Ctrl failed to setInfo wait=%d mdpflags=%d " - "zorder=%d", args.wait, args.mdpFlags, args.zorder); - return false; - } - return true; -} - -inline int Ctrl::getId() const { - // FIXME check channel up? - return mMdp.getId(); +inline int Ctrl::getPipeId() const { + return mMdp.getPipeId(); } inline int Ctrl::getFd() const { - // FIXME check channel up? return mMdp.getFd(); } -inline bool Ctrl::getRotSessId(int& id) const { - // FIXME check channel up? - // should be -1 in case of no rot session active - id = mRot->getSessId(); - return true; -} - inline utils::ScreenInfo Ctrl::getScreenInfo() const { return mInfo; } inline utils::Dim Ctrl::getCrop() const { - return mCrop; + return mMdp.getSrcRectDim(); } - - -inline Data::Data() : mRot(0) { +inline Data::Data() { mMdp.reset(); } inline Data::~Data() { close(); } -inline void Data::setRot(RotatorBase* rot) { mRot = rot; } +inline void Data::setPipeId(int id) { mMdp.setPipeId(id); } -inline void Data::setMemoryId(int id) { mMdp.setMemoryId(id); } +inline int Data::getPipeId() const { return mMdp.getPipeId(); } -// really a reqid -inline void Data::setId(int id) { mMdp.setId(id); } - -inline int Data::getId() const { return mMdp.getId(); } - -inline bool Data::open(uint32_t fbnum, - RotatorBase* rot) { - if(!mMdp.open(fbnum)) { - ALOGE("Data cannot open mdp"); +inline bool Data::init(uint32_t fbnum) { + if(!mMdp.init(fbnum)) { + ALOGE("Data cannot init mdp"); return false; } - - OVASSERT(rot, "rot is null"); - mRot = rot; - - // rotator should be already opened here return true; } @@ -313,49 +214,22 @@ inline bool Data::close() { return true; } -inline bool Data::queueBuffer(uint32_t offset) { - // FIXME asserts on state validity - - mMdp.setOffset(offset); - mRot->setRotDataSrcMemId(mMdp.getMemoryId()); - // will play if succeeded - if(!mRot->prepareQueueBuf(offset)) { - ALOGE("Data failed to prepareQueueBuf"); - return false; - } - // Play can go either from mdp or rot - if(!this->play()){ - ALOGE("Data error in MDP/ROT play"); - return false; - } - - return true; +inline bool Data::queueBuffer(int fd, uint32_t offset) { + return mMdp.play(fd, offset); } inline bool Data::waitForVsync() { - - // Call mdp playWait - if(!this->playWait()){ - ALOGE("Error in MDP playWait"); + // Call mdp waitForVsync + if(!mMdp.waitForVsync()){ + ALOGE("Error in MDP %s", __FUNCTION__); return false; } - return true; } -inline bool Data::play() { - int fd = mMdp.getFd(); - return mRot->enabled() ? mRot->play(fd) : mMdp.play(); -} - -inline bool Data::playWait() { - return mMdp.playWait(); -} - inline void Data::dump() const { ALOGE("== Dump Data MDP start =="); mMdp.dump(); - mRot->dump(); ALOGE("== Dump Data MDP end =="); } diff --git a/liboverlay/overlayImpl.h b/liboverlay/overlayImpl.h index 5f999f2..6f950c0 100644 --- a/liboverlay/overlayImpl.h +++ b/liboverlay/overlayImpl.h @@ -33,8 +33,6 @@ #include "overlayUtils.h" #include "overlayRotator.h" -// FIXME make int to be uint32 whenever possible - namespace overlay { // Interface only. No member, no definiton (except ~ which can @@ -44,8 +42,8 @@ public: /* empty dtor. can be =0 with cpp impl*/ virtual ~OverlayImplBase() {} - /* Open pipe/rot for one dest */ - virtual bool openPipe(RotatorBase* rot, utils::eDest dest) = 0; + /* Init pipe/rot for one dest */ + virtual bool initPipe(RotatorBase* rot, utils::eDest dest) = 0; /* Close pipe/rot for all specified dest */ virtual bool closePipe(utils::eDest dest) = 0; @@ -53,12 +51,10 @@ public: /* Copy specified pipe/rot from ov passed in (used by state machine only) */ virtual bool copyOvPipe(OverlayImplBase* ov, utils::eDest dest) = 0; - /* TODO open func customized for RGBx pipes */ - - /* Open all pipes - * To open just one pipe, use openPipe() + /* Init all pipes + * To init just one pipe, use initPipe() * */ - virtual bool open(RotatorBase* rot0, + virtual bool init(RotatorBase* rot0, RotatorBase* rot1, RotatorBase* rot2) = 0; @@ -72,12 +68,8 @@ public: * */ virtual bool commit(utils::eDest dest = utils::OV_PIPE_ALL) = 0; - /* Queue buffer with offset*/ - virtual bool queueBuffer(uint32_t offset, - utils::eDest dest = utils::OV_PIPE_ALL) = 0; - - /* For RGBx pipes, dequeue buffer (that is fb chunk)*/ - virtual bool dequeueBuffer(void*& buf, + /* Queue buffer with fd from an offset*/ + virtual bool queueBuffer(int fd, uint32_t offset, utils::eDest dest = utils::OV_PIPE_ALL) = 0; /* Wait for vsync to be done on dest */ @@ -93,16 +85,13 @@ public: /* Set parameters - usually needed for Rotator, but would * be passed down the stack as well */ - virtual bool setParameter(const utils::Params& param, + virtual bool setTransform(const utils::eTransform& param, utils::eDest dest = utils::OV_PIPE_ALL) = 0; /* Set new source including orientation */ virtual bool setSource(const utils::PipeArgs[utils::MAX_PIPES], utils::eDest dest = utils::OV_PIPE_ALL) = 0; - /* set memory id to the underlying pipes */ - virtual void setMemoryId(int id, utils::eDest dest = utils::OV_PIPE_ALL) = 0; - /* Get the overlay pipe type */ virtual utils::eOverlayPipeType getOvPipeType(utils::eDest dest) const = 0; @@ -112,22 +101,21 @@ public: class NullPipe { public: - /* TODO open func customized for RGBx pipes */ - bool open(RotatorBase* rot); - bool close(); - bool start(const utils::PipeArgs& args); - bool commit(); - bool setCrop(const utils::Dim& d); - bool setPosition(const utils::Dim& dim); - bool setParameter(const utils::Params& param); - bool setSource(const utils::PipeArgs& args); - bool queueBuffer(uint32_t offset); - bool dequeueBuffer(void*& buf); - bool waitForVsync(); - void setMemoryId(int id); - utils::PipeArgs getArgs() const; - utils::eOverlayPipeType getOvPipeType() const; - void dump() const; + bool init(RotatorBase* rot) { return true; } + bool close() { return true; } + bool start(const utils::PipeArgs& args) { return true; } + bool commit() { return true; } + bool setCrop(const utils::Dim& d) { return true; } + bool setPosition(const utils::Dim& dim) { return true; } + bool setTransform(const utils::eTransform& param) { return true; } + bool setSource(const utils::PipeArgs& args) { return true; } + bool queueBuffer(int fd, uint32_t offset) { return true; } + bool waitForVsync() { return true; } + // NullPipe will return by val here as opposed to other Pipes. + utils::eOverlayPipeType getOvPipeType() const { + return utils::OV_PIPE_TYPE_NULL; + } + void dump() const {} }; /* @@ -143,7 +131,6 @@ public: /* ctor */ OverlayImpl(); - OverlayImpl(P0* p0, P1* p1, P2* p2); /* * Comments of the below functions are the same as the one @@ -151,12 +138,11 @@ public: * */ virtual ~OverlayImpl(); - virtual bool openPipe(RotatorBase* rot, utils::eDest dest); + virtual bool initPipe(RotatorBase* rot, utils::eDest dest); virtual bool closePipe(utils::eDest dest); virtual bool copyOvPipe(OverlayImplBase* ov, utils::eDest dest); - /* TODO open func customized for RGBx pipes */ - virtual bool open(RotatorBase* rot0, + virtual bool init(RotatorBase* rot0, RotatorBase* rot1, RotatorBase* rot2); virtual bool close(); @@ -165,16 +151,13 @@ public: utils::eDest dest = utils::OV_PIPE_ALL); virtual bool setPosition(const utils::Dim& dim, utils::eDest dest = utils::OV_PIPE_ALL); - virtual bool setParameter(const utils::Params& param, + virtual bool setTransform(const utils::eTransform& param, utils::eDest dest = utils::OV_PIPE_ALL); virtual bool setSource(const utils::PipeArgs[utils::MAX_PIPES], utils::eDest dest = utils::OV_PIPE_ALL); - virtual bool queueBuffer(uint32_t offset, - utils::eDest dest = utils::OV_PIPE_ALL); - virtual bool dequeueBuffer(void*& buf, + virtual bool queueBuffer(int fd, uint32_t offset, utils::eDest dest = utils::OV_PIPE_ALL); virtual bool waitForVsync(utils::eDest dest = utils::OV_PIPE1); - virtual void setMemoryId(int id, utils::eDest dest = utils::OV_PIPE_ALL); virtual utils::eOverlayPipeType getOvPipeType(utils::eDest dest) const; virtual void dump() const; @@ -197,74 +180,97 @@ private: - - //-----------Inlines and Template defn--------------------------------- +/**** OverlayImpl ****/ + template OverlayImpl::OverlayImpl() : - mPipe0(new P0), mPipe1(new P1), mPipe2(new P2), + mPipe0(0), mPipe1(0), mPipe2(0), mRotP0(0), mRotP1(0), mRotP2(0) -{} - -template -OverlayImpl::OverlayImpl(P0* p0, P1* p1, P2* p2) : - mPipe0(p0), mPipe1(p1), mPipe2(p2), - mRotP0(0), mRotP1(0), mRotP2(0) -{} +{ + //Do not create a pipe here. + //Either initPipe can create a pipe OR + //copyOvPipe can assign a pipe. +} template OverlayImpl::~OverlayImpl() { - // no op in the meantime. needed to be clean - // since state machine will do delete. so we - // do not want to close/delete pipes here + //Do not delete pipes. + //closePipe will close and delete. } -/* Open only one pipe/rot pair per call */ +/* Init only one pipe/rot pair per call */ template -bool OverlayImpl::openPipe(RotatorBase* rot, utils::eDest dest) +bool OverlayImpl::initPipe(RotatorBase* rot, utils::eDest dest) { OVASSERT(rot, "%s: OverlayImpl rot is null", __FUNCTION__); OVASSERT(utils::isValidDest(dest), "%s: OverlayImpl invalid dest=%d", __FUNCTION__, dest); - // Need to down case rotator to mdp one. - // we assume p0/p1/p2/px all use the _same_ underlying mdp structure. - // FIXME STATIC_ASSERT here - bool ret = true; if (utils::OV_PIPE0 & dest) { - OVASSERT(mPipe0, "%s: OverlayImpl pipe0 is null", __FUNCTION__); - ALOGE_IF(DEBUG_OVERLAY, "Open pipe0"); - ret = mPipe0->open(rot); + ALOGE_IF(DEBUG_OVERLAY, "init pipe0"); + mRotP0 = rot; + ret = mRotP0->init(); if(!ret) { - ALOGE("%s: OverlayImpl pipe0 failed to open", __FUNCTION__); + ALOGE("%s: OverlayImpl rot0 failed to init", __FUNCTION__); + return false; } + + mPipe0 = new P0(); + OVASSERT(mPipe0, "%s: OverlayImpl pipe0 is null", __FUNCTION__); + ret = mPipe0->init(rot); + if(!ret) { + ALOGE("%s: OverlayImpl pipe0 failed to init", __FUNCTION__); + return false; + } + return ret; } if (utils::OV_PIPE1 & dest) { - OVASSERT(mPipe1, "%s: OverlayImpl pipe1 is null", __FUNCTION__); - ALOGE_IF(DEBUG_OVERLAY, "Open pipe1"); - ret = mPipe1->open(rot); + ALOGE_IF(DEBUG_OVERLAY, "init pipe1"); + mRotP1 = rot; + ret = mRotP1->init(); if(!ret) { - ALOGE("%s: OverlayImpl pipe1 failed to open", __FUNCTION__); + ALOGE("%s: OverlayImpl rot1 failed to init", __FUNCTION__); + return false; } + + mPipe1 = new P1(); + OVASSERT(mPipe1, "%s: OverlayImpl pipe1 is null", __FUNCTION__); + ret = mPipe1->init(rot); + if(!ret) { + ALOGE("%s: OverlayImpl pipe1 failed to init", __FUNCTION__); + return false; + } + return ret; } if (utils::OV_PIPE2 & dest) { - OVASSERT(mPipe2, "%s: OverlayImpl pipe2 is null", __FUNCTION__); - ALOGE_IF(DEBUG_OVERLAY, "Open pipe2"); - ret = mPipe2->open(rot); + ALOGE_IF(DEBUG_OVERLAY, "init pipe2"); + mRotP2 = rot; + ret = mRotP2->init(); if(!ret) { - ALOGE("%s: OverlayImpl pipe2 failed to open", __FUNCTION__); + ALOGE("%s: OverlayImpl rot2 failed to init", __FUNCTION__); + return false; } + + mPipe2 = new P2(); + OVASSERT(mPipe2, "%s: OverlayImpl pipe2 is null", __FUNCTION__); + ret = mPipe2->init(rot); + if(!ret) { + ALOGE("%s: OverlayImpl pipe2 failed to init", __FUNCTION__); + return false; + } + return ret; } @@ -356,44 +362,48 @@ bool OverlayImpl::copyOvPipe(OverlayImplBase* ov, if (utils::OV_PIPE0 & dest) { mPipe0 = ovimpl->mPipe0; mRotP0 = ovimpl->mRotP0; + ovimpl->mPipe0 = 0; + ovimpl->mRotP0 = 0; } if (utils::OV_PIPE1 & dest) { mPipe1 = ovimpl->mPipe1; mRotP1 = ovimpl->mRotP1; + ovimpl->mPipe1 = 0; + ovimpl->mRotP1 = 0; } if (utils::OV_PIPE2 & dest) { mPipe2 = ovimpl->mPipe2; mRotP2 = ovimpl->mRotP2; + ovimpl->mPipe2 = 0; + ovimpl->mRotP2 = 0; } return true; } -/* TODO open func customized for RGBx pipes */ - -/* Open all pipes/rot */ +/* Init all pipes/rot */ template -bool OverlayImpl::open(RotatorBase* rot0, +bool OverlayImpl::init(RotatorBase* rot0, RotatorBase* rot1, RotatorBase* rot2) { - if (!this->openPipe(rot0, utils::OV_PIPE0)) { + if (!this->initPipe(rot0, utils::OV_PIPE0)) { if (!this->close()) { ALOGE("%s: failed to close at least one pipe", __FUNCTION__); } return false; } - if (!this->openPipe(rot1, utils::OV_PIPE1)) { + if (!this->initPipe(rot1, utils::OV_PIPE1)) { if (!this->close()) { ALOGE("%s: failed to close at least one pipe", __FUNCTION__); } return false; } - if (!this->openPipe(rot2, utils::OV_PIPE2)) { + if (!this->initPipe(rot2, utils::OV_PIPE2)) { if (!this->close()) { ALOGE("%s: failed to close at least one pipe", __FUNCTION__); } @@ -509,7 +519,7 @@ bool OverlayImpl::setPosition(const utils::Dim& d, } template -bool OverlayImpl::setParameter(const utils::Params& param, +bool OverlayImpl::setTransform(const utils::eTransform& param, utils::eDest dest) { OVASSERT(mPipe0 && mPipe1 && mPipe2, @@ -517,21 +527,21 @@ bool OverlayImpl::setParameter(const utils::Params& param, __FUNCTION__, mPipe0, mPipe1, mPipe2); if (utils::OV_PIPE0 & dest) { - if(!mPipe0->setParameter(param)) { + if(!mPipe0->setTransform(param)) { ALOGE("OverlayImpl p0 failed to setparam"); return false; } } if (utils::OV_PIPE1 & dest) { - if(!mPipe1->setParameter(param)) { + if(!mPipe1->setTransform(param)) { ALOGE("OverlayImpl p1 failed to setparam"); return false; } } if (utils::OV_PIPE2 & dest) { - if(!mPipe2->setParameter(param)) { + if(!mPipe2->setTransform(param)) { ALOGE("OverlayImpl p2 failed to setparam"); return false; } @@ -541,7 +551,8 @@ bool OverlayImpl::setParameter(const utils::Params& param, } template -bool OverlayImpl::setSource(const utils::PipeArgs args[utils::MAX_PIPES], +bool OverlayImpl::setSource( + const utils::PipeArgs args[utils::MAX_PIPES], utils::eDest dest) { OVASSERT(mPipe0 && mPipe1 && mPipe2, @@ -573,28 +584,29 @@ bool OverlayImpl::setSource(const utils::PipeArgs args[utils::MAX_PI } template -bool OverlayImpl::queueBuffer(uint32_t offset, utils::eDest dest) +bool OverlayImpl::queueBuffer(int fd, uint32_t offset, + utils::eDest dest) { OVASSERT(mPipe0 && mPipe1 && mPipe2, "%s: Pipes are null p0=%p p1=%p p2=%p", __FUNCTION__, mPipe0, mPipe1, mPipe2); if (utils::OV_PIPE0 & dest) { - if(!mPipe0->queueBuffer(offset)) { + if(!mPipe0->queueBuffer(fd, offset)) { ALOGE("OverlayImpl p0 failed to queueBuffer"); return false; } } if (utils::OV_PIPE1 & dest) { - if(!mPipe1->queueBuffer(offset)) { + if(!mPipe1->queueBuffer(fd, offset)) { ALOGE("OverlayImpl p1 failed to queueBuffer"); return false; } } if (utils::OV_PIPE2 & dest) { - if(!mPipe2->queueBuffer(offset)) { + if(!mPipe2->queueBuffer(fd, offset)) { ALOGE("OverlayImpl p2 failed to queueBuffer"); return false; } @@ -603,37 +615,6 @@ bool OverlayImpl::queueBuffer(uint32_t offset, utils::eDest dest) return true; } -template -bool OverlayImpl::dequeueBuffer(void*& buf, utils::eDest dest) -{ - OVASSERT(mPipe0 && mPipe1 && mPipe2, - "%s: Pipes are null p0=%p p1=%p p2=%p", - __FUNCTION__, mPipe0, mPipe1, mPipe2); - - if (utils::OV_PIPE0 & dest) { - if(!mPipe0->dequeueBuffer(buf)) { - ALOGE("OverlayImpl p0 failed to dequeueBuffer"); - return false; - } - } - - if (utils::OV_PIPE1 & dest) { - if(!mPipe1->dequeueBuffer(buf)) { - ALOGE("OverlayImpl p1 failed to dequeueBuffer"); - return false; - } - } - - if (utils::OV_PIPE2 & dest) { - if(!mPipe2->dequeueBuffer(buf)) { - ALOGE("OverlayImpl p2 failed to dequeueBuffer"); - return false; - } - } - - return true; -} - template bool OverlayImpl::waitForVsync(utils::eDest dest) { @@ -666,27 +647,8 @@ bool OverlayImpl::waitForVsync(utils::eDest dest) } template -void OverlayImpl::setMemoryId(int id, utils::eDest dest) -{ - OVASSERT(mPipe0 && mPipe1 && mPipe2, - "%s: Pipes are null p0=%p p1=%p p2=%p", - __FUNCTION__, mPipe0, mPipe1, mPipe2); - - if (utils::OV_PIPE0 & dest) { - mPipe0->setMemoryId(id); - } - - if (utils::OV_PIPE1 & dest) { - mPipe1->setMemoryId(id); - } - - if (utils::OV_PIPE2 & dest) { - mPipe2->setMemoryId(id); - } -} - -template -utils::eOverlayPipeType OverlayImpl::getOvPipeType(utils::eDest dest) const +utils::eOverlayPipeType OverlayImpl::getOvPipeType( + utils::eDest dest) const { OVASSERT(utils::isValidDest(dest), "%s: OverlayImpl invalid dest=%d", __FUNCTION__, dest); diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp index 09499c0..2cdd003 100644 --- a/liboverlay/overlayMdp.cpp +++ b/liboverlay/overlayMdp.cpp @@ -23,11 +23,11 @@ namespace ovutils = overlay::utils; namespace overlay { -bool MdpCtrl::open(uint32_t fbnum) { - // FD open +bool MdpCtrl::init(uint32_t fbnum) { + // FD init if(!utils::openDev(mFd, fbnum, - Res::devTemplate, O_RDWR)){ - ALOGE("Ctrl failed to open fbnum=%d", fbnum); + Res::fbPath, O_RDWR)){ + ALOGE("Ctrl failed to init fbnum=%d", fbnum); return false; } return true; @@ -36,12 +36,15 @@ bool MdpCtrl::open(uint32_t fbnum) { void MdpCtrl::reset() { utils::memset0(mOVInfo); utils::memset0(mLkgo); - mOVInfo.id = -1; - mLkgo.id = -1; + mOVInfo.id = MSMFB_NEW_REQUEST; + mLkgo.id = MSMFB_NEW_REQUEST; + mOrientation = utils::OVERLAY_TRANSFORM_0; + mRotUsed = false; } bool MdpCtrl::close() { - if(-1 == static_cast(mOVInfo.id)) return true; + if(MSMFB_NEW_REQUEST == static_cast(mOVInfo.id)) + return true; if(!mdp_wrapper::unsetOverlay(mFd.getFD(), mOVInfo.id)) { ALOGE("MdpCtrl close error in unset"); return false; @@ -53,6 +56,86 @@ bool MdpCtrl::close() { return true; } +bool MdpCtrl::setSource(const utils::PipeArgs& args) { + + setSrcWhf(args.whf); + + //TODO These are hardcoded. Can be moved out of setSource. + mOVInfo.alpha = 0xff; + mOVInfo.transp_mask = 0xffffffff; + + //TODO These calls should ideally be a part of setPipeParams API + setFlags(args.mdpFlags); + setZ(args.zorder); + setIsFg(args.isFg); + return true; +} + +bool MdpCtrl::setCrop(const utils::Dim& d) { + setSrcRectDim(d); + return true; +} + +bool MdpCtrl::setPosition(const overlay::utils::Dim& d, + int fbw, int fbh) +{ + ovutils::Dim dim(d); + ovutils::Dim ovsrcdim = getSrcRectDim(); + // Scaling of upto a max of 20 times supported + if(dim.w >(ovsrcdim.w * ovutils::HW_OV_MAGNIFICATION_LIMIT)){ + dim.w = ovutils::HW_OV_MAGNIFICATION_LIMIT * ovsrcdim.w; + dim.x = (fbw - dim.w) / 2; + } + if(dim.h >(ovsrcdim.h * ovutils::HW_OV_MAGNIFICATION_LIMIT)) { + dim.h = ovutils::HW_OV_MAGNIFICATION_LIMIT * ovsrcdim.h; + dim.y = (fbh - dim.h) / 2; + } + + setDstRectDim(dim); + return true; +} + +bool MdpCtrl::setTransform(const utils::eTransform& orient, + const bool& rotUsed) { + mOrientation = orient; + int rot = utils::getMdpOrient(orient); + setUserData(rot); + //Rotator can be requested by client even if layer has 0 orientation. + mRotUsed = rotUsed; + return true; +} + +void MdpCtrl::doTransform() { + adjustSrcWhf(mRotUsed); + setRotationFlags(); + //180 will be H + V + //270 will be H + V + 90 + if(mOrientation & utils::OVERLAY_TRANSFORM_FLIP_H) { + overlayTransFlipH(); + } + if(mOrientation & utils::OVERLAY_TRANSFORM_FLIP_V) { + overlayTransFlipV(); + } + if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90) { + overlayTransRot90(); + } +} + +bool MdpCtrl::set() { + //deferred calcs, so APIs could be called in any order. + doTransform(); + if(!mdp_wrapper::setOverlay(mFd.getFD(), mOVInfo)) { + ALOGE("MdpCtrl failed to setOverlay, restoring last known " + "good ov info"); + mdp_wrapper::dump("== Bad OVInfo is: ", mOVInfo); + mdp_wrapper::dump("== Last good known OVInfo is: ", mLkgo); + this->restore(); + return false; + } + this->save(); + return true; +} + bool MdpCtrl::getScreenInfo(overlay::utils::ScreenInfo& info) { fb_fix_screeninfo finfo; if (!mdp_wrapper::getFScreenInfo(mFd.getFD(), finfo)) { @@ -81,193 +164,24 @@ bool MdpCtrl::get() { return true; } -// that is the second part of original setParameter function -void MdpCtrl::setSrcFormat(const utils::Whf& whf) { - - //By default mdp src format is the same as buffer's - mOVInfo.src.format = whf.format; - - //If rotation is used and input formats are tiled then output of rotator is - //non-tiled. - // FIXME mRotInfo.enable = 1; for enable - if (getUserData()) { // if rotations enabled in MdpCtrl - if (whf.format == MDP_Y_CRCB_H2V2_TILE) - mOVInfo.src.format = MDP_Y_CRCB_H2V2; - else if (whf.format == MDP_Y_CBCR_H2V2_TILE) - mOVInfo.src.format = MDP_Y_CBCR_H2V2; - return; +//Adjust width, height, format if rotator is used. +void MdpCtrl::adjustSrcWhf(const bool& rotUsed) { + if(rotUsed) { + utils::Whf whf = getSrcWhf(); + if(whf.format == MDP_Y_CRCB_H2V2_TILE || + whf.format == MDP_Y_CBCR_H2V2_TILE) { + whf.w = utils::alignup(whf.w, 64); + whf.h = utils::alignup(whf.h, 32); + } + //For example: If original format is tiled, rotator outputs non-tiled, + //so update mdp's src fmt to that. + whf.format = utils::getRotOutFmt(whf.format); + setSrcWhf(whf); } - -} - -bool MdpCtrl::set() { - if(!this->ovChanged()) { - return true; // nothing todo here. - } - - if(!mdp_wrapper::setOverlay(mFd.getFD(), mOVInfo)) { - ALOGE("MdpCtrl failed to setOverlay, restoring last known " - "good ov info"); - mdp_wrapper::dump("== Bad OVInfo is: ", mOVInfo); - mdp_wrapper::dump("== Last good known OVInfo is: ", mLkgo); - this->restore(); - // FIXME, do we need to set the old one? - return false; - } - this->save(); - return true; -} - -bool MdpCtrl::setPosition(const overlay::utils::Dim& d, - int fbw, int fbh) -{ - // Validatee against FB size - if(!d.check(fbw, fbh)) { - ALOGE("MdpCtrl setPosition failed dest dim violate screen limits"); - return false; - } - - ovutils::Dim dim(d); - ovutils::Dim ovsrcdim = getSrcRectDim(); - // Scaling of upto a max of 8 times supported - if(dim.w >(ovsrcdim.w * ovutils::HW_OV_MAGNIFICATION_LIMIT)){ - dim.w = ovutils::HW_OV_MAGNIFICATION_LIMIT * ovsrcdim.w; - dim.x = (fbw - dim.w) / 2; - } - if(dim.h >(ovsrcdim.h * ovutils::HW_OV_MAGNIFICATION_LIMIT)) { - dim.h = ovutils::HW_OV_MAGNIFICATION_LIMIT * ovsrcdim.h; - dim.y = (fbh - dim.h) / 2; - } - - //dim.even_out(); - setDstRectDim(dim); - return true; -} - -void MdpCtrl::updateSource(RotatorBase* r, - const utils::PipeArgs& args, - const utils::ScreenInfo& info) { - utils::Whf whf(args.whf); - mOVInfo.src.width = whf.w; - mOVInfo.src.height = whf.h; - mOVInfo.src_rect.x = 0; - mOVInfo.src_rect.y = 0; - mOVInfo.dst_rect.x = 0; - mOVInfo.dst_rect.y = 0; - mOVInfo.dst_rect.w = whf.w; - mOVInfo.dst_rect.h = whf.h; - mOVInfo.src.format = whf.format; - - if(whf.format == MDP_Y_CRCB_H2V2_TILE || - (whf.format == MDP_Y_CBCR_H2V2_TILE)) { - // passing by value, setInfo fills it and return by val - mOVInfo = r->setInfo(args, mOVInfo); - } else { - mOVInfo.src_rect.w = whf.w; - mOVInfo.src_rect.h = whf.h; - } - - if (whf.w > info.mFBWidth) - mOVInfo.dst_rect.w = info.mFBWidth; - if (whf.h > info.mFBHeight) - mOVInfo.dst_rect.h = info.mFBHeight; - mSize = whf.size; -} - - -bool MdpCtrl::setInfo(RotatorBase* r, - const utils::PipeArgs& args, - const utils::ScreenInfo& info) -{ - // new request - utils::Whf whf(args.whf); - mOVInfo.id = MSMFB_NEW_REQUEST; - - updateSource(r, args, info); - - setUserData(0); - mOVInfo.alpha = 0xff; - mOVInfo.transp_mask = 0xffffffff; - setZ(args.zorder); - setFlags(args.mdpFlags); - setWait(args.wait); - setIsFg(args.isFg); - mSize = whf.size; - return true; -} - -bool MdpCtrl::setCrop(const utils::Dim& cdim) { - utils::Dim d(cdim); - const utils::Whf ovwhf = getSrcWhf(); - int udata = getUserData(); - switch(udata) { - case MDP_ROT_NOP: - break; // nothing to do here - case MDP_ROT_90: - case MDP_ROT_90 | MDP_FLIP_UD: - case MDP_ROT_90 | MDP_FLIP_LR: - { - if (ovwhf.w < (d.y + d.h)) { - ALOGE("MdpCtrl setCrop failed ROT 90 udata=%d", - udata); - d.dump(); - this->dump(); - return false; - } - uint32_t tmp = d.x; - d.x = ovwhf.w - (d.y + d.h); - d.y = tmp; - utils::swap(d.w, d.h); - }break; - case MDP_ROT_270: - { - if (ovwhf.h < (d.x + d.w)) { - ALOGE("MdpCtrl setCrop failed ROT 270 udata=%d", - udata); - d.dump(); - this->dump(); - return false; - } - uint32_t tmp = d.y; - d.y = ovwhf.h - (d.x + d.w); - d.x = tmp; - utils::swap(d.w, d.h); - }break; - case MDP_ROT_180: - { - if ((ovwhf.h < (d.y + d.h)) || - (ovwhf.w < ( d.x + d.w))) { - ALOGE("MdpCtrl setCrop failed ROT 180 udata=%d", - udata); - d.dump(); - this->dump(); - return false; - } - d.x = ovwhf.w - (d.x + d.w); - d.y = ovwhf.h - (d.y + d.h); - }break; - default: - if(!(udata & (MDP_FLIP_UD | MDP_FLIP_LR))) { - ALOGE("MdpCtrl setCrop unknown rot %d", udata); - return false; - } - } - - if(getSrcRectDim() == d) { - return true; // Nothing to do here - } - - utils::normalizeCrop(d.x, d.w); - utils::normalizeCrop(d.y, d.h); - - setSrcRectDim(d); - - return true; } void MdpCtrl::dump() const { ALOGE("== Dump MdpCtrl start =="); - ALOGE("size=%d", mSize); mFd.dump(); mdp_wrapper::dump("mOVInfo", mOVInfo); ALOGE("== Dump MdpCtrl end =="); diff --git a/liboverlay/overlayMdp.h b/liboverlay/overlayMdp.h index 29f8fd5..30bda79 100644 --- a/liboverlay/overlayMdp.h +++ b/liboverlay/overlayMdp.h @@ -22,12 +22,9 @@ #include "overlayUtils.h" #include "mdpWrapper.h" -#include "overlayRotator.h" namespace overlay{ -class RotatorBase; - /* * Mdp Ctrl holds corresponding fd and MDP related struct. * It is simple wrapper to MDP services @@ -40,20 +37,20 @@ public: /* dtor close */ ~MdpCtrl(); - /* Open underlying device using fbnum */ - bool open(uint32_t fbnum); + /* init underlying device using fbnum */ + bool init(uint32_t fbnum); /* unset overlay, reset and close fd */ bool close(); - /* reset and set ov id to -1*/ + /* reset and set ov id to -1 / MSMFB_NEW_REQUEST */ void reset(); /* get orient / user_data[0] */ int getOrient() const; /* returns session id */ - int getId() const; + int getPipeId() const; /* returns the fd associated to ctrl*/ int getFd() const; @@ -64,29 +61,15 @@ public: /* overlay get */ bool get(); - /* returns flags from mdp structure. - * Flags are WAIT/NOWAIT/PIPE SHARED*/ + /* returns flags from mdp structure */ int getFlags() const; /* set flags to mdp structure */ void setFlags(int f); - /* code taken from OverlayControlChannel::setOverlayInformation */ - bool setInfo(RotatorBase* r, - const utils::PipeArgs& args, - const utils::ScreenInfo& info); - - /* given whf, update src */ - void updateSource(RotatorBase* r, - const utils::PipeArgs& args, - const utils::ScreenInfo& info); - /* set z order */ void setZ(utils::eZorder z); - /* set Wait/nowait */ - void setWait(utils::eWait wait); - /* set isFg flag */ void setIsFg(utils::eIsFg isFg); @@ -102,8 +85,8 @@ public: /* set src whf */ void setSrcWhf(const utils::Whf& whf); - /* set source format based on rot info */ - void setSrcFormat(const utils::Whf& whf); + /* adjust source width height format based on rot info */ + void adjustSrcWhf(const bool& rotUsed); /* swap src w/h*/ void swapSrcWH(); @@ -128,7 +111,7 @@ public: void setUserData(int v); /* return true if current overlay is different - * than lask known good overlay */ + * than last known good overlay */ bool ovChanged() const; /* save mOVInfo to be last known good ov*/ @@ -137,6 +120,9 @@ public: /* restore last known good ov to be the current */ void restore(); + /* Sets the source total width, height, format */ + bool setSource(const utils::PipeArgs& pargs); + /* * Sets ROI, the unpadded region, for source buffer. * Should be called before a setPosition, for small clips. @@ -144,6 +130,8 @@ public: */ bool setCrop(const utils::Dim& d); + bool setTransform(const utils::eTransform& orient, const bool& rotUsed); + /* given a dim and w/h, set overlay dim */ bool setPosition(const utils::Dim& dim, int w, int h); @@ -152,8 +140,19 @@ public: /* dump state of the object */ void dump() const; + private: + /* helper functions for overlayTransform */ + void doTransform(); + void overlayTransFlipH(); + void overlayTransFlipV(); + void overlayTransRot90(); + + utils::eTransform mOrientation; //Holds requested orientation + bool mRotUsed; //whether rotator should be used even if requested + //orientation is 0. + /* last good known ov info */ mdp_overlay mLkgo; @@ -162,9 +161,6 @@ private: /* FD for the mdp fbnum */ OvFD mFd; - - /* cached size FIXME do we need it? */ - uint32_t mSize; }; @@ -201,8 +197,8 @@ public: /* dtor close*/ ~MdpData(); - /* open FD */ - bool open(uint32_t fbnum); + /* init FD */ + bool init(uint32_t fbnum); /* memset0 the underlying mdp object */ void reset(); @@ -210,29 +206,23 @@ public: /* close fd, and reset */ bool close(); - /* Set FD / memid */ - void setMemoryId(int id); - /* set id of mdp data */ - void setId(int id); + void setPipeId(int id); /* return ses id of data */ - int getId() const; + int getPipeId() const; /* get underlying fd*/ int getFd() const; /* get memory_id */ - int getMemoryId() const; - - /* set offset in underlying mdp obj */ - void setOffset(uint32_t o); + int getSrcMemoryId() const; /* calls wrapper play */ - bool play(); + bool play(int fd, uint32_t offset); - /* calls wrapper playWait */ - bool playWait(); + /* calls wrapper waitForVsync */ + bool waitForVsync(); /* dump state of the object */ void dump() const; @@ -247,21 +237,22 @@ private: //--------------Inlines--------------------------------- namespace utils { - inline bool openDev(OvFD& fd, int fb, - const char* const s, - int flags) { - return overlay::open(fd, fb, Res::devTemplate, O_RDWR); - } +inline bool openDev(OvFD& fd, int fbnum, + const char* const devpath, + int flags) { + return overlay::open(fd, fbnum, devpath, flags); +} +} +namespace { +// just a helper func for common operations x-(y+z) +int compute(uint32_t x, uint32_t y, uint32_t z) { + return x-(y+z); +} } - -template - inline void init(T& t) { - memset(&t, 0, sizeof(T)); - } ///// MdpCtrl ////// -inline MdpCtrl::MdpCtrl() : mSize(0) { +inline MdpCtrl::MdpCtrl() { reset(); } @@ -273,7 +264,7 @@ inline int MdpCtrl::getOrient() const { return getUserData(); } -inline int MdpCtrl::getId() const { +inline int MdpCtrl::getPipeId() const { return mOVInfo.id; } @@ -293,10 +284,6 @@ inline void MdpCtrl::setZ(overlay::utils::eZorder z) { mOVInfo.z_order = z; } -inline void MdpCtrl::setWait(overlay::utils::eWait wait) { - mOVInfo.flags = utils::setWait(wait, mOVInfo.flags); -} - inline void MdpCtrl::setIsFg(overlay::utils::eIsFg isFg) { mOVInfo.is_fg = isFg; } @@ -310,27 +297,25 @@ inline bool MdpCtrl::ovChanged() const { } inline void MdpCtrl::save() { - if(static_cast(mOVInfo.id) == -1) { + if(static_cast(mOVInfo.id) == MSMFB_NEW_REQUEST) { ALOGE("MdpCtrl current ov has id -1, will not save"); - // FIXME dump both? return; } mLkgo = mOVInfo; } inline void MdpCtrl::restore() { - if(static_cast(mLkgo.id) == -1) { + if(static_cast(mLkgo.id) == MSMFB_NEW_REQUEST) { ALOGE("MdpCtrl Lkgo ov has id -1, will not restore"); - // FIXME dump both? return; } mOVInfo = mLkgo; } inline overlay::utils::Whf MdpCtrl::getSrcWhf() const { - return utils::Whf(mOVInfo.src.width, - mOVInfo.src.height, - mOVInfo.src.format); + return utils::Whf( mOVInfo.src.width, + mOVInfo.src.height, + mOVInfo.src.format); } inline void MdpCtrl::setSrcWhf(const overlay::utils::Whf& whf) { @@ -340,10 +325,10 @@ inline void MdpCtrl::setSrcWhf(const overlay::utils::Whf& whf) { } inline overlay::utils::Dim MdpCtrl::getSrcRectDim() const { - return utils::Dim(mOVInfo.src_rect.x, - mOVInfo.src_rect.y, - mOVInfo.src_rect.w, - mOVInfo.src_rect.h); + return utils::Dim( mOVInfo.src_rect.x, + mOVInfo.src_rect.y, + mOVInfo.src_rect.w, + mOVInfo.src_rect.h); } inline void MdpCtrl::setSrcRectDim(const overlay::utils::Dim d) { @@ -354,10 +339,10 @@ inline void MdpCtrl::setSrcRectDim(const overlay::utils::Dim d) { } inline overlay::utils::Dim MdpCtrl::getDstRectDim() const { - return utils::Dim(mOVInfo.dst_rect.x, - mOVInfo.dst_rect.y, - mOVInfo.dst_rect.w, - mOVInfo.dst_rect.h); + return utils::Dim( mOVInfo.dst_rect.x, + mOVInfo.dst_rect.y, + mOVInfo.dst_rect.w, + mOVInfo.dst_rect.h); } inline void MdpCtrl::setDstRectDim(const overlay::utils::Dim d) { @@ -379,14 +364,46 @@ inline void MdpCtrl::setRotationFlags() { mOVInfo.flags &= ~MDP_SOURCE_ROTATED_90; } - inline void MdpCtrl::swapSrcWH() { utils::swap(mOVInfo.src.width, - mOVInfo.src.height); } + mOVInfo.src.height); +} inline void MdpCtrl::swapSrcRectWH() { - utils::swap(mOVInfo.src_rect.h, - mOVInfo.src_rect.w); } + utils::swap(mOVInfo.src_rect.w, + mOVInfo.src_rect.h); +} + +inline void MdpCtrl::overlayTransFlipH() +{ + utils::Dim d = getSrcRectDim(); + utils::Whf whf = getSrcWhf(); + d.x = compute(whf.w, d.x, d.w); + setSrcRectDim(d); +} + +inline void MdpCtrl::overlayTransFlipV() +{ + utils::Dim d = getSrcRectDim(); + utils::Whf whf = getSrcWhf(); + d.y = compute(whf.h, d.y, d.h); + setSrcRectDim(d); +} + +inline void MdpCtrl::overlayTransRot90() +{ + utils::Dim d = getSrcRectDim(); + utils::Whf whf = getSrcWhf(); + int tmp = d.x; + d.x = compute(whf.h, + d.y, + d.h); + d.y = tmp; + setSrcRectDim(d); + swapSrcWH(); + swapSrcRectWH(); +} + /////// MdpCtrl3D ////// @@ -434,10 +451,10 @@ inline MdpData::MdpData() { reset(); } inline MdpData::~MdpData() { close(); } -inline bool MdpData::open(uint32_t fbnum) { - // FD open - if(!utils::openDev(mFd, fbnum, Res::devTemplate, O_RDWR)){ - ALOGE("Ctrl failed to open fbnum=%d", fbnum); +inline bool MdpData::init(uint32_t fbnum) { + // FD init + if(!utils::openDev(mFd, fbnum, Res::fbPath, O_RDWR)){ + ALOGE("Ctrl failed to init fbnum=%d", fbnum); return false; } return true; @@ -457,28 +474,29 @@ inline bool MdpData::close() { return true; } -inline void MdpData::setMemoryId(int id) { mOvData.data.memory_id = id; } -inline int MdpData::getMemoryId() const { return mOvData.data.memory_id; } +inline int MdpData::getSrcMemoryId() const { return mOvData.data.memory_id; } -inline void MdpData::setId(int id) { mOvData.id = id; } +inline void MdpData::setPipeId(int id) { mOvData.id = id; } -inline int MdpData::getId() const { return mOvData.id; } +inline int MdpData::getPipeId() const { return mOvData.id; } inline int MdpData::getFd() const { return mFd.getFD(); } -inline void MdpData::setOffset(uint32_t o) { mOvData.data.offset = o; } - -inline bool MdpData::play() { +inline bool MdpData::play(int fd, uint32_t offset) { + mOvData.data.memory_id = fd; + mOvData.data.offset = offset; if(!mdp_wrapper::play(mFd.getFD(), mOvData)){ ALOGE("MdpData failed to play"); + dump(); return false; } return true; } -inline bool MdpData::playWait() { - if(!mdp_wrapper::playWait(mFd.getFD(), mOvData)){ - ALOGE("MdpData failed to playWait"); +inline bool MdpData::waitForVsync() { + if(!mdp_wrapper::waitForVsync(mFd.getFD(), mOvData)){ + ALOGE("%s failed", __FUNCTION__); + dump(); return false; } return true; diff --git a/liboverlay/overlayMem.h b/liboverlay/overlayMem.h index 7c04890..f8109d1 100644 --- a/liboverlay/overlayMem.h +++ b/liboverlay/overlayMem.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. +* Copyright (c) 2011, Code Aurora Forum. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -54,7 +54,7 @@ public: /* Use libgralloc to retrieve fd, base addr, alloc type */ bool open(uint32_t numbufs, - uint32_t bufSz, int flags = O_RDWR); + uint32_t bufSz, bool isSecure); /* close fd. assign base address to invalid*/ bool close(); @@ -115,14 +115,17 @@ inline OvMem::OvMem() { inline OvMem::~OvMem() { } inline bool OvMem::open(uint32_t numbufs, - uint32_t bufSz, int flags) + uint32_t bufSz, bool isSecure) { alloc_data data; - //XXX: secure buffers and IOMMU heap - int allocFlags = GRALLOC_USAGE_PRIVATE_MM_HEAP | - GRALLOC_USAGE_PRIVATE_DO_NOT_MAP; - int err = 0; + int allocFlags = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP; + if(isSecure) { + allocFlags |= GRALLOC_USAGE_PRIVATE_MM_HEAP; + allocFlags |= GRALLOC_USAGE_PRIVATE_DO_NOT_MAP; + allocFlags |= GRALLOC_USAGE_PRIVATE_CP_BUFFER; + } + int err = 0; OVASSERT(numbufs && bufSz, "numbufs=%d bufSz=%d", numbufs, bufSz); mBufSz = bufSz; @@ -138,6 +141,7 @@ inline bool OvMem::open(uint32_t numbufs, err = mAlloc->allocate(data, allocFlags, 0); if (err != 0) { ALOGE("OvMem: error allocating memory"); + return false; } mFd = data.fd; @@ -159,6 +163,7 @@ inline bool OvMem::close() ret = memalloc->free_buffer(mBaseAddr, mBufSz * mNumBuffers, 0, mFd); if (ret != 0) { ALOGE("OvMem: error freeing buffer"); + return false; } mFd = -1; @@ -166,7 +171,7 @@ inline bool OvMem::close() mAllocType = 0; mBufSz = 0; mNumBuffers = 0; - return ret; + return true; } inline bool OvMem::valid() const @@ -196,8 +201,9 @@ inline uint32_t OvMem::numBufs() const inline void OvMem::dump() const { - ALOGE("%s: fd=%d addr=%p type=%d bufsz=%u", - __FUNCTION__, mFd, mBaseAddr, mAllocType, mBufSz); + ALOGE("== Dump OvMem start =="); + ALOGE("fd=%d addr=%p type=%d bufsz=%u", mFd, mBaseAddr, mAllocType, mBufSz); + ALOGE("== Dump OvMem end =="); } } // overlay diff --git a/liboverlay/overlayRotator.cpp b/liboverlay/overlayRotator.cpp index 30c5ea5..306e28f 100644 --- a/liboverlay/overlayRotator.cpp +++ b/liboverlay/overlayRotator.cpp @@ -17,72 +17,110 @@ #include "overlayRotator.h" #include "overlayUtils.h" -#include "overlayMdp.h" namespace ovutils = overlay::utils; namespace overlay { -namespace utils { -inline mdp_overlay setInfoNullRot(const utils::PipeArgs& args, - const mdp_overlay& o) -{ - mdp_overlay ov = o; - utils::Whf whf(args.whf); - utils::Dim d(utils::getSrcRectDim(ov)); - - d.w = whf.w - (utils::alignup(whf.w, 64) - whf.w); - d.h = whf.h - (utils::alignup(whf.h, 32) - whf.h); - utils::setSrcRectDim(ov, d); - return ov; +int IRotatorHw::getRotatorHwType() { + //TODO figure out based on ioctl + return TYPE_MDP; } -inline mdp_overlay setInfoRot(const utils::PipeArgs& args, - const mdp_overlay& o) -{ - /* If there are no orientation, then we use setInfoRot - * That is even if we are a real rotator object (not null) - * Note, that if args.rotFlags are ENABLED - * it means we would still like to have rot - * even though it is ROT_0 */ - if(OVERLAY_TRANSFORM_0 == args.orientation && - utils::ROT_FLAG_ENABLED != args.rotFlags) { - return setInfoNullRot(args, o); +bool RotMem::close() { + bool ret = true; + for(uint32_t i=0; i < RotMem::MAX_ROT_MEM; ++i) { + // skip current, and if valid, close + if(m[i].valid()) { + if(m[i].close() == false) { + ALOGE("%s error in closing rot mem %d", __FUNCTION__, i); + ret = false; + } + } } - - mdp_overlay ov = o; - utils::Whf whf(args.whf); - utils::Dim d(utils::getSrcRectDim(ov)); - d.w = whf.w; - d.h = whf.h; - utils::Whf localwhf (utils::getSrcWhf(ov)); - localwhf.w = utils::alignup(whf.w, 64); - localwhf.h = utils::alignup(whf.h, 32); - d.x = localwhf.w - whf.w; - d.y = localwhf.h - whf.h; - utils::setSrcRectDim(ov, d); - utils::setSrcWhf(ov, localwhf); - return ov; + return ret; } -} // utils - -bool MdpRot::open() +bool MdpRot::init() { if(!mFd.open(Res::rotPath, O_RDWR)){ - ALOGE("MdpRot failed to open %s", Res::rotPath); + ALOGE("MdpRot failed to init %s", Res::rotPath); return false; } return true; } +void MdpRot::setSource(const overlay::utils::Whf& awhf) { + utils::Whf whf(awhf); + + mRotImgInfo.src.format = whf.format; + if(whf.format == MDP_Y_CRCB_H2V2_TILE || + whf.format == MDP_Y_CBCR_H2V2_TILE) { + whf.w = utils::alignup(awhf.w, 64); + whf.h = utils::alignup(awhf.h, 32); + } + + mRotImgInfo.src.width = whf.w; + mRotImgInfo.src.height = whf.h; + + mRotImgInfo.src_rect.w = whf.w; + mRotImgInfo.src_rect.h = whf.h; + + mRotImgInfo.dst.width = whf.w; + mRotImgInfo.dst.height = whf.h; + + mBufSize = awhf.size; +} + +void MdpRot::setFlags(const utils::eMdpFlags& flags) { + mRotImgInfo.secure = 0; + if(flags & utils::OV_MDP_SECURE_OVERLAY_SESSION) + mRotImgInfo.secure = 1; +} + +void MdpRot::setTransform(const utils::eTransform& rot, const bool& rotUsed) +{ + mOrientation = rot; + int r = utils::getMdpOrient(rot); + ALOGE_IF(DEBUG_OVERLAY, "%s: r=%d", __FUNCTION__, r); + setRotations(r); + setDisable(); + if(rotUsed) { + setEnable(); + } +} + +void MdpRot::doTransform() { + switch(mOrientation) { + case utils::OVERLAY_TRANSFORM_ROT_90: + case utils::OVERLAY_TRANSFORM_ROT_90_FLIP_H: + case utils::OVERLAY_TRANSFORM_ROT_90_FLIP_V: + case utils::OVERLAY_TRANSFORM_ROT_270: + utils::swap(mRotImgInfo.dst.width, mRotImgInfo.dst.height); + break; + default: + break; + } +} + +bool MdpRot::commit() { + doTransform(); + if(!overlay::mdp_wrapper::startRotator(mFd.getFD(), mRotImgInfo)) { + ALOGE("MdpRot commit failed"); + dump(); + return false; + } + mRotDataInfo.session_id = mRotImgInfo.session_id; + return true; +} + bool MdpRot::open_i(uint32_t numbufs, uint32_t bufsz) { OvMem mem; OVASSERT(MAP_FAILED == mem.addr(), "MAP failed in open_i"); - if(!mem.open(numbufs, bufsz)){ + if(!mem.open(numbufs, bufsz, mRotImgInfo.secure)){ ALOGE("%s: Failed to open", __func__); mem.close(); return false; @@ -91,25 +129,12 @@ bool MdpRot::open_i(uint32_t numbufs, uint32_t bufsz) OVASSERT(MAP_FAILED != mem.addr(), "MAP failed"); OVASSERT(mem.getFD() != -1, "getFd is -1"); - mData.data.memory_id = mem.getFD(); mRotDataInfo.dst.memory_id = mem.getFD(); mRotDataInfo.dst.offset = 0; mMem.curr().m = mem; return true; } -bool MdpRot::RotMem::close() { - bool ret = true; - for(uint32_t i=0; i < RotMem::MAX_ROT_MEM; ++i) { - // skip current, and if valid, close - if(m[i].valid() && (m[i].close() != 0)) { - ALOGE("%s error in closing prev rot mem %d", __FUNCTION__, i); - ret = false; - } - } - return ret; -} - bool MdpRot::close() { bool success = true; if(mFd.valid() && (getSessId() > 0)) { @@ -131,300 +156,78 @@ bool MdpRot::close() { return success; } -bool MdpRot::unmapNonCurrent() { - bool ret = true; - for(uint32_t i=0; i < RotMem::MAX_ROT_MEM; ++i) { - // skip current, and if valid, close - if(i != mMem._curr % RotMem::MAX_ROT_MEM && - mMem.m[i].valid() && - !mMem.m[i].close()) { - ALOGE("%s error in closing prev rot mem %d", __FUNCTION__, i); - ret = false; - } - } - return ret; -} - -bool MdpRot::remap(uint32_t numbufs, - const utils::PipeArgs& args) { +bool MdpRot::remap(uint32_t numbufs) { // if current size changed, remap - if(args.whf.size == mMem.curr().size()) { - ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, args.whf.size); - return true; - } - - // remap only if we have orientation. - // If rotFlags are ENABLED, it means we need rotation bufs - // even when orientation is 0 - if(utils::OVERLAY_TRANSFORM_0 == args.orientation && - utils::ROT_FLAG_ENABLED != args.rotFlags) { - ALOGE_IF(DEBUG_OVERLAY, "%s: orientation=%d, rotFlags=%d", - __FUNCTION__, args.orientation, args.rotFlags); + if(mBufSize == mMem.curr().size()) { + ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, mBufSize); return true; } ALOGE_IF(DEBUG_OVERLAY, "%s: size changed - remapping", __FUNCTION__); OVASSERT(!mMem.prev().valid(), "Prev should not be valid"); - // remap and have the current to be the new one. // ++mMem will make curr to be prev, and prev will be curr ++mMem; - if(!open_i(numbufs, args.whf.size)) { + if(!open_i(numbufs, mBufSize)) { ALOGE("%s Error could not open", __FUNCTION__); return false; } - OVASSERT(numbufs <= ROT_MAX_BUF_OFFSET, - "Numbufs %d > ROT_MAX_BUF_OFFSET", numbufs); for (uint32_t i = 0; i < numbufs; ++i) { - mMem.curr().mRotOffset[i] = i * args.whf.size; + mMem.curr().mRotOffset[i] = i * mBufSize; } return true; } -bool MdpRot::start() { - if(!overlay::mdp_wrapper::startRotator(mFd.getFD(), mRotImgInfo)) { - ALOGE("MdpRot start failed"); - this->dump(); - return false; - } - mRotDataInfo.session_id = mRotImgInfo.session_id; - return true; -} - void MdpRot::reset() { ovutils::memset0(mRotImgInfo); ovutils::memset0(mRotDataInfo); - ovutils::memset0(mData); ovutils::memset0(mMem.curr().mRotOffset); ovutils::memset0(mMem.prev().mRotOffset); mMem.curr().mCurrOffset = 0; mMem.prev().mCurrOffset = 0; - isSrcFB = false; + mBufSize = 0; + mOrientation = utils::OVERLAY_TRANSFORM_0; } -bool MdpRot::prepareQueueBuf(uint32_t offset) { - // FIXME if it fails, what happens to the above current item? +bool MdpRot::queueBuffer(int fd, uint32_t offset) { if(enabled()) { - OVASSERT(mMem.curr().m.numBufs(), - "prepareQueueBuf numbufs is 0"); - - // If the rotator source is FB - if(isSrcFB) { - mRotDataInfo.src.flags |= MDP_MEMORY_ID_TYPE_FB; - } - + mRotDataInfo.src.memory_id = fd; mRotDataInfo.src.offset = offset; + + remap(RotMem::Mem::ROT_NUM_BUFS); + OVASSERT(mMem.curr().m.numBufs(), + "queueBuffer numbufs is 0"); mRotDataInfo.dst.offset = mMem.curr().mRotOffset[mMem.curr().mCurrOffset]; mMem.curr().mCurrOffset = (mMem.curr().mCurrOffset + 1) % mMem.curr().m.numBufs(); + if(!overlay::mdp_wrapper::rotate(mFd.getFD(), mRotDataInfo)) { ALOGE("MdpRot failed rotate"); + dump(); return false; } - mData.data.offset = mRotDataInfo.dst.offset; - } - return true; -} - -bool MdpRot::play(int fd) { - if(!overlay::mdp_wrapper::play(fd, mData)) { - ALOGE("MdpRot failed to play with fd=%d", fd); - return false; - } - - // if the prev mem is valid, we need to close - if(mMem.prev().valid()) { - // FIXME FIXME FIXME if no wait for vsync the above - // play will return immediatly and might cause - // tearing when prev.close is called. - if(!mMem.prev().close()) { - ALOGE("%s error in closing prev rot mem", __FUNCTION__); + // if the prev mem is valid, we need to close + if(mMem.prev().valid()) { + // FIXME if no wait for vsync the above + // play will return immediatly and might cause + // tearing when prev.close is called. + if(!mMem.prev().close()) { + ALOGE("%s error in closing prev rot mem", __FUNCTION__); + return false; + } } } return true; } -///// Null Rot //// - -mdp_overlay NullRotator::setInfo( - const utils::PipeArgs& args, - const mdp_overlay& o) { - return utils::setInfoNullRot(args, o); -} - -///// Rotator //// - -mdp_overlay Rotator::setInfo( - const utils::PipeArgs& args, - const mdp_overlay& o) -{ - return utils::setInfoRot(args, o); -} - -bool Rotator::overlayTransform(MdpCtrl& mdp, - utils::eTransform& rot) -{ - ALOGE_IF(DEBUG_OVERLAY, "%s: rot=%d", __FUNCTION__, rot); - switch(int(rot)) { - case 0: - case HAL_TRANSFORM_FLIP_H: - case HAL_TRANSFORM_FLIP_V: - overlayTransFlipHV(mdp, rot); - break; - case HAL_TRANSFORM_ROT_90: - case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H): - case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_V): - overlayTransFlipRot90(mdp, rot); - break; - case HAL_TRANSFORM_ROT_180: - overlayTransFlipRot180(mdp); - break; - case HAL_TRANSFORM_ROT_270: - overlayTransFlipRot270(mdp); - break; - default: - ALOGE("%s: Error due to unknown rot value %d", __FUNCTION__, rot); - return false; - } - - /* everything below is rotation related */ - int r = utils::getMdpOrient(rot); - ALOGE_IF(DEBUG_OVERLAY, "%s: r=%d", __FUNCTION__, r); - if (r == -1) { - ALOGE("Ctrl setParameter rot it -1"); - return false; - } - - // Need to have both in sync - mdp.setUserData(r); - this->setRotations(r); - this->setDisable(); - if(r) { - this->setEnable(); - } - - /* set src format using rotation info - * e.g. (12-->5 in case of rotation) */ - mdp.setSrcFormat(this->getSrcWhf()); - - // based on 90/270 set flags - mdp.setRotationFlags(); - return true; -} - -void Rotator::overlayTransFlipHV(MdpCtrl& mdp, - utils::eTransform& rot) -{ - int val = mdp.getUserData(); - ALOGE_IF(DEBUG_OVERLAY, "%s: prev=%d", __FUNCTION__, val); - utils::Dim d = mdp.getSrcRectDim(); - utils::Whf whf = mdp.getSrcWhf(); - if (val == MDP_ROT_90) { - int tmp = d.y; - d.y = compute(whf.w, - d.x, - d.w); - d.x = tmp; - mdp.setSrcRectDim(d); - utils::swapOVRotWidthHeight(mRot, mdp); - } - else if (val == MDP_ROT_270) { - int tmp = d.x; - d.x = compute(whf.h, - d.y, - d.h); - d.y = tmp; - mdp.setSrcRectDim(d); - utils::swapOVRotWidthHeight(mRot, mdp); - } -} - -void Rotator::overlayTransFlipRot90(MdpCtrl& mdp, - utils::eTransform& rot) -{ - int val = mdp.getUserData(); - ALOGE_IF(DEBUG_OVERLAY, "%s: prev=%d", __FUNCTION__, val); - utils::Dim d = mdp.getSrcRectDim(); - utils::Whf whf = mdp.getSrcWhf(); - if (val == MDP_ROT_270) { - d.x = compute(whf.w, - d.x, - d.w); - d.y = compute(whf.h, - d.y, - d.h); - } - else if (val == MDP_ROT_NOP || val == MDP_ROT_180) { - int tmp = d.x; - d.x = compute(whf.h, - d.y, - d.h); - d.y = tmp; - mdp.setSrcRectDim(d); - utils::swapOVRotWidthHeight(mRot, mdp); - } -} - -void Rotator::overlayTransFlipRot180(MdpCtrl& mdp) -{ - int val = mdp.getUserData(); - ALOGE_IF(DEBUG_OVERLAY, "%s: prev=%d", __FUNCTION__, val); - utils::Dim d = mdp.getSrcRectDim(); - utils::Whf whf = mdp.getSrcWhf(); - if (val == MDP_ROT_270) { - int tmp = d.y; - d.y = compute(whf.w, - d.x, - d.w); - d.x = tmp; - mdp.setSrcRectDim(d); - utils::swapOVRotWidthHeight(mRot, mdp); - } - else if (val == MDP_ROT_90) { - int tmp = d.x; - d.x = compute(whf.h, - d.y, - d.h); - d.y = tmp; - mdp.setSrcRectDim(d); - utils::swapOVRotWidthHeight(mRot, mdp); - } -} - -void Rotator::overlayTransFlipRot270(MdpCtrl& mdp) -{ - int val = mdp.getUserData(); - ALOGE_IF(DEBUG_OVERLAY, "%s: prev=%d", __FUNCTION__, val); - utils::Dim d = mdp.getSrcRectDim(); - utils::Whf whf = mdp.getSrcWhf(); - if (val == MDP_ROT_90) { - d.y = compute(whf.h, - d.y, - d.h); - d.x = compute(whf.w, - d.x, - d.w); - } - else if (val == MDP_ROT_NOP || val == MDP_ROT_180) { - int tmp = d.y; - d.y = compute(whf.w, - d.x, - d.w); - d.x = tmp; - mdp.setSrcRectDim(d); - utils::swapOVRotWidthHeight(mRot, mdp); - } -} - void MdpRot::dump() const { ALOGE("== Dump MdpRot start =="); mFd.dump(); mMem.curr().m.dump(); mdp_wrapper::dump("mRotImgInfo", mRotImgInfo); mdp_wrapper::dump("mRotDataInfo", mRotDataInfo); - mdp_wrapper::dump("mData", mData); ALOGE("== Dump MdpRot end =="); } } diff --git a/liboverlay/overlayRotator.h b/liboverlay/overlayRotator.h index 39c4f0c..153fb2c 100644 --- a/liboverlay/overlayRotator.h +++ b/liboverlay/overlayRotator.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. +* Copyright (c) 2011, Code Aurora Forum. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -27,8 +27,8 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef OVERLAY_ROTATOR_H -#define OVERLAY_ROTATOR_H +#ifndef OVERlAY_ROTATOR_H +#define OVERlAY_ROTATOR_H #include @@ -37,158 +37,111 @@ #include "overlayMem.h" namespace overlay { - class MdpCtrl; + +class IRotatorHw; /* -* MDP rot holds MDP's rotation related structures. -* -* */ -class MdpRot { -public: - /* ctor */ - explicit MdpRot(); - - /* open fd for rotator. map bufs is defered */ - bool open(); - - /* remap rot buffers */ - bool remap(uint32_t numbufs, const utils::PipeArgs& args); - - /* Unmap everything that is not current */ - bool unmapNonCurrent(); - - /* close fd, mem */ - bool close(); - - /* reset underlying data, basically memset 0 */ - void reset(); - - /* calls underlying wrappers to start rotator */ - bool start(); - - /* start underlying but use given whf and flags */ - bool start(const utils::PipeArgs& args); - - /* start underlying but use given whf and flags. - * Has the ability to parameterize the dst fmt */ - template - bool start(const utils::PipeArgs& args); - - /* assign memory id to mdp structure */ - void setDataMemId(int fd); - void setRotDataSrcMemId(int fd); - - /* Mark src as FB (non-ION) */ - void setSrcFB(bool); - - /* get dst (for offset and memory id) non-virt */ - int getDstMemId() const; - uint32_t getDstOffset() const; - - /* set enable/disable flag */ - void setEnable(); - void setDisable(); - bool enabled() const; - - /* set rotator flag*/ - void setRotations(uint32_t r); - - /* set the req data id in mData */ - void setDataReqId(int id); - - /* swap rot info dst w/h */ - void swapDstWH(); - - /* returns a copy of src whf */ - utils::Whf getSrcWhf() const; - - /* setup rotator data before queue buf calls - * call play if rotate call succeed. return false if failed */ - bool prepareQueueBuf(uint32_t offset); - - /* call play on mdp*/ - bool play(int fd); - - /* set src whf */ - void setSrcWhf(const utils::Whf& whf); - - /* returns rotator session id */ - int getSessId() const; - - /* dump the state of the object */ - void dump() const; - -private: - bool open_i(uint32_t numbufs, uint32_t bufsz); - - /* max buf no for offset */ - enum { ROT_MAX_BUF_OFFSET = 2 }; - /* rot info*/ - msm_rotator_img_info mRotImgInfo; - /* rot data */ - msm_rotator_data_info mRotDataInfo; - /* data needed for rotator */ - msmfb_overlay_data mData; - /* rotator fd */ - OvFD mFd; - /* Array of memory map for rotator - * The array enable us to change rot buffers/mapping - * on the fly*/ - struct RotMem { - enum {MAX_ROT_MEM = 2}; - struct Mem { - Mem() : mCurrOffset(0) {utils::memset0(mRotOffset); } - bool valid() { return m.valid(); } - bool close() { return m.close(); } - uint32_t size() const { return m.bufSz(); } - /* rotator data info dst offset */ - uint32_t mRotOffset[ROT_MAX_BUF_OFFSET]; - /* current offset slot from mRotOffset */ - uint32_t mCurrOffset; - OvMem m; - }; - RotMem() : _curr(0) {} - Mem& curr() { return m[_curr % MAX_ROT_MEM]; } - const Mem& curr() const { return m[_curr % MAX_ROT_MEM]; } - Mem& prev() { return m[(_curr+1) % MAX_ROT_MEM]; } - RotMem& operator++() { ++_curr; return *this; } - bool close(); - uint32_t _curr; - Mem m[MAX_ROT_MEM]; - } mMem; - bool isSrcFB; -}; - -/* -* RotatorBase. No memebers, just interface. -* ~ can also be =0 with empty impl in cpp. +* RotatorBase. No members, just interface. +* can also be =0 with empty impl in cpp. * */ class RotatorBase { public: /* Most of the below are No op funcs for RotatorBase */ virtual ~RotatorBase() {} - virtual bool open() = 0; - virtual bool remap(uint32_t numbufs, const utils::PipeArgs& args) = 0; + virtual bool init() = 0; virtual bool close() = 0; - virtual bool start(const utils::PipeArgs& args) = 0; - virtual bool start() = 0; - virtual mdp_overlay setInfo(const utils::PipeArgs& args, - const mdp_overlay& o) = 0; - virtual bool overlayTransform(MdpCtrl& mdp, - utils::eTransform& rot) = 0; - virtual void setSrcWhf(const utils::Whf& wfh) = 0; - virtual utils::Whf getSrcWhf() const = 0; - virtual void setRotations(uint32_t r) = 0; - virtual void setDataReqId(int id) = 0; - virtual bool prepareQueueBuf(uint32_t offset) = 0; - virtual bool play(int fd) = 0; + virtual void setSource(const utils::Whf& wfh) = 0; + virtual void setFlags(const utils::eMdpFlags& flags) = 0; + virtual void setTransform(const utils::eTransform& rot, + const bool& rotUsed) = 0; + virtual bool commit() = 0; + virtual bool queueBuffer(int fd, uint32_t offset) = 0; + virtual void setEnable() = 0; virtual void setDisable() = 0; + virtual void setRotations(uint32_t r) = 0; + virtual void setSrcFB() = 0; + virtual bool enabled() const = 0; - virtual void setDataMemId(int fd) = 0; - virtual void setRotDataSrcMemId(int fd) = 0; - virtual void setSrcFB(bool) = 0; virtual int getSessId() const = 0; + virtual int getDstMemId() const = 0; + virtual uint32_t getDstOffset() const = 0; virtual void dump() const = 0; + +protected: + //Hardware specific rotator impl. + IRotatorHw *mRot; +}; + +/* + * Rotator Hw Interface. Any hardware specific implementation should inherit + * from this. + */ +class IRotatorHw { +public: + /* Most of the below are No op funcs for RotatorBase */ + virtual ~IRotatorHw() {} + /* init fd for rotator. map bufs is defered */ + virtual bool init() = 0; + /* close fd, mem */ + virtual bool close() = 0; + /* set src */ + virtual void setSource(const utils::Whf& wfh) = 0; + /* set mdp flags, will use only stuff necessary for rotator */ + virtual void setFlags(const utils::eMdpFlags& flags) = 0; + /* Set rotation and calculate */ + virtual void setTransform(const utils::eTransform& rot, + const bool& rotUsed) = 0; + /* calls underlying wrappers to start rotator */ + virtual bool commit() = 0; + /* Lazy buffer allocation. queue buffer */ + virtual bool queueBuffer(int fd, uint32_t offset) = 0; + /* set enable/disable flag */ + virtual void setEnable() = 0; + virtual void setDisable() = 0; + /* set rotator flag*/ + virtual void setRotations(uint32_t r) = 0; + /* Mark src as FB (non-ION) */ + virtual void setSrcFB() = 0; + /* Retusn true if rotator enabled */ + virtual bool enabled() const = 0; + /* returns rotator session id */ + virtual int getSessId() const = 0; + /* get dst (for offset and memory id) non-virt */ + virtual int getDstMemId() const = 0; + virtual uint32_t getDstOffset() const = 0; + /* dump the state of the object */ + virtual void dump() const = 0; + + enum { TYPE_MDP, TYPE_MDSS }; + /*Returns rotator h/w type */ + static int getRotatorHwType(); +}; + +/* +* Actual Rotator impl. +* */ +class Rotator : public RotatorBase +{ +public: + explicit Rotator(); + virtual ~Rotator(); + virtual bool init(); + virtual bool close(); + virtual void setSource(const utils::Whf& wfh); + virtual void setFlags(const utils::eMdpFlags& flags); + virtual void setTransform(const utils::eTransform& rot, + const bool& rotUsed); + virtual bool commit(); + virtual void setRotations(uint32_t r); + virtual void setSrcFB(); + virtual int getDstMemId() const; + virtual uint32_t getDstOffset() const; + virtual void setEnable(); + virtual void setDisable(); + virtual bool enabled () const; + virtual int getSessId() const; + virtual bool queueBuffer(int fd, uint32_t offset); + virtual void dump() const; }; /* @@ -198,357 +151,217 @@ class NullRotator : public RotatorBase { public: /* Most of the below are No op funcs for RotatorBase */ virtual ~NullRotator(); - virtual bool open(); - virtual bool remap(uint32_t numbufs, const utils::PipeArgs& args); + virtual bool init(); virtual bool close(); - virtual bool start(const utils::PipeArgs& args); - virtual bool start(); - /* null rotator behavior should set info in a specific way */ - virtual mdp_overlay setInfo(const utils::PipeArgs& args, - const mdp_overlay& o); - virtual bool overlayTransform(MdpCtrl& o, - utils::eTransform& rot); - virtual void setSrcWhf(const utils::Whf& wfh); - virtual utils::Whf getSrcWhf() const; + virtual void setSource(const utils::Whf& wfh); + virtual void setFlags(const utils::eMdpFlags& flags); + virtual void setTransform(const utils::eTransform& rot, + const bool& rotUsed); + virtual bool commit(); virtual void setRotations(uint32_t r); - virtual void setDataReqId(int id); - virtual bool prepareQueueBuf(uint32_t offset); - virtual bool play(int fd); + virtual bool queueBuffer(int fd, uint32_t offset); virtual void setEnable(); virtual void setDisable(); virtual bool enabled () const; - virtual void setDataMemId(int fd); - virtual void setRotDataSrcMemId(int fd); - virtual void setSrcFB(bool); + virtual void setSrcFB(); virtual int getSessId() const; + virtual int getDstMemId() const; + virtual uint32_t getDstOffset() const; virtual void dump() const; }; +/* + Manages the case where new rotator memory needs to be + allocated, before previous is freed, due to resolution change etc. If we make + rotator memory to be always max size, irrespctive of source resolution then + we don't need this RotMem wrapper. The inner class is sufficient. +*/ +struct RotMem { + // Max rotator memory allocations + enum { MAX_ROT_MEM = 2}; + + //Manages the rotator buffer offsets. + struct Mem { + Mem() : mCurrOffset(0) {utils::memset0(mRotOffset); } + bool valid() { return m.valid(); } + bool close() { return m.close(); } + uint32_t size() const { return m.bufSz(); } + // Max rotator buffers + enum { ROT_NUM_BUFS = 2 }; + // rotator data info dst offset + uint32_t mRotOffset[ROT_NUM_BUFS]; + // current offset slot from mRotOffset + uint32_t mCurrOffset; + OvMem m; + }; + + RotMem() : _curr(0) {} + Mem& curr() { return m[_curr % MAX_ROT_MEM]; } + const Mem& curr() const { return m[_curr % MAX_ROT_MEM]; } + Mem& prev() { return m[(_curr+1) % MAX_ROT_MEM]; } + RotMem& operator++() { ++_curr; return *this; } + bool close(); + uint32_t _curr; + Mem m[MAX_ROT_MEM]; +}; /* -* Rotator impl. +* MDP rot holds MDP's rotation related structures. +* * */ -class Rotator : public RotatorBase -{ +class MdpRot : public IRotatorHw { public: - /* construct underlying object */ - explicit Rotator(); - - /* close underlying rot */ - virtual ~Rotator(); - - /* calls underlying open */ - virtual bool open(); - - /* remap rot buffers */ - virtual bool remap(uint32_t numbufs, const utils::PipeArgs& args); - - /* calls underlying close */ - virtual bool close(); - - /* calls underlying start */ - virtual bool start(); - - /* calls underlying start with whf and flags */ - virtual bool start(const utils::PipeArgs& args); - - /* non virtual - calls underlying start with whf and flags. - * Has the ability to parameterize the dst */ - template - bool start(const utils::PipeArgs& args); - - /* Unmap everything that is not current */ - bool unmapNonCurrent(); - - /* set info using whf and given mdp */ - virtual mdp_overlay setInfo(const utils::PipeArgs& args, - const mdp_overlay& o); - - /* transform function for the MDP */ - virtual bool overlayTransform(MdpCtrl& mdp, - utils::eTransform& rot); - - /* set src whf */ - virtual void setSrcWhf(const utils::Whf& wfh); - - /* set Rotations */ - virtual void setRotations(uint32_t r); - - /* set the req data id in mData */ - virtual void setDataReqId(int id); - - /* set memory_id */ - virtual void setDataMemId(int fd); - virtual void setRotDataSrcMemId(int fd); - - /* Mark the src for rotator as FB. usually set by UI mirroing cases */ - virtual void setSrcFB(bool); - - /* get dst (for offset and memory id) non-virt */ + explicit MdpRot(); + ~MdpRot(); + bool init(); + bool close(); + void setSource(const utils::Whf& whf); + virtual void setFlags(const utils::eMdpFlags& flags); + void setTransform(const utils::eTransform& rot, + const bool& rotUsed); + bool commit(); + bool queueBuffer(int fd, uint32_t offset); + void setEnable(); + void setDisable(); + void setRotations(uint32_t r); + void setSrcFB(); + bool enabled() const; + int getSessId() const; int getDstMemId() const; uint32_t getDstOffset() const; + void dump() const; - /* set enable/disable flag */ - virtual void setEnable(); - virtual void setDisable(); - virtual bool enabled () const; - - /* return rotator sess id */ - virtual int getSessId() const; - - /* return a copy of src whf*/ - virtual utils::Whf getSrcWhf() const; - - /* prepare rot for queue buf*/ - virtual bool prepareQueueBuf(uint32_t offset); - - /* call play on mdp*/ - virtual bool play(int fd); - - /* dump the state of the object */ - virtual void dump() const; private: - /* helper functions for overlayTransform */ - void overlayTransFlipHV(MdpCtrl& mdp, - utils::eTransform& rot); - void overlayTransFlipRot90(MdpCtrl& mdp, - utils::eTransform& rot); - void overlayTransFlipRot180(MdpCtrl& mdp); - void overlayTransFlipRot270(MdpCtrl& mdp); + /* remap rot buffers */ + bool remap(uint32_t numbufs); + bool open_i(uint32_t numbufs, uint32_t bufsz); + /* Deferred transform calculations */ + void doTransform(); + /* reset underlying data, basically memset 0 */ + void reset(); - /* underlying rotator MDP object */ - MdpRot mRot; + /* rot info*/ + msm_rotator_img_info mRotImgInfo; + /* rot data */ + msm_rotator_data_info mRotDataInfo; + /* Orientation */ + utils::eTransform mOrientation; + /* rotator fd */ + OvFD mFd; + /* Rotator memory manager */ + RotMem mMem; + /* Single Rotator buffer size */ + uint32_t mBufSize; }; //--------------inlines------------------------------------ -//// MdpRot //// -inline MdpRot::MdpRot() { reset(); } -inline bool MdpRot::start(const utils::PipeArgs& args) { - return this->start(args); + +///// Rotator ///// +inline Rotator::Rotator() { + int type = IRotatorHw::getRotatorHwType(); + if(type == IRotatorHw::TYPE_MDP) { + mRot = new MdpRot(); //will do reset + } else if(type == IRotatorHw::TYPE_MDSS) { + //TODO create mdss specific rotator + } else { + ALOGE("%s Unknown h/w type %d", __FUNCTION__, type); + } +} +inline Rotator::~Rotator() { + delete mRot; //will do close +} +inline bool Rotator::init() { + if(!mRot->init()) { + ALOGE("Rotator::init failed"); + return false; + } + return true; +} +inline bool Rotator::close() { + return mRot->close(); +} +inline void Rotator::setSource(const utils::Whf& whf) { + mRot->setSource(whf); +} +inline void Rotator::setFlags(const utils::eMdpFlags& flags) { + mRot->setFlags(flags); +} +inline void Rotator::setTransform(const utils::eTransform& rot, + const bool& rotUsed) +{ + mRot->setTransform(rot, rotUsed); +} +inline bool Rotator::commit() { + return mRot->commit(); +} +inline void Rotator::setEnable(){ mRot->setEnable(); } +inline void Rotator::setDisable(){ mRot->setDisable(); } +inline bool Rotator::enabled() const { return mRot->enabled(); } +inline void Rotator::setSrcFB() { mRot->setSrcFB(); } +inline int Rotator::getDstMemId() const { + return mRot->getDstMemId(); +} +inline uint32_t Rotator::getDstOffset() const { + return mRot->getDstOffset(); +} +inline void Rotator::setRotations(uint32_t rot) { + mRot->setRotations (rot); +} +inline int Rotator::getSessId() const { + return mRot->getSessId(); +} +inline void Rotator::dump() const { + ALOGE("== Dump Rotator start =="); + mRot->dump(); + ALOGE("== Dump Rotator end =="); +} +inline bool Rotator::queueBuffer(int fd, uint32_t offset) { + return mRot->queueBuffer(fd, offset); } -inline void MdpRot::setDataMemId(int fd) { mData.data.memory_id = fd; } -inline void MdpRot::setRotDataSrcMemId(int fd) { - mRotDataInfo.src.memory_id = fd; } +///// Null Rotator ///// +inline NullRotator::~NullRotator() {} +inline bool NullRotator::init() { return true; } +inline bool NullRotator::close() { return true; } +inline bool NullRotator::commit() { return true; } +inline void NullRotator::setSource(const utils::Whf& wfh) {} +inline void NullRotator::setFlags(const utils::eMdpFlags& flags) {} +inline void NullRotator::setTransform(const utils::eTransform& rot, const bool&) +{} +inline void NullRotator::setRotations(uint32_t) {} +inline void NullRotator::setEnable() {} +inline void NullRotator::setDisable() {} +inline bool NullRotator::enabled() const { return false; } +inline int NullRotator::getSessId() const { return -1; } +inline bool NullRotator::queueBuffer(int fd, uint32_t offset) { return true; } +inline void NullRotator::setSrcFB() {} +inline int NullRotator::getDstMemId() const { return -1; } +inline uint32_t NullRotator::getDstOffset() const { return 0;} +inline void NullRotator::dump() const { + ALOGE("== Dump NullRotator dump (null) start/end =="); +} + + +//// MdpRot //// +inline MdpRot::MdpRot() { reset(); } +inline MdpRot::~MdpRot() { close(); } inline void MdpRot::setEnable() { mRotImgInfo.enable = 1; } inline void MdpRot::setDisable() { mRotImgInfo.enable = 0; } inline bool MdpRot::enabled() const { return mRotImgInfo.enable; } - inline void MdpRot::setRotations(uint32_t r) { mRotImgInfo.rotations = r; } -inline void MdpRot::setDataReqId(int id) { mData.id = id; } -inline void MdpRot::swapDstWH() { - overlay::utils::swap(mRotImgInfo.dst.width, - mRotImgInfo.dst.height); } - -inline overlay::utils::Whf MdpRot::getSrcWhf() const { - return overlay::utils::Whf(mRotImgInfo.src.width, - mRotImgInfo.src.height, - mRotImgInfo.src.format); -} - inline int MdpRot::getDstMemId() const { return mRotDataInfo.dst.memory_id; } inline uint32_t MdpRot::getDstOffset() const { return mRotDataInfo.dst.offset; } - -inline void MdpRot::setSrcWhf(const overlay::utils::Whf& whf) { - mRotImgInfo.src.width = whf.w; - mRotImgInfo.src.height = whf.h; - mRotImgInfo.src.format = whf.format; -} - inline int MdpRot::getSessId() const { return mRotImgInfo.session_id; } - -inline void MdpRot::setSrcFB(bool mark) { isSrcFB = mark; } - -///// Null Rotator ///// -inline NullRotator::~NullRotator() {} -inline bool NullRotator::open() { - return true; } -inline bool NullRotator::remap(uint32_t numbufs, - const utils::PipeArgs& args){ - return true; } -inline bool NullRotator::close() { return true; } -inline bool NullRotator::start(const utils::PipeArgs& args) -{ return true; } - -inline bool NullRotator::start() { return true; } -inline bool NullRotator::overlayTransform(MdpCtrl& o, - utils::eTransform& rot) -{ return true; } -inline void NullRotator::setSrcWhf(const overlay::utils::Whf& wfh) {} -inline void NullRotator::setRotations(uint32_t) {} -inline void NullRotator::setDataReqId(int id) {} -inline void NullRotator::setEnable() {} -inline void NullRotator::setDisable() {} -inline bool NullRotator::enabled() const { return false; } -inline int NullRotator::getSessId() const { return -1; } -inline overlay::utils::Whf NullRotator::getSrcWhf() const { - return overlay::utils::Whf(); } -inline bool NullRotator::prepareQueueBuf(uint32_t offset) -{ return true; } -inline bool NullRotator::play(int fd) -{ return true; } -inline void NullRotator::setDataMemId(int fd) {} -inline void NullRotator::setRotDataSrcMemId(int fd) {} -inline void NullRotator::setSrcFB(bool) {} -inline void NullRotator::dump() const { - ALOGE("== Dump NullRotator dump (null) start/end =="); -} - -///// Rotator ///// -inline Rotator::Rotator() { } - -inline Rotator::~Rotator() { - mRot.close(); // also will do reset -} - -inline bool Rotator::open() { - if(!mRot.open()) { - ALOGE("Rotator::open failed"); - return false; - } - return true; -} - -template -inline bool Rotator::start(const utils::PipeArgs& args) { - return mRot.start(args); -} - -inline bool Rotator::remap(uint32_t numbufs, - const utils::PipeArgs& args){ - if(!mRot.remap(numbufs, args)) { - ALOGE("%s failed", __FUNCTION__); - return false; - } - return true; -} - -inline bool Rotator::close() { - return mRot.close(); -} - -inline bool Rotator::start() { - return mRot.start(); -} - -inline bool Rotator::start(const utils::PipeArgs& args) { - return mRot.start(args); -} - -inline bool Rotator::unmapNonCurrent() { - return mRot.unmapNonCurrent(); -} - -inline void Rotator::setEnable(){ mRot.setEnable(); } -inline void Rotator::setDisable(){ mRot.setDisable(); } -inline bool Rotator::enabled() const { return mRot.enabled(); } -inline void Rotator::setDataMemId(int fd) { - mRot.setDataMemId(fd); } - -inline void Rotator::setRotDataSrcMemId(int fd) { - mRot.setRotDataSrcMemId(fd); -} - -inline void Rotator::setSrcFB(bool mark) { mRot.setSrcFB(mark); } - -inline int Rotator::getDstMemId() const { - return mRot.getDstMemId(); -} -inline uint32_t Rotator::getDstOffset() const { - return mRot.getDstOffset(); -} - -inline void Rotator::setDataReqId(int id) { - mRot.setDataReqId(id); -} - -inline void Rotator::setSrcWhf( - const overlay::utils::Whf& whf) { - mRot.setSrcWhf(whf); -} - -inline void Rotator::setRotations(uint32_t rot) { - mRot.setRotations (rot); -} - -inline int Rotator::getSessId() const { - return mRot.getSessId(); } - -inline void Rotator::dump() const { - ALOGE("== Dump Rotator start =="); - mRot.dump(); - ALOGE("== Dump Rotator end =="); -} - -inline overlay::utils::Whf Rotator::getSrcWhf() const { - return mRot.getSrcWhf(); } - -inline bool Rotator::prepareQueueBuf(uint32_t offset) -{ - return mRot.prepareQueueBuf(offset); -} - -inline bool Rotator::play(int fd) -{ - return mRot.play(fd); -} - -template -bool MdpRot::start(const utils::PipeArgs& args) { - // Do nothing when no orientation - if(utils::OVERLAY_TRANSFORM_0 == args.orientation && - utils::ROT_FLAG_ENABLED != args.rotFlags) { - return true; - } - utils::Whf whf(args.whf); - mRotImgInfo.src.format = whf.format; - mRotImgInfo.src.width = whf.w; - mRotImgInfo.src.height = whf.h; - mRotImgInfo.src_rect.w = whf.w; - mRotImgInfo.src_rect.h = whf.h; - mRotImgInfo.dst.width = whf.w; - mRotImgInfo.dst.height = whf.h; - if(whf.format == MDP_Y_CRCB_H2V2_TILE || - whf.format == MDP_Y_CBCR_H2V2_TILE) { - mRotImgInfo.src.width = utils::alignup(whf.w, 64); - mRotImgInfo.src.height = utils::alignup(whf.h, 32); - mRotImgInfo.src_rect.w = utils::alignup(whf.w, 64); - mRotImgInfo.src_rect.h = utils::alignup(whf.h, 32); - mRotImgInfo.dst.width = utils::alignup(whf.w, 64); - mRotImgInfo.dst.height = utils::alignup(whf.h, 32); - mRotImgInfo.dst.format = MDP_Y_CRCB_H2V2; - } - // either utils::getRotOutFmt(whf.format); or supplied fmt - // utils::RotOutFmt::fmt; - mRotImgInfo.dst.format = utils::RotOutFmt::fmt(whf.format); - mRotImgInfo.dst_x = 0; - mRotImgInfo.dst_y = 0; - mRotImgInfo.src_rect.x = 0; - mRotImgInfo.src_rect.y = 0; - mRotImgInfo.rotations = 0; - // ROT_FLAG_DISABLED / ENABLED - // Refer to overlayUtils.h eRotFlags - // for more info - mRotImgInfo.enable = args.rotFlags; - mRotImgInfo.session_id = mRotImgInfo.session_id ? - mRotImgInfo.session_id : 0; - - return start(); +inline void MdpRot::setSrcFB() { + mRotDataInfo.src.flags |= MDP_MEMORY_ID_TYPE_FB; } } // overlay -namespace { -// just a helper func for Rotator common operations x-(y+z) -int compute(uint32_t x, uint32_t y, uint32_t z) { - return x-(y+z); -} -} - -#endif // OVERLAY_ROTATOR_H +#endif // OVERlAY_ROTATOR_H diff --git a/liboverlay/overlayState.h b/liboverlay/overlayState.h index 1d13a2e..ea6860f 100644 --- a/liboverlay/overlayState.h +++ b/liboverlay/overlayState.h @@ -34,22 +34,16 @@ #include "overlayImpl.h" #include "overlayRotator.h" #include "pipes/overlayGenPipe.h" -#include "pipes/overlayBypassPipe.h" -#include "pipes/overlayHdmiPipe.h" +#include "pipes/overlayVideoExtPipe.h" #include "pipes/overlayUIMirrorPipe.h" #include "pipes/overlay3DPipe.h" -// FIXME make int to be uint32 whenever possible - namespace overlay { /* * Used by Overlay class. Invokes each event * */ -/* TODO case of RGBx will call mOv open with diff -* params customized for RGBx pipes */ - class OverlayState : utils::NoCopy { public: /**/ @@ -153,11 +147,11 @@ template <> struct StateTraits template <> struct StateTraits { typedef overlay::GenericPipe pipe0; - typedef overlay::HdmiPipe pipe1; + typedef overlay::VideoExtPipe pipe1; typedef overlay::NullPipe pipe2; // place holder typedef Rotator rot0; - typedef NullRotator rot1; + typedef Rotator rot1; typedef NullRotator rot2; typedef overlay::OverlayImpl ovimpl; @@ -231,11 +225,11 @@ template <> struct StateTraits template <> struct StateTraits { typedef overlay::GenericPipe pipe0; - typedef overlay::HdmiPipe pipe1; + typedef overlay::VideoExtPipe pipe1; typedef overlay::UIMirrorPipe pipe2; typedef Rotator rot0; - typedef NullRotator rot1; + typedef Rotator rot1; typedef Rotator rot2; typedef overlay::OverlayImpl ovimpl; @@ -243,7 +237,7 @@ template <> struct StateTraits template <> struct StateTraits { - typedef overlay::BypassPipe pipe0; + typedef overlay::GenericPipe pipe0; typedef overlay::NullPipe pipe1; // place holder typedef overlay::NullPipe pipe2; // place holder @@ -256,8 +250,8 @@ template <> struct StateTraits template <> struct StateTraits { - typedef overlay::BypassPipe pipe0; - typedef overlay::BypassPipe pipe1; + typedef overlay::GenericPipe pipe0; + typedef overlay::GenericPipe pipe1; typedef overlay::NullPipe pipe2; // place holder typedef NullRotator rot0; @@ -269,9 +263,9 @@ template <> struct StateTraits template <> struct StateTraits { - typedef overlay::BypassPipe pipe0; - typedef overlay::BypassPipe pipe1; - typedef overlay::BypassPipe pipe2; + typedef overlay::GenericPipe pipe0; + typedef overlay::GenericPipe pipe1; + typedef overlay::GenericPipe pipe2; typedef NullRotator rot0; typedef NullRotator rot1; @@ -310,8 +304,8 @@ inline OverlayImplBase* handle_closed_to_xxx() RotatorBase* rot0 = new typename StateTraits::rot0; RotatorBase* rot1 = new typename StateTraits::rot1; RotatorBase* rot2 = new typename StateTraits::rot2; - if(!ov->open(rot0, rot1, rot2)) { - ALOGE("Overlay failed to open in state %d", STATE); + if(!ov->init(rot0, rot1, rot2)) { + ALOGE("Overlay failed to init in state %d", STATE); return 0; } return ov; @@ -329,7 +323,7 @@ inline OverlayImplBase* handle_xxx_to_closed(OverlayImplBase* ov) return 0; } -/* Hard transitions from any state to any state will close and then open */ +/* Hard transitions from any state to any state will close and then init */ template inline OverlayImplBase* handle_xxx_to_xxx(OverlayImplBase* ov) { @@ -392,6 +386,7 @@ inline OverlayImplBase* OverlayState::handleEvent(utils::eOverlayState newState, // FIXME, how to communicate bad transition? // Should we have bool returned from transition func? + // This is also a very good interview question. return newov; } diff --git a/liboverlay/overlayTransitions.cpp b/liboverlay/overlayTransitions.cpp index 45d3720..8096ad5 100644 --- a/liboverlay/overlayTransitions.cpp +++ b/liboverlay/overlayTransitions.cpp @@ -42,12 +42,12 @@ OverlayImplBase* OverlayState::handle_xxx_to_2D_2DPanel( // Create new ovimpl based on new state typedef StateTraits NewState; - OverlayImplBase* newov = new NewState::ovimpl; + OverlayImplBase* newov = new NewState::ovimpl(); //=========================================================== // For each pipe: // - If pipe matches, copy from previous into new ovimpl - // - Otherwise open for new and delete from previous ovimpl + // - Otherwise init for new and delete from previous ovimpl //=========================================================== // pipe0/rot0 (GenericPipe) @@ -55,10 +55,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_2D_2DPanel( ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (GenericPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE0); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (GenericPipe)", __FUNCTION__); - RotatorBase* rot0 = new NewState::rot0; + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (GenericPipe)", __FUNCTION__); ov->closePipe(utils::OV_PIPE0); - newov->openPipe(rot0, utils::OV_PIPE0); + RotatorBase* rot0 = new NewState::rot0; + newov->initPipe(rot0, utils::OV_PIPE0); } // pipe1/rot1 (NullPipe) @@ -66,10 +66,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_2D_2DPanel( ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (NullPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE1); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (NullPipe)", __FUNCTION__); - RotatorBase* rot1 = new NewState::rot1; + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (NullPipe)", __FUNCTION__); ov->closePipe(utils::OV_PIPE1); - newov->openPipe(rot1, utils::OV_PIPE1); + RotatorBase* rot1 = new NewState::rot1; + newov->initPipe(rot1, utils::OV_PIPE1); } // pipe2/rot2 (NullPipe) @@ -77,10 +77,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_2D_2DPanel( ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE2); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (NullPipe)", __FUNCTION__); - RotatorBase* rot2 = new NewState::rot2; + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (NullPipe)", __FUNCTION__); ov->closePipe(utils::OV_PIPE2); - newov->openPipe(rot2, utils::OV_PIPE2); + RotatorBase* rot2 = new NewState::rot2; + newov->initPipe(rot2, utils::OV_PIPE2); } // All pipes are copied or deleted so no more need for previous ovimpl @@ -106,7 +106,7 @@ OverlayImplBase* OverlayState::handle_xxx_to_2D_2DTV( //=========================================================== // For each pipe: // - If pipe matches, copy from previous into new ovimpl - // - Otherwise open for new and delete from previous ovimpl + // - Otherwise init for new and delete from previous ovimpl //=========================================================== // pipe0/rot0 (GenericPipe) @@ -114,21 +114,21 @@ OverlayImplBase* OverlayState::handle_xxx_to_2D_2DTV( ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (GenericPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE0); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (GenericPipe)", __FUNCTION__); + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (GenericPipe)", __FUNCTION__); RotatorBase* rot0 = new NewState::rot0; ov->closePipe(utils::OV_PIPE0); - newov->openPipe(rot0, utils::OV_PIPE0); + newov->initPipe(rot0, utils::OV_PIPE0); } - // pipe1/rot1 (HdmiPipe) - if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_HDMI) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (HdmiPipe)", __FUNCTION__); + // pipe1/rot1 (VideoExtPipe) + if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_VIDEO_EXT) { + ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (VideoExtPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE1); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (HdmiPipe)", __FUNCTION__); + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (VideoExtPipe)", __FUNCTION__); RotatorBase* rot1 = new NewState::rot1; ov->closePipe(utils::OV_PIPE1); - newov->openPipe(rot1, utils::OV_PIPE1); + newov->initPipe(rot1, utils::OV_PIPE1); } // pipe2/rot2 (NullPipe) @@ -136,10 +136,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_2D_2DTV( ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE2); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (NullPipe)", __FUNCTION__); + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (NullPipe)", __FUNCTION__); RotatorBase* rot2 = new NewState::rot2; ov->closePipe(utils::OV_PIPE2); - newov->openPipe(rot2, utils::OV_PIPE2); + newov->initPipe(rot2, utils::OV_PIPE2); } // All pipes are copied or deleted so no more need for previous ovimpl @@ -162,21 +162,22 @@ OverlayImplBase* OverlayState::handle_xxx_to_3D_2DPanel( typedef StateTraits NewState; OverlayImplBase* newov = new NewState::ovimpl; - //=========================================================== + //================================================================= // For each pipe: - // - If pipe matches, copy from previous into new ovimpl - // - Otherwise open for new and delete from previous ovimpl - //=========================================================== + // - If pipe matches, copy from previous into new ovimpl. + // (which also makes previous pipe ref 0, so nobody can use) + // - Otherwise init pipe for new ovimpl and delete from previous + //================================================================= // pipe0/rot0 (M3DPrimaryPipe) if (ov->getOvPipeType(utils::OV_PIPE0) == utils::OV_PIPE_TYPE_M3D_PRIMARY) { ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (M3DPrimaryPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE0); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (M3DPrimaryPipe)", __FUNCTION__); + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (M3DPrimaryPipe)", __FUNCTION__); RotatorBase* rot0 = new NewState::rot0; ov->closePipe(utils::OV_PIPE0); - newov->openPipe(rot0, utils::OV_PIPE0); + newov->initPipe(rot0, utils::OV_PIPE0); } // pipe1/rot1 (NullPipe) @@ -184,10 +185,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_3D_2DPanel( ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (NullPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE1); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (NullPipe)", __FUNCTION__); + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (NullPipe)", __FUNCTION__); RotatorBase* rot1 = new NewState::rot1; ov->closePipe(utils::OV_PIPE1); - newov->openPipe(rot1, utils::OV_PIPE1); + newov->initPipe(rot1, utils::OV_PIPE1); } // pipe2/rot2 (NullPipe) @@ -195,10 +196,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_3D_2DPanel( ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE2); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (NullPipe)", __FUNCTION__); + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (NullPipe)", __FUNCTION__); RotatorBase* rot2 = new NewState::rot2; ov->closePipe(utils::OV_PIPE2); - newov->openPipe(rot2, utils::OV_PIPE2); + newov->initPipe(rot2, utils::OV_PIPE2); } // All pipes are copied or deleted so no more need for previous ovimpl @@ -224,7 +225,7 @@ OverlayImplBase* OverlayState::handle_xxx_to_3D_2DTV( //=========================================================== // For each pipe: // - If pipe matches, copy from previous into new ovimpl - // - Otherwise open for new and delete from previous ovimpl + // - Otherwise init for new and delete from previous ovimpl //=========================================================== // pipe0/rot0 (M3DPrimaryPipe) @@ -232,10 +233,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_3D_2DTV( ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (M3DPrimaryPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE0); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (M3DPrimaryPipe)", __FUNCTION__); + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (M3DPrimaryPipe)", __FUNCTION__); RotatorBase* rot0 = new NewState::rot0; ov->closePipe(utils::OV_PIPE0); - newov->openPipe(rot0, utils::OV_PIPE0); + newov->initPipe(rot0, utils::OV_PIPE0); } // pipe1/rot1 (M3DExtPipe) @@ -243,10 +244,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_3D_2DTV( ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (M3DExtPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE1); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (M3DExtPipe)", __FUNCTION__); + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (M3DExtPipe)", __FUNCTION__); RotatorBase* rot1 = new NewState::rot1; ov->closePipe(utils::OV_PIPE1); - newov->openPipe(rot1, utils::OV_PIPE1); + newov->initPipe(rot1, utils::OV_PIPE1); } // pipe2/rot2 (NullPipe) @@ -254,10 +255,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_3D_2DTV( ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE2); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (NullPipe)", __FUNCTION__); + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (NullPipe)", __FUNCTION__); RotatorBase* rot2 = new NewState::rot2; ov->closePipe(utils::OV_PIPE2); - newov->openPipe(rot2, utils::OV_PIPE2); + newov->initPipe(rot2, utils::OV_PIPE2); } // All pipes are copied or deleted so no more need for previous ovimpl @@ -283,7 +284,7 @@ OverlayImplBase* OverlayState::handle_xxx_to_2D_trueUI_Mirror( //=========================================================== // For each pipe: // - If pipe matches, copy from previous into new ovimpl - // - Otherwise open for new and delete from previous ovimpl + // - Otherwise init for new and delete from previous ovimpl //=========================================================== // pipe0/rot0 (GenericPipe) @@ -291,21 +292,21 @@ OverlayImplBase* OverlayState::handle_xxx_to_2D_trueUI_Mirror( ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (GenericPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE0); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (GenericPipe)", __FUNCTION__); + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (GenericPipe)", __FUNCTION__); RotatorBase* rot0 = new NewState::rot0; ov->closePipe(utils::OV_PIPE0); - newov->openPipe(rot0, utils::OV_PIPE0); + newov->initPipe(rot0, utils::OV_PIPE0); } - // pipe1/rot1 (HdmiPipe) - if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_HDMI) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (HdmiPipe)", __FUNCTION__); + // pipe1/rot1 (VideoExtPipe) + if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_VIDEO_EXT) { + ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (VideoExtPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE1); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (HdmiPipe)", __FUNCTION__); + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (VideoExtPipe)", __FUNCTION__); RotatorBase* rot1 = new NewState::rot1; ov->closePipe(utils::OV_PIPE1); - newov->openPipe(rot1, utils::OV_PIPE1); + newov->initPipe(rot1, utils::OV_PIPE1); } // pipe2/rot2 (UIMirrorPipe) @@ -313,10 +314,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_2D_trueUI_Mirror( ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (UIMirrorPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE2); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (UIMirrorPipe)", __FUNCTION__); + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (UIMirrorPipe)", __FUNCTION__); RotatorBase* rot2 = new NewState::rot2; ov->closePipe(utils::OV_PIPE2); - newov->openPipe(rot2, utils::OV_PIPE2); + newov->initPipe(rot2, utils::OV_PIPE2); } // All pipes are copied or deleted so no more need for previous ovimpl @@ -341,7 +342,7 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass1(OverlayImplBase* ov) //=========================================================== // For each pipe: // - If pipe matches, copy from previous into new ovimpl - // - Otherwise open for new and delete from previous ovimpl + // - Otherwise init for new and delete from previous ovimpl //=========================================================== // pipe0/rot0 (BypassPipe) @@ -349,10 +350,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass1(OverlayImplBase* ov) ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (BypassPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE0); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (BypassPipe)", __FUNCTION__); + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (BypassPipe)", __FUNCTION__); RotatorBase* rot0 = new NewState::rot0; ov->closePipe(utils::OV_PIPE0); - newov->openPipe(rot0, utils::OV_PIPE0); + newov->initPipe(rot0, utils::OV_PIPE0); } // pipe1/rot1 (NullPipe) @@ -360,10 +361,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass1(OverlayImplBase* ov) ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (NullPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE1); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (NullPipe)", __FUNCTION__); + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (NullPipe)", __FUNCTION__); RotatorBase* rot1 = new NewState::rot1; ov->closePipe(utils::OV_PIPE1); - newov->openPipe(rot1, utils::OV_PIPE1); + newov->initPipe(rot1, utils::OV_PIPE1); } // pipe2/rot2 (NullPipe) @@ -371,10 +372,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass1(OverlayImplBase* ov) ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE2); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (NullPipe)", __FUNCTION__); + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (NullPipe)", __FUNCTION__); RotatorBase* rot2 = new NewState::rot2; ov->closePipe(utils::OV_PIPE2); - newov->openPipe(rot2, utils::OV_PIPE2); + newov->initPipe(rot2, utils::OV_PIPE2); } // All pipes are copied or deleted so no more need for previous ovimpl @@ -399,7 +400,7 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass2(OverlayImplBase* ov) //=========================================================== // For each pipe: // - If pipe matches, copy from previous into new ovimpl - // - Otherwise open for new and delete from previous ovimpl + // - Otherwise init for new and delete from previous ovimpl //=========================================================== // pipe0/rot0 (BypassPipe) @@ -407,10 +408,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass2(OverlayImplBase* ov) ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (BypassPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE0); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (BypassPipe)", __FUNCTION__); + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (BypassPipe)", __FUNCTION__); RotatorBase* rot0 = new NewState::rot0; ov->closePipe(utils::OV_PIPE0); - newov->openPipe(rot0, utils::OV_PIPE0); + newov->initPipe(rot0, utils::OV_PIPE0); } // pipe1/rot1 (BypassPipe) @@ -418,10 +419,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass2(OverlayImplBase* ov) ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (BypassPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE1); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (BypassPipe)", __FUNCTION__); + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (BypassPipe)", __FUNCTION__); RotatorBase* rot1 = new NewState::rot1; ov->closePipe(utils::OV_PIPE1); - newov->openPipe(rot1, utils::OV_PIPE1); + newov->initPipe(rot1, utils::OV_PIPE1); } // pipe2/rot2 (NullPipe) @@ -429,10 +430,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass2(OverlayImplBase* ov) ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE2); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (NullPipe)", __FUNCTION__); + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (NullPipe)", __FUNCTION__); RotatorBase* rot2 = new NewState::rot2; ov->closePipe(utils::OV_PIPE2); - newov->openPipe(rot2, utils::OV_PIPE2); + newov->initPipe(rot2, utils::OV_PIPE2); } // All pipes are copied or deleted so no more need for previous ovimpl @@ -457,7 +458,7 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass3(OverlayImplBase* ov) //=========================================================== // For each pipe: // - If pipe matches, copy from previous into new ovimpl - // - Otherwise open for new and delete from previous ovimpl + // - Otherwise init for new and delete from previous ovimpl //=========================================================== // pipe0/rot0 (BypassPipe) @@ -465,10 +466,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass3(OverlayImplBase* ov) ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (BypassPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE0); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (BypassPipe)", __FUNCTION__); + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (BypassPipe)", __FUNCTION__); RotatorBase* rot0 = new NewState::rot0; ov->closePipe(utils::OV_PIPE0); - newov->openPipe(rot0, utils::OV_PIPE0); + newov->initPipe(rot0, utils::OV_PIPE0); } // pipe1/rot1 (BypassPipe) @@ -476,10 +477,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass3(OverlayImplBase* ov) ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (BypassPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE1); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (BypassPipe)", __FUNCTION__); + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (BypassPipe)", __FUNCTION__); RotatorBase* rot1 = new NewState::rot1; ov->closePipe(utils::OV_PIPE1); - newov->openPipe(rot1, utils::OV_PIPE1); + newov->initPipe(rot1, utils::OV_PIPE1); } // pipe2/rot2 (BypassPipe) @@ -487,10 +488,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass3(OverlayImplBase* ov) ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (BypassPipe)", __FUNCTION__); newov->copyOvPipe(ov, utils::OV_PIPE2); } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (BypassPipe)", __FUNCTION__); + ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (BypassPipe)", __FUNCTION__); RotatorBase* rot2 = new NewState::rot2; ov->closePipe(utils::OV_PIPE2); - newov->openPipe(rot2, utils::OV_PIPE2); + newov->initPipe(rot2, utils::OV_PIPE2); } // All pipes are copied or deleted so no more need for previous ovimpl diff --git a/liboverlay/overlayUtils.cpp b/liboverlay/overlayUtils.cpp index 38e3ab2..ce18174 100644 --- a/liboverlay/overlayUtils.cpp +++ b/liboverlay/overlayUtils.cpp @@ -70,7 +70,7 @@ struct IOFile { namespace overlay { //----------From class Res ------------------------------ -const char* const Res::devTemplate = "/dev/graphics/fb%u"; +const char* const Res::fbPath = "/dev/graphics/fb%u"; const char* const Res::rotPath = "/dev/msm_rotator"; const char* const Res::format3DFile = "/sys/class/graphics/fb1/format_3d"; @@ -92,7 +92,7 @@ FrameBufferInfo::FrameBufferInfo() { OvFD mFd; // Use open defined in overlayFD file to open fd for fb0 - if(!overlay::open(mFd, 0, Res::devTemplate)) { + if(!overlay::open(mFd, 0, Res::fbPath)) { ALOGE("FrameBufferInfo: failed to open fd"); return; } @@ -142,45 +142,13 @@ int FrameBufferInfo::getHeight() const { } bool FrameBufferInfo::supportTrueMirroring() const { - return mBorderFillSupported; + char value[PROPERTY_VALUE_MAX] = {0}; + property_get("hw.trueMirrorSupported", value, "0"); + int trueMirroringSupported = atoi(value); + return (trueMirroringSupported && mBorderFillSupported); } //-------------------------------------------------------- -uint32_t getSize(const Whf& whf) { - int aligned_height=0, pitch=0; - - uint32_t size = whf.w * whf.h; - switch (whf.format) { - case MDP_RGBA_8888: - case MDP_BGRA_8888: - case MDP_RGBX_8888: - size *= 4; - break; - case MDP_RGB_565: - case MDP_Y_CBCR_H2V1: - size *= 2; - break; - case MDP_Y_CBCR_H2V2: - case MDP_Y_CRCB_H2V2: - size = (size * 3) / 2; - break; - case MDP_Y_CRCB_H2V2_TILE: - case MDP_Y_CBCR_H2V2_TILE: - aligned_height = align(whf.h , 32); - pitch = align(whf.w, 128); - size = pitch * aligned_height; - size = align(size, 8192); - - aligned_height = align(whf.h >> 1, 32); - size += pitch * aligned_height; - size = align(size, 8192); - break; - default: - ALOGE("getSize unknown format %d", whf.format); - return 0; - } - return size; -} int getMdpFormat(int format) { switch (format) { @@ -205,18 +173,25 @@ int getMdpFormat(int format) { case HAL_PIXEL_FORMAT_YV12: return MDP_Y_CR_CB_H2V2; default: - ALOGE("Error getMdpFormat format=%d", format); + ALOGE("Error getMdpFormat format=0x%x", format); return -1; } // not reached return -1; } -bool isHDMIConnected () { - char value[PROPERTY_VALUE_MAX] = {0}; - property_get("hw.hdmiON", value, "0"); - int isHDMI = atoi(value); - return isHDMI ? true : false; +//Set by client as HDMI/WFD +void setExtType(const int& type) { + if(type != HDMI && type != WFD) { + ALOGE("%s: Unrecognized type %d", __func__, type); + return; + } + sExtType = type; +} + +//Return External panel type set by client. +int getExtType() { + return sExtType; } bool is3DTV() { @@ -229,7 +204,7 @@ bool is3DTV() { bool isPanel3D() { OvFD fd; - if(!overlay::open(fd, 0 /*fb*/, Res::devTemplate)){ + if(!overlay::open(fd, 0 /*fb*/, Res::fbPath)){ ALOGE("isPanel3D Can't open framebuffer 0"); return false; } @@ -299,39 +274,6 @@ uint32_t getS3DFormat(uint32_t fmt) { return fmt3D; } -void normalizeCrop(uint32_t& xy, uint32_t& wh) { - if (xy & 0x0001) { - // x or y is odd, increment it's value - xy += 1; - // Since we've incremented x(y), we need to decrement - // w(h) accordingly - if (wh & 0x0001) { - // w or h is odd, decrement it by 1, to make it even - even_out(wh); - } else { - // w(h) is already even, hence we decrement by 2 - wh -=2; - } - } else { - even_out(wh); - } -} - -void scale(mdp_overlay& ov) -{ - /* Scaling of upto a max of 8 times supported */ - overlay::utils::Dim dst(overlay::utils::getDstRectDim(ov)); - overlay::utils::Dim src(overlay::utils::getSrcRectDim(ov)); - if(dst.w >(src.w * overlay::utils::HW_OV_MAGNIFICATION_LIMIT)) { - dst.w = overlay::utils::HW_OV_MAGNIFICATION_LIMIT * src.w; - } - if(dst.h >(src.h * overlay::utils::HW_OV_MAGNIFICATION_LIMIT)) { - dst.h = overlay::utils::HW_OV_MAGNIFICATION_LIMIT * src.h; - } - - setDstRectDim(dst, ov); -} - } // utils } // overlay diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h index 7d964a9..f82fb88 100644 --- a/liboverlay/overlayUtils.h +++ b/liboverlay/overlayUtils.h @@ -35,14 +35,14 @@ #include // open, O_RDWR, etc #include #include // buffer_handle_t -#include // MDP_OV_PLAY_NOWAIT etc ... +#include // flags #include #include #include #include #include #include - +#include "gralloc_priv.h" //for interlace /* * * Collection of utilities functions/structs/enums etc... @@ -70,12 +70,6 @@ class Overlay; namespace utils { struct Whf; struct Dim; -template - inline void even_out(T& x) { if (x & 0x0001) --x; } - -inline uint32_t getBit(uint32_t x, uint32_t mask) { - return (x & mask); -} inline uint32_t setBit(uint32_t x, uint32_t mask) { return (x | mask); @@ -89,7 +83,7 @@ inline uint32_t clrBit(uint32_t x, uint32_t mask) { * and assignment operator private * * Usage: -* * class SomeClass : utils::NoCopy {...}; +* class SomeClass : utils::NoCopy {...}; */ class NoCopy { protected: @@ -147,7 +141,14 @@ enum { BARRIER_LAND = 1, BARRIER_PORT = 2 }; inline uint32_t format3D(uint32_t x) { return x & 0xFF000; } -inline uint32_t colorFormat(uint32_t x) { return x & 0xFFF; } +inline uint32_t colorFormat(uint32_t fmt) { + /*TODO enable this block only if format has interlace / 3D info in top bits. + if(fmt & INTERLACE_MASK) { + fmt = fmt ^ HAL_PIXEL_FORMAT_INTERLACE; + } + fmt = fmt & 0xFFF;*/ + return fmt; +} inline uint32_t format3DOutput(uint32_t x) { return (x & 0xF000) >> SHIFT_OUT_3D; } inline uint32_t format3DInput(uint32_t x) { return x & 0xF0000; } @@ -160,12 +161,15 @@ bool usePanel3D(); bool send3DInfoPacket (uint32_t fmt); bool enableBarrier (uint32_t orientation); uint32_t getS3DFormat(uint32_t fmt); + template - bool getPositionS3D(const Whf& whf, Dim& out); +bool getPositionS3D(const Whf& whf, Dim& out); + template - bool getCropS3D(const Dim& in, Dim& out, uint32_t fmt); +bool getCropS3D(const Dim& in, Dim& out, uint32_t fmt); + template - void swapWidthHeight(Type& width, Type& height); +void swapWidthHeight(Type& width, Type& height); struct Dim { Dim () : x(0), y(0), @@ -193,13 +197,6 @@ struct Dim { return !operator==(d); } - void even_out() { - utils::even_out(x); - utils::even_out(y); - utils::even_out(w); - utils::even_out(h); - } - void dump() const; uint32_t x; uint32_t y; @@ -227,26 +224,12 @@ struct Whf { void dump() const; uint32_t w; uint32_t h; - // FIXME need to be int32_t ? uint32_t format; uint32_t size; }; enum { MAX_PATH_LEN = 256 }; -enum eParams { - OVERLAY_DITHER, - OVERLAY_TRANSFORM, - OVERLAY_TRANSFORM_UI -}; - -struct Params{ - Params(eParams p, int v) : param(p), value(v) {} - eParams param; - int value; -}; - - /** * Rotator flags: not to be confused with orientation flags. * Ususally, you want to open the rotator to make sure it is @@ -267,19 +250,6 @@ enum eRotFlags { ROT_FLAG_ENABLED = 1 // needed in rot }; -/* Used for rotator open. - * FIXME that is default, might be configs */ -enum { ROT_NUM_BUFS = 2 }; - -/* Wait/No wait for waiting for vsync - * WAIT - wait for vsync, ignore fb (no need to compose w/ fb) - * NO_WAIT - do not wait for vsync and return immediatly since - * we need to run composition code */ -enum eWait { - WAIT, - NO_WAIT -}; - /* The values for is_fg flag for control alpha and transp * IS_FG_OFF means is_fg = 0 * IS_FG_SET means is_fg = 1 @@ -298,15 +268,17 @@ enum eMdpFlags { OV_MDP_FLAGS_NONE = 0, OV_MDP_PIPE_SHARE = MDP_OV_PIPE_SHARE, OV_MDP_DEINTERLACE = MDP_DEINTERLACE, - OV_MDP_PLAY_NOWAIT = MDP_OV_PLAY_NOWAIT, - OV_MDP_SECURE_OVERLAY_SESSION = MDP_SECURE_OVERLAY_SESSION + OV_MDP_PLAY_NOWAIT = MDP_OV_PLAY_NOWAIT, //deprecated + OV_MDP_SECURE_OVERLAY_SESSION = MDP_SECURE_OVERLAY_SESSION, + OV_MDP_SOURCE_ROTATED_90 = MDP_SOURCE_ROTATED_90, + OV_MDP_MEMORY_ID_TYPE_FB = MDP_MEMORY_ID_TYPE_FB, }; enum eOverlayPipeType { OV_PIPE_TYPE_NULL, OV_PIPE_TYPE_BYPASS, OV_PIPE_TYPE_GENERIC, - OV_PIPE_TYPE_HDMI, + OV_PIPE_TYPE_VIDEO_EXT, OV_PIPE_TYPE_M3D_EXTERNAL, OV_PIPE_TYPE_M3D_PRIMARY, OV_PIPE_TYPE_RGB, @@ -327,24 +299,12 @@ enum eMdpPipeType { OV_MDP_PIPE_VG }; -/* Corresponds to pipes in eDest */ -enum eChannel { - CHANNEL_0, - CHANNEL_1, - CHANNEL_2 -}; - // Max pipes via overlay (VG0, VG1, RGB1) enum { MAX_PIPES = 3 }; /* Used to identify destination channels and * also 3D channels e.g. when in 3D mode with 2 * pipes opened and it is used in get crop/pos 3D - * - * PLEASE NOTE : DO NOT USE eDest FOR ARRAYS - * i.e. args[OV_PIPE1] since it is a BIT MASK - * use CHANNELS enum instead. Each OV_PIPEX is - * not specific to a display (primary/external). * */ enum eDest { OV_PIPE0 = 1 << 0, @@ -356,65 +316,51 @@ enum eDest { /* values for copybit_set_parameter(OVERLAY_TRANSFORM) */ enum eTransform { /* No rot */ - OVERLAY_TRANSFORM_0 = 0x0, - /* flip source image horizontally */ - OVERLAY_TRANSFORM_FLIP_H = HAL_TRANSFORM_FLIP_H, - /* flip source image vertically */ - OVERLAY_TRANSFORM_FLIP_V = HAL_TRANSFORM_FLIP_V, - /* rotate source image 90 degrees */ - OVERLAY_TRANSFORM_ROT_90 = HAL_TRANSFORM_ROT_90, + OVERLAY_TRANSFORM_0 = 0x0, + /* flip source image horizontally 0x1 */ + OVERLAY_TRANSFORM_FLIP_H = HAL_TRANSFORM_FLIP_H, + /* flip source image vertically 0x2 */ + OVERLAY_TRANSFORM_FLIP_V = HAL_TRANSFORM_FLIP_V, /* rotate source image 180 degrees * It is basically bit-or-ed H | V == 0x3 */ - OVERLAY_TRANSFORM_ROT_180 = HAL_TRANSFORM_ROT_180, + OVERLAY_TRANSFORM_ROT_180 = HAL_TRANSFORM_ROT_180, + /* rotate source image 90 degrees 0x4 */ + OVERLAY_TRANSFORM_ROT_90 = HAL_TRANSFORM_ROT_90, + /* rotate source image 90 degrees and flip horizontally 0x5 */ + OVERLAY_TRANSFORM_ROT_90_FLIP_H = HAL_TRANSFORM_ROT_90 | + HAL_TRANSFORM_FLIP_H, + /* rotate source image 90 degrees and flip vertically 0x6 */ + OVERLAY_TRANSFORM_ROT_90_FLIP_V = HAL_TRANSFORM_ROT_90 | + HAL_TRANSFORM_FLIP_V, /* rotate source image 270 degrees * Basically 180 | 90 == 0x7 */ - OVERLAY_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270, + OVERLAY_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270, /* rotate invalid like in Transform.h */ - OVERLAY_TRANSFORM_INV = 0x80 -}; - -/* offset and fd are play info */ -struct PlayInfo { - PlayInfo() : fd(-1), offset(0) {} - PlayInfo(int _fd, uint32_t _offset) : - fd(_fd), offset(_offset) {} - bool operator==(const PlayInfo& p) { - return (fd == p.fd && offset == p.offset); - } - int fd; - uint32_t offset; + OVERLAY_TRANSFORM_INV = 0x80 }; // Used to consolidate pipe params struct PipeArgs { PipeArgs() : mdpFlags(OV_MDP_FLAGS_NONE), - orientation(OVERLAY_TRANSFORM_0), - wait(NO_WAIT), zorder(Z_SYSTEM_ALLOC), isFg(IS_FG_OFF), rotFlags(ROT_FLAG_DISABLED){ } - PipeArgs(eMdpFlags f, eTransform o, - Whf _whf, eWait w, + PipeArgs(eMdpFlags f, Whf _whf, eZorder z, eIsFg fg, eRotFlags r) : mdpFlags(f), - orientation(o), whf(_whf), - wait(w), zorder(z), isFg(fg), rotFlags(r) { } - eMdpFlags mdpFlags; // for mdp_overlay flags PIPE_SHARE, NO_WAIT, etc - eTransform orientation; // FIXME docs + eMdpFlags mdpFlags; // for mdp_overlay flags Whf whf; - eWait wait; // flags WAIT/NO_WAIT eZorder zorder; // stage number eIsFg isFg; // control alpha & transp eRotFlags rotFlags; - PlayInfo play; }; enum eOverlayState{ @@ -464,21 +410,13 @@ enum { WFD = 2 }; +//TODO Make this a part of some appropriate class static int sExtType = HDMI; //HDMI or WFD - //Set by client as HDMI/WFD -static inline void setExtType(const int& type) { - if(type != HDMI || type != WFD) { - ALOGE("%s: Unrecognized type %d", __func__, type); - return; - } - sExtType = type; -} - +void setExtType(const int& type); //Return External panel type set by client. -static inline int getExtType() { - return sExtType; -} +int getExtType(); + //Gets the FB number for the external type. //As of now, HDMI always has fb1, WFD could use fb1 or fb2 @@ -503,6 +441,7 @@ static int getFBForPanel(int panel) { // PRIMARY OR EXTERNAL } // number of rgb pipes bufs (max) + // 2 for rgb0/1 double bufs enum { RGB_PIPE_NUM_BUFS = 2 }; @@ -524,52 +463,17 @@ int getRotOutFmt(uint32_t format); * rotation is 90, 180 etc * It returns MDP related enum/define that match rot+flip*/ int getMdpOrient(eTransform rotation); -uint32_t getSize(const Whf& whf); -uint32_t getSizeByMdp(const Whf& whf); const char* getFormatString(uint32_t format); const char* getStateString(eOverlayState state); -inline int setWait(eWait wait, int flags) { - return (wait == WAIT) ? - flags &= ~MDP_OV_PLAY_NOWAIT : - flags |= MDP_OV_PLAY_NOWAIT; -} -/* possible overlay formats libhardware/include/hardware/hardware.h */ -enum eFormat { - OVERLAY_FORMAT_RGBA_8888 = HAL_PIXEL_FORMAT_RGBA_8888, - OVERLAY_FORMAT_RGB_565 = HAL_PIXEL_FORMAT_RGB_565, - OVERLAY_FORMAT_BGRA_8888 = HAL_PIXEL_FORMAT_BGRA_8888, - OVERLAY_FORMAT_YCbYCr_422_I = 0x14, - OVERLAY_FORMAT_CbYCrY_422_I = 0x16, - OVERLAY_FORMAT_DEFAULT = 99 // The actual color format is - // determined by the overlay -}; - // Cannot use HW_OVERLAY_MAGNIFICATION_LIMIT, since at the time // of integration, HW_OVERLAY_MAGNIFICATION_LIMIT was a define enum { HW_OV_MAGNIFICATION_LIMIT = 20, HW_OV_MINIFICATION_LIMIT = 8 }; -inline bool rotated(int orie) { - return (orie == OVERLAY_TRANSFORM_ROT_90 || - orie == OVERLAY_TRANSFORM_ROT_270); -} - -/* used by crop funcs in order to - * normalizes the crop values to be all even */ -void normalizeCrop(uint32_t& xy, uint32_t& wh); - template - inline void memset0(T& t) { ::memset(&t, 0, sizeof(T)); } - -template - inline void swapOVRotWidthHeight(ROT& rot, MDP& mdp) - { - mdp.swapSrcWH(); - mdp.swapSrcRectWH(); - rot.swapDstWH(); - } +inline void memset0(T& t) { ::memset(&t, 0, sizeof(T)); } template inline void swap ( T& a, T& b ) { @@ -587,35 +491,6 @@ inline int align(int value, int a) { return a ? ((value + (a-1)) & ~(a-1)) : value; } - -template -inline utils::Dim getSrcRectDim(const MDP& ov) { - return utils::Dim(ov.src_rect.x, - ov.src_rect.y, - ov.src_rect.w, - ov.src_rect.h); -} - -template -inline utils::Whf getSrcWhf(const MDP& ov) { - return utils::Whf(ov.src.width, - ov.src.height, - ov.src.format); -} -template -inline void setSrcRectDim(MDP& ov, const utils::Dim& d) { - ov.src_rect.x = d.x; - ov.src_rect.y = d.y; - ov.src_rect.w = d.w; - ov.src_rect.h = d.h; -} -template -inline void setSrcWhf(MDP& ov, const utils::Whf& whf) { - ov.src.width = whf.w; - ov.src.height = whf.h; - ov.src.format = whf.format; -} - enum eRotOutFmt { ROT_OUT_FMT_DEFAULT, ROT_OUT_FMT_Y_CRCB_H2V2 @@ -691,21 +566,30 @@ inline const char* getFormatString(uint32_t format){ "MDP_RGB_565", "MDP_XRGB_8888", "MDP_Y_CBCR_H2V2", + "MDP_Y_CBCR_H2V2_ADRENO", "MDP_ARGB_8888", "MDP_RGB_888", "MDP_Y_CRCB_H2V2", "MDP_YCRYCB_H2V1", "MDP_Y_CRCB_H2V1", "MDP_Y_CBCR_H2V1", + "MDP_Y_CRCB_H1V2", + "MDP_Y_CBCR_H1V2", "MDP_RGBA_8888", "MDP_BGRA_8888", "MDP_RGBX_8888", "MDP_Y_CRCB_H2V2_TILE", "MDP_Y_CBCR_H2V2_TILE", "MDP_Y_CR_CB_H2V2", + "MDP_Y_CR_CB_GH2V2", "MDP_Y_CB_CR_H2V2", - "MDP_IMGTYPE_LIMIT", + "MDP_Y_CRCB_H1V1", + "MDP_Y_CBCR_H1V1", + "MDP_YCRCB_H1V1", + "MDP_YCBCR_H1V1", "MDP_BGR_565", + "MDP_IMGTYPE_LIMIT", + "MDP_RGB_BORDERFILL", "MDP_FB_FORMAT", "MDP_IMGTYPE_LIMIT2" }; @@ -746,15 +630,6 @@ inline const char* getStateString(eOverlayState state){ return "BAD_STATE"; } -inline uint32_t getSizeByMdp(const Whf& whf) { - Whf _whf(whf); - int fmt = getMdpFormat(whf.format); - OVASSERT(-1 != fmt, "getSizeByMdp error in format %d", - whf.format); - _whf.format = fmt; - return getSize(_whf); -} - inline void Whf::dump() const { ALOGE("== Dump WHF w=%d h=%d f=%d s=%d start/end ==", w, h, format, size); @@ -766,21 +641,21 @@ inline void Dim::dump() const { inline int getMdpOrient(eTransform rotation) { ALOGE_IF(DEBUG_OVERLAY, "%s: rot=%d", __FUNCTION__, rotation); - switch(int(rotation)) + switch(rotation) { case OVERLAY_TRANSFORM_0 : return 0; - case HAL_TRANSFORM_FLIP_V: return MDP_FLIP_UD; - case HAL_TRANSFORM_FLIP_H: return MDP_FLIP_LR; - case HAL_TRANSFORM_ROT_90: return MDP_ROT_90; - case HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_V: - return MDP_ROT_90|MDP_FLIP_LR; - case HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H: - return MDP_ROT_90|MDP_FLIP_UD; - case HAL_TRANSFORM_ROT_180: return MDP_ROT_180; - case HAL_TRANSFORM_ROT_270: return MDP_ROT_270; + case OVERLAY_TRANSFORM_FLIP_V: return MDP_FLIP_UD; + case OVERLAY_TRANSFORM_FLIP_H: return MDP_FLIP_LR; + case OVERLAY_TRANSFORM_ROT_90: return MDP_ROT_90; + case OVERLAY_TRANSFORM_ROT_90_FLIP_V: + return MDP_ROT_90 | MDP_FLIP_UD; + case OVERLAY_TRANSFORM_ROT_90_FLIP_H: + return MDP_ROT_90 | MDP_FLIP_LR; + case OVERLAY_TRANSFORM_ROT_180: return MDP_ROT_180; + case OVERLAY_TRANSFORM_ROT_270: return MDP_ROT_270; default: - ALOGE("%s: invalid rotation value (value = 0x%x", - __FUNCTION__, rotation); + ALOGE("%s: invalid rotation value (value = 0x%x", + __FUNCTION__, rotation); } return -1; } @@ -801,28 +676,11 @@ inline int getRotOutFmt(uint32_t format) { return -1; } -template<> -struct RotOutFmt -{ - static inline int fmt(uint32_t format) { - return getRotOutFmt(format); - } -}; - -template<> -struct RotOutFmt -{ - static inline int fmt(uint32_t) { - return MDP_Y_CRCB_H2V2; - } -}; inline uint32_t getColorFormat(uint32_t format) { - //XXX: Earlier this used to mask the format - //to check for interlaced or 3D. Just return - //the format now - return format; + return (format == HAL_PIXEL_FORMAT_YV12) ? + format : colorFormat(format); } // FB0 @@ -937,43 +795,6 @@ inline void ScreenInfo::dump(const char* const s) const { s, mFBWidth, mFBHeight, mFBbpp, mFBystride); } -inline void setSrcRectDim(const overlay::utils::Dim d, - mdp_overlay& ov) { - ov.src_rect.x = d.x; - ov.src_rect.y = d.y; - ov.src_rect.w = d.w; - ov.src_rect.h = d.h; -} - -inline void setDstRectDim(const overlay::utils::Dim d, - mdp_overlay& ov) { - ov.dst_rect.x = d.x; - ov.dst_rect.y = d.y; - ov.dst_rect.w = d.w; - ov.dst_rect.h = d.h; -} - -inline overlay::utils::Whf getSrcWhf(const mdp_overlay& ov) { - return overlay::utils::Whf(ov.src.width, - ov.src.height, - ov.src.format); -} - -inline overlay::utils::Dim getSrcRectDim(const mdp_overlay& ov) { - return overlay::utils::Dim(ov.src_rect.x, - ov.src_rect.y, - ov.src_rect.w, - ov.src_rect.h); -} - -inline overlay::utils::Dim getDstRectDim(const mdp_overlay& ov) { - return overlay::utils::Dim(ov.dst_rect.x, - ov.dst_rect.y, - ov.dst_rect.w, - ov.dst_rect.h); -} - - } // namespace utils ends //--------------------Class Res stuff (namespace overlay only) ----------- @@ -981,7 +802,7 @@ inline overlay::utils::Dim getDstRectDim(const mdp_overlay& ov) { class Res { public: // /dev/graphics/fb%u - static const char* const devTemplate; + static const char* const fbPath; // /dev/msm_rotator static const char* const rotPath; // /sys/class/graphics/fb1/format_3d @@ -1060,7 +881,9 @@ inline OvFD::OvFD() : mFD (INVAL) { mPath[0] = 0; } -inline OvFD::~OvFD() { /* no op in the meantime */ } +inline OvFD::~OvFD() { + //no op since copy() can be used to share fd, in 3d cases. +} inline bool OvFD::open(const char* const dev, int flags) { diff --git a/liboverlay/pipes/overlay3DPipe.h b/liboverlay/pipes/overlay3DPipe.h index dce4bf4..86ebed7 100644 --- a/liboverlay/pipes/overlay3DPipe.h +++ b/liboverlay/pipes/overlay3DPipe.h @@ -50,20 +50,15 @@ public: /* Please look at overlayGenPipe.h for info */ explicit M3DExtPipe(); ~M3DExtPipe(); - bool open(RotatorBase* rot); + bool init(RotatorBase* rot); bool close(); bool commit(); - void setId(int id); - void setMemoryId(int id); - bool queueBuffer(uint32_t offset); - bool dequeueBuffer(void*& buf); + bool queueBuffer(int fd, uint32_t offset); bool waitForVsync(); bool setCrop(const utils::Dim& d); - bool start(const utils::PipeArgs& args); bool setPosition(const utils::Dim& dim); - bool setParameter(const utils::Params& param); + bool setTransform(const utils::eTransform& param); bool setSource(const utils::PipeArgs& args); - const utils::PipeArgs& getArgs() const; utils::eOverlayPipeType getOvPipeType() const; void dump() const; private: @@ -87,20 +82,15 @@ public: /* Please look at overlayGenPipe.h for info */ explicit M3DPrimaryPipe(); ~M3DPrimaryPipe(); - bool open(RotatorBase* rot); + bool init(RotatorBase* rot); bool close(); bool commit(); - void setId(int id); - void setMemoryId(int id); - bool queueBuffer(uint32_t offset); - bool dequeueBuffer(void*& buf); + bool queueBuffer(int fd, uint32_t offset); bool waitForVsync(); bool setCrop(const utils::Dim& d); - bool start(const utils::PipeArgs& args); bool setPosition(const utils::Dim& dim); - bool setParameter(const utils::Params& param); + bool setTransform(const utils::eTransform& param); bool setSource(const utils::PipeArgs& args); - const utils::PipeArgs& getArgs() const; utils::eOverlayPipeType getOvPipeType() const; void dump() const; private: @@ -124,20 +114,15 @@ public: /* Please look at overlayGenPipe.h for info */ explicit S3DExtPipe(); ~S3DExtPipe(); - bool open(RotatorBase* rot); + bool init(RotatorBase* rot); bool close(); bool commit(); - void setId(int id); - void setMemoryId(int id); - bool queueBuffer(uint32_t offset); - bool dequeueBuffer(void*& buf); + bool queueBuffer(int fd, uint32_t offset); bool waitForVsync(); bool setCrop(const utils::Dim& d); - bool start(const utils::PipeArgs& args); bool setPosition(const utils::Dim& dim); - bool setParameter(const utils::Params& param); + bool setTransform(const utils::eTransform& param); bool setSource(const utils::PipeArgs& args); - const utils::PipeArgs& getArgs() const; utils::eOverlayPipeType getOvPipeType() const; void dump() const; private: @@ -161,20 +146,15 @@ public: /* Please look at overlayGenPipe.h for info */ explicit S3DPrimaryPipe(); ~S3DPrimaryPipe(); - bool open(RotatorBase* rot); + bool init(RotatorBase* rot); bool close(); bool commit(); - void setId(int id); - void setMemoryId(int id); - bool queueBuffer(uint32_t offset); - bool dequeueBuffer(void*& buf); + bool queueBuffer(int fd, uint32_t offset); bool waitForVsync(); bool setCrop(const utils::Dim& d); - bool start(const utils::PipeArgs& args); bool setPosition(const utils::Dim& dim); - bool setParameter(const utils::Params& param); + bool setTransform(const utils::eTransform& param); bool setSource(const utils::PipeArgs& args); - const utils::PipeArgs& getArgs() const; utils::eOverlayPipeType getOvPipeType() const; void dump() const; private: @@ -197,10 +177,10 @@ inline M3DExtPipe::M3DExtPipe() : mM3Dfmt(0) {} template inline M3DExtPipe::~M3DExtPipe() { close(); } template -inline bool M3DExtPipe::open(RotatorBase* rot) { - ALOGE_IF(DEBUG_OVERLAY, "M3DExtPipe open"); - if(!mM3d.open(rot)) { - ALOGE("3Dpipe failed to open"); +inline bool M3DExtPipe::init(RotatorBase* rot) { + ALOGE_IF(DEBUG_OVERLAY, "M3DExtPipe init"); + if(!mM3d.init(rot)) { + ALOGE("3Dpipe failed to init"); return false; } return true; @@ -212,15 +192,9 @@ inline bool M3DExtPipe::close() { template inline bool M3DExtPipe::commit() { return mM3d.commit(); } template -inline void M3DExtPipe::setId(int id) { mM3d.setId(id); } -template -inline void M3DExtPipe::setMemoryId(int id) { mM3d.setMemoryId(id); } -template -inline bool M3DExtPipe::queueBuffer(uint32_t offset) { - return mM3d.queueBuffer(offset); } -template -inline bool M3DExtPipe::dequeueBuffer(void*& buf) { - return mM3d.dequeueBuffer(buf); } +inline bool M3DExtPipe::queueBuffer(int fd, uint32_t offset) { + return mM3d.queueBuffer(fd, offset); +} template inline bool M3DExtPipe::waitForVsync() { return mM3d.waitForVsync(); } @@ -233,14 +207,7 @@ inline bool M3DExtPipe::setCrop(const utils::Dim& d) { } return mM3d.setCrop(_dim); } -template -inline bool M3DExtPipe::start(const utils::PipeArgs& args) { - if(!mM3d.start(args)) { - ALOGE("M3DExtPipe start failed"); - return false; - } - return true; -} + template inline bool M3DExtPipe::setPosition(const utils::Dim& d) { utils::Dim _dim; @@ -258,8 +225,8 @@ inline bool M3DExtPipe::setPosition(const utils::Dim& d) { return mM3d.setPosition(_dim); } template -inline bool M3DExtPipe::setParameter(const utils::Params& param) { - return mM3d.setParameter(param); +inline bool M3DExtPipe::setTransform(const utils::eTransform& param) { + return mM3d.setTransform(param); } template inline bool M3DExtPipe::setSource(const utils::PipeArgs& args) @@ -267,19 +234,9 @@ inline bool M3DExtPipe::setSource(const utils::PipeArgs& args) // extract 3D fmt mM3Dfmt = utils::format3DInput(utils::getS3DFormat(args.whf.format)) | utils::HAL_3D_OUT_MONOS_MASK; - if(mM3d.isClosed()){ - if(!this->start(args)) { - ALOGE("M3DExtPipe setSource failed to start"); - return false; - } - } return mM3d.setSource(args); } template -inline const utils::PipeArgs& M3DExtPipe::getArgs() const { - return mM3d.getArgs(); -} -template inline utils::eOverlayPipeType M3DExtPipe::getOvPipeType() const { return utils::OV_PIPE_TYPE_M3D_EXTERNAL; } @@ -296,10 +253,10 @@ inline M3DPrimaryPipe::M3DPrimaryPipe() : mM3Dfmt(0) {} template inline M3DPrimaryPipe::~M3DPrimaryPipe() { close(); } template -inline bool M3DPrimaryPipe::open(RotatorBase* rot) { - ALOGE_IF(DEBUG_OVERLAY, "M3DPrimaryPipe open"); - if(!mM3d.open(rot)) { - ALOGE("3Dpipe failed to open"); +inline bool M3DPrimaryPipe::init(RotatorBase* rot) { + ALOGE_IF(DEBUG_OVERLAY, "M3DPrimaryPipe init"); + if(!mM3d.init(rot)) { + ALOGE("3Dpipe failed to init"); return false; } return true; @@ -311,15 +268,9 @@ inline bool M3DPrimaryPipe::close() { template inline bool M3DPrimaryPipe::commit() { return mM3d.commit(); } template -inline void M3DPrimaryPipe::setId(int id) { mM3d.setId(id); } -template -inline void M3DPrimaryPipe::setMemoryId(int id) { mM3d.setMemoryId(id); } -template -inline bool M3DPrimaryPipe::queueBuffer(uint32_t offset) { - return mM3d.queueBuffer(offset); } -template -inline bool M3DPrimaryPipe::dequeueBuffer(void*& buf) { - return mM3d.dequeueBuffer(buf); } +inline bool M3DPrimaryPipe::queueBuffer(int fd, uint32_t offset) { + return mM3d.queueBuffer(fd, offset); +} template inline bool M3DPrimaryPipe::waitForVsync() { return mM3d.waitForVsync(); } @@ -333,20 +284,12 @@ inline bool M3DPrimaryPipe::setCrop(const utils::Dim& d) { return mM3d.setCrop(_dim); } template -inline bool M3DPrimaryPipe::start(const utils::PipeArgs& args) { - if(!mM3d.start(args)) { - ALOGE("M3DPrimaryPipe start failed"); - return false; - } - return true; -} -template inline bool M3DPrimaryPipe::setPosition(const utils::Dim& d) { return mM3d.setPosition(d); } template -inline bool M3DPrimaryPipe::setParameter(const utils::Params& param) { - return mM3d.setParameter(param); +inline bool M3DPrimaryPipe::setTransform(const utils::eTransform& param) { + return mM3d.setTransform(param); } template inline bool M3DPrimaryPipe::setSource(const utils::PipeArgs& args) @@ -354,19 +297,9 @@ inline bool M3DPrimaryPipe::setSource(const utils::PipeArgs& args) // extract 3D fmt mM3Dfmt = utils::format3DInput(utils::getS3DFormat(args.whf.format)) | utils::HAL_3D_OUT_MONOS_MASK; - if (mM3d.isClosed()) { - if (!this->start(args)) { - ALOGE("M3DPrimaryPipe setSource failed to start"); - return false; - } - } return mM3d.setSource(args); } template -inline const utils::PipeArgs& M3DPrimaryPipe::getArgs() const { - return mM3d.getArgs(); -} -template inline utils::eOverlayPipeType M3DPrimaryPipe::getOvPipeType() const { return utils::OV_PIPE_TYPE_M3D_PRIMARY; } @@ -382,10 +315,10 @@ inline S3DExtPipe::S3DExtPipe() : mS3Dfmt(0) {} template inline S3DExtPipe::~S3DExtPipe() { close(); } template -inline bool S3DExtPipe::open(RotatorBase* rot) { - ALOGE_IF(DEBUG_OVERLAY, "S3DExtPipe open"); - if(!mS3d.open(rot)) { - ALOGE("3Dpipe failed to open"); +inline bool S3DExtPipe::init(RotatorBase* rot) { + ALOGE_IF(DEBUG_OVERLAY, "S3DExtPipe init"); + if(!mS3d.init(rot)) { + ALOGE("3Dpipe failed to init"); return false; } return true; @@ -400,16 +333,9 @@ inline bool S3DExtPipe::close() { template inline bool S3DExtPipe::commit() { return mS3d.commit(); } template -inline void S3DExtPipe::setId(int id) { mS3d.setId(id); } -template -inline void S3DExtPipe::setMemoryId(int id) { mS3d.setMemoryId(id); } -template -inline bool S3DExtPipe::queueBuffer(uint32_t offset) { - //this->dump(); - return mS3d.queueBuffer(offset); } -template -inline bool S3DExtPipe::dequeueBuffer(void*& buf) { - return mS3d.dequeueBuffer(buf); } +inline bool S3DExtPipe::queueBuffer(int fd, uint32_t offset) { + return mS3d.queueBuffer(fd, offset); +} template inline bool S3DExtPipe::waitForVsync() { return mS3d.waitForVsync(); } @@ -423,20 +349,6 @@ inline bool S3DExtPipe::setCrop(const utils::Dim& d) { return mS3d.setCrop(_dim); } template -inline bool S3DExtPipe::start(const utils::PipeArgs& args) { - OVASSERT(mS3Dfmt, "S3DExtPipe mS3Dfmt should not be 0 here"); - if(!mS3d.start(args)) { - ALOGE("S3DExtPipe start failed"); - return false; - } - uint32_t fmt = mS3Dfmt & utils::OUTPUT_3D_MASK; - if(!utils::send3DInfoPacket(fmt)){ - ALOGE("Error S3DExtPipe start error send3DInfoPacket %d", fmt); - return false; - } - return true; -} -template inline bool S3DExtPipe::setPosition(const utils::Dim& d) { utils::Dim _dim; @@ -450,25 +362,15 @@ inline bool S3DExtPipe::setPosition(const utils::Dim& d) return mS3d.setPosition(_dim); } template -inline bool S3DExtPipe::setParameter(const utils::Params& param) { - return mS3d.setParameter(param); +inline bool S3DExtPipe::setTransform(const utils::eTransform& param) { + return mS3d.setTransform(param); } template inline bool S3DExtPipe::setSource(const utils::PipeArgs& args) { mS3Dfmt = utils::getS3DFormat(args.whf.format); - if(mS3d.isClosed()){ - if(!this->start(args)) { - ALOGE("S3DExtPipe setSource failed to start"); - return false; - } - } return mS3d.setSource(args); } template -inline const utils::PipeArgs& S3DExtPipe::getArgs() const { - return mS3d.getArgs(); -} -template inline utils::eOverlayPipeType S3DExtPipe::getOvPipeType() const { return utils::OV_PIPE_TYPE_S3D_EXTERNAL; } @@ -484,10 +386,10 @@ inline S3DPrimaryPipe::S3DPrimaryPipe() : mS3Dfmt(0) {} template inline S3DPrimaryPipe::~S3DPrimaryPipe() { close(); } template -inline bool S3DPrimaryPipe::open(RotatorBase* rot) { - ALOGE_IF(DEBUG_OVERLAY, "S3DPrimaryPipe open"); - if(!mS3d.open(rot)) { - ALOGE("3Dpipe failed to open"); +inline bool S3DPrimaryPipe::init(RotatorBase* rot) { + ALOGE_IF(DEBUG_OVERLAY, "S3DPrimaryPipe init"); + if(!mS3d.init(rot)) { + ALOGE("3Dpipe failed to init"); return false; } // set the ctrl fd @@ -502,18 +404,20 @@ inline bool S3DPrimaryPipe::close() { mCtrl3D.close(); return mS3d.close(); } + template -inline bool S3DPrimaryPipe::commit() { return mS3d.commit(); } +inline bool S3DPrimaryPipe::commit() { + uint32_t fmt = mS3Dfmt & utils::OUTPUT_3D_MASK; + if(!utils::send3DInfoPacket(fmt)){ + ALOGE("Error S3DExtPipe start error send3DInfoPacket %d", fmt); + return false; + } + return mS3d.commit(); +} template -inline void S3DPrimaryPipe::setId(int id) { mS3d.setId(id); } -template -inline void S3DPrimaryPipe::setMemoryId(int id) { mS3d.setMemoryId(id); } -template -inline bool S3DPrimaryPipe::queueBuffer(uint32_t offset) { - return mS3d.queueBuffer(offset); } -template -inline bool S3DPrimaryPipe::dequeueBuffer(void*& buf) { - return mS3d.dequeueBuffer(buf); } +inline bool S3DPrimaryPipe::queueBuffer(int fd, uint32_t offset) { + return mS3d.queueBuffer(fd, offset); +} template inline bool S3DPrimaryPipe::waitForVsync() { return mS3d.waitForVsync(); } @@ -527,14 +431,6 @@ inline bool S3DPrimaryPipe::setCrop(const utils::Dim& d) { return mS3d.setCrop(_dim); } template -inline bool S3DPrimaryPipe::start(const utils::PipeArgs& args) { - if(!mS3d.start(args)) { - ALOGE("S3DPrimaryPipe start failed"); - return false; - } - return true; -} -template inline bool S3DPrimaryPipe::setPosition(const utils::Dim& d) { utils::Whf fbwhf(mS3d.getScreenInfo().mFBWidth, @@ -562,47 +458,35 @@ inline bool S3DPrimaryPipe::setPosition(const utils::Dim& d) * So the easiest way to achieve it, is to make sure FB0 is having it before * setParam is running */ template <> -inline bool S3DPrimaryPipe::setParameter( - const utils::Params& param) { - if(utils::OVERLAY_TRANSFORM == param.param){ - uint32_t barrier=0; - switch(param.value) { - case HAL_TRANSFORM_ROT_90: - case HAL_TRANSFORM_ROT_270: - barrier = utils::BARRIER_LAND; - break; - default: - barrier = utils::BARRIER_PORT; - break; - } - if(!utils::enableBarrier(barrier)) { - ALOGE("S3DPrimaryPipe setParameter failed to enable barrier"); - } +inline bool S3DPrimaryPipe::setTransform( + const utils::eTransform& param) { + uint32_t barrier=0; + switch(param) { + case utils::OVERLAY_TRANSFORM_ROT_90: + case utils::OVERLAY_TRANSFORM_ROT_270: + barrier = utils::BARRIER_LAND; + break; + default: + barrier = utils::BARRIER_PORT; + break; } - return mS3d.setParameter(param); + if(!utils::enableBarrier(barrier)) { + ALOGE("S3DPrimaryPipe setTransform failed to enable barrier"); + } + return mS3d.setTransform(param); } template -inline bool S3DPrimaryPipe::setParameter(const utils::Params& param) { - return mS3d.setParameter(param); +inline bool S3DPrimaryPipe::setTransform(const utils::eTransform& param) { + return mS3d.setTransform(param); } template inline bool S3DPrimaryPipe::setSource(const utils::PipeArgs& args) { mS3Dfmt = utils::getS3DFormat(args.whf.format); - if(mS3d.isClosed()){ - if(!this->start(args)) { - ALOGE("S3DPrimaryPipe setSource failed to start"); - return false; - } - } return mS3d.setSource(args); } template -inline const utils::PipeArgs& S3DPrimaryPipe::getArgs() const { - return mS3d.getArgs(); -} -template inline utils::eOverlayPipeType S3DPrimaryPipe::getOvPipeType() const { return utils::OV_PIPE_TYPE_S3D_PRIMARY; } diff --git a/liboverlay/pipes/overlayBypassPipe.h b/liboverlay/pipes/overlayBypassPipe.h deleted file mode 100644 index 593a693..0000000 --- a/liboverlay/pipes/overlayBypassPipe.h +++ /dev/null @@ -1,213 +0,0 @@ -/* -* Copyright (c) 2012, Code Aurora Forum. All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are -* met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above -* copyright notice, this list of conditions and the following -* disclaimer in the documentation and/or other materials provided -* with the distribution. -* * Neither the name of Code Aurora Forum, Inc. nor the names of its -* contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED -* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT -* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS -* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef OVERLAY_BYPASS_PIPE_H -#define OVERLAY_BYPASS_PIPE_H - -#include "overlayGenPipe.h" -#include "overlayUtils.h" -#include "overlayCtrlData.h" -#include "overlayMdp.h" -#include "overlayRotator.h" - -namespace overlay { - -/* A specific impl of GenericPipe -* Whenever needed to have a pass through - we do it. -* If there is a special need for a different behavior - do it here -* PipeType = 0 (RGB), 1 (VG) */ -template -class BypassPipe : utils::NoCopy { -public: - /* Please look at overlayGenPipe.h for info */ - explicit BypassPipe(); - ~BypassPipe(); - bool open(RotatorBase* rot); - bool close(); - bool commit(); - void setId(int id); - void setMemoryId(int id); - bool queueBuffer(uint32_t offset); - bool dequeueBuffer(void*& buf); - bool waitForVsync(); - bool setCrop(const utils::Dim& dim); - bool start(const utils::PipeArgs& args); - bool setPosition(const utils::Dim& dim); - bool setParameter(const utils::Params& param); - bool setSource(const utils::PipeArgs& args); - const utils::PipeArgs& getArgs() const; - utils::eOverlayPipeType getOvPipeType() const; - void dump() const; -private: - overlay::GenericPipe mBypass; -}; - -//------------------Inlines and Templates--------------------- - -template -inline BypassPipe::BypassPipe() {} - -template -inline BypassPipe::~BypassPipe() { - close(); -} - -template -inline bool BypassPipe::open(RotatorBase* rot) { - ALOGE_IF(DEBUG_OVERLAY, "BypassPipe open"); - return mBypass.open(rot); -} - -template -inline bool BypassPipe::close() { - return mBypass.close(); -} - -template -inline bool BypassPipe::commit() { - return mBypass.commit(); -} - -template -inline void BypassPipe::setId(int id) { - mBypass.setId(id); -} - -template -inline void BypassPipe::setMemoryId(int id) { - mBypass.setMemoryId(id); -} - -template -inline bool BypassPipe::queueBuffer( - uint32_t offset) { - return mBypass.queueBuffer(offset); -} - -template -inline bool BypassPipe::dequeueBuffer( - void*& buf) { - return mBypass.dequeueBuffer(buf); -} - -template -inline bool BypassPipe::waitForVsync() { - return mBypass.waitForVsync(); -} - -template -inline bool BypassPipe::setCrop( - const utils::Dim& dim) { - return mBypass.setCrop(dim); -} - -template -inline bool BypassPipe::start( - const utils::PipeArgs& args) { - return mBypass.start(args); -} - -template -inline bool BypassPipe::setPosition( - const utils::Dim& dim) { - return mBypass.setPosition(dim); -} - -template -inline bool BypassPipe::setParameter( - const utils::Params& param) { - return mBypass.setParameter(param); -} - -template -inline bool BypassPipe::setSource( - const utils::PipeArgs& args) { - utils::PipeArgs arg(args); - - // Stride aligned to 32 - arg.whf.w = utils::align(arg.whf.w, 32); - arg.whf.h = utils::align(arg.whf.h, 32); - - // VG or RG pipe - if (PipeType == utils::OV_MDP_PIPE_VG) { - setMdpFlags(arg.mdpFlags, utils::OV_MDP_PIPE_SHARE); - } - - // Set is_fg flag - arg.isFg = IsFg; - - // Wait or no wait - arg.wait = Wait; - - // Z-order - arg.zorder = Zorder; - - return mBypass.setSource(arg); -} - -template -inline const utils::PipeArgs& BypassPipe::getArgs() const { - return mBypass.getArgs(); -} - -template -inline utils::eOverlayPipeType BypassPipe::getOvPipeType() const { - return utils::OV_PIPE_TYPE_BYPASS; -} - -template -inline void BypassPipe::dump() const { - ALOGE("Bypass VG Pipe"); - mBypass.dump(); -} - -} // overlay - -#endif // OVERLAY_BYPASS_PIPE_H diff --git a/liboverlay/pipes/overlayGenPipe.h b/liboverlay/pipes/overlayGenPipe.h index 1fd4a4f..c2d774b 100644 --- a/liboverlay/pipes/overlayGenPipe.h +++ b/liboverlay/pipes/overlayGenPipe.h @@ -34,65 +34,38 @@ #include "overlayRotator.h" #include "overlayCtrlData.h" -// FIXME make int to be uint32 whenever possible - namespace overlay { template class GenericPipe : utils::NoCopy { public: - /* ctor init */ + /* ctor */ explicit GenericPipe(); - - /* dtor close */ + /* dtor */ ~GenericPipe(); - - /* CTRL/DATA/ROT open */ - bool open(RotatorBase* rot); - + /* CTRL/DATA init. Not owning rotator, will not init it */ + bool init(RotatorBase* rot); /* CTRL/DATA close. Not owning rotator, will not close it */ bool close(); + /* Control APIs */ + /* set source using whf, orient and wait flag */ + bool setSource(const utils::PipeArgs& args); + /* set crop a.k.a the region of interest */ + bool setCrop(const utils::Dim& d); + /* set orientation*/ + bool setTransform(const utils::eTransform& param); + /* set mdp posision using dim */ + bool setPosition(const utils::Dim& dim); /* commit changes to the overlay "set"*/ bool commit(); - /* "Data" related interface */ - - /* set ID directly to data channel */ - void setId(int id); - - /* Set FD / memid */ - void setMemoryId(int id); - + /* Data APIs */ /* queue buffer to the overlay */ - bool queueBuffer(uint32_t offset); - - /* dequeue buffer to the overlay NOTSUPPORTED */ - bool dequeueBuffer(void*& buf); - + bool queueBuffer(int fd, uint32_t offset); /* wait for vsync to be done */ bool waitForVsync(); - /* set crop data FIXME setROI (Region Of Intrest) */ - bool setCrop(const utils::Dim& d); - - /* "Ctrl" related interface */ - - /* - * Start a session, opens the rotator - * FIXME, we might want to open the rotator separately - */ - bool start(const utils::PipeArgs& args); - - /* set mdp posision using dim */ - bool setPosition(const utils::Dim& dim); - - /* set param using Params (param,value pair) */ - bool setParameter(const utils::Params& param); - - /* set source using whf, orient and wait flag */ - bool setSource(const utils::PipeArgs& args); - /* return cached startup args */ const utils::PipeArgs& getArgs() const; @@ -123,33 +96,33 @@ public: /* dump the state of the object */ void dump() const; private: - /* set Closed channel */ + /* set Closed pipe */ bool setClosed(); - // kick off rotator. - bool startRotator(); /* Ctrl/Data aggregator */ CtrlData mCtrlData; - /* caching startup params. useful when need - * to have the exact copy of that pipe. - * For example when HDMI is connected, and we would - * like to open/start the pipe with the args */ - utils::PipeArgs mArgs; - /* rotator mdp base * Can point to NullRotator or to Rotator*/ RotatorBase* mRot; - /* my flags */ - enum { CLOSED = 1<<0 }; - uint32_t mFlags; + //Whether rotator is used for 0-rot or otherwise + bool mRotUsed; + + /* Pipe open or closed */ + enum ePipeState { + CLOSED, + OPEN + }; + ePipeState pipeState; }; //------------------------Inlines and Templates ---------------------- template -GenericPipe::GenericPipe() : mRot(0), mFlags(CLOSED) {} +GenericPipe::GenericPipe() : mRot(0), mRotUsed(false), + pipeState(CLOSED) { +} template GenericPipe::~GenericPipe() { @@ -157,33 +130,42 @@ GenericPipe::~GenericPipe() { } template -bool GenericPipe::open(RotatorBase* rot) +bool GenericPipe::init(RotatorBase* rot) { + ALOGE_IF(DEBUG_OVERLAY, "GenericPipe init"); OVASSERT(rot, "rot is null"); - // open ctrl and data + + // init ctrl and data uint32_t fbnum = utils::getFBForPanel(PANEL); - ALOGE_IF(DEBUG_OVERLAY, "GenericPipe open"); - if(!mCtrlData.ctrl.open(fbnum, rot)) { - ALOGE("GenericPipe failed to open ctrl"); + + if(!mCtrlData.ctrl.init(fbnum)) { + ALOGE("GenericPipe failed to init ctrl"); return false; } - if(!mCtrlData.data.open(fbnum, rot)) { - ALOGE("GenericPipe failed to open data"); + + if(!mCtrlData.data.init(fbnum)) { + ALOGE("GenericPipe failed to init data"); return false; } + + //Cache the rot ref. Ownership is with OverlayImpl. mRot = rot; - // NOTE: we won't have the flags as non CLOSED since we - // consider the pipe opened for business only when we call - // start() + mRotUsed = false; + + // NOTE:init() on the rot is called by OverlayImpl + // Pipes only have to worry about using rot, and not init or close. return true; } template bool GenericPipe::close() { - if(isClosed()) return true; + if(isClosed()) + return true; + bool ret = true; + if(!mCtrlData.ctrl.close()) { ALOGE("GenericPipe failed to close ctrl"); ret = false; @@ -192,153 +174,118 @@ bool GenericPipe::close() { ALOGE("GenericPipe failed to close data"); ret = false; } + + // NOTE:close() on the rot is called by OverlayImpl + // Pipes only have to worry about using rot, and not init or close. + setClosed(); return ret; } template -inline bool GenericPipe::commit(){ - OVASSERT(isOpen(), "State is closed, cannot commit"); - return mCtrlData.ctrl.commit(); +inline bool GenericPipe::setSource( + const utils::PipeArgs& args) +{ + utils::PipeArgs newargs(args); + //Interlace video handling. + if(newargs.whf.format & INTERLACE_MASK) { + setMdpFlags(newargs.mdpFlags, utils::OV_MDP_DEINTERLACE); + } + utils::Whf whf(newargs.whf); + //Extract HAL format from lower bytes. Deinterlace if interlaced. + whf.format = utils::getColorFormat(whf.format); + //Get MDP equivalent of HAL format. + whf.format = utils::getMdpFormat(whf.format); + newargs.whf = whf; + + //Cache if user wants 0-rotation + mRotUsed = newargs.rotFlags & utils::ROT_FLAG_ENABLED; + mRot->setSource(newargs.whf); + mRot->setFlags(newargs.mdpFlags); + return mCtrlData.ctrl.setSource(newargs); } template -inline void GenericPipe::setMemoryId(int id) { - OVASSERT(isOpen(), "State is closed, cannot setMemoryId"); - mCtrlData.data.setMemoryId(id); +inline bool GenericPipe::setCrop( + const overlay::utils::Dim& d) { + return mCtrlData.ctrl.setCrop(d); } template -inline void GenericPipe::setId(int id) { - mCtrlData.data.setId(id); } +inline bool GenericPipe::setTransform( + const utils::eTransform& orient) +{ + //Rotation could be enabled by user for zero-rot or the layer could have + //some transform. Mark rotation enabled in either case. + mRotUsed |= (orient != utils::OVERLAY_TRANSFORM_0); + mRot->setTransform(orient, mRotUsed); + + return mCtrlData.ctrl.setTransform(orient, mRotUsed); +} + +template +inline bool GenericPipe::setPosition(const utils::Dim& d) +{ + return mCtrlData.ctrl.setPosition(d); +} + +template +inline bool GenericPipe::commit() { + bool ret = false; + //If wanting to use rotator, start it. + if(mRotUsed) { + if(!mRot->commit()) { + ALOGE("GenPipe Rotator commit failed"); + return false; + } + } + ret = mCtrlData.ctrl.commit(); + pipeState = ret ? OPEN : CLOSED; + return ret; +} + +template +inline bool GenericPipe::queueBuffer(int fd, uint32_t offset) { + //TODO Move pipe-id transfer to CtrlData class. Make ctrl and data private. + OVASSERT(isOpen(), "State is closed, cannot queueBuffer"); + int pipeId = mCtrlData.ctrl.getPipeId(); + OVASSERT(-1 != pipeId, "Ctrl ID should not be -1"); + // set pipe id from ctrl to data + mCtrlData.data.setPipeId(pipeId); + + int finalFd = fd; + uint32_t finalOffset = offset; + //If rotator is to be used, queue to it, so it can ROTATE. + if(mRotUsed) { + if(!mRot->queueBuffer(fd, offset)) { + ALOGE("GenPipe Rotator play failed"); + return false; + } + //Configure MDP's source buffer as the current output buffer of rotator + if(mRot->getDstMemId() != -1) { + finalFd = mRot->getDstMemId(); + finalOffset = mRot->getDstOffset(); + } else { + //Could be -1 for NullRotator, if queue above succeeds. + //Need an actual rotator. Modify overlay State Traits. + //Not fatal, keep queuing to MDP without rotation. + ALOGE("Null rotator in use, where an actual is required"); + } + } + return mCtrlData.data.queueBuffer(finalFd, finalOffset); +} template inline int GenericPipe::getCtrlFd() const { return mCtrlData.ctrl.getFd(); } -template -inline bool GenericPipe::setCrop( - const overlay::utils::Dim& d) { - OVASSERT(isOpen(), "State is closed, cannot setCrop"); - return mCtrlData.ctrl.setCrop(d); -} - -template -bool GenericPipe::start(const utils::PipeArgs& args) -{ - /* open before your start control rotator */ - uint32_t sz = args.whf.size; //utils::getSizeByMdp(args.whf); - OVASSERT(sz, "GenericPipe sz=%d", sz); - if(!mRot->open()) { - ALOGE("GenericPipe start failed to open rot"); - return false; - } - - if(!mCtrlData.ctrl.start(args)){ - ALOGE("GenericPipe failed to start"); - return false; - } - - int ctrlId = mCtrlData.ctrl.getId(); - OVASSERT(-1 != ctrlId, "Ctrl ID should not be -1"); - // set ID requeset to assoc ctrl to data - setId(ctrlId); - // set ID request to assoc MDP data to ROT MDP data - mRot->setDataReqId(mCtrlData.data.getId()); - - // cache the args for future reference. - mArgs = args; - - // we got here so we are open+start and good to go - mFlags = 0; // clear flags from CLOSED - // TODO make it more robust when more flags - // are added - - return true; -} - -template -inline const utils::PipeArgs& GenericPipe::getArgs() const -{ - return mArgs; -} - -template -bool GenericPipe::startRotator() { - // kick off rotator - if(!mRot->start()) { - ALOGE("GenericPipe failed to start rotator"); - return false; - } - return true; -} - -template -inline bool GenericPipe::queueBuffer(uint32_t offset) { - OVASSERT(isOpen(), "State is closed, cannot queueBuffer"); - return mCtrlData.data.queueBuffer(offset); -} - -template -inline bool GenericPipe::dequeueBuffer(void*&) { - OVASSERT(isOpen(), "State is closed, cannot dequeueBuffer"); - // can also set error to NOTSUPPORTED in the future - return false; -} - template inline bool GenericPipe::waitForVsync() { OVASSERT(isOpen(), "State is closed, cannot waitForVsync"); - return mCtrlData.data.waitForVsync(); } -template -inline bool GenericPipe::setPosition(const utils::Dim& dim) -{ - OVASSERT(isOpen(), "State is closed, cannot setPosition"); - return mCtrlData.ctrl.setPosition(dim); -} - -template -inline bool GenericPipe::setParameter( - const utils::Params& param) -{ - OVASSERT(isOpen(), "State is closed, cannot setParameter"); - // Currently setParameter would start rotator - if(!mCtrlData.ctrl.setParameter(param)) { - ALOGE("GenericPipe failed to setparam"); - return false; - } - // if rot flags are ENABLED it means we would always - // like to have rot. Even with 0 rot. (solves tearing) - if(utils::ROT_FLAG_ENABLED == mArgs.rotFlags) { - mRot->setEnable(); - } - return startRotator(); -} - -template -inline bool GenericPipe::setSource( - const utils::PipeArgs& args) -{ - // cache the recent args. - mArgs = args; - // setSource is the 1st thing that is being called on a pipe. - // If pipe is closed, we should start everything. - // we assume it is being opened with the correct FDs. - if(isClosed()) { - if(!this->start(args)) { - ALOGE("GenericPipe setSource failed to start"); - return false; - } - return true; - } - - return mCtrlData.ctrl.setSource(args); -} - template inline utils::Dim GenericPipe::getAspectRatio( const utils::Whf& whf) const @@ -374,7 +321,7 @@ template void GenericPipe::dump() const { ALOGE("== Dump Generic pipe start =="); - ALOGE("flags=0x%x", mFlags); + ALOGE("pipe state = %d", (int)pipeState); OVASSERT(mRot, "GenericPipe should have a valid Rot"); mCtrlData.ctrl.dump(); mCtrlData.data.dump(); @@ -384,20 +331,20 @@ void GenericPipe::dump() const template inline bool GenericPipe::isClosed() const { - return utils::getBit(mFlags, CLOSED); + return (pipeState == CLOSED); } template inline bool GenericPipe::isOpen() const { - return !isClosed(); + return (pipeState == OPEN); } template inline bool GenericPipe::setClosed() { - return utils::setBit(mFlags, CLOSED); + pipeState = CLOSED; + return true; } - } //namespace overlay #endif // OVERLAY_GENERIC_PIPE_H diff --git a/liboverlay/pipes/overlayUIMirrorPipe.h b/liboverlay/pipes/overlayUIMirrorPipe.h index 47fbc37..1c22020 100644 --- a/liboverlay/pipes/overlayUIMirrorPipe.h +++ b/liboverlay/pipes/overlayUIMirrorPipe.h @@ -46,74 +46,61 @@ public: /* Please look at overlayGenPipe.h for info */ explicit UIMirrorPipe(); ~UIMirrorPipe(); - bool open(RotatorBase* rot); + bool init(RotatorBase* rot); bool close(); bool commit(); - void setId(int id); - void setMemoryId(int id); - bool queueBuffer(uint32_t offset); - bool dequeueBuffer(void*& buf); + bool queueBuffer(int fd, uint32_t offset); bool waitForVsync(); bool setCrop(const utils::Dim& dim); - bool start(const utils::PipeArgs& args); bool setPosition(const utils::Dim& dim); - bool setParameter(const utils::Params& param); + bool setTransform(const utils::eTransform& param); bool setSource(const utils::PipeArgs& args); - const utils::PipeArgs& getArgs() const; utils::eOverlayPipeType getOvPipeType() const; void dump() const; private: overlay::GenericPipe mUI; + utils::eTransform mPrimFBOr; //Primary FB's orientation }; //----------------------------Inlines ----------------------------- -inline UIMirrorPipe::UIMirrorPipe() {} +inline UIMirrorPipe::UIMirrorPipe() { mPrimFBOr = utils::OVERLAY_TRANSFORM_0; } inline UIMirrorPipe::~UIMirrorPipe() { close(); } -inline bool UIMirrorPipe::open(RotatorBase* rot) { - ALOGE_IF(DEBUG_OVERLAY, "UIMirrorPipe open"); - bool ret = mUI.open(rot); - //If source to rotator is framebuffer, which is the case we UI Mirror pipe, - //we need to inform driver during playback. Since FB does not use ION. - rot->setSrcFB(true); +inline bool UIMirrorPipe::init(RotatorBase* rot) { + ALOGE_IF(DEBUG_OVERLAY, "UIMirrorPipe init"); + bool ret = mUI.init(rot); + //If source to rotator is FB, which is the case with UI Mirror pipe, + //we need to inform driver during playback, since FB does not use ION. + rot->setSrcFB(); return ret; } inline bool UIMirrorPipe::close() { return mUI.close(); } inline bool UIMirrorPipe::commit() { return mUI.commit(); } -inline void UIMirrorPipe::setId(int id) { mUI.setId(id); } -inline void UIMirrorPipe::setMemoryId(int id) { mUI.setMemoryId(id); } -inline bool UIMirrorPipe::queueBuffer(uint32_t offset) { - return mUI.queueBuffer(offset); } -inline bool UIMirrorPipe::dequeueBuffer(void*& buf) { - return mUI.dequeueBuffer(buf); } +inline bool UIMirrorPipe::queueBuffer(int fd, uint32_t offset) { + return mUI.queueBuffer(fd, offset); +} inline bool UIMirrorPipe::waitForVsync() { return mUI.waitForVsync(); } inline bool UIMirrorPipe::setCrop(const utils::Dim& dim) { return mUI.setCrop(dim); } -inline bool UIMirrorPipe::start(const utils::PipeArgs& args) { - if(!mUI.start(args)) { - ALOGE("%s failed to start", __FUNCTION__); - return false; - } - return true; -} -inline bool UIMirrorPipe::setPosition(const utils::Dim& dim) { +inline bool UIMirrorPipe::setPosition(const utils::Dim& dim) { ovutils::Dim pdim; - switch (dim.o) { - case 0: - case HAL_TRANSFORM_ROT_180: + //using utils::eTransform; + switch (mPrimFBOr) { + case utils::OVERLAY_TRANSFORM_0: + case utils::OVERLAY_TRANSFORM_ROT_180: { - ovutils::Whf whf(dim.x, dim.y, 0); + ovutils::Whf whf(dim.w, dim.h, 0); pdim = mUI.getAspectRatio(whf); break; } - case HAL_TRANSFORM_ROT_90: - case HAL_TRANSFORM_ROT_270: + case utils::OVERLAY_TRANSFORM_ROT_90: + case utils::OVERLAY_TRANSFORM_ROT_270: { // Calculate the Aspectratio for the UI in the landscape mode // Width and height will be swapped as there is rotation - ovutils::Whf whf(dim.y, dim.x, 0); + ovutils::Whf whf(dim.h, dim.w, 0); pdim = mUI.getAspectRatio(whf); break; } @@ -121,43 +108,43 @@ inline bool UIMirrorPipe::setPosition(const utils::Dim& dim) { ALOGE("%s: Unknown orientation %d", __FUNCTION__, dim.o); return false; } - - ovutils::even_out(pdim.x); - ovutils::even_out(pdim.y); - ovutils::even_out(pdim.w); - ovutils::even_out(pdim.h); return mUI.setPosition(pdim); } -inline bool UIMirrorPipe::setParameter(const utils::Params& param) { - OVASSERT(utils::OVERLAY_TRANSFORM_UI == param.param, - "%p Expecting OVERLAY_TRANSFORM_UI", __FUNCTION__); +inline bool UIMirrorPipe::setTransform(const utils::eTransform& param) { - int orientation = param.value; + //Cache the primary FB orientation, since the TV's will be 0, we need this + //info to translate later. + mPrimFBOr = param; + utils::eTransform transform = param; // Figure out orientation to transform to - switch (param.value) { - case 0: - orientation = 0; + switch (param) { + case utils::OVERLAY_TRANSFORM_0: + transform = utils::OVERLAY_TRANSFORM_0; break; - case HAL_TRANSFORM_ROT_180: - orientation = HAL_TRANSFORM_ROT_180; + case utils::OVERLAY_TRANSFORM_ROT_180: + //If prim FB is drawn 180 rotated, rotate by additional 180 to make + //it to 0, which is TV's orientation. + transform = utils::OVERLAY_TRANSFORM_ROT_180; break; - case HAL_TRANSFORM_ROT_90: - orientation = HAL_TRANSFORM_ROT_270; + case utils::OVERLAY_TRANSFORM_ROT_90: + //If prim FB is drawn 90 rotated, rotate by additional 270 to make + //it to 0, which is TV's orientation. + transform = utils::OVERLAY_TRANSFORM_ROT_270; break; - case HAL_TRANSFORM_ROT_270: - orientation = HAL_TRANSFORM_ROT_90; + case utils::OVERLAY_TRANSFORM_ROT_270: + //If prim FB is drawn 270 rotated, rotate by additional 90 to make + //it to 0, which is TV's orientation. + transform = utils::OVERLAY_TRANSFORM_ROT_90; break; default: - ALOGE("%s: Unknown orientation %d", __FUNCTION__, param.value); + ALOGE("%s: Unknown orientation %d", __FUNCTION__, + static_cast(param)); return false; } - ovutils::eTransform transform = - static_cast(orientation); - const ovutils::Params prms (ovutils::OVERLAY_TRANSFORM, transform); - return mUI.setParameter(prms); + return mUI.setTransform(transform); } inline bool UIMirrorPipe::setSource(const utils::PipeArgs& args) { @@ -175,9 +162,6 @@ inline bool UIMirrorPipe::setSource(const utils::PipeArgs& args) { return mUI.setSource(arg); } -inline const utils::PipeArgs& UIMirrorPipe::getArgs() const { - return mUI.getArgs(); -} inline utils::eOverlayPipeType UIMirrorPipe::getOvPipeType() const { return utils::OV_PIPE_TYPE_UI_MIRROR; } diff --git a/liboverlay/pipes/overlayHdmiPipe.h b/liboverlay/pipes/overlayVideoExtPipe.h similarity index 55% rename from liboverlay/pipes/overlayHdmiPipe.h rename to liboverlay/pipes/overlayVideoExtPipe.h index 48c3817..8196fe7 100644 --- a/liboverlay/pipes/overlayHdmiPipe.h +++ b/liboverlay/pipes/overlayVideoExtPipe.h @@ -27,8 +27,8 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef OVERLAY_HDMI_PIPE_H -#define OVERLAY_HDMI_PIPE_H +#ifndef OVERLAY_VIDEO_EXT_PIPE_H +#define OVERLAY_VIDEO_EXT_PIPE_H #include "overlayGenPipe.h" #include "overlayUtils.h" @@ -41,88 +41,79 @@ namespace overlay { /* A specific impl of GenericPipe * Whenever needed to have a pass through - we do it. * If there is a special need for a different behavior - do it here */ -class HdmiPipe : utils::NoCopy { +class VideoExtPipe : utils::NoCopy { public: /* Please look at overlayGenPipe.h for info */ - explicit HdmiPipe(); - ~HdmiPipe(); - bool open(RotatorBase* rot); + explicit VideoExtPipe(); + ~VideoExtPipe(); + bool init(RotatorBase* rot); bool close(); bool commit(); - void setId(int id); - void setMemoryId(int id); - bool queueBuffer(uint32_t offset); - bool dequeueBuffer(void*& buf); + bool queueBuffer(int fd, uint32_t offset); bool waitForVsync(); bool setCrop(const utils::Dim& dim); - bool start(const utils::PipeArgs& args); bool setPosition(const utils::Dim& dim); - bool setParameter(const utils::Params& param); + bool setTransform(const utils::eTransform& param); bool setSource(const utils::PipeArgs& args); - const utils::PipeArgs& getArgs() const; utils::eOverlayPipeType getOvPipeType() const; void dump() const; private: - overlay::GenericPipe mHdmi; + overlay::GenericPipe mVideoExt; }; //------------------Inlines ----------------------------- -inline HdmiPipe::HdmiPipe() {} -inline HdmiPipe::~HdmiPipe() { close(); } -inline bool HdmiPipe::open(RotatorBase* rot) { - ALOGE_IF(DEBUG_OVERLAY, "HdmiPipe open"); - return mHdmi.open(rot); +inline VideoExtPipe::VideoExtPipe() {} +inline VideoExtPipe::~VideoExtPipe() { close(); } +inline bool VideoExtPipe::init(RotatorBase* rot) { + ALOGE_IF(DEBUG_OVERLAY, "VideoExtPipe init"); + return mVideoExt.init(rot); } -inline bool HdmiPipe::close() { return mHdmi.close(); } -inline bool HdmiPipe::commit() { return mHdmi.commit(); } -inline void HdmiPipe::setId(int id) { mHdmi.setId(id); } -inline void HdmiPipe::setMemoryId(int id) { mHdmi.setMemoryId(id); } -inline bool HdmiPipe::queueBuffer(uint32_t offset) { - return mHdmi.queueBuffer(offset); } -inline bool HdmiPipe::dequeueBuffer(void*& buf) { - return mHdmi.dequeueBuffer(buf); } -inline bool HdmiPipe::waitForVsync() { - return mHdmi.waitForVsync(); } -inline bool HdmiPipe::setCrop(const utils::Dim& dim) { - return mHdmi.setCrop(dim); } -inline bool HdmiPipe::start(const utils::PipeArgs& args) { - return mHdmi.start(args); } -inline bool HdmiPipe::setPosition(const utils::Dim& dim) +inline bool VideoExtPipe::close() { return mVideoExt.close(); } +inline bool VideoExtPipe::commit() { return mVideoExt.commit(); } +inline bool VideoExtPipe::queueBuffer(int fd, uint32_t offset) { + return mVideoExt.queueBuffer(fd, offset); +} +inline bool VideoExtPipe::waitForVsync() { + return mVideoExt.waitForVsync(); +} +inline bool VideoExtPipe::setCrop(const utils::Dim& dim) { + return mVideoExt.setCrop(dim); +} +inline bool VideoExtPipe::setPosition(const utils::Dim& dim) { utils::Dim d; // Need to change dim to aspect ratio if (utils::FrameBufferInfo::getInstance()->supportTrueMirroring()) { // Use dim info to calculate aspect ratio for true UI mirroring - d = mHdmi.getAspectRatio(dim); + d = mVideoExt.getAspectRatio(dim); } else { // Use cached crop data to get aspect ratio - utils::Dim crop = mHdmi.getCrop(); + utils::Dim crop = mVideoExt.getCrop(); utils::Whf whf(crop.w, crop.h, 0); - d = mHdmi.getAspectRatio(whf); + d = mVideoExt.getAspectRatio(whf); } - ALOGE_IF(DEBUG_OVERLAY, "Calculated aspect ratio for HDMI: x=%d, y=%d, w=%d, h=%d, o=%d", + ALOGE_IF(DEBUG_OVERLAY, "Calculated aspect ratio for EXT: x=%d, y=%d, w=%d," + "h=%d, o=%d", d.x, d.y, d.w, d.h, d.o); - return mHdmi.setPosition(d); + return mVideoExt.setPosition(d); } -inline bool HdmiPipe::setParameter(const utils::Params& param) { - return mHdmi.setParameter(param); } -inline bool HdmiPipe::setSource(const utils::PipeArgs& args) { +inline bool VideoExtPipe::setTransform(const utils::eTransform& param) { + return mVideoExt.setTransform(param); +} +inline bool VideoExtPipe::setSource(const utils::PipeArgs& args) { utils::PipeArgs arg(args); - return mHdmi.setSource(arg); + return mVideoExt.setSource(arg); } -inline const utils::PipeArgs& HdmiPipe::getArgs() const { - return mHdmi.getArgs(); +inline utils::eOverlayPipeType VideoExtPipe::getOvPipeType() const { + return utils::OV_PIPE_TYPE_VIDEO_EXT; } -inline utils::eOverlayPipeType HdmiPipe::getOvPipeType() const { - return utils::OV_PIPE_TYPE_HDMI; -} -inline void HdmiPipe::dump() const { - ALOGE("HDMI Pipe"); - mHdmi.dump(); +inline void VideoExtPipe::dump() const { + ALOGE("Video Ext Pipe"); + mVideoExt.dump(); } } // overlay -#endif // OVERLAY_HDMI_PIPE_H +#endif // OVERLAY_VIDEO_EXT_PIPE_H diff --git a/libqdutils/Android.mk b/libqdutils/Android.mk index 178ce39..dfeae09 100644 --- a/libqdutils/Android.mk +++ b/libqdutils/Android.mk @@ -1,11 +1,12 @@ LOCAL_PATH := $(call my-dir) +include $(LOCAL_PATH)/../common.mk include $(CLEAR_VARS) -LOCAL_SRC_FILES := profiler.cpp mdp_version.cpp -LOCAL_SHARED_LIBRARIES := libutils libcutils -LOCAL_C_INCLUDES := hardware/qcom/display/libgralloc - -LOCAL_CFLAGS += -DDEBUG_CALC_FPS -LOCAL_MODULE := libqdutils -LOCAL_MODULE_TAGS := optional +LOCAL_MODULE := libqdutils +LOCAL_MODULE_TAGS := optional +LOCAL_SHARED_LIBRARIES := $(common_libs) +LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes) +LOCAL_CFLAGS := $(common_flags) +LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) +LOCAL_SRC_FILES := profiler.cpp mdp_version.cpp include $(BUILD_SHARED_LIBRARY) diff --git a/libtilerenderer/Android.mk b/libtilerenderer/Android.mk index e0bf342..af8f25f 100644 --- a/libtilerenderer/Android.mk +++ b/libtilerenderer/Android.mk @@ -1,26 +1,22 @@ LOCAL_PATH := $(call my-dir) +include $(LOCAL_PATH)/../common.mk include $(CLEAR_VARS) ifeq ($(USE_OPENGL_RENDERER),true) -LOCAL_PRELINK_MODULE := false -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES) -LOCAL_SHARED_LIBRARIES := libutils libcutils libGLESv2 libhwui +LOCAL_MODULE := libtilerenderer +LOCAL_MODULE_TAGS := optional +LOCAL_C_INCLUDES := \ + frameworks/base/include/utils \ + frameworks/base/libs/hwui \ + external/skia/include/core \ + external/skia/include/effects \ + external/skia/include/images \ + external/skia/src/ports \ + external/skia/include/utils \ + hardware/libhardware/include/hardware \ + frameworks/base/opengl/include/GLES2 -LOCAL_C_INCLUDES += \ - frameworks/base/include/utils \ - frameworks/base/libs/hwui \ - external/skia/include/core \ - external/skia/include/effects \ - external/skia/include/images \ - external/skia/src/ports \ - external/skia/include/utils \ - hardware/libhardware/include/hardware \ - frameworks/base/opengl/include/GLES2 - -LOCAL_SRC_FILES := \ - tilerenderer.cpp - -LOCAL_MODULE := libtilerenderer -LOCAL_MODULE_TAGS := optional +LOCAL_SHARED_LIBRARIES := $(common_libs) libGLESv2 libhwui +LOCAL_SRC_FILES := tilerenderer.cpp include $(BUILD_SHARED_LIBRARY) endif