/* // Copyright (c) 2014 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. */ #include <HwcTrace.h> #include <Drm.h> #include <HwcLayerList.h> #include <Hwcomposer.h> #include <GraphicBuffer.h> #include <IDisplayDevice.h> #include <PlaneCapabilities.h> #include <DisplayQuery.h> namespace android { namespace intel { HwcLayerList::HwcLayerList(hwc_display_contents_1_t *list, int disp) : mList(list), mLayerCount(0), mLayers(), mFBLayers(), mStaticLayersIndex(), mSpriteCandidates(), mOverlayCandidates(), mZOrderConfig(), mFrameBufferTarget(NULL), mDisplayIndex(disp), mLayerSize(0) { initialize(); } HwcLayerList::~HwcLayerList() { deinitialize(); } bool HwcLayerList::checkSupported(int planeType, HwcLayer *hwcLayer) { bool valid = false; hwc_layer_1_t& layer = *(hwcLayer->getLayer()); // if layer was forced to use FB if (hwcLayer->getType() == HwcLayer::LAYER_FORCE_FB) { VTRACE("layer was forced to use HWC_FRAMEBUFFER"); return false; } // check layer flags if (layer.flags & HWC_SKIP_LAYER) { VTRACE("plane type %d: (skip layer flag was set)", planeType); return false; } if (layer.handle == 0) { WTRACE("invalid buffer handle"); return false; } // check usage if (!hwcLayer->getUsage() & GRALLOC_USAGE_HW_COMPOSER) { WTRACE("not a composer layer"); return false; } // check layer transform valid = PlaneCapabilities::isTransformSupported(planeType, hwcLayer); if (!valid) { VTRACE("plane type %d: (bad transform)", planeType); return false; } // check buffer format valid = PlaneCapabilities::isFormatSupported(planeType, hwcLayer); if (!valid) { VTRACE("plane type %d: (bad buffer format)", planeType); return false; } // check buffer size valid = PlaneCapabilities::isSizeSupported(planeType, hwcLayer); if (!valid) { VTRACE("plane type %d: (bad buffer size)", planeType); return false; } // check layer blending valid = PlaneCapabilities::isBlendingSupported(planeType, hwcLayer); if (!valid) { VTRACE("plane type %d: (bad blending)", planeType); return false; } // check layer scaling valid = PlaneCapabilities::isScalingSupported(planeType, hwcLayer); if (!valid) { VTRACE("plane type %d: (bad scaling)", planeType); return false; } // TODO: check visible region? return true; } bool HwcLayerList::checkCursorSupported(HwcLayer *hwcLayer) { hwc_layer_1_t& layer = *(hwcLayer->getLayer()); // if layer was forced to use FB if (hwcLayer->getType() == HwcLayer::LAYER_FORCE_FB) { VTRACE("layer was forced to use HWC_FRAMEBUFFER"); return false; } // check layer flags if (layer.flags & HWC_SKIP_LAYER) { VTRACE("skip layer flag was set"); return false; } if (!(layer.flags & HWC_IS_CURSOR_LAYER)) { VTRACE("not a cursor layer"); return false; } if (hwcLayer->getIndex() != mLayerCount - 2) { WTRACE("cursor layer is not on top of zorder"); return false; } if (layer.handle == 0) { WTRACE("invalid buffer handle"); return false; } // check usage if (!(hwcLayer->getUsage() & GRALLOC_USAGE_HW_COMPOSER)) { WTRACE("not a composer layer"); return false; } uint32_t format = hwcLayer->getFormat(); if (format != HAL_PIXEL_FORMAT_BGRA_8888 && format != HAL_PIXEL_FORMAT_RGBA_8888) { WTRACE("unexpected color format %u for cursor", format); return false; } uint32_t trans = hwcLayer->getLayer()->transform; if (trans != 0) { WTRACE("unexpected transform %u for cursor", trans); return false; } hwc_frect_t& src = hwcLayer->getLayer()->sourceCropf; hwc_rect_t& dest = hwcLayer->getLayer()->displayFrame; int srcW = (int)src.right - (int)src.left; int srcH = (int)src.bottom - (int)src.top; int dstW = dest.right - dest.left; int dstH = dest.bottom - dest.top; if (srcW != dstW || srcH != dstH) { WTRACE("unexpected scaling for cursor: %dx%d => %dx%d", srcW, srcH, dstW, dstH); //return false; } if (srcW > 256 || srcH > 256) { WTRACE("unexpected size %dx%d for cursor", srcW, srcH); return false; } BufferManager *bm = Hwcomposer::getInstance().getBufferManager(); if (bm) { DataBuffer *buffer = bm->lockDataBuffer(hwcLayer->getHandle()); if (buffer) { uint32_t w = buffer->getWidth(); uint32_t h = buffer->getHeight(); if ((w != 64 || h != 64) && (w != 128 || h != 128) && (w != 256 || h != 256)) { bm->unlockDataBuffer(buffer); return false; } } bm->unlockDataBuffer(buffer); } return true; } bool HwcLayerList::initialize() { if (!mList || mList->numHwLayers == 0) { ETRACE("invalid hwc list"); return false; } mLayerCount = (int)mList->numHwLayers; mLayers.setCapacity(mLayerCount); mFBLayers.setCapacity(mLayerCount); mSpriteCandidates.setCapacity(mLayerCount); mOverlayCandidates.setCapacity(mLayerCount); mCursorCandidates.setCapacity(mLayerCount); mZOrderConfig.setCapacity(mLayerCount); Hwcomposer& hwc = Hwcomposer::getInstance(); for (int i = 0; i < mLayerCount; i++) { hwc_layer_1_t *layer = &mList->hwLayers[i]; if (!layer) { DEINIT_AND_RETURN_FALSE("layer %d is null", i); } HwcLayer *hwcLayer = new HwcLayer(i, layer); if (!hwcLayer) { DEINIT_AND_RETURN_FALSE("failed to allocate hwc layer %d", i); } if (layer->compositionType == HWC_FRAMEBUFFER_TARGET) { hwcLayer->setType(HwcLayer::LAYER_FRAMEBUFFER_TARGET); mFrameBufferTarget = hwcLayer; } else if (layer->compositionType == HWC_OVERLAY){ // skipped layer, filtered by Display Analyzer hwcLayer->setType(HwcLayer::LAYER_SKIPPED); } else if (layer->compositionType == HWC_FORCE_FRAMEBUFFER) { layer->compositionType = HWC_FRAMEBUFFER; hwcLayer->setType(HwcLayer::LAYER_FORCE_FB); // add layer to FB layer list for zorder check during plane assignment mFBLayers.add(hwcLayer); } else if (layer->compositionType == HWC_FRAMEBUFFER) { // by default use GPU composition hwcLayer->setType(HwcLayer::LAYER_FB); mFBLayers.add(hwcLayer); if (checkCursorSupported(hwcLayer)) { mCursorCandidates.add(hwcLayer); } else if (checkSupported(DisplayPlane::PLANE_SPRITE, hwcLayer)) { mSpriteCandidates.add(hwcLayer); } else if (hwc.getDisplayAnalyzer()->isOverlayAllowed() && checkSupported(DisplayPlane::PLANE_OVERLAY, hwcLayer)) { mOverlayCandidates.add(hwcLayer); } else { // noncandidate layer } } else if (layer->compositionType == HWC_SIDEBAND){ hwcLayer->setType(HwcLayer::LAYER_SIDEBAND); } else { DEINIT_AND_RETURN_FALSE("invalid composition type %d", layer->compositionType); } // add layer to layer list mLayers.add(hwcLayer); } if (mFrameBufferTarget == NULL) { ETRACE("no frame buffer target?"); return false; } // If has layer besides of FB_Target, but no FBLayers, skip plane allocation // Note: There is case that SF passes down a layerlist with only FB_Target // layer; we need to have this FB_Target to be flipped as well, otherwise it // will have the buffer queue blocked. (The buffer hold by driver cannot be // released if new buffers' flip is skipped). if ((mFBLayers.size() == 0) && (mLayers.size() > 1)) { VTRACE("no FB layers, skip plane allocation"); return true; } allocatePlanes(); //dump(); return true; } void HwcLayerList::deinitialize() { if (mLayerCount == 0) { return; } DisplayPlaneManager *planeManager = Hwcomposer::getInstance().getPlaneManager(); for (int i = 0; i < mLayerCount; i++) { HwcLayer *hwcLayer = mLayers.itemAt(i); if (hwcLayer) { DisplayPlane *plane = hwcLayer->detachPlane(); if (plane) { planeManager->reclaimPlane(mDisplayIndex, *plane); } } delete hwcLayer; } mLayers.clear(); mFBLayers.clear(); mOverlayCandidates.clear(); mSpriteCandidates.clear(); mCursorCandidates.clear(); mZOrderConfig.clear(); mFrameBufferTarget = NULL; mLayerCount = 0; } bool HwcLayerList::allocatePlanes() { return assignCursorPlanes(); } bool HwcLayerList::assignCursorPlanes() { int cursorCandidates = (int)mCursorCandidates.size(); if (cursorCandidates == 0) { return assignOverlayPlanes(); } DisplayPlaneManager *planeManager = Hwcomposer::getInstance().getPlaneManager(); int planeNumber = planeManager->getFreePlanes(mDisplayIndex, DisplayPlane::PLANE_CURSOR); if (planeNumber == 0) { DTRACE("no cursor plane available. candidates %d", cursorCandidates); return assignOverlayPlanes(); } if (planeNumber > cursorCandidates) { // assuming all cursor planes have the same capabilities, just // need up to number of candidates for plane assignment planeNumber = cursorCandidates; } for (int i = planeNumber; i >= 0; i--) { // assign as many cursor planes as possible if (assignCursorPlanes(0, i)) { return true; } if (mZOrderConfig.size() != 0) { ETRACE("ZOrder config is not cleaned up!"); } } return false; } bool HwcLayerList::assignCursorPlanes(int index, int planeNumber) { // index indicates position in mCursorCandidates to start plane assignment if (planeNumber == 0) { return assignOverlayPlanes(); } int cursorCandidates = (int)mCursorCandidates.size(); for (int i = index; i <= cursorCandidates - planeNumber; i++) { ZOrderLayer *zlayer = addZOrderLayer(DisplayPlane::PLANE_CURSOR, mCursorCandidates[i]); if (assignCursorPlanes(i + 1, planeNumber - 1)) { return true; } removeZOrderLayer(zlayer); } return false; } bool HwcLayerList::assignOverlayPlanes() { int overlayCandidates = (int)mOverlayCandidates.size(); if (overlayCandidates == 0) { return assignSpritePlanes(); } DisplayPlaneManager *planeManager = Hwcomposer::getInstance().getPlaneManager(); int planeNumber = planeManager->getFreePlanes(mDisplayIndex, DisplayPlane::PLANE_OVERLAY); if (planeNumber == 0) { DTRACE("no overlay plane available. candidates %d", overlayCandidates); return assignSpritePlanes(); } if (planeNumber > overlayCandidates) { // assuming all overlay planes have the same capabilities, just // need up to number of candidates for plane assignment planeNumber = overlayCandidates; } for (int i = planeNumber; i >= 0; i--) { // assign as many overlay planes as possible if (assignOverlayPlanes(0, i)) { return true; } if (mZOrderConfig.size() != 0) { ETRACE("ZOrder config is not cleaned up!"); } } return false; } bool HwcLayerList::assignOverlayPlanes(int index, int planeNumber) { // index indicates position in mOverlayCandidates to start plane assignment if (planeNumber == 0) { return assignSpritePlanes(); } int overlayCandidates = (int)mOverlayCandidates.size(); for (int i = index; i <= overlayCandidates - planeNumber; i++) { ZOrderLayer *zlayer = addZOrderLayer(DisplayPlane::PLANE_OVERLAY, mOverlayCandidates[i]); if (assignOverlayPlanes(i + 1, planeNumber - 1)) { return true; } removeZOrderLayer(zlayer); } return false; } bool HwcLayerList::assignSpritePlanes() { int spriteCandidates = (int)mSpriteCandidates.size(); if (spriteCandidates == 0) { return assignPrimaryPlane(); } // number does not include primary plane DisplayPlaneManager *planeManager = Hwcomposer::getInstance().getPlaneManager(); int planeNumber = planeManager->getFreePlanes(mDisplayIndex, DisplayPlane::PLANE_SPRITE); if (planeNumber == 0) { VTRACE("no sprite plane available, candidates %d", spriteCandidates); return assignPrimaryPlane(); } if (planeNumber > spriteCandidates) { // assuming all sprite planes have the same capabilities, just // need up to number of candidates for plane assignment planeNumber = spriteCandidates; } for (int i = planeNumber; i >= 0; i--) { // assign as many sprite planes as possible if (assignSpritePlanes(0, i)) { return true; } if (mOverlayCandidates.size() == 0 && mZOrderConfig.size() != 0) { ETRACE("ZOrder config is not cleaned up!"); } } return false; } bool HwcLayerList::assignSpritePlanes(int index, int planeNumber) { if (planeNumber == 0) { return assignPrimaryPlane(); } int spriteCandidates = (int)mSpriteCandidates.size(); for (int i = index; i <= spriteCandidates - planeNumber; i++) { ZOrderLayer *zlayer = addZOrderLayer(DisplayPlane::PLANE_SPRITE, mSpriteCandidates[i]); if (assignSpritePlanes(i + 1, planeNumber - 1)) { return true; } removeZOrderLayer(zlayer); } return false; } bool HwcLayerList::assignPrimaryPlane() { // find a sprit layer that is not candidate but has lower priority than candidates. HwcLayer *spriteLayer = NULL; for (int i = (int)mSpriteCandidates.size() - 1; i >= 0; i--) { if (mSpriteCandidates[i]->mPlaneCandidate) break; spriteLayer = mSpriteCandidates[i]; } int candidates = (int)mZOrderConfig.size(); int layers = (int)mFBLayers.size(); bool ok = false; if (candidates == layers - 1 && spriteLayer != NULL) { // primary plane is configured as sprite, all sprite candidates are offloaded to display planes ok = assignPrimaryPlaneHelper(spriteLayer); if (!ok) { VTRACE("failed to use primary as sprite plane"); } } else if (candidates == 0) { // none assigned, use primary plane for frame buffer target and set zorder to 0 ok = assignPrimaryPlaneHelper(mFrameBufferTarget, 0); if (!ok) { ETRACE("failed to compose all layers to primary plane, should never happen"); } } else if (candidates == layers) { // all assigned, primary plane may be used during ZOrder config. ok = attachPlanes(); if (!ok) { VTRACE("failed to assign layers without primary"); } } else { // check if the remaining planes can be composed to frame buffer target (FBT) // look up a legitimate Z order position to place FBT. for (int i = 0; i < layers && !ok; i++) { if (mFBLayers[i]->mPlaneCandidate) { continue; } if (useAsFrameBufferTarget(mFBLayers[i])) { ok = assignPrimaryPlaneHelper(mFrameBufferTarget, mFBLayers[i]->getZOrder()); if (!ok) { VTRACE("failed to use zorder %d for frame buffer target", mFBLayers[i]->getZOrder()); } } } if (!ok) { VTRACE("no possible zorder for frame buffer target"); } } return ok; } bool HwcLayerList::assignPrimaryPlaneHelper(HwcLayer *hwcLayer, int zorder) { ZOrderLayer *zlayer = addZOrderLayer(DisplayPlane::PLANE_PRIMARY, hwcLayer, zorder); bool ok = attachPlanes(); if (!ok) { removeZOrderLayer(zlayer); } return ok; } bool HwcLayerList::attachPlanes() { DisplayPlaneManager *planeManager = Hwcomposer::getInstance().getPlaneManager(); if (!planeManager->isValidZOrder(mDisplayIndex, mZOrderConfig)) { VTRACE("invalid z order, size of config %d", mZOrderConfig.size()); return false; } if (!planeManager->assignPlanes(mDisplayIndex, mZOrderConfig)) { WTRACE("failed to assign planes"); return false; } VTRACE("============= plane assignment==================="); for (int i = 0; i < (int)mZOrderConfig.size(); i++) { ZOrderLayer *zlayer = mZOrderConfig.itemAt(i); if (zlayer->plane == NULL || zlayer->hwcLayer == NULL) { ETRACE("invalid ZOrderLayer, should never happen!!"); return false; } zlayer->plane->setZOrder(i); if (zlayer->plane->getType() == DisplayPlane::PLANE_CURSOR) { zlayer->hwcLayer->setType(HwcLayer::LAYER_CURSOR_OVERLAY); mFBLayers.remove(zlayer->hwcLayer); } else if (zlayer->hwcLayer != mFrameBufferTarget) { zlayer->hwcLayer->setType(HwcLayer::LAYER_OVERLAY); // update FB layers for smart composition mFBLayers.remove(zlayer->hwcLayer); } zlayer->hwcLayer->attachPlane(zlayer->plane, mDisplayIndex); VTRACE("total %d, layer %d, type %d, index %d, zorder %d", mLayerCount - 1, zlayer->hwcLayer->getIndex(), zlayer->plane->getType(), zlayer->plane->getIndex(), zlayer->zorder); delete zlayer; } mZOrderConfig.clear(); return true; } bool HwcLayerList::useAsFrameBufferTarget(HwcLayer *target) { // check if zorder of target can be used as zorder of frame buffer target // eligible only when all noncandidate layers can be merged to the target layer: // 1) noncandidate layer and candidate layer below the target layer can't overlap // if candidate layer is on top of non candidate layer, as "noncandidate layer" needs // to be moved up to target layer in z order; // 2) noncandidate layer and candidate layers above the target layer can't overlap // if candidate layer is below noncandidate layer, as "noncandidate layer" needs // to be moved down to target layer in z order. int targetLayerIndex = target->getIndex(); // check candidate and noncandidate layers below this candidate does not overlap for (int below = 0; below < targetLayerIndex; below++) { if (mFBLayers[below]->mPlaneCandidate) { continue; } else { // check candidate layer above this noncandidate layer does not overlap for (int above = below + 1; above < targetLayerIndex; above++) { if (mFBLayers[above]->mPlaneCandidate == false) { continue; } if (hasIntersection(mFBLayers[above], mFBLayers[below])) { return false; } } } } // check candidate and noncandidate layers above this candidate does not overlap for (int above = targetLayerIndex + 1; above < mFBLayers.size(); above++) { if (mFBLayers[above]->mPlaneCandidate) { continue; } else { // check candidate layer below this noncandidate layer does not overlap for (int below = targetLayerIndex + 1; below < above; below++) { if (mFBLayers[below]->mPlaneCandidate == false) { continue; } if (hasIntersection(mFBLayers[above], mFBLayers[below])) { return false; } } } } return true; } bool HwcLayerList::hasIntersection(HwcLayer *la, HwcLayer *lb) { hwc_layer_1_t *a = la->getLayer(); hwc_layer_1_t *b = lb->getLayer(); hwc_rect_t *aRect = &a->displayFrame; hwc_rect_t *bRect = &b->displayFrame; if (bRect->right <= aRect->left || bRect->left >= aRect->right || bRect->top >= aRect->bottom || bRect->bottom <= aRect->top) return false; return true; } ZOrderLayer* HwcLayerList::addZOrderLayer(int type, HwcLayer *hwcLayer, int zorder) { ZOrderLayer *layer = new ZOrderLayer; layer->planeType = type; layer->hwcLayer = hwcLayer; layer->zorder = (zorder != -1) ? zorder : hwcLayer->getZOrder(); layer->plane = NULL; if (hwcLayer->mPlaneCandidate) { ETRACE("plane is candidate!, order = %d", zorder); } hwcLayer->mPlaneCandidate = true; if ((int)mZOrderConfig.indexOf(layer) >= 0) { ETRACE("layer exists!"); } mZOrderConfig.add(layer); return layer; } void HwcLayerList::removeZOrderLayer(ZOrderLayer *layer) { if ((int)mZOrderConfig.indexOf(layer) < 0) { ETRACE("layer does not exist!"); } mZOrderConfig.remove(layer); if (layer->hwcLayer->mPlaneCandidate == false) { ETRACE("plane is not candidate!, order %d", layer->zorder); } layer->hwcLayer->mPlaneCandidate = false; delete layer; } void HwcLayerList::addStaticLayerSize(HwcLayer *hwcLayer) { // Calculate static layer size to avoid only composition navigation bar // and status bar etc. hwc_layer_1_t *a = hwcLayer->getLayer(); hwc_rect_t *Rect = &a->displayFrame; mLayerSize = mLayerSize + ((Rect->right - Rect->left) * (Rect->bottom - Rect->top)); } bool HwcLayerList::checkStaticLayerSize() { // Check static layer size if over threshold: half display size bool ret = false; int width = 0; int height = 0; drmModeModeInfo mode; Drm *drm = Hwcomposer::getInstance().getDrm(); drm->getModeInfo(mDisplayIndex, mode); width = mode.hdisplay; height = mode.vdisplay; if (mLayerSize > (width * height/2)) ret = true; return ret; } void HwcLayerList::setupSmartComposition() { uint32_t compositionType = HWC_OVERLAY; HwcLayer *hwcLayer = NULL; // setup smart composition only there's no update on all FB layers for (size_t i = 0; i < mFBLayers.size(); i++) { hwcLayer = mFBLayers.itemAt(i); if (hwcLayer->isUpdated() || hwcLayer->getStaticCount() == LAYER_STATIC_THRESHOLD) { compositionType = HWC_FRAMEBUFFER; } } VTRACE("smart composition enabled %s", (compositionType == HWC_OVERLAY) ? "TRUE" : "FALSE"); for (size_t i = 0; i < mFBLayers.size(); i++) { hwcLayer = mFBLayers.itemAt(i); switch (hwcLayer->getType()) { case HwcLayer::LAYER_FB: case HwcLayer::LAYER_FORCE_FB: hwcLayer->setCompositionType(compositionType); break; default: ETRACE("Invalid layer type %d", hwcLayer->getType()); break; } } } bool HwcLayerList::setupSmartComposition2() { bool ret = false; HwcLayer *hwcLayer = NULL; int layerIndex = 0; int i = 0; if (mList->flags & HWC_GEOMETRY_CHANGED) { // clear static layers vector once geometry changed mStaticLayersIndex.setCapacity(mLayerCount); mStaticLayersIndex.clear(); return ret; } if (mStaticLayersIndex.size() > 0) { // exit criteria: once either static layer has update for (i = 0; i < mStaticLayersIndex.size(); i++) { layerIndex = mStaticLayersIndex.itemAt(i); hwcLayer = mLayers.itemAt(layerIndex); if (hwcLayer->isUpdated()) { ret = true; } } if (ret == true) { for (i = 0; i < mStaticLayersIndex.size(); i++) { layerIndex = mStaticLayersIndex.itemAt(i); hwcLayer = mLayers.itemAt(layerIndex); hwcLayer->setCompositionType(HWC_FRAMEBUFFER); } DTRACE("Exit Smart Composition2 !"); mLayerSize = 0; mStaticLayersIndex.clear(); } } else { // entry criteria: hwc layers has no update if (mFBLayers.size() == 0) { for (i = 0; i < mLayerCount - 1; i++) { hwcLayer = mLayers.itemAt(i); if (hwcLayer->getPlane() && hwcLayer->getCompositionType() == HWC_OVERLAY && hwcLayer->getStaticCount() >= LAYER_STATIC_THRESHOLD) { mStaticLayersIndex.add(i); } } // check if all static layers in sequence // if all in sequence, set FORCE_FB for static layers // TODO: optimization here // 1. If two connected, can trigger smart composition2 // 2. Caculate layer size to see if it saves more bandwidth // 3. Dynamically check and add new static layers int staticLayerCount = mStaticLayersIndex.size(); if (staticLayerCount > 1 && staticLayerCount < mLayerCount-1) { layerIndex = mStaticLayersIndex.itemAt(0); hwcLayer = mLayers.itemAt(layerIndex); mLayerSize = 0; addStaticLayerSize(hwcLayer); int preIndex = hwcLayer->getIndex(); for (i = 1; i < staticLayerCount; i++) { layerIndex = mStaticLayersIndex.itemAt(i); hwcLayer = mLayers.itemAt(layerIndex); int index = hwcLayer->getIndex(); if (index == preIndex + 1) { addStaticLayerSize(hwcLayer); preIndex = index; } else break; } if ((i == staticLayerCount) && checkStaticLayerSize()) { for (i =0; i < staticLayerCount; i++) { layerIndex = mStaticLayersIndex.itemAt(i); hwcLayer = mLayers.itemAt(layerIndex); hwcLayer->setCompositionType(HWC_FORCE_FRAMEBUFFER); } DTRACE("In Smart Composition2 !"); ret = true; } else { mLayerSize = 0; } } if (!ret) mStaticLayersIndex.clear(); } } // return ture to trigger remap layers with HW plane return ret; } #if 1 // support overlay fallback to GLES bool HwcLayerList::update(hwc_display_contents_1_t *list) { bool ret; // basic check to make sure the consistance if (!list) { ETRACE("null layer list"); return false; } if ((int)list->numHwLayers != mLayerCount) { ETRACE("layer count doesn't match (%zd, %d)", list->numHwLayers, mLayerCount); return false; } // update list mList = list; bool ok = true; // update all layers, call each layer's update() for (int i = 0; i < mLayerCount; i++) { HwcLayer *hwcLayer = mLayers.itemAt(i); if (!hwcLayer) { ETRACE("no HWC layer for layer %d", i); continue; } if (!hwcLayer->update(&list->hwLayers[i])) { ok = false; hwcLayer->setCompositionType(HWC_FORCE_FRAMEBUFFER); } } if (!ok || setupSmartComposition2()) { ITRACE("overlay fallback to GLES. flags: %#x", list->flags); for (int i = 0; i < mLayerCount - 1; i++) { HwcLayer *hwcLayer = mLayers.itemAt(i); if (hwcLayer->getPlane() && (hwcLayer->getCompositionType() == HWC_OVERLAY || hwcLayer->getCompositionType() == HWC_CURSOR_OVERLAY)) { hwcLayer->setCompositionType(HWC_FRAMEBUFFER); } } mLayers.itemAt(mLayerCount - 1)->setCompositionType(HWC_FRAMEBUFFER_TARGET); deinitialize(); mList = list; initialize(); // update all layers again after plane re-allocation for (int i = 0; i < mLayerCount; i++) { HwcLayer *hwcLayer = mLayers.itemAt(i); if (!hwcLayer) { ETRACE("no HWC layer for layer %d", i); continue; } if (!hwcLayer->update(&list->hwLayers[i])) { DTRACE("fallback to GLES update failed on layer[%d]!\n", i); } } } setupSmartComposition(); return true; } #else bool HwcLayerList::update(hwc_display_contents_1_t *list) { bool ret; // basic check to make sure the consistance if (!list) { ETRACE("null layer list"); return false; } if ((int)list->numHwLayers != mLayerCount) { ETRACE("layer count doesn't match (%d, %d)", list->numHwLayers, mLayerCount); return false; } // update list mList = list; // update all layers, call each layer's update() for (int i = 0; i < mLayerCount; i++) { HwcLayer *hwcLayer = mLayers.itemAt(i); if (!hwcLayer) { ETRACE("no HWC layer for layer %d", i); continue; } hwcLayer->update(&list->hwLayers[i]); } setupSmartComposition(); return true; } #endif DisplayPlane* HwcLayerList::getPlane(uint32_t index) const { HwcLayer *hwcLayer; if (index >= mLayers.size()) { ETRACE("invalid layer index %d", index); return 0; } hwcLayer = mLayers.itemAt(index); if ((hwcLayer->getType() == HwcLayer::LAYER_FB) || (hwcLayer->getType() == HwcLayer::LAYER_FORCE_FB) || (hwcLayer->getType() == HwcLayer::LAYER_SKIPPED)) { return 0; } if (hwcLayer->getHandle() == 0) { DTRACE("plane is attached with invalid handle"); return 0; } return hwcLayer->getPlane(); } void HwcLayerList::postFlip() { for (size_t i = 0; i < mLayers.size(); i++) { HwcLayer *hwcLayer = mLayers.itemAt(i); hwcLayer->postFlip(); } } void HwcLayerList::dump(Dump& d) { d.append("Layer list: (number of layers %d):\n", mLayers.size()); d.append(" LAYER | TYPE | PLANE | INDEX | Z Order \n"); d.append("-------+------------------------+----------------------------\n"); for (size_t i = 0; i < mLayers.size(); i++) { HwcLayer *hwcLayer = mLayers.itemAt(i); DisplayPlane *plane; long int planeIndex = -1; long int zorder = -1; const char *type = "HWC_FB"; const char *planeType = "N/A"; if (hwcLayer) { switch (hwcLayer->getType()) { case HwcLayer::LAYER_FB: case HwcLayer::LAYER_FORCE_FB: type = "HWC_FB"; break; case HwcLayer::LAYER_OVERLAY: case HwcLayer::LAYER_SKIPPED: type = "HWC_OVERLAY"; break; case HwcLayer::LAYER_FRAMEBUFFER_TARGET: type = "HWC_FRAMEBUFFER_TARGET"; break; case HwcLayer::LAYER_SIDEBAND: type = "HWC_SIDEBAND"; break; case HwcLayer::LAYER_CURSOR_OVERLAY: type = "HWC_CURSOR_OVERLAY"; break; default: type = "Unknown"; } plane = hwcLayer->getPlane(); if (plane) { planeIndex = plane->getIndex(); zorder = plane->getZOrder(); switch (plane->getType()) { case DisplayPlane::PLANE_OVERLAY: planeType = "OVERLAY"; break; case DisplayPlane::PLANE_SPRITE: planeType = "SPRITE"; break; case DisplayPlane::PLANE_PRIMARY: planeType = "PRIMARY"; break; case DisplayPlane::PLANE_CURSOR: planeType = "CURSOR"; break; default: planeType = "Unknown"; } } d.append(" %2d | %22s | %8s | %3ld | %3ld \n", i, type, planeType, planeIndex, zorder); } } } void HwcLayerList::dump() { static char const* compositionTypeName[] = { "GLES", "HWC", "BG", "FBT", "SB", "CUR", "N/A"}; static char const* planeTypeName[] = { "SPRITE", "OVERLAY", "PRIMARY", "CURSOR", "UNKNOWN"}; DTRACE(" numHwLayers = %zu, flags = %08x", mList->numHwLayers, mList->flags); DTRACE(" type | handle | hints | flags | tr | blend | alpha | format | source crop | frame | index | zorder | plane "); DTRACE("------+----------+-------+-------+----+-------+-------+----------+-----------------------------------+---------------------------+-------+--------+---------"); for (int i = 0 ; i < mLayerCount ; i++) { const hwc_layer_1_t&l = mList->hwLayers[i]; DisplayPlane *plane = mLayers[i]->getPlane(); int planeIndex = -1; int zorder = -1; const char *planeType = "N/A"; if (plane) { planeIndex = plane->getIndex(); zorder = plane->getZOrder(); planeType = planeTypeName[plane->getType()]; } DTRACE( " %4s | %p | %5x | %5x | %2x | %5x | %5x | %8x | [%7.1f,%7.1f,%7.1f,%7.1f] | [%5d,%5d,%5d,%5d] | %5d | %6d | %7s ", compositionTypeName[l.compositionType], mLayers[i]->getHandle(), l.hints, l.flags, l.transform, l.blending, l.planeAlpha, mLayers[i]->getFormat(), l.sourceCropf.left, l.sourceCropf.top, l.sourceCropf.right, l.sourceCropf.bottom, l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom, planeIndex, zorder, planeType); } } } // namespace intel } // namespace android