C++程序  |  409行  |  10.21 KB

/*
// 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 <common/utils/HwcTrace.h>
#include <Hwcomposer.h>
#include <DisplayPlane.h>
#include <GraphicBuffer.h>
#include <DisplayQuery.h>

namespace android {
namespace intel {

DisplayPlane::DisplayPlane(int index, int type, int disp)
    : mIndex(index),
      mType(type),
      mZOrder(-1),
      mDevice(disp),
      mInitialized(false),
      mDataBuffers(),
      mActiveBuffers(),
      mCacheCapacity(0),
      mIsProtectedBuffer(false),
      mTransform(0),
      mPlaneAlpha(0),
      mBlending(HWC_BLENDING_NONE),
      mCurrentDataBuffer(0),
      mUpdateMasks(0),
      mForceScaling(false),
      mDisplayWidth(0),
      mDisplayHeight(0),
      mScalingSource(0),
      mScalingTarget(0)
{
    CTRACE();
    memset(&mPosition, 0, sizeof(mPosition));
    memset(&mSrcCrop, 0, sizeof(mSrcCrop));
}

DisplayPlane::~DisplayPlane()
{
    WARN_IF_NOT_DEINIT();
}

bool DisplayPlane::initialize(uint32_t bufferCount)
{
    CTRACE();

    if (bufferCount < MIN_DATA_BUFFER_COUNT) {
        WLOGTRACE("buffer count %d is too small", bufferCount);
        bufferCount = MIN_DATA_BUFFER_COUNT;
    }

    // create buffer cache, adding few extra slots as buffer rendering is async
    // buffer could still be queued in the display pipeline such that they
    // can't be unmapped]
    mCacheCapacity = bufferCount;
    mDataBuffers.setCapacity(bufferCount);
    mActiveBuffers.setCapacity(MIN_DATA_BUFFER_COUNT);
    mInitialized = true;
    return true;
}

void DisplayPlane::deinitialize()
{
    // invalidate cached data buffers
    if (mDataBuffers.size()) {
        // invalidateBufferCache will assert if object is not initialized
        // so invoking it only there is buffer to invalidate.
        invalidateBufferCache();
    }

    // invalidate active buffers
    if (mActiveBuffers.size()) {
        invalidateActiveBuffers();
    }

    mCurrentDataBuffer = 0;
    mInitialized = false;
}

void DisplayPlane::checkPosition(int& x, int& y, int& w, int& h)
{
    drmModeModeInfoPtr mode = &mModeInfo;

    if (mode->hdisplay == 0 || mode->vdisplay == 0)
        return;

    if (x < 0)
        x = 0;
    if (y < 0)
        y = 0;
    if ((x + w) > mode->hdisplay)
        w = mode->hdisplay - x;
    if ((y + h) > mode->vdisplay)
        h = mode->vdisplay - y;
}

void DisplayPlane::setPosition(int x, int y, int w, int h)
{
    ALOGTRACE("Position = %d, %d - %dx%d", x, y, w, h);

    if (mForceScaling) {
        // set in assignToDevice
        mPosition.x = (int) (((float)x/DEFAULT_DRM_FB_WIDTH)*mDisplayWidth);
        mPosition.y = (int) (((float)y/DEFAULT_DRM_FB_HEIGHT)*mDisplayHeight);
        mPosition.w = (int) (((float)w/DEFAULT_DRM_FB_WIDTH)*mDisplayWidth);
        mPosition.h = (int) (((float)h/DEFAULT_DRM_FB_HEIGHT)*mDisplayHeight);

        mDisplayCrop.x = 0;
        mDisplayCrop.y = 0;
        mDisplayCrop.w = mDisplayWidth;
        mDisplayCrop.h = mDisplayHeight;

        return;
    }

    if (mPosition.x != x || mPosition.y != y ||
        mPosition.w != w || mPosition.h != h) {
        mUpdateMasks |= PLANE_POSITION_CHANGED;
        mPosition.x = x;
        mPosition.y = y;
        mPosition.w = w;
        mPosition.h = h;
    }
}

void DisplayPlane::setSourceCrop(int x, int y, int w, int h)
{
    ALOGTRACE("Source crop = %d, %d - %dx%d", x, y, w, h);

    if (mSrcCrop.x != x || mSrcCrop.y != y ||
        mSrcCrop.w != w || mSrcCrop.h != h) {
        mUpdateMasks |= PLANE_SOURCE_CROP_CHANGED;
        mSrcCrop.x = x;
        mSrcCrop.y = y;
        mSrcCrop.w = w;
        mSrcCrop.h = h;
    }
}

void DisplayPlane::setTransform(int trans)
{
    ALOGTRACE("transform = %d", trans);

    if (mTransform == trans) {
        return;
    }

    mTransform = trans;

    mUpdateMasks |= PLANE_TRANSFORM_CHANGED;
}

void DisplayPlane::setPlaneAlpha(uint8_t alpha, uint32_t blending)
{
    ALOGTRACE("plane alpha = 0x%x", alpha);

    if (mPlaneAlpha != alpha) {
        mPlaneAlpha = alpha;
        mUpdateMasks |= PLANE_BUFFER_CHANGED;
    }

    if (mBlending != blending) {
        mBlending = blending;
        mUpdateMasks |= PLANE_BUFFER_CHANGED;
    }
}

bool DisplayPlane::setDataBuffer(uint32_t handle)
{
    DataBuffer *buffer;
    BufferMapper *mapper;
    ssize_t index;
    bool ret;
    bool isCompression;
    BufferManager *bm = Hwcomposer::getInstance().getBufferManager();

    RETURN_FALSE_IF_NOT_INIT();
    ALOGTRACE("handle = %#x", handle);

    if (!handle) {
        WLOGTRACE("invalid buffer handle");
        return false;
    }

    // do not need to update the buffer handle
    if (mCurrentDataBuffer != handle)
        mUpdateMasks |= PLANE_BUFFER_CHANGED;

    // if no update then do Not need set data buffer
    if (!mUpdateMasks)
        return true;

    buffer = bm->lockDataBuffer(handle);
    if (!buffer) {
        ELOGTRACE("failed to get buffer");
        return false;
    }

    mIsProtectedBuffer = GraphicBuffer::isProtectedBuffer((GraphicBuffer*)buffer);
    isCompression = GraphicBuffer::isCompressionBuffer((GraphicBuffer*)buffer);

    // map buffer if it's not in cache
    index = mDataBuffers.indexOfKey(buffer->getKey());
    if (index < 0) {
        VLOGTRACE("unmapped buffer, mapping...");
        mapper = mapBuffer(buffer);
        // Skip the unsupported format in case that a new gralloc buffer was
        // created and added into the mapped list, triggered by SoftwareRender
        // with color conversion from known formats to YV12.
        if (!mapper || mapper->getFormat() == HAL_PIXEL_FORMAT_YV12) {
            ELOGTRACE("failed to map buffer %#x", handle);
            bm->unlockDataBuffer(buffer);
            return false;
        }
    } else {
        VLOGTRACE("got mapper in saved data buffers and update source Crop");
        mapper = mDataBuffers.valueAt(index);
    }

    // always update source crop to mapper
    mapper->setCrop(mSrcCrop.x, mSrcCrop.y, mSrcCrop.w, mSrcCrop.h);

    mapper->setIsCompression(isCompression);

    // unlock buffer after getting mapper
    bm->unlockDataBuffer(buffer);
    buffer = NULL;

    ret = setDataBuffer(*mapper);
    if (ret) {
        mCurrentDataBuffer = handle;
        // update active buffers
        updateActiveBuffers(mapper);
    }
    return ret;
}

BufferMapper* DisplayPlane::mapBuffer(DataBuffer *buffer)
{
    BufferManager *bm = Hwcomposer::getInstance().getBufferManager();

    // invalidate buffer cache  if cache is full
    if ((int)mDataBuffers.size() >= mCacheCapacity) {
        invalidateBufferCache();
    }

    BufferMapper *mapper = bm->map(*buffer);
    if (!mapper) {
        ELOGTRACE("failed to map buffer");
        return NULL;
    }

    // add it to data buffers
    ssize_t index = mDataBuffers.add(buffer->getKey(), mapper);
    if (index < 0) {
        ELOGTRACE("failed to add mapper");
        bm->unmap(mapper);
        return NULL;
    }

    return mapper;
}

bool DisplayPlane::isActiveBuffer(BufferMapper *mapper)
{
    for (size_t i = 0; i < mActiveBuffers.size(); i++) {
        BufferMapper *activeMapper = mActiveBuffers.itemAt(i);
        if (!activeMapper)
            continue;
        if (activeMapper->getKey() == mapper->getKey())
            return true;
    }

    return false;
}

void DisplayPlane::updateActiveBuffers(BufferMapper *mapper)
{
    BufferManager *bm = Hwcomposer::getInstance().getBufferManager();

    // unmap the first entry (oldest buffer)
    if (mActiveBuffers.size() >= MIN_DATA_BUFFER_COUNT) {
        BufferMapper *oldest = mActiveBuffers.itemAt(0);
        bm->unmap(oldest);
        mActiveBuffers.removeAt(0);
    }

    // queue it to active buffers
    if (!isActiveBuffer(mapper)) {
        mapper->incRef();
        mActiveBuffers.push_back(mapper);
    }
}

void DisplayPlane::invalidateActiveBuffers()
{
    BufferManager *bm = Hwcomposer::getInstance().getBufferManager();
    BufferMapper* mapper;

    RETURN_VOID_IF_NOT_INIT();

    VLOGTRACE("invalidating active buffers");

    for (size_t i = 0; i < mActiveBuffers.size(); i++) {
        mapper = mActiveBuffers.itemAt(i);
        // unmap it
        bm->unmap(mapper);
    }

    // clear recorded data buffers
    mActiveBuffers.clear();
}

void DisplayPlane::invalidateBufferCache()
{
    BufferManager *bm = Hwcomposer::getInstance().getBufferManager();
    BufferMapper* mapper;

    RETURN_VOID_IF_NOT_INIT();

    for (size_t i = 0; i < mDataBuffers.size(); i++) {
        mapper = mDataBuffers.valueAt(i);
        bm->unmap(mapper);
    }

    mDataBuffers.clear();
    // reset current buffer
    mCurrentDataBuffer = 0;
}

bool DisplayPlane::assignToDevice(int disp)
{
    RETURN_FALSE_IF_NOT_INIT();
    ALOGTRACE("disp = %d", disp);

    mDevice = disp;

    Drm *drm = Hwcomposer::getInstance().getDrm();
    if (!drm->getModeInfo(mDevice, mModeInfo)) {
        ELOGTRACE("failed to get mode info");
    }

    mPanelOrientation = drm->getPanelOrientation(mDevice);

    mForceScaling = DisplayQuery::forceFbScaling(disp);
    drm->getDisplayResolution(disp, mDisplayWidth, mDisplayHeight);

    if (mForceScaling) {
        mModeInfo.hdisplay = mDisplayWidth;
        mModeInfo.vdisplay = mDisplayHeight;

    }

    return true;
}

bool DisplayPlane::flip(void * /* ctx */)
{
    RETURN_FALSE_IF_NOT_INIT();

    // always flip
    return true;
}

void DisplayPlane::postFlip()
{
    mUpdateMasks = 0;
}

bool DisplayPlane::reset()
{
    // reclaim all allocated resources
    if (mDataBuffers.size() > 0) {
        invalidateBufferCache();
    }

    if (mActiveBuffers.size() > 0) {
        invalidateActiveBuffers();
    }

    return true;
}

void DisplayPlane::setZOrder(int zorder)
{
    mZOrder = zorder;
}

int DisplayPlane::getZOrder() const
{
    return mZOrder;
}

} // namespace intel
} // namespace android