|
|
/* |
|
|
// 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 <common/RotationBufferProvider.h> |
|
|
#include <system/graphics-base.h> |
|
|
|
|
|
namespace android { |
|
|
namespace intel { |
|
|
|
|
|
#define CHECK_VA_STATUS_RETURN(FUNC) \ |
|
|
if (vaStatus != VA_STATUS_SUCCESS) {\ |
|
|
ETRACE(FUNC" failed. vaStatus = %#x", vaStatus);\ |
|
|
return false;\ |
|
|
} |
|
|
|
|
|
#define CHECK_VA_STATUS_BREAK(FUNC) \ |
|
|
if (vaStatus != VA_STATUS_SUCCESS) {\ |
|
|
ETRACE(FUNC" failed. vaStatus = %#x", vaStatus);\ |
|
|
break;\ |
|
|
} |
|
|
|
|
|
// With this display value, VA will hook VED driver insead of VSP driver for buffer rotation |
|
|
#define DISPLAYVALUE 0x56454450 |
|
|
|
|
|
RotationBufferProvider::RotationBufferProvider(Wsbm* wsbm) |
|
|
: mWsbm(wsbm), |
|
|
mVaInitialized(false), |
|
|
mVaDpy(0), |
|
|
mVaCfg(0), |
|
|
mVaCtx(0), |
|
|
mVaBufFilter(0), |
|
|
mSourceSurface(0), |
|
|
mDisplay(DISPLAYVALUE), |
|
|
mWidth(0), |
|
|
mHeight(0), |
|
|
mTransform(0), |
|
|
mRotatedWidth(0), |
|
|
mRotatedHeight(0), |
|
|
mRotatedStride(0), |
|
|
mTargetIndex(0), |
|
|
mTTMWrappers(), |
|
|
mBobDeinterlace(0) |
|
|
{ |
|
|
for (int i = 0; i < MAX_SURFACE_NUM; i++) { |
|
|
mKhandles[i] = 0; |
|
|
mRotatedSurfaces[i] = 0; |
|
|
mDrmBuf[i] = NULL; |
|
|
} |
|
|
} |
|
|
|
|
|
RotationBufferProvider::~RotationBufferProvider() |
|
|
{ |
|
|
} |
|
|
|
|
|
uint32_t RotationBufferProvider::getMilliseconds() |
|
|
{ |
|
|
struct timeval ptimeval; |
|
|
gettimeofday(&ptimeval, NULL); |
|
|
return (uint32_t)((ptimeval.tv_sec * 1000) + (ptimeval.tv_usec / 1000)); |
|
|
} |
|
|
|
|
|
bool RotationBufferProvider::initialize() |
|
|
{ |
|
|
if (NULL == mWsbm) |
|
|
return false; |
|
|
mTTMWrappers.setCapacity(TTM_WRAPPER_COUNT); |
|
|
return true; |
|
|
} |
|
|
|
|
|
void RotationBufferProvider::deinitialize() |
|
|
{ |
|
|
stopVA(); |
|
|
reset(); |
|
|
} |
|
|
|
|
|
void RotationBufferProvider::reset() |
|
|
{ |
|
|
if (mTTMWrappers.size()) { |
|
|
invalidateCaches(); |
|
|
} |
|
|
} |
|
|
|
|
|
void RotationBufferProvider::invalidateCaches() |
|
|
{ |
|
|
void *buf; |
|
|
|
|
|
for (size_t i = 0; i < mTTMWrappers.size(); i++) { |
|
|
buf = mTTMWrappers.valueAt(i); |
|
|
if (!mWsbm->destroyTTMBuffer(buf)) |
|
|
WTRACE("failed to free TTMBuffer"); |
|
|
} |
|
|
mTTMWrappers.clear(); |
|
|
} |
|
|
|
|
|
int RotationBufferProvider::transFromHalToVa(int transform) |
|
|
{ |
|
|
if (transform == HAL_TRANSFORM_ROT_90) |
|
|
return VA_ROTATION_90; |
|
|
if (transform == HAL_TRANSFORM_ROT_180) |
|
|
return VA_ROTATION_180; |
|
|
if (transform == HAL_TRANSFORM_ROT_270) |
|
|
return VA_ROTATION_270; |
|
|
return 0; |
|
|
} |
|
|
|
|
|
int RotationBufferProvider::getStride(bool isTarget, int width) |
|
|
{ |
|
|
int stride = 0; |
|
|
if (width <= 512) |
|
|
stride = 512; |
|
|
else if (width <= 1024) |
|
|
stride = 1024; |
|
|
else if (width <= 1280) { |
|
|
stride = 1280; |
|
|
if (isTarget) |
|
|
stride = 2048; |
|
|
} else if (width <= 2048) |
|
|
stride = 2048; |
|
|
else if (width <= 4096) |
|
|
stride = 4096; |
|
|
else |
|
|
stride = (width + 0x3f) & ~0x3f; |
|
|
return stride; |
|
|
} |
|
|
|
|
|
buffer_handle_t RotationBufferProvider::createWsbmBuffer(int width, int height, void **buf) |
|
|
{ |
|
|
int size = width * height * 3 / 2; // YUV420 NV12 format |
|
|
int allignment = 16 * 2048; // tiling row stride aligned |
|
|
bool ret = mWsbm->allocateTTMBuffer(size, allignment, buf); |
|
|
|
|
|
if (ret == false) { |
|
|
ETRACE("failed to allocate TTM buffer"); |
|
|
return 0; |
|
|
} |
|
|
|
|
|
return (buffer_handle_t) mWsbm->getKBufHandle(*buf); |
|
|
} |
|
|
|
|
|
bool RotationBufferProvider::createVaSurface(VideoPayloadBuffer *payload, int transform, bool isTarget) |
|
|
{ |
|
|
VAStatus vaStatus; |
|
|
VASurfaceAttributeTPI attribTpi; |
|
|
VASurfaceAttributeTPI *vaSurfaceAttrib = &attribTpi; |
|
|
int stride; |
|
|
unsigned long buffers; |
|
|
VASurfaceID *surface; |
|
|
int width = 0, height = 0, bufferHeight = 0; |
|
|
|
|
|
if (isTarget) { |
|
|
if (transFromHalToVa(transform) == VA_ROTATION_180) { |
|
|
width = payload->width; |
|
|
height = payload->height; |
|
|
} else { |
|
|
width = payload->height; |
|
|
height = payload->width; |
|
|
} |
|
|
mRotatedWidth = width; |
|
|
mRotatedHeight = height; |
|
|
bufferHeight = (height + 0x1f) & ~0x1f; |
|
|
stride = getStride(isTarget, width); |
|
|
} else { |
|
|
width = payload->width; |
|
|
height = payload->height; |
|
|
bufferHeight = (payload->height + 0x1f) & ~0x1f; |
|
|
stride = payload->luma_stride; /* NV12 srouce buffer */ |
|
|
} |
|
|
|
|
|
if (!stride) { |
|
|
ETRACE("invalid stride value"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
mBobDeinterlace = payload->bob_deinterlace; |
|
|
// adjust source target for Bob deinterlace |
|
|
if (!isTarget && mBobDeinterlace) { |
|
|
height >>= 1; |
|
|
bufferHeight >>= 1; |
|
|
stride <<= 1; |
|
|
} |
|
|
|
|
|
vaSurfaceAttrib->count = 1; |
|
|
vaSurfaceAttrib->width = width; |
|
|
vaSurfaceAttrib->height = height; |
|
|
vaSurfaceAttrib->pixel_format = payload->format; |
|
|
vaSurfaceAttrib->type = VAExternalMemoryKernelDRMBufffer; |
|
|
vaSurfaceAttrib->tiling = payload->tiling; |
|
|
vaSurfaceAttrib->size = (stride * bufferHeight * 3) / 2; |
|
|
vaSurfaceAttrib->luma_offset = 0; |
|
|
vaSurfaceAttrib->chroma_v_offset = stride * bufferHeight; |
|
|
vaSurfaceAttrib->luma_stride = vaSurfaceAttrib->chroma_u_stride |
|
|
= vaSurfaceAttrib->chroma_v_stride |
|
|
= stride; |
|
|
vaSurfaceAttrib->chroma_u_offset = vaSurfaceAttrib->chroma_v_offset; |
|
|
vaSurfaceAttrib->buffers = &buffers; |
|
|
|
|
|
if (isTarget) { |
|
|
buffer_handle_t khandle = createWsbmBuffer(stride, bufferHeight, &mDrmBuf[mTargetIndex]); |
|
|
if (khandle == 0) { |
|
|
ETRACE("failed to create buffer by wsbm"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
mKhandles[mTargetIndex] = khandle; |
|
|
vaSurfaceAttrib->buffers[0] = (uintptr_t) khandle; |
|
|
mRotatedStride = stride; |
|
|
surface = &mRotatedSurfaces[mTargetIndex]; |
|
|
} else { |
|
|
vaSurfaceAttrib->buffers[0] = (uintptr_t) payload->khandle; |
|
|
surface = &mSourceSurface; |
|
|
/* set src surface width/height to video crop size */ |
|
|
if (payload->crop_width && payload->crop_height) { |
|
|
width = payload->crop_width; |
|
|
height = (payload->crop_height >> mBobDeinterlace); |
|
|
} else { |
|
|
VTRACE("Invalid cropping width or height"); |
|
|
payload->crop_width = width; |
|
|
payload->crop_height = height; |
|
|
} |
|
|
} |
|
|
|
|
|
vaStatus = vaCreateSurfacesWithAttribute(mVaDpy, |
|
|
width, |
|
|
height, |
|
|
VA_RT_FORMAT_YUV420, |
|
|
1, |
|
|
surface, |
|
|
vaSurfaceAttrib); |
|
|
if (vaStatus != VA_STATUS_SUCCESS) { |
|
|
ETRACE("vaCreateSurfacesWithAttribute returns %d", vaStatus); |
|
|
ETRACE("Attributes: target: %d, width: %d, height %d, bufferHeight %d, tiling %d", |
|
|
isTarget, width, height, bufferHeight, payload->tiling); |
|
|
*surface = 0; |
|
|
return false; |
|
|
} |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
bool RotationBufferProvider::startVA(VideoPayloadBuffer *payload, int transform) |
|
|
{ |
|
|
bool ret = true; |
|
|
VAStatus vaStatus; |
|
|
VAEntrypoint *entryPoint; |
|
|
VAConfigAttrib attribDummy; |
|
|
int numEntryPoints; |
|
|
bool supportVideoProcessing = false; |
|
|
int majorVer = 0, minorVer = 0; |
|
|
|
|
|
// VA will hold a copy of the param pointer, so local varialbe doesn't work |
|
|
mVaDpy = vaGetDisplay(&mDisplay); |
|
|
if (NULL == mVaDpy) { |
|
|
ETRACE("failed to get VADisplay"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
vaStatus = vaInitialize(mVaDpy, &majorVer, &minorVer); |
|
|
CHECK_VA_STATUS_RETURN("vaInitialize"); |
|
|
|
|
|
numEntryPoints = vaMaxNumEntrypoints(mVaDpy); |
|
|
|
|
|
if (numEntryPoints <= 0) { |
|
|
ETRACE("numEntryPoints value is invalid"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
entryPoint = (VAEntrypoint*)malloc(sizeof(VAEntrypoint) * numEntryPoints); |
|
|
if (NULL == entryPoint) { |
|
|
ETRACE("failed to malloc memory for entryPoint"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
vaStatus = vaQueryConfigEntrypoints(mVaDpy, |
|
|
VAProfileNone, |
|
|
entryPoint, |
|
|
&numEntryPoints); |
|
|
CHECK_VA_STATUS_RETURN("vaQueryConfigEntrypoints"); |
|
|
|
|
|
for (int i = 0; i < numEntryPoints; i++) |
|
|
if (entryPoint[i] == VAEntrypointVideoProc) |
|
|
supportVideoProcessing = true; |
|
|
|
|
|
free(entryPoint); |
|
|
entryPoint = NULL; |
|
|
|
|
|
if (!supportVideoProcessing) { |
|
|
ETRACE("VAEntrypointVideoProc is not supported"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
vaStatus = vaCreateConfig(mVaDpy, |
|
|
VAProfileNone, |
|
|
VAEntrypointVideoProc, |
|
|
&attribDummy, |
|
|
0, |
|
|
&mVaCfg); |
|
|
CHECK_VA_STATUS_RETURN("vaCreateConfig"); |
|
|
|
|
|
// create first target surface |
|
|
ret = createVaSurface(payload, transform, true); |
|
|
if (ret == false) { |
|
|
ETRACE("failed to create target surface with attribute"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
vaStatus = vaCreateContext(mVaDpy, |
|
|
mVaCfg, |
|
|
payload->width, |
|
|
payload->height, |
|
|
0, |
|
|
&mRotatedSurfaces[0], |
|
|
1, |
|
|
&mVaCtx); |
|
|
CHECK_VA_STATUS_RETURN("vaCreateContext"); |
|
|
|
|
|
VAProcFilterType filters[VAProcFilterCount]; |
|
|
unsigned int numFilters = VAProcFilterCount; |
|
|
vaStatus = vaQueryVideoProcFilters(mVaDpy, mVaCtx, filters, &numFilters); |
|
|
CHECK_VA_STATUS_RETURN("vaQueryVideoProcFilters"); |
|
|
|
|
|
bool supportVideoProcFilter = false; |
|
|
for (unsigned int j = 0; j < numFilters; j++) |
|
|
if (filters[j] == VAProcFilterNone) |
|
|
supportVideoProcFilter = true; |
|
|
|
|
|
if (!supportVideoProcFilter) { |
|
|
ETRACE("VAProcFilterNone is not supported"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
VAProcFilterParameterBuffer filter; |
|
|
filter.type = VAProcFilterNone; |
|
|
filter.value = 0; |
|
|
|
|
|
vaStatus = vaCreateBuffer(mVaDpy, |
|
|
mVaCtx, |
|
|
VAProcFilterParameterBufferType, |
|
|
sizeof(filter), |
|
|
1, |
|
|
&filter, |
|
|
&mVaBufFilter); |
|
|
CHECK_VA_STATUS_RETURN("vaCreateBuffer"); |
|
|
|
|
|
VAProcPipelineCaps pipelineCaps; |
|
|
unsigned int numCaps = 1; |
|
|
vaStatus = vaQueryVideoProcPipelineCaps(mVaDpy, |
|
|
mVaCtx, |
|
|
&mVaBufFilter, |
|
|
numCaps, |
|
|
&pipelineCaps); |
|
|
CHECK_VA_STATUS_RETURN("vaQueryVideoProcPipelineCaps"); |
|
|
|
|
|
if (!(pipelineCaps.rotation_flags & (1 << transFromHalToVa(transform)))) { |
|
|
ETRACE("VA_ROTATION_xxx: 0x%08x is not supported by the filter", |
|
|
transFromHalToVa(transform)); |
|
|
return false; |
|
|
} |
|
|
|
|
|
mVaInitialized = true; |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
bool RotationBufferProvider::setupRotationBuffer(VideoPayloadBuffer *payload, int transform) |
|
|
{ |
|
|
#ifdef DEBUG_ROTATION_PERFROMANCE |
|
|
uint32_t setup_Begin = getMilliseconds(); |
|
|
#endif |
|
|
VAStatus vaStatus; |
|
|
int stride; |
|
|
bool ret = false; |
|
|
|
|
|
if (payload->format != VA_FOURCC_NV12 || payload->width == 0 || payload->height == 0) { |
|
|
WTRACE("payload data is not correct: format %#x, width %d, height %d", |
|
|
payload->format, payload->width, payload->height); |
|
|
return ret; |
|
|
} |
|
|
|
|
|
if (payload->width > 1280 && payload->width <= 2048) { |
|
|
payload->tiling = 1; |
|
|
} |
|
|
|
|
|
do { |
|
|
if (isContextChanged(payload->width, payload->height, transform)) { |
|
|
DTRACE("VA is restarted as rotation context changes"); |
|
|
|
|
|
if (mVaInitialized) { |
|
|
stopVA(); // need to re-initialize VA for new rotation config |
|
|
} |
|
|
mTransform = transform; |
|
|
mWidth = payload->width; |
|
|
mHeight = payload->height; |
|
|
} |
|
|
|
|
|
if (!mVaInitialized) { |
|
|
ret = startVA(payload, transform); |
|
|
if (ret == false) { |
|
|
vaStatus = VA_STATUS_ERROR_OPERATION_FAILED; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
// start to create next target surface |
|
|
if (!mRotatedSurfaces[mTargetIndex]) { |
|
|
ret = createVaSurface(payload, transform, true); |
|
|
if (ret == false) { |
|
|
ETRACE("failed to create target surface with attribute"); |
|
|
vaStatus = VA_STATUS_ERROR_OPERATION_FAILED; |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
// create source surface |
|
|
ret = createVaSurface(payload, transform, false); |
|
|
if (ret == false) { |
|
|
ETRACE("failed to create source surface with attribute"); |
|
|
vaStatus = VA_STATUS_ERROR_OPERATION_FAILED; |
|
|
break; |
|
|
} |
|
|
|
|
|
#ifdef DEBUG_ROTATION_PERFROMANCE |
|
|
uint32_t beginPicture = getMilliseconds(); |
|
|
#endif |
|
|
vaStatus = vaBeginPicture(mVaDpy, mVaCtx, mRotatedSurfaces[mTargetIndex]); |
|
|
CHECK_VA_STATUS_BREAK("vaBeginPicture"); |
|
|
|
|
|
VABufferID pipelineBuf; |
|
|
void *p; |
|
|
VAProcPipelineParameterBuffer *pipelineParam; |
|
|
vaStatus = vaCreateBuffer(mVaDpy, |
|
|
mVaCtx, |
|
|
VAProcPipelineParameterBufferType, |
|
|
sizeof(*pipelineParam), |
|
|
1, |
|
|
NULL, |
|
|
&pipelineBuf); |
|
|
CHECK_VA_STATUS_BREAK("vaCreateBuffer"); |
|
|
|
|
|
vaStatus = vaMapBuffer(mVaDpy, pipelineBuf, &p); |
|
|
CHECK_VA_STATUS_BREAK("vaMapBuffer"); |
|
|
|
|
|
pipelineParam = (VAProcPipelineParameterBuffer*)p; |
|
|
pipelineParam->surface = mSourceSurface; |
|
|
pipelineParam->rotation_state = transFromHalToVa(transform); |
|
|
pipelineParam->filters = &mVaBufFilter; |
|
|
pipelineParam->num_filters = 1; |
|
|
pipelineParam->surface_region = NULL; |
|
|
pipelineParam->output_region = NULL; |
|
|
pipelineParam->num_forward_references = 0; |
|
|
pipelineParam->num_backward_references = 0; |
|
|
vaStatus = vaUnmapBuffer(mVaDpy, pipelineBuf); |
|
|
CHECK_VA_STATUS_BREAK("vaUnmapBuffer"); |
|
|
|
|
|
vaStatus = vaRenderPicture(mVaDpy, mVaCtx, &pipelineBuf, 1); |
|
|
CHECK_VA_STATUS_BREAK("vaRenderPicture"); |
|
|
|
|
|
vaStatus = vaEndPicture(mVaDpy, mVaCtx); |
|
|
CHECK_VA_STATUS_BREAK("vaEndPicture"); |
|
|
|
|
|
vaStatus = vaSyncSurface(mVaDpy, mRotatedSurfaces[mTargetIndex]); |
|
|
CHECK_VA_STATUS_BREAK("vaSyncSurface"); |
|
|
|
|
|
#ifdef DEBUG_ROTATION_PERFROMANCE |
|
|
ITRACE("time spent %dms from vaBeginPicture to vaSyncSurface", |
|
|
getMilliseconds() - beginPicture); |
|
|
#endif |
|
|
|
|
|
// Populate payload fields so that overlayPlane can flip the buffer |
|
|
payload->rotated_width = mRotatedStride; |
|
|
payload->rotated_height = mRotatedHeight; |
|
|
payload->rotated_buffer_handle = mKhandles[mTargetIndex]; |
|
|
// setting client transform to 0 to force re-generating rotated buffer whenever needed. |
|
|
payload->client_transform = 0; |
|
|
mTargetIndex++; |
|
|
if (mTargetIndex >= MAX_SURFACE_NUM) |
|
|
mTargetIndex = 0; |
|
|
|
|
|
} while (0); |
|
|
|
|
|
#ifdef DEBUG_ROTATION_PERFROMANCE |
|
|
ITRACE("time spent %dms for setupRotationBuffer", |
|
|
getMilliseconds() - setup_Begin); |
|
|
#endif |
|
|
|
|
|
if (mSourceSurface > 0) { |
|
|
vaStatus = vaDestroySurfaces(mVaDpy, &mSourceSurface, 1); |
|
|
if (vaStatus != VA_STATUS_SUCCESS) |
|
|
WTRACE("vaDestroySurfaces failed, vaStatus = %d", vaStatus); |
|
|
mSourceSurface = 0; |
|
|
} |
|
|
|
|
|
if (vaStatus != VA_STATUS_SUCCESS) { |
|
|
stopVA(); |
|
|
return false; // To not block HWC, just abort instead of retry |
|
|
} |
|
|
|
|
|
if (!payload->khandle) { |
|
|
WTRACE("khandle is reset by decoder, surface is invalid!"); |
|
|
return false; |
|
|
} |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
bool RotationBufferProvider::prepareBufferInfo(int w, int h, int stride, VideoPayloadBuffer *payload, void *user_pt) |
|
|
{ |
|
|
int chroma_offset, size; |
|
|
void *buf = NULL; |
|
|
|
|
|
payload->width = payload->crop_width = w; |
|
|
payload->height = payload->crop_height = h; |
|
|
payload->coded_width = ((w + 0xf) & ~0xf); |
|
|
payload->coded_height = ((h + 0xf) & ~0xf); |
|
|
payload->format = VA_FOURCC_NV12; |
|
|
payload->tiling = 1; |
|
|
payload->luma_stride = stride; |
|
|
payload->chroma_u_stride = stride; |
|
|
payload->chroma_v_stride = stride; |
|
|
payload->client_transform = 0; |
|
|
payload->bob_deinterlace = 0; |
|
|
|
|
|
chroma_offset = stride * h; |
|
|
size = stride * h + stride * h / 2; |
|
|
|
|
|
ssize_t index; |
|
|
index = mTTMWrappers.indexOfKey((uint64_t)user_pt); |
|
|
if (index < 0) { |
|
|
VTRACE("wrapped userPt as wsbm buffer"); |
|
|
bool ret = mWsbm->allocateTTMBufferUB(size, 0, &buf, user_pt); |
|
|
if (ret == false) { |
|
|
ETRACE("failed to allocate TTM buffer"); |
|
|
return ret; |
|
|
} |
|
|
|
|
|
if (mTTMWrappers.size() >= TTM_WRAPPER_COUNT) { |
|
|
WTRACE("mTTMWrappers is unexpectedly full. Invalidate caches"); |
|
|
invalidateCaches(); |
|
|
} |
|
|
|
|
|
index = mTTMWrappers.add((uint64_t)user_pt, buf); |
|
|
} else { |
|
|
VTRACE("got wsbmBuffer in saved caches"); |
|
|
buf = mTTMWrappers.valueAt(index); |
|
|
} |
|
|
|
|
|
payload->khandle = (buffer_handle_t) mWsbm->getKBufHandle(buf); |
|
|
return true; |
|
|
} |
|
|
|
|
|
void RotationBufferProvider::freeVaSurfaces() |
|
|
{ |
|
|
bool ret; |
|
|
VAStatus vaStatus; |
|
|
|
|
|
for (int i = 0; i < MAX_SURFACE_NUM; i++) { |
|
|
if (NULL != mDrmBuf[i]) { |
|
|
ret = mWsbm->destroyTTMBuffer(mDrmBuf[i]); |
|
|
if (!ret) |
|
|
WTRACE("failed to free TTMBuffer"); |
|
|
mDrmBuf[i] = NULL; |
|
|
} |
|
|
} |
|
|
|
|
|
// remove wsbm buffer ref from VA |
|
|
for (int j = 0; j < MAX_SURFACE_NUM; j++) { |
|
|
if (0 != mRotatedSurfaces[j]) { |
|
|
vaStatus = vaDestroySurfaces(mVaDpy, &mRotatedSurfaces[j], 1); |
|
|
if (vaStatus != VA_STATUS_SUCCESS) |
|
|
WTRACE("vaDestroySurfaces failed, vaStatus = %d", vaStatus); |
|
|
} |
|
|
mRotatedSurfaces[j] = 0; |
|
|
} |
|
|
} |
|
|
|
|
|
void RotationBufferProvider::stopVA() |
|
|
{ |
|
|
freeVaSurfaces(); |
|
|
|
|
|
if (0 != mVaBufFilter) |
|
|
vaDestroyBuffer(mVaDpy, mVaBufFilter); |
|
|
if (0 != mVaCfg) |
|
|
vaDestroyConfig(mVaDpy,mVaCfg); |
|
|
if (0 != mVaCtx) |
|
|
vaDestroyContext(mVaDpy, mVaCtx); |
|
|
if (0 != mVaDpy) |
|
|
vaTerminate(mVaDpy); |
|
|
|
|
|
mVaInitialized = false; |
|
|
|
|
|
for (int i = 0; i < MAX_SURFACE_NUM; i++) { |
|
|
mKhandles[i] = 0; |
|
|
mRotatedSurfaces[i] = 0; |
|
|
mDrmBuf[i] = NULL; |
|
|
} |
|
|
// reset VA variable |
|
|
mVaDpy = 0; |
|
|
mVaCfg = 0; |
|
|
mVaCtx = 0; |
|
|
mVaBufFilter = 0; |
|
|
mSourceSurface = 0; |
|
|
|
|
|
mWidth = 0; |
|
|
mHeight = 0; |
|
|
mRotatedWidth = 0; |
|
|
mRotatedHeight = 0; |
|
|
mRotatedStride = 0; |
|
|
mTargetIndex = 0; |
|
|
mBobDeinterlace = 0; |
|
|
} |
|
|
|
|
|
bool RotationBufferProvider::isContextChanged(int width, int height, int transform) |
|
|
{ |
|
|
// check rotation config |
|
|
if (height == mHeight && |
|
|
width == mWidth && |
|
|
transform == mTransform) { |
|
|
return false; |
|
|
} |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
} // name space intel |
|
|
} // name space android
|
|
|
|