/*
// 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 <IDisplayDevice.h>
#include <DisplayPlaneManager.h>
namespace android {
namespace intel {
DisplayPlaneManager::DisplayPlaneManager()
: mTotalPlaneCount(0),
mPrimaryPlaneCount(DEFAULT_PRIMARY_PLANE_COUNT),
mSpritePlaneCount(0),
mOverlayPlaneCount(0),
mInitialized(false)
{
int i;
for (i = 0; i < DisplayPlane::PLANE_MAX; i++) {
mPlaneCount[i] = 0;
mFreePlanes[i] = 0;
mReclaimedPlanes[i] = 0;
}
}
DisplayPlaneManager::~DisplayPlaneManager()
{
WARN_IF_NOT_DEINIT();
}
void DisplayPlaneManager::deinitialize()
{
int i;
size_t j;
for (i = 0; i < DisplayPlane::PLANE_MAX; i++) {
for (j = 0; j < mPlanes[i].size(); j++) {
// reset plane
DisplayPlane *plane = mPlanes[i].itemAt(j);
plane->reset();
DEINIT_AND_DELETE_OBJ(plane);
}
mPlanes[i].clear();
}
mInitialized = false;
}
bool DisplayPlaneManager::initialize()
{
int i, j;
if (mInitialized) {
WTRACE("object has been initialized");
return true;
}
// calculate total plane number and free plane bitmaps
mPlaneCount[DisplayPlane::PLANE_SPRITE] = mSpritePlaneCount;
mPlaneCount[DisplayPlane::PLANE_OVERLAY] = mOverlayPlaneCount;
mPlaneCount[DisplayPlane::PLANE_PRIMARY] = mPrimaryPlaneCount;
mPlaneCount[DisplayPlane::PLANE_CURSOR] = mCursorPlaneCount;
mTotalPlaneCount = mSpritePlaneCount+ mOverlayPlaneCount+ mPrimaryPlaneCount + mCursorPlaneCount;
if (mTotalPlaneCount == 0) {
ETRACE("plane count is not initialized");
return false;
}
for (i = 0; i < DisplayPlane::PLANE_MAX; i++) {
mFreePlanes[i] = ((1 << mPlaneCount[i]) - 1);
}
// allocate plane pools
for (i = 0; i < DisplayPlane::PLANE_MAX; i++) {
if (mPlaneCount[i]) {
mPlanes[i].setCapacity(mPlaneCount[i]);
for (j = 0; j < mPlaneCount[i]; j++) {
DisplayPlane* plane = allocPlane(j, i);
if (!plane) {
ETRACE("failed to allocate plane %d, type %d", j, i);
DEINIT_AND_RETURN_FALSE();
}
mPlanes[i].push_back(plane);
}
}
}
mInitialized = true;
return true;
}
int DisplayPlaneManager::getPlane(uint32_t& mask)
{
if (!mask)
return -1;
for (int i = 0; i < 32; i++) {
int bit = (1 << i);
if (bit & mask) {
mask &= ~bit;
return i;
}
}
return -1;
}
void DisplayPlaneManager::putPlane(int index, uint32_t& mask)
{
if (index < 0 || index >= 32)
return;
int bit = (1 << index);
if (bit & mask) {
WTRACE("bit %d was set", index);
return;
}
mask |= bit;
}
int DisplayPlaneManager::getPlane(uint32_t& mask, int index)
{
if (!mask || index < 0 || index > mTotalPlaneCount)
return -1;
int bit = (1 << index);
if (bit & mask) {
mask &= ~bit;
return index;
}
return -1;
}
DisplayPlane* DisplayPlaneManager::getPlane(int type, int index)
{
RETURN_NULL_IF_NOT_INIT();
if (type < 0 || type >= DisplayPlane::PLANE_MAX) {
ETRACE("Invalid plane type %d", type);
return 0;
}
int freePlaneIndex = getPlane(mReclaimedPlanes[type], index);
if (freePlaneIndex >= 0)
return mPlanes[type].itemAt(freePlaneIndex);
freePlaneIndex = getPlane(mFreePlanes[type], index);
if (freePlaneIndex >= 0)
return mPlanes[type].itemAt(freePlaneIndex);
return 0;
}
DisplayPlane* DisplayPlaneManager::getAnyPlane(int type)
{
RETURN_NULL_IF_NOT_INIT();
if (type < 0 || type >= DisplayPlane::PLANE_MAX) {
ETRACE("Invalid plane type %d", type);
return 0;
}
int freePlaneIndex = getPlane(mReclaimedPlanes[type]);
if (freePlaneIndex >= 0)
return mPlanes[type].itemAt(freePlaneIndex);
freePlaneIndex = getPlane(mFreePlanes[type]);
if (freePlaneIndex >= 0)
return mPlanes[type].itemAt(freePlaneIndex);
return 0;
}
void DisplayPlaneManager::putPlane(int dsp, DisplayPlane& plane)
{
int index;
int type;
RETURN_VOID_IF_NOT_INIT();
index = plane.getIndex();
type = plane.getType();
if (type < 0 || type >= DisplayPlane::PLANE_MAX) {
ETRACE("Invalid plane type %d", type);
return;
}
putPlane(index, mFreePlanes[type]);
}
bool DisplayPlaneManager::isFreePlane(int type, int index)
{
if (type < 0 || type >= DisplayPlane::PLANE_MAX) {
ETRACE("Invalid plane type %d", type);
return false;
}
int freePlanes = mFreePlanes[type] | mReclaimedPlanes[type];
if ((freePlanes & (1 << index)) == 0)
return false;
return true;
}
int DisplayPlaneManager::getFreePlanes(int dsp, int type)
{
RETURN_NULL_IF_NOT_INIT();
if (dsp < 0 || dsp > IDisplayDevice::DEVICE_EXTERNAL) {
ETRACE("Invalid display device %d", dsp);
return 0;
}
if (type < 0 || type >= DisplayPlane::PLANE_MAX) {
ETRACE("Invalid plane type %d", type);
return 0;
}
uint32_t freePlanes = mFreePlanes[type] | mReclaimedPlanes[type];
if (type == DisplayPlane::PLANE_PRIMARY ||
type == DisplayPlane::PLANE_CURSOR) {
return ((freePlanes & (1 << dsp)) == 0) ? 0 : 1;
} else {
int count = 0;
for (int i = 0; i < 32; i++) {
if ((1 << i) & freePlanes) {
count++;
}
}
return count;
}
return 0;
}
void DisplayPlaneManager::reclaimPlane(int dsp, DisplayPlane& plane)
{
RETURN_VOID_IF_NOT_INIT();
int index = plane.getIndex();
int type = plane.getType();
ATRACE("reclaimPlane = %d, type = %d", index, plane.getType());
if (type < 0 || type >= DisplayPlane::PLANE_MAX) {
ETRACE("Invalid plane type %d", type);
return;
}
putPlane(index, mReclaimedPlanes[type]);
// NOTE: don't invalidate plane's data cache here because the reclaimed
// plane might be re-assigned to the same layer later
}
void DisplayPlaneManager::disableReclaimedPlanes()
{
int i, j;
bool ret;
RETURN_VOID_IF_NOT_INIT();
for (i = 0; i < DisplayPlane::PLANE_MAX; i++) {
// disable reclaimed planes
if (mReclaimedPlanes[i]) {
for (j = 0; j < mPlaneCount[i]; j++) {
int bit = (1 << j);
if (mReclaimedPlanes[i] & bit) {
DisplayPlane* plane = mPlanes[i].itemAt(j);
// check plane state first
ret = plane->isDisabled();
// reset plane
if (ret)
ret = plane->reset();
if (ret) {
// only merge into free bitmap if it is successfully disabled and reset
// otherwise, plane will be disabled and reset again.
mFreePlanes[i] |=bit;
mReclaimedPlanes[i] &= ~bit;
}
}
}
}
}
}
bool DisplayPlaneManager::isOverlayPlanesDisabled()
{
for (int i = 0; i < DisplayPlane::PLANE_MAX; i++) {
for (int j = 0; j < mPlaneCount[i]; j++) {
DisplayPlane* plane = (DisplayPlane *)mPlanes[i][j];
if (plane && plane->getType() == DisplayPlane::PLANE_OVERLAY) {
if (!plane->isDisabled())
return false;
}
}
}
return true;
}
void DisplayPlaneManager::dump(Dump& d)
{
d.append("Display Plane Manager state:\n");
d.append("-------------------------------------------------------------\n");
d.append(" PLANE TYPE | COUNT | FREE | RECLAIMED \n");
d.append("------------+-------+----------+-----------\n");
d.append(" SPRITE | %2d | %08x | %08x\n",
mPlaneCount[DisplayPlane::PLANE_SPRITE],
mFreePlanes[DisplayPlane::PLANE_SPRITE],
mReclaimedPlanes[DisplayPlane::PLANE_SPRITE]);
d.append(" OVERLAY | %2d | %08x | %08x\n",
mPlaneCount[DisplayPlane::PLANE_OVERLAY],
mFreePlanes[DisplayPlane::PLANE_OVERLAY],
mReclaimedPlanes[DisplayPlane::PLANE_OVERLAY]);
d.append(" PRIMARY | %2d | %08x | %08x\n",
mPlaneCount[DisplayPlane::PLANE_PRIMARY],
mFreePlanes[DisplayPlane::PLANE_PRIMARY],
mReclaimedPlanes[DisplayPlane::PLANE_PRIMARY]);
d.append(" CURSOR | %2d | %08x | %08x\n",
mPlaneCount[DisplayPlane::PLANE_CURSOR],
mFreePlanes[DisplayPlane::PLANE_CURSOR],
mReclaimedPlanes[DisplayPlane::PLANE_CURSOR]);
}
} // namespace intel
} // namespace android