blob: 07a3ab4b4e4b0ace79828bf6ee5a89c8eafcf56a [file] [log] [blame]
/*
* Copyright (c) 2017, Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "cm_surface_manager.h"
#include "cm_debug.h"
#include "cm_def.h"
#include "cm_device.h"
#include "cm_mem.h"
int32_t CmSurfaceManager::Surface2DSanityCheck(uint32_t width,
uint32_t height,
CM_SURFACE_FORMAT format)
{
if ((width < CM_MIN_SURF_WIDTH) || (width > CM_MAX_2D_SURF_WIDTH))
{
CmAssert(0);
return CM_INVALID_WIDTH;
}
if ((height < CM_MIN_SURF_HEIGHT) || (height > CM_MAX_2D_SURF_HEIGHT))
{
CmAssert(0);
return CM_INVALID_HEIGHT;
}
switch (format)
{
case CM_SURFACE_FORMAT_X8R8G8B8:
case CM_SURFACE_FORMAT_A8R8G8B8:
case CM_SURFACE_FORMAT_A8B8G8R8:
case CM_SURFACE_FORMAT_R32F:
case CM_SURFACE_FORMAT_A16B16G16R16:
case CM_SURFACE_FORMAT_R10G10B10A2:
case CM_SURFACE_FORMAT_A16B16G16R16F:
case CM_SURFACE_FORMAT_L16:
case CM_SURFACE_FORMAT_D16:
case CM_SURFACE_FORMAT_A8:
case CM_SURFACE_FORMAT_P8:
case CM_SURFACE_FORMAT_V8U8:
case CM_SURFACE_FORMAT_R16_UINT:
case CM_SURFACE_FORMAT_R8_UINT:
case CM_SURFACE_FORMAT_Y216:
case CM_SURFACE_FORMAT_Y416:
case CM_SURFACE_FORMAT_AYUV:
case CM_SURFACE_FORMAT_Y210:
case CM_SURFACE_FORMAT_Y410:
case CM_SURFACE_FORMAT_R32G32B32A32F:
break;
case CM_SURFACE_FORMAT_UYVY:
case CM_SURFACE_FORMAT_YUY2:
if (width & 0x1)
{
CmAssert(0);
return CM_INVALID_WIDTH;
}
break;
case CM_SURFACE_FORMAT_P016:
case CM_SURFACE_FORMAT_P010:
case CM_SURFACE_FORMAT_YV12:
case CM_SURFACE_FORMAT_422H:
case CM_SURFACE_FORMAT_444P:
case CM_SURFACE_FORMAT_422V:
case CM_SURFACE_FORMAT_411P:
case CM_SURFACE_FORMAT_411R:
case CM_SURFACE_FORMAT_RGBP:
case CM_SURFACE_FORMAT_BGRP:
case CM_SURFACE_FORMAT_IMC3:
case CM_SURFACE_FORMAT_P208:
if (width & 0x1)
{
CmAssert(0);
return CM_INVALID_WIDTH;
}
if (height & 0x1)
{
CmAssert(0);
return CM_INVALID_HEIGHT;
}
break;
case CM_SURFACE_FORMAT_NV12:
if (width & 0x1)
{
CmAssert(0);
return CM_INVALID_WIDTH;
}
if (height & 0x1)
{
CmAssert(0);
return CM_INVALID_HEIGHT;
}
break;
default:
CmAssert(0);
return CM_SURFACE_FORMAT_NOT_SUPPORTED;
}
return CM_SUCCESS;
}
int32_t CmSurfaceManager::CreateSurface2D(uint32_t width,
uint32_t height,
CM_SURFACE_FORMAT format,
CmSurface2D *&surface)
{
int32_t result = CM_SUCCESS;
//Sanity check
CHK_RET(Surface2DSanityCheck(width, height, format));
// Passes the reference to CMRT@UMD to create a CmSurface.
CHK_RET(AllocateSurface2DInUmd(width, height, format, true, false, 0, surface));
CHK_NULL(surface);
finish:
if (FAILED(result))
{
surface = nullptr;
}
return result;
}
int32_t CmSurfaceManager::CreateSurface2D(VASurfaceID vaSurface,
CmSurface2D *&surface)
{ // Not created by Cm , but it is created through Libva
return CreateSurface2D(vaSurface, false, true, surface);
}
int32_t CmSurfaceManager::CreateSurface2D(VASurfaceID *vaSurfaceArray,
const uint32_t surfaceCount,
CmSurface2D **surfaceArray)
{
int32_t result = CM_FAILURE;
uint32_t surfIndex = 0;
for (surfIndex = 0; surfIndex < surfaceCount; surfIndex++)
{
CHK_RET(CreateSurface2D(vaSurfaceArray[surfIndex], surfaceArray[surfIndex]));
CHK_NULL(surfaceArray[surfIndex]);
}
finish:
if (result != CM_SUCCESS)
{
for (uint32_t j = 0; j < surfIndex; j++)
{
DestroySurface(surfaceArray[j]);
}
}
return result;
}
int32_t CmSurfaceManager::CreateVaSurface2D(uint32_t width,
uint32_t height,
CM_SURFACE_FORMAT format,
VASurfaceID &vaSurface,
CmSurface2D *&surface)
{
int32_t hr = CM_SUCCESS;
VAStatus vaStatus = VA_STATUS_SUCCESS;
VADisplay *dpy = nullptr;
uint32_t vaFormat = 0;
vaFormat = ConvertToLibvaFormat(format);
//Create Va Surface
m_device->GetVaDpy(dpy);
if(dpy == nullptr)
{
CmAssert(0);
return CM_INVALID_LIBVA_INITIALIZE;
}
// Set attribute for vaCreateSurfaces
VASurfaceAttrib surfaceAttrib;
surfaceAttrib.type = VASurfaceAttribPixelFormat;
surfaceAttrib.value.type = VAGenericValueTypeInteger;
surfaceAttrib.flags = VA_SURFACE_ATTRIB_SETTABLE;
surfaceAttrib.value.value.i = vaFormat;
// since no 10-bit format is supported in MDF,
// the VA_RT_FORMAT_YUV420 will be overwritten
// by the format in attribute
vaStatus = vaCreateSurfaces(*dpy, VA_RT_FORMAT_YUV420, width, height, &vaSurface, 1,
&surfaceAttrib, 1);
if (vaStatus != VA_STATUS_SUCCESS)
{
CmAssert(0);
return CM_VA_SURFACE_NOT_SUPPORTED;
}
//Create Cm Surface
hr = CreateSurface2D(vaSurface, true, true, surface);
if (hr != CM_SUCCESS)
{
CmAssert(0);
vaStatus = vaDestroySurfaces(*dpy, &vaSurface, 1);
return hr;
}
return CM_SUCCESS;
}
int32_t CmSurfaceManager::CreateSurface2D(VASurfaceID &vaSurface,
bool cmCreated,
bool createdbyLibva,
CmSurface2D *&surface)
{
int32_t result = CM_SUCCESS;
//Pass it to CMRT@UMD to create CmSurface
CHK_RET(AllocateSurface2DInUmd(0, 0, (CM_SURFACE_FORMAT)0, cmCreated, createdbyLibva,
vaSurface, surface));
CHK_NULL(surface);
finish:
return result;
}
int32_t CmSurfaceManager::ConvertToLibvaFormat(int32_t format)
{
int32_t vaFmt = format;
switch (format)
{
case VA_CM_FMT_A8R8G8B8:
vaFmt = VA_FOURCC_ARGB;
break;
default:
vaFmt = format;
break;
}
return vaFmt;
}
int32_t CmSurfaceManager::AllocateSurface2DInUmd(uint32_t width,
uint32_t height,
CM_SURFACE_FORMAT format,
bool cmCreated,
bool createdbyLibva,
VASurfaceID vaSurface,
CmSurface2D *&surface)
{
VADisplay *display = nullptr;
m_device->GetVaDpy(display);
CM_CREATESURFACE2D_PARAM inParam;
CmSafeMemSet(&inParam, 0, sizeof(CM_CREATESURFACE2D_PARAM));
inParam.width = width;
inParam.height = height;
inParam.format = format;
inParam.isCmCreated = cmCreated;
inParam.isLibvaCreated = createdbyLibva;
inParam.vaSurfaceID = vaSurface;
inParam.vaDpy = display;
int32_t hr = m_device->OSALExtensionExecute(CM_FN_CMDEVICE_CREATESURFACE2D,
&inParam, sizeof(inParam),
nullptr, 0);
CHK_FAILURE_RETURN(hr);
CHK_FAILURE_RETURN(inParam.returnValue);
surface = (CmSurface2D *)inParam.cmSurface2DHandle;
return hr;
}