diff options
author | Naseer Ahmed <naseer@codeaurora.org> | 2012-07-20 09:06:13 -0700 |
---|---|---|
committer | Brian Muramatsu <btmura@google.com> | 2012-07-23 12:38:12 -0700 |
commit | 0c8b7b5c841a7fad5df11b7e02d7cd792cfcc734 (patch) | |
tree | 279cb7e8c2e0fa2ab64c45c4926ea3f0a3f2e594 /libgralloc/framebuffer.cpp | |
parent | f48aef64b218d42bd2ede62dcb03a3d7831ebbf9 (diff) | |
download | android_hardware_qcom_display-0c8b7b5c841a7fad5df11b7e02d7cd792cfcc734.tar.gz android_hardware_qcom_display-0c8b7b5c841a7fad5df11b7e02d7cd792cfcc734.tar.bz2 android_hardware_qcom_display-0c8b7b5c841a7fad5df11b7e02d7cd792cfcc734.zip |
hwcomposer: Add support for UI mirroring
- Uevent observer as part of Hwcomposer
- HPD, enabling/disabling external display from HWC
Change-Id: I52b4f30c78e98c5b52c86722046389f458c2dbee
Diffstat (limited to 'libgralloc/framebuffer.cpp')
-rw-r--r-- | libgralloc/framebuffer.cpp | 467 |
1 files changed, 32 insertions, 435 deletions
diff --git a/libgralloc/framebuffer.cpp b/libgralloc/framebuffer.cpp index f689d529f..31978f01c 100644 --- a/libgralloc/framebuffer.cpp +++ b/libgralloc/framebuffer.cpp @@ -43,9 +43,6 @@ #include <cutils/properties.h> #include <profiler.h> -#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,402 +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<private_module_t*>(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<private_handle_t const*>(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::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<private_module_t*>( - 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<private_module_t*>( - 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<private_module_t*>( - 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<private_module_t*>( - 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) @@ -510,6 +111,7 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer) private_module_t* m = reinterpret_cast<private_module_t*>(dev->common.module); + if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) { genlock_lock_buffer(hnd, GENLOCK_READ_LOCK, GENLOCK_MAX_TIMEOUT); @@ -519,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) { @@ -579,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) { @@ -600,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)) @@ -627,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) @@ -738,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)); @@ -748,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; } @@ -778,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<private_module_t*>( - 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); } @@ -828,8 +423,10 @@ int fb_device_open(hw_module_t const* module, const char* name, const_cast<float&>(dev->device.xdpi) = m->xdpi; const_cast<float&>(dev->device.ydpi) = m->ydpi; const_cast<float&>(dev->device.fps) = m->fps; - const_cast<int&>(dev->device.minSwapInterval) = PRIV_MIN_SWAP_INTERVAL; - const_cast<int&>(dev->device.maxSwapInterval) = PRIV_MAX_SWAP_INTERVAL; + const_cast<int&>(dev->device.minSwapInterval) = + PRIV_MIN_SWAP_INTERVAL; + const_cast<int&>(dev->device.maxSwapInterval) = + PRIV_MAX_SWAP_INTERVAL; const_cast<int&>(dev->device.numFramebuffers) = m->numBuffers; if (m->finfo.reserved[0] == 0x5444 && m->finfo.reserved[1] == 0x5055) { |