|
|
/* |
|
|
// 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 <math.h> |
|
|
#include <HwcTrace.h> |
|
|
#include <Drm.h> |
|
|
#include <Hwcomposer.h> |
|
|
#include <tangier/TngOverlayPlane.h> |
|
|
#include <tangier/TngGrallocBuffer.h> |
|
|
|
|
|
namespace android { |
|
|
namespace intel { |
|
|
|
|
|
TngOverlayPlane::TngOverlayPlane(int index, int disp) |
|
|
: OverlayPlaneBase(index, disp), |
|
|
mRotationBufProvider(NULL) |
|
|
{ |
|
|
CTRACE(); |
|
|
|
|
|
memset(&mContext, 0, sizeof(mContext)); |
|
|
} |
|
|
|
|
|
TngOverlayPlane::~TngOverlayPlane() |
|
|
{ |
|
|
CTRACE(); |
|
|
} |
|
|
|
|
|
bool TngOverlayPlane::flip(void *ctx) |
|
|
{ |
|
|
RETURN_FALSE_IF_NOT_INIT(); |
|
|
|
|
|
if (!DisplayPlane::flip(ctx)) |
|
|
return false; |
|
|
|
|
|
mContext.type = DC_OVERLAY_PLANE; |
|
|
mContext.ctx.ov_ctx.ovadd = 0x0; |
|
|
mContext.ctx.ov_ctx.ovadd = (mBackBuffer[mCurrent]->gttOffsetInPage << 12); |
|
|
mContext.ctx.ov_ctx.index = mIndex; |
|
|
mContext.ctx.ov_ctx.pipe = mDevice; |
|
|
mContext.ctx.ov_ctx.ovadd |= mPipeConfig; |
|
|
mContext.ctx.ov_ctx.ovadd |= 0x1; |
|
|
|
|
|
// move to next back buffer |
|
|
//mCurrent = (mCurrent + 1) % OVERLAY_BACK_BUFFER_COUNT; |
|
|
|
|
|
VTRACE("ovadd = %#x, index = %d, device = %d", |
|
|
mContext.ctx.ov_ctx.ovadd, |
|
|
mIndex, |
|
|
mDevice); |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
bool TngOverlayPlane::reset() |
|
|
{ |
|
|
OverlayPlaneBase::reset(); |
|
|
if (mRotationBufProvider) |
|
|
mRotationBufProvider->reset(); |
|
|
return true; |
|
|
} |
|
|
|
|
|
void* TngOverlayPlane::getContext() const |
|
|
{ |
|
|
CTRACE(); |
|
|
return (void *)&mContext; |
|
|
} |
|
|
|
|
|
bool TngOverlayPlane::setDataBuffer(BufferMapper& mapper) |
|
|
{ |
|
|
if (OverlayPlaneBase::setDataBuffer(mapper) == false) { |
|
|
return false; |
|
|
} |
|
|
|
|
|
if (mIsProtectedBuffer) { |
|
|
// Bit 0: Decryption request, only allowed to change on a synchronous flip |
|
|
// This request will be qualified with the separate decryption enable bit for OV |
|
|
mBackBuffer[mCurrent]->buf->OSTART_0Y |= 0x1; |
|
|
mBackBuffer[mCurrent]->buf->OSTART_1Y |= 0x1; |
|
|
} |
|
|
|
|
|
mContext.gtt_key = (uint64_t)mapper.getCpuAddress(0); |
|
|
return true; |
|
|
} |
|
|
|
|
|
bool TngOverlayPlane::initialize(uint32_t bufferCount) |
|
|
{ |
|
|
if (!OverlayPlaneBase::initialize(bufferCount)) { |
|
|
ETRACE("failed to initialize OverlayPlaneBase"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
// setup rotation buffer |
|
|
mRotationBufProvider = new RotationBufferProvider(mWsbm); |
|
|
if (!mRotationBufProvider || !mRotationBufProvider->initialize()) { |
|
|
DEINIT_AND_RETURN_FALSE("failed to initialize RotationBufferProvider"); |
|
|
} |
|
|
return true; |
|
|
} |
|
|
|
|
|
void TngOverlayPlane::deinitialize() |
|
|
{ |
|
|
DEINIT_AND_DELETE_OBJ(mRotationBufProvider); |
|
|
OverlayPlaneBase::deinitialize(); |
|
|
} |
|
|
|
|
|
bool TngOverlayPlane::rotatedBufferReady(BufferMapper& mapper, BufferMapper* &rotatedMapper) |
|
|
{ |
|
|
struct VideoPayloadBuffer *payload; |
|
|
VideoPayloadBuffer buffer_info; |
|
|
uint32_t format; |
|
|
// only NV12_VED has rotated buffer |
|
|
format = mapper.getFormat(); |
|
|
|
|
|
if (format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar && |
|
|
format != OMX_INTEL_COLOR_FormatYUV420PackedSemiPlanar_Tiled && |
|
|
format != HAL_PIXEL_FORMAT_NV12) { |
|
|
ETRACE("Invalid video format %#x", format); |
|
|
return false; |
|
|
} |
|
|
|
|
|
payload = (struct VideoPayloadBuffer *)mapper.getCpuAddress(SUB_BUFFER1); |
|
|
|
|
|
if (payload == NULL && format == HAL_PIXEL_FORMAT_NV12) { |
|
|
// need to populate buffer_info |
|
|
void *p = mapper.getCpuAddress(SUB_BUFFER0); |
|
|
if (!p) { |
|
|
ETRACE("failed to get buffer user pointer"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
bool ret = mRotationBufProvider->prepareBufferInfo(mapper.getWidth(), |
|
|
mapper.getHeight(), |
|
|
mapper.getStride().yuv.yStride, |
|
|
&buffer_info, p); |
|
|
if (ret == false) { |
|
|
ETRACE("failed to prepare buffer info"); |
|
|
return false; |
|
|
} |
|
|
payload = &buffer_info; |
|
|
} |
|
|
|
|
|
// check payload |
|
|
if (!payload) { |
|
|
ETRACE("no payload found"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
if (payload->force_output_method == FORCE_OUTPUT_GPU) { |
|
|
ETRACE("Output method is not supported!"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
if (payload->client_transform != mTransform || |
|
|
mBobDeinterlace) { |
|
|
payload->hwc_timestamp = systemTime(); |
|
|
payload->layer_transform = mTransform; |
|
|
if (!mRotationBufProvider->setupRotationBuffer(payload, mTransform)) { |
|
|
ETRACE("failed to setup rotation buffer"); |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
rotatedMapper = getTTMMapper(mapper, payload); |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
bool TngOverlayPlane::flush(uint32_t flags) |
|
|
{ |
|
|
RETURN_FALSE_IF_NOT_INIT(); |
|
|
ATRACE("flags = %#x, type = %d, index = %d", flags, mType, mIndex); |
|
|
|
|
|
if (!(flags & PLANE_ENABLE) && !(flags & PLANE_DISABLE)) |
|
|
return false; |
|
|
|
|
|
struct drm_psb_register_rw_arg arg; |
|
|
memset(&arg, 0, sizeof(struct drm_psb_register_rw_arg)); |
|
|
|
|
|
if (flags & PLANE_DISABLE) |
|
|
arg.plane_disable_mask = 1; |
|
|
else if (flags & PLANE_ENABLE) |
|
|
arg.plane_enable_mask = 1; |
|
|
|
|
|
arg.plane.type = DC_OVERLAY_PLANE; |
|
|
arg.plane.index = mIndex; |
|
|
arg.plane.ctx = (mBackBuffer[mCurrent]->gttOffsetInPage << 12); |
|
|
// pipe select |
|
|
arg.plane.ctx |= mPipeConfig; |
|
|
|
|
|
if (flags & PLANE_DISABLE) { |
|
|
DTRACE("disabling overlay %d on device %d", mIndex, mDevice); |
|
|
} |
|
|
|
|
|
// issue ioctl |
|
|
Drm *drm = Hwcomposer::getInstance().getDrm(); |
|
|
bool ret = drm->writeReadIoctl(DRM_PSB_REGISTER_RW, &arg, sizeof(arg)); |
|
|
if (ret == false) { |
|
|
WTRACE("overlay update failed with error code %d", ret); |
|
|
return false; |
|
|
} |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
} // namespace intel |
|
|
} // namespace android
|
|
|
|