/* * 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; }