hwc: Allow HWC to support Virtual Display
This change allows virtual display to be composed
by HWC for supporting Google WFD App + QCOM WFD stack.
Change-Id: If8892230256e72fa34e3fb5ae715c3ad8cbd5b64
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 187ec4a..519126f 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -84,7 +84,7 @@
static void reset(hwc_context_t *ctx, int numDisplays,
hwc_display_contents_1_t** displays) {
memset(ctx->listStats, 0, sizeof(ctx->listStats));
- for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++){
+ for(int i = 0; i < MAX_DISPLAYS; i++) {
hwc_display_contents_1_t *list = displays[i];
// XXX:SurfaceFlinger no longer guarantees that this
// value is reset on every prepare. However, for the layer
@@ -148,25 +148,31 @@
}
static int hwc_prepare_external(hwc_composer_device_1 *dev,
- hwc_display_contents_1_t *list) {
+ hwc_display_contents_1_t *list, int dpy) {
hwc_context_t* ctx = (hwc_context_t*)(dev);
- const int dpy = HWC_DISPLAY_EXTERNAL;
if (LIKELY(list && list->numHwLayers > 1) &&
ctx->dpyAttr[dpy].isActive &&
ctx->dpyAttr[dpy].connected) {
-
uint32_t last = list->numHwLayers - 1;
- hwc_layer_1_t *fbLayer = &list->hwLayers[last];
- if(fbLayer->handle) {
- setListStats(ctx, list, dpy);
- reset_layer_prop(ctx, dpy);
- VideoOverlay::prepare(ctx, list, dpy);
- ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer);
- ctx->mLayerCache[dpy]->updateLayerCache(list);
- if(ctx->mCopyBit[dpy])
- ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
- ctx->mExtDispConfiguring = false;
+ if(!ctx->dpyAttr[dpy].isPause) {
+ hwc_layer_1_t *fbLayer = &list->hwLayers[last];
+ if(fbLayer->handle) {
+ setListStats(ctx, list, dpy);
+ reset_layer_prop(ctx, dpy);
+ VideoOverlay::prepare(ctx, list, dpy);
+ ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer);
+ ctx->mLayerCache[dpy]->updateLayerCache(list);
+ if(ctx->mCopyBit[dpy])
+ ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
+ ctx->mExtDispConfiguring = false;
+ }
+ } else {
+ // External Display is in Pause state.
+ // ToDo:
+ // Mark all application layers as OVERLAY so that
+ // GPU will not compose. This is done for power
+ // optimization
}
}
return 0;
@@ -182,14 +188,15 @@
ctx->mOverlay->configBegin();
- for (int32_t i = numDisplays - 1; i >= 0; i--) {
+ for (int32_t i = numDisplays; i >= 0; i--) {
hwc_display_contents_1_t *list = displays[i];
switch(i) {
case HWC_DISPLAY_PRIMARY:
ret = hwc_prepare_primary(dev, list);
break;
case HWC_DISPLAY_EXTERNAL:
- ret = hwc_prepare_external(dev, list);
+ case HWC_DISPLAY_VIRTUAL:
+ ret = hwc_prepare_external(dev, list, i);
break;
default:
ret = -EINVAL;
@@ -244,8 +251,9 @@
}
break;
case HWC_DISPLAY_EXTERNAL:
+ case HWC_DISPLAY_VIRTUAL:
if(blank) {
- // External Display post commits the changes to display
+ // External/Virtual Display post commits the changes to display
// Call this on blank, so that any pipe unsets gets committed
if (!ctx->mExtDisplay->post()) {
ret = -1;
@@ -342,13 +350,12 @@
}
static int hwc_set_external(hwc_context_t *ctx,
- hwc_display_contents_1_t* list) {
+ hwc_display_contents_1_t* list, int dpy) {
int ret = 0;
- const int dpy = HWC_DISPLAY_EXTERNAL;
-
Locker::Autolock _l(ctx->mExtSetLock);
if (LIKELY(list) && ctx->dpyAttr[dpy].isActive &&
+ !ctx->dpyAttr[dpy].isPause &&
ctx->dpyAttr[dpy].connected) {
uint32_t last = list->numHwLayers - 1;
hwc_layer_1_t *fbLayer = &list->hwLayers[last];
@@ -388,14 +395,19 @@
int ret = 0;
hwc_context_t* ctx = (hwc_context_t*)(dev);
Locker::Autolock _l(ctx->mBlankLock);
- for (uint32_t i = 0; i < numDisplays; i++) {
+ for (uint32_t i = 0; i <= numDisplays; i++) {
hwc_display_contents_1_t* list = displays[i];
switch(i) {
case HWC_DISPLAY_PRIMARY:
ret = hwc_set_primary(ctx, list);
break;
case HWC_DISPLAY_EXTERNAL:
- ret = hwc_set_external(ctx, list);
+ case HWC_DISPLAY_VIRTUAL:
+ /* ToDo: We are using hwc_set_external path for both External and
+ Virtual displays on HWC1.1. Eventually, we will have
+ separate functions when we move to HWC1.2
+ */
+ ret = hwc_set_external(ctx, list, i);
break;
default:
ret = -EINVAL;