diff options
author | Andy Qiu <junhai.qiu@intel.com> | 2013-09-12 15:19:06 -0700 |
---|---|---|
committer | cactus <cactus@intel.com> | 2013-09-25 19:36:37 -0700 |
commit | 6a56bd739af22a3c34067426edbb3082504d8e03 (patch) | |
tree | 62c0e21199fb6885e5c6ff02ef6cec264b3fab47 /ips | |
parent | 44b16cd6030c452bac3e2d9e6bf44da759cb3ffe (diff) | |
download | hwcomposer-6a56bd739af22a3c34067426edbb3082504d8e03.tar.gz |
[hwc] enhance overlay management
BZ: 140456
This patch enables dynamic overlay assignment to different pipe. When
overlay is assigned to a different pipe, HWC will first mark overlay
is "disabled pending" and then query kernel whether it is fully disabled
subsequently. Overlay can be re-enabled only when it is fully disabled,
to avoid "overlay crash" issue.
Change-Id: I26d3e94bc47770877aadf19992ea90e6c968e017
Signed-off-by: Andy Qiu <junhai.qiu@intel.com>
Reviewed-on: http://android.intel.com:8080/131833
Reviewed-by: Patel, Hitesh K <hitesh.k.patel@intel.com>
Tested-by: Patel, Hitesh K <hitesh.k.patel@intel.com>
Reviewed-by: cactus <cactus@intel.com>
Tested-by: cactus <cactus@intel.com>
Diffstat (limited to 'ips')
-rw-r--r-- | ips/common/OverlayPlaneBase.cpp | 65 | ||||
-rw-r--r-- | ips/common/OverlayPlaneBase.h | 12 | ||||
-rw-r--r-- | ips/tangier/TngOverlayPlane.cpp | 28 | ||||
-rw-r--r-- | ips/tangier/TngOverlayPlane.h | 1 |
4 files changed, 101 insertions, 5 deletions
diff --git a/ips/common/OverlayPlaneBase.cpp b/ips/common/OverlayPlaneBase.cpp index dcdb868..b9e2695 100644 --- a/ips/common/OverlayPlaneBase.cpp +++ b/ips/common/OverlayPlaneBase.cpp @@ -49,7 +49,10 @@ OverlayPlaneBase::OverlayPlaneBase(int index, int disp) mActiveTTMBuffers(), mBackBuffer(0), mWsbm(0), - mPipeConfig(0) + mPipeConfig(0), + mDisablePending(false), + mDisablePendingDevice(0), + mDisablePendingCount(0) { CTRACE(); } @@ -94,6 +97,11 @@ bool OverlayPlaneBase::initialize(uint32_t bufferCount) // disable overlay when created flush(PLANE_DISABLE); + + // overlay by default is in "disabled" status + mDisablePending = false; + mDisablePendingDevice = 0; + mDisablePendingCount = 0; return true; } @@ -112,6 +120,25 @@ void OverlayPlaneBase::deinitialize() DEINIT_AND_DELETE_OBJ(mWsbm); } +bool OverlayPlaneBase::setDataBuffer(uint32_t handle) +{ + if (mDisablePending) { + if (isFlushed() || mDisablePendingCount >= OVERLAY_DISABLING_COUNT_MAX) { + mDisablePending = false; + mDisablePendingDevice = 0; + mDisablePendingCount = 0; + enable(); + } else { + mDisablePendingCount++; + WTRACE("overlay %d disabling on device %d is still pending, count: %d", + mIndex, mDisablePendingDevice, mDisablePendingCount); + return false; + } + } + + return DisplayPlane::setDataBuffer(handle); +} + void OverlayPlaneBase::invalidateBufferCache() { BufferMapper* mapper; @@ -133,7 +160,7 @@ bool OverlayPlaneBase::assignToDevice(int disp) uint32_t pipeConfig = 0; RETURN_FALSE_IF_NOT_INIT(); - ATRACE("disp = %d", disp); + DTRACE("overlay %d assigned to disp %d", mIndex, disp); switch (disp) { case IDisplayDevice::DEVICE_EXTERNAL: @@ -146,12 +173,18 @@ bool OverlayPlaneBase::assignToDevice(int disp) } // if pipe switching happened, then disable overlay first - if (mPipeConfig != pipeConfig) + if (mPipeConfig != pipeConfig) { + DTRACE("overlay %d switched from %d to %d", mIndex, mDevice, disp); disable(); + } mPipeConfig = pipeConfig; mDevice = disp; + if (!mDisablePending) { + enable(); + } + return true; } @@ -190,6 +223,19 @@ bool OverlayPlaneBase::reset() { RETURN_FALSE_IF_NOT_INIT(); + if (mDisablePending) { + if (isFlushed() || mDisablePendingCount >= OVERLAY_DISABLING_COUNT_MAX) { + mDisablePending = false; + mDisablePendingDevice = 0; + mDisablePendingCount = 0; + } else { + mDisablePendingCount++; + WTRACE("overlay %d disabling is still pending on device %d, count %d", + mIndex, mDisablePendingDevice, mDisablePendingCount); + return false; + } + } + DisplayPlane::reset(); // invalidate active TTM buffers @@ -200,8 +246,6 @@ bool OverlayPlaneBase::reset() // reset back buffer resetBackBuffer(); - // flush - flush(PLANE_DISABLE); return true; } @@ -232,10 +276,21 @@ bool OverlayPlaneBase::disable() if (!(backBuffer->OCMD & 0x1)) return true; + if (mDisablePending) { + WTRACE("overlay %d disabling is still pending on device %d, skip disabling", + mIndex, mDisablePendingDevice); + return true; + } + backBuffer->OCMD &= ~0x1; // flush flush(PLANE_DISABLE); + + // "disable" is asynchronous and needs at least one vsync to complete + mDisablePending = true; + mDisablePendingDevice = mDevice; + mDisablePendingCount = 0; return true; } diff --git a/ips/common/OverlayPlaneBase.h b/ips/common/OverlayPlaneBase.h index 46084b2..e18ee28 100644 --- a/ips/common/OverlayPlaneBase.h +++ b/ips/common/OverlayPlaneBase.h @@ -50,6 +50,8 @@ public: OverlayPlaneBase(int index, int disp); virtual ~OverlayPlaneBase(); + virtual bool setDataBuffer(uint32_t handle); + virtual void invalidateBufferCache(); virtual bool assignToDevice(int disp); @@ -69,6 +71,7 @@ public: protected: // generic overlay register flush virtual bool flush(uint32_t flags) = 0; + virtual bool isFlushed() = 0; virtual bool setDataBuffer(BufferMapper& mapper); virtual bool bufferOffsetSetup(BufferMapper& mapper); virtual uint32_t calculateSWidthSW(uint32_t offset, uint32_t width); @@ -118,6 +121,15 @@ protected: Wsbm *mWsbm; // pipe config uint32_t mPipeConfig; + + // variables for asynchronous overlay disabling + enum { + // maximum wait count before aborting overlay disabling + OVERLAY_DISABLING_COUNT_MAX = 60, + }; + bool mDisablePending; + bool mDisablePendingDevice; + int mDisablePendingCount; }; } // namespace intel diff --git a/ips/tangier/TngOverlayPlane.cpp b/ips/tangier/TngOverlayPlane.cpp index e3cf7d7..bd9fcbe 100644 --- a/ips/tangier/TngOverlayPlane.cpp +++ b/ips/tangier/TngOverlayPlane.cpp @@ -185,6 +185,10 @@ bool TngOverlayPlane::flush(uint32_t flags) // pipe select arg.plane.ctx |= mPipeConfig; + if (flags & PLANE_DISABLE) { + DTRACE("disabling overlay %d on device %d", mIndex, mDevice); + } + // issue ioctl Drm *drm = Hwcomposer::getInstance().getDrm(); bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg)); @@ -196,5 +200,29 @@ bool TngOverlayPlane::flush(uint32_t flags) return true; } +bool TngOverlayPlane::isFlushed() +{ + RETURN_FALSE_IF_NOT_INIT(); + + struct drm_psb_register_rw_arg arg; + memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg)); + + arg.overlay_read_mask = OVSTATUS_REGRBIT_OVR_UPDT; + arg.plane.type = DC_OVERLAY_PLANE; + arg.plane.index = mIndex; + arg.plane.ctx = 0; + + Drm *drm = Hwcomposer::getInstance().getDrm(); + bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg)); + if (ret == false) { + WTRACE("overlay read failed with error code %d", ret); + return false; + } + + DTRACE("overlay %d flush status %s on device %d, current device %d", + mIndex, arg.plane.ctx ? "DONE" : "PENDING", mDisablePendingDevice, mDevice); + return arg.plane.ctx == 1; +} + } // namespace intel } // namespace android diff --git a/ips/tangier/TngOverlayPlane.h b/ips/tangier/TngOverlayPlane.h index 7c7e62c..22da8e0 100644 --- a/ips/tangier/TngOverlayPlane.h +++ b/ips/tangier/TngOverlayPlane.h @@ -56,6 +56,7 @@ public: protected: virtual bool setDataBuffer(BufferMapper& mapper); virtual bool flush(uint32_t flags); + virtual bool isFlushed(); protected: struct intel_dc_plane_ctx mContext; |