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>
This commit is contained in:
@@ -77,11 +77,23 @@ static void hwc_registerProcs(struct hwc_composer_device_1* dev,
|
||||
}
|
||||
|
||||
//Helper
|
||||
static void reset(hwc_context_t *ctx, int numDisplays) {
|
||||
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++){
|
||||
ctx->overlayInUse[i] = false;
|
||||
ctx->listStats[i].yuvIndex = -1;
|
||||
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
|
||||
// cache we need to reset it.
|
||||
// We can probably rethink that later on
|
||||
if (LIKELY(list && list->numHwLayers > 1)) {
|
||||
for(uint32_t j = 0; j < list->numHwLayers; j++) {
|
||||
if(list->hwLayers[j].compositionType != HWC_FRAMEBUFFER_TARGET)
|
||||
list->hwLayers[j].compositionType = HWC_FRAMEBUFFER;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,6 +115,7 @@ static int hwc_prepare_primary(hwc_composer_device_1 *dev,
|
||||
} else {
|
||||
ctx->overlayInUse[HWC_DISPLAY_PRIMARY] = false;
|
||||
}
|
||||
ctx->mLayerCache->updateLayerCache(list);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -141,7 +154,7 @@ static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
|
||||
{
|
||||
int ret = 0;
|
||||
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
||||
reset(ctx, numDisplays);
|
||||
reset(ctx, numDisplays, displays);
|
||||
|
||||
//If securing of h/w in progress skip comp using overlay.
|
||||
if(ctx->mSecuring == true) return 0;
|
||||
|
||||
@@ -60,6 +60,7 @@ void initContext(hwc_context_t *ctx)
|
||||
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 hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy) {
|
||||
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 @@ int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy) {
|
||||
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 @@ int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy) {
|
||||
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
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
|
||||
#define FINAL_TRANSFORM_MASK 0x000F
|
||||
#define MAX_NUM_DISPLAYS 4 //Yes, this is ambitious
|
||||
#define MAX_NUM_LAYERS 32
|
||||
|
||||
//Fwrd decls
|
||||
struct hwc_context_t;
|
||||
@@ -81,6 +82,26 @@ enum {
|
||||
HWC_LAYER_RESERVED_1 = 0x00000008
|
||||
};
|
||||
|
||||
class LayerCache {
|
||||
public:
|
||||
LayerCache() {
|
||||
canUseLayerCache = false;
|
||||
numHwLayers = 0;
|
||||
for(uint32_t i = 0; i < MAX_NUM_LAYERS; i++) {
|
||||
hnd[i] = NULL;
|
||||
}
|
||||
}
|
||||
//LayerCache optimization
|
||||
void updateLayerCache(hwc_display_contents_1_t* list);
|
||||
void resetLayerCache(int num);
|
||||
void markCachedLayersAsOverlay(hwc_display_contents_1_t* list);
|
||||
private:
|
||||
uint32_t numHwLayers;
|
||||
bool canUseLayerCache;
|
||||
buffer_handle_t hnd[MAX_NUM_LAYERS];
|
||||
|
||||
};
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Utility functions - implemented in hwc_utils.cpp
|
||||
@@ -196,6 +217,8 @@ struct hwc_context_t {
|
||||
|
||||
qhwc::ListStats listStats[HWC_NUM_DISPLAY_TYPES];
|
||||
|
||||
qhwc::LayerCache *mLayerCache;
|
||||
|
||||
//Securing in progress indicator
|
||||
bool mSecuring;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user