hwc: cache layers on framebuffer
In the cases where all the layers that are marked as HWC_FRAMEBUFFER did not
change, we can mark them as HWC_OVERLAY since their contents are already on the
framebuffer and do not need any additional processing.
This optimization shows power improvement for video playback.
Bug: 7623741
Change-Id: Ia178a926e6f56a3ec9291250a22a66f212c30b14
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 41a9c5a..a6a6f3e 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -60,6 +60,7 @@
ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
ctx->mExtDisplay = new ExternalDisplay(ctx);
+ ctx->mLayerCache = new LayerCache();
MDPComp::init(ctx);
pthread_mutex_init(&(ctx->vstate.lock), NULL);
@@ -208,7 +209,7 @@
int ret = 0;
#ifdef USE_FENCE_SYNC
struct mdp_buf_sync data;
- int acquireFd[4];
+ int acquireFd[MAX_NUM_LAYERS];
int count = 0;
int releaseFd = -1;
int fbFd = -1;
@@ -219,7 +220,8 @@
for(uint32_t i = 0; i < list->numHwLayers; i++) {
if((list->hwLayers[i].compositionType == HWC_OVERLAY ||
list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) &&
- list->hwLayers[i].acquireFenceFd != -1) {
+ list->hwLayers[i].acquireFenceFd != -1 &&
+ (list->hwLayers[i].flags & HWC_MDPCOMP)) {
acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
}
}
@@ -251,4 +253,71 @@
return ret;
}
+void LayerCache::resetLayerCache(int num) {
+ for(uint32_t i = 0; i < MAX_NUM_LAYERS; i++) {
+ hnd[i] = NULL;
+ }
+ numHwLayers = num;
+}
+
+void LayerCache::updateLayerCache(hwc_display_contents_1_t* list) {
+
+ int numFbLayers = 0;
+ int numCacheableLayers = 0;
+
+ canUseLayerCache = false;
+ //Bail if geometry changed or num of layers changed
+ if(list->flags & HWC_GEOMETRY_CHANGED ||
+ list->numHwLayers != numHwLayers ) {
+ resetLayerCache(list->numHwLayers);
+ return;
+ }
+
+ for(uint32_t i = 0; i < list->numHwLayers; i++) {
+ //Bail on skip layers
+ if(list->hwLayers[i].flags & HWC_SKIP_LAYER) {
+ resetLayerCache(list->numHwLayers);
+ return;
+ }
+
+ if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER) {
+ numFbLayers++;
+ if(hnd[i] == NULL) {
+ hnd[i] = list->hwLayers[i].handle;
+ } else if (hnd[i] ==
+ list->hwLayers[i].handle) {
+ numCacheableLayers++;
+ } else {
+ hnd[i] = NULL;
+ return;
+ }
+ } else {
+ hnd[i] = NULL;
+ }
+ }
+ if(numFbLayers == numCacheableLayers)
+ canUseLayerCache = true;
+
+ //XXX: The marking part is separate, if MDP comp wants
+ // to use it in the future. Right now getting MDP comp
+ // to use this is more trouble than it is worth.
+ markCachedLayersAsOverlay(list);
+}
+
+void LayerCache::markCachedLayersAsOverlay(hwc_display_contents_1_t* list) {
+ //This optimization only works if ALL the layer handles
+ //that were on the framebuffer didn't change.
+ if(canUseLayerCache){
+ for(uint32_t i = 0; i < list->numHwLayers; i++) {
+ if (list->hwLayers[i].handle &&
+ list->hwLayers[i].handle == hnd[i] &&
+ list->hwLayers[i].compositionType != HWC_FRAMEBUFFER_TARGET)
+ {
+ list->hwLayers[i].compositionType = HWC_OVERLAY;
+ }
+ }
+ }
+
+}
+
};//namespace