hwc: Fix Pause/Resume issues
1. During PAUSE event, trigger an invalidate frame
which will unset the pipes (in draw call) and invoke
display commit as part of hwc_event thread.
This is required to avoid iommu page faults arising when
WFD encoder is in the middle of configuring buffers
and providing to Writeback as part of RESUME event and
Display HAL tries to invoke display commit as part of PAUSE.
2. Allow usage of rotator for Primary when WFD is in Pause
state.
The above changes are required to support secure/non-secure
video playback on HDCP WFD session and Pause/Resume.
Change-Id: I7391ae4cc7cd8b968873996a1a00fee5fbe6039c
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index 916b346..5590798 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -33,7 +33,7 @@
#include "external.h"
#include "virtual.h"
#include "mdp_version.h"
-
+using namespace overlay;
namespace qhwc {
#define HWC_UEVENT_SWITCH_STR "change@/devices/virtual/switch/"
#define HWC_UEVENT_THREAD_NAME "hwcUeventThread"
@@ -233,7 +233,6 @@
* surface for the same. */
ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].isActive = true;
}
-
if(dpy == HWC_DISPLAY_EXTERNAL ||
ctx->mVirtualonExtActive) {
ALOGE_IF(UEVENT_DEBUG, "%s: Sending EXTERNAL_OFFLINE ONLINE"
@@ -243,33 +242,51 @@
}
break;
}
- case EXTERNAL_PAUSE:
- {
- ctx->dpyAttr[dpy].isActive = true;
- ctx->dpyAttr[dpy].isPause = true;
- break;
- }
- case EXTERNAL_RESUME:
- {
- //Treat Resume as Online event
- //Since external didnt have any pipes, force primary to give up
- //its pipes; we don't allow inter-mixer pipe transfers.
- {
- Locker::Autolock _l(ctx->mDrawLock);
- ctx->dpyAttr[dpy].isConfiguring = true;
- ctx->dpyAttr[dpy].isActive = true;
- ctx->proc->invalidate(ctx->proc);
+ case EXTERNAL_PAUSE:
+ { // pause case
+ ALOGD("%s Received Pause event",__FUNCTION__);
+ {
+ Locker::Autolock _l(ctx->mDrawLock);
+ ctx->dpyAttr[dpy].isActive = true;
+ ctx->dpyAttr[dpy].isPause = true;
+ ctx->proc->invalidate(ctx->proc);
+ }
+ usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
+ * 2 / 1000);
+ // At this point all the pipes used by External have been
+ // marked as UNSET.
+ {
+ Locker::Autolock _l(ctx->mDrawLock);
+ // Perform commit to unstage the pipes.
+ if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
+ ALOGE("%s: display commit fail! for %d dpy",
+ __FUNCTION__, dpy);
+ }
+ }
+ break;
}
- usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
- * 2 / 1000);
- {
- //At this point external has all the pipes it would need.
- Locker::Autolock _l(ctx->mDrawLock);
- ctx->dpyAttr[dpy].isPause = false;
- ctx->proc->invalidate(ctx->proc);
+ case EXTERNAL_RESUME:
+ { // resume case
+ ALOGD("%s Received resume event",__FUNCTION__);
+ //Treat Resume as Online event
+ //Since external didnt have any pipes, force primary to give up
+ //its pipes; we don't allow inter-mixer pipe transfers.
+ {
+ Locker::Autolock _l(ctx->mDrawLock);
+ ctx->dpyAttr[dpy].isConfiguring = true;
+ ctx->dpyAttr[dpy].isActive = true;
+ ctx->proc->invalidate(ctx->proc);
+ }
+ usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
+ * 2 / 1000);
+ //At this point external has all the pipes it would need.
+ {
+ Locker::Autolock _l(ctx->mDrawLock);
+ ctx->dpyAttr[dpy].isPause = false;
+ ctx->proc->invalidate(ctx->proc);
+ }
+ break;
}
- break;
- }
default:
{
ALOGE("%s: Invalid state to swtich:%d", __FUNCTION__, switch_state);