From 3368d08ed59dfa4772d40e70b34e645b360ed588 Mon Sep 17 00:00:00 2001 From: Tatenda Chipeperekwa Date: Fri, 30 Aug 2013 14:03:15 -0700 Subject: [PATCH] hal: adding support for DRC on WiFi display When Dynamic Resolution Change (DRC) is triggered in the WiFi display stack, it results in a PAUSE and a RESUME event. During DRC, the dimensions of the framebuffer are changed. To support DRC we need to: 1. Check if a RESUME event is the result of a valid DRC event 2. Reconfigure the display's attributes to reflect resolution change 3. Enable MDP downscaling when necessary (Valid DRC cases) Change-Id: Idc3cbc94de99a4a7299e2f6b26c3e35937c1d6c8 --- libhwcomposer/hwc_uevents.cpp | 9 +++++++ libvirtual/virtual.cpp | 47 +++++++++++++++++++++++++---------- 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp index 55907985..cc5b4823 100644 --- a/libhwcomposer/hwc_uevents.cpp +++ b/libhwcomposer/hwc_uevents.cpp @@ -273,6 +273,15 @@ static void handle_uevent(hwc_context_t* ctx, const char* udata, int len) //its pipes; we don't allow inter-mixer pipe transfers. { Locker::Autolock _l(ctx->mDrawLock); + + // A dynamic resolution change (DRC) can be made for a WiFi + // display. In order to support the resolution change, we + // need to reconfigure the corresponding display attributes. + // Since DRC is only on WiFi display, we only need to call + // configure() on the VirtualDisplay device. + if(dpy == HWC_DISPLAY_VIRTUAL) + ctx->mVirtualDisplay->configure(); + ctx->dpyAttr[dpy].isConfiguring = true; ctx->dpyAttr[dpy].isActive = true; ctx->proc->invalidate(ctx->proc); diff --git a/libvirtual/virtual.cpp b/libvirtual/virtual.cpp index 8e96a569..c94a5c6c 100644 --- a/libvirtual/virtual.cpp +++ b/libvirtual/virtual.cpp @@ -76,6 +76,10 @@ void VirtualDisplay::getAttributes(int& width, int& height) { int VirtualDisplay::teardown() { closeFrameBuffer(); memset(&mVInfo, 0, sizeof(mVInfo)); + // Reset the resolution when we close the fb for this device. We need + // this to distinguish between an ONLINE and RESUME event. + mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].xres = 0; + mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].yres = 0; return 0; } @@ -92,24 +96,41 @@ VirtualDisplay::~VirtualDisplay() void VirtualDisplay::setAttributes() { if(mHwcContext) { - // Always set dpyAttr res to mVInfo res - mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].xres = mVInfo.xres; - mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].yres = mVInfo.yres; + unsigned int &w = mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].xres; + unsigned int &h = mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].yres; + + // Always set dpyAttr res to mVInfo res, only on an ONLINE event. Keep + // the original configuration to cater for DRC initiated RESUME events + if(w == 0 || h == 0){ + w = mVInfo.xres; + h = mVInfo.yres; + } mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].mDownScaleMode = false; + if(!qdutils::MDPVersion::getInstance().is8x26()) { uint32_t priW = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].xres; uint32_t priH = mHwcContext->dpyAttr[HWC_DISPLAY_PRIMARY].yres; - // if primary resolution is more than the wfd resolution + + // Find the maximum resolution between primary and virtual + uint32_t maxArea = max((w * h), (priW * priH)); + + // If primary resolution is more than the wfd resolution // configure dpy attr to primary resolution and set - // downscale mode - if((priW * priH) > (mVInfo.xres * mVInfo.yres)) { - mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].xres = priW; - mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].yres = priH; - // WFD is always in landscape, so always assign the higher - // dimension to wfd's xres - if(priH > priW) { - mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].xres = priH; - mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].yres = priW; + // downscale mode. + // DRC is only valid when the original resolution on the WiFi + // display is greater than the new resolution in mVInfo. + if(maxArea > (mVInfo.xres * mVInfo.yres)) { + if(maxArea == (priW * priH)) { + // Here we account for the case when primary resolution is + // greater than that of the WiFi display + w = priW; + h = priH; + // WFD is always in landscape, so always assign the higher + // dimension to wfd's xres + if(priH > priW) { + w = priH; + h = priW; + } } // Set External Display MDP Downscale mode indicator mHwcContext->dpyAttr[HWC_DISPLAY_VIRTUAL].mDownScaleMode = true;