blob: 49f13b01c6decde6ac739e8ed48e438b8a2feb64 [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.
*/
//!
//! \file cm_surface_2d_rt.cpp
//! \brief Contains OS-agnostic CmSurface2DRTBase member functions
//!
#include "cm_surface_2d_rt.h"
#include "cm_event_rt.h"
#include "cm_surface_manager.h"
#include "cm_device_rt.h"
#include "cm_mem.h"
#include "cm_queue_rt.h"
#include "cm_wrapper_os.h"
#define COPY_OPTION(option) (option & 0x1)
namespace CMRT_UMD
{
//*-----------------------------------------------------------------------------
//| Purpose: Constructor of CmSurface2DBase
//| Returns: None.
//*-----------------------------------------------------------------------------
CmSurface2DRTBase::CmSurface2DRTBase(
uint32_t handle,
uint32_t width,
uint32_t height,
uint32_t pitch,
CM_SURFACE_FORMAT format,
CmSurfaceManager* pSurfaceManager,
bool isCmCreated) :
CmSurface(pSurfaceManager, isCmCreated),
m_width(width),
m_height(height),
m_handle(handle),
m_pitch(pitch),
m_format(format),
m_umdResource(nullptr),
m_numAliases(0),
m_frameType(CM_FRAME)
{
CmSurface::SetMemoryObjectControl(MEMORY_OBJECT_CONTROL_UNKNOW, CM_USE_PTE, 0);
CmSafeMemSet(m_aliasIndexes, 0, sizeof(SurfaceIndex*) * CM_HAL_MAX_NUM_2D_ALIASES);
}
//*-----------------------------------------------------------------------------
//| Purpose: Destructor of CmSurface2DRTBase
//| Returns: None.
//*-----------------------------------------------------------------------------
CmSurface2DRTBase::~CmSurface2DRTBase(void){}
//*-----------------------------------------------------------------------------
//| Purpose: Initialize CmSurface2D
//| Returns: Result of the operation.
//*-----------------------------------------------------------------------------
int32_t CmSurface2DRTBase::Initialize( uint32_t index )
{
return CmSurface::Initialize( index );
}
bool CmSurface2DRTBase::IsGPUCopy(void *sysMem, uint32_t widthInBytes, uint32_t height, uint32_t horizontalStrideInBytes)
{
return ( (widthInBytes <= CM_MAX_THREADSPACE_WIDTH_FOR_MW*128) && (height <= CM_MAX_THREADSPACE_HEIGHT_FOR_MW*32) && (uintptr_t(sysMem) & 0xF) == 0 && (horizontalStrideInBytes & 0xF) == 0 );
}
bool CmSurface2DRTBase::IsUnalignedGPUCopy(uint32_t widthInBytes, uint32_t height)
{
return (widthInBytes <= CM_MAX_THREADSPACE_WIDTH_FOR_MW*64) && (height <= CM_MAX_THREADSPACE_HEIGHT_FOR_MW*8);
}
//*-----------------------------------------------------------------------------
//| Purpose: Get planar memory layout information details
//| Returns: Result of the operation.
//*-----------------------------------------------------------------------------
int32_t GetPlanarInfomation(CM_HAL_SURFACE2D_LOCK_UNLOCK_PARAM inParam, uint32_t& sizePerPixel, uint32_t& UVwidth, uint32_t& UVheight, uint32_t& UVpitch, uint32_t& planes)
{
//default single plane format UVheight = 0
UVheight = 0;
UVpitch = 0;
UVwidth = 0;
planes = 1;
switch (inParam.format)
{
case CM_SURFACE_FORMAT_R32G32B32A32F:
sizePerPixel = 16;
break;
case CM_SURFACE_FORMAT_A16B16G16R16:
case CM_SURFACE_FORMAT_A16B16G16R16F:
case CM_SURFACE_FORMAT_Y416:
case CM_SURFACE_FORMAT_D32F_S8X24_UINT:
case CM_SURFACE_FORMAT_R32G8X24_TYPELESS:
sizePerPixel = 8;
break;
case CM_SURFACE_FORMAT_X8R8G8B8:
case CM_SURFACE_FORMAT_A8R8G8B8:
case CM_SURFACE_FORMAT_A8B8G8R8:
case CM_SURFACE_FORMAT_R32F:
case CM_SURFACE_FORMAT_D32F:
case CM_SURFACE_FORMAT_R32_UINT:
case CM_SURFACE_FORMAT_R32_SINT:
case CM_SURFACE_FORMAT_R10G10B10A2:
case CM_SURFACE_FORMAT_AYUV:
case CM_SURFACE_FORMAT_R16G16_UNORM:
case CM_SURFACE_FORMAT_Y410:
case CM_SURFACE_FORMAT_Y216:
case CM_SURFACE_FORMAT_Y210:
case CM_SURFACE_FORMAT_D24_UNORM_S8_UINT:
case CM_SURFACE_FORMAT_R32_TYPELESS:
case CM_SURFACE_FORMAT_R24G8_TYPELESS:
case CM_SURFACE_FORMAT_R16G16_SINT:
sizePerPixel = 4;
break;
case CM_SURFACE_FORMAT_R8G8_SNORM:
case CM_SURFACE_FORMAT_R16_UINT:
case CM_SURFACE_FORMAT_R16_SINT:
case CM_SURFACE_FORMAT_R16_UNORM:
case CM_SURFACE_FORMAT_D16:
case CM_SURFACE_FORMAT_L16:
case CM_SURFACE_FORMAT_R8G8_UNORM:
case CM_SURFACE_FORMAT_UYVY:
case CM_SURFACE_FORMAT_VYUY:
case CM_SURFACE_FORMAT_YUY2:
case CM_SURFACE_FORMAT_Y16_SNORM:
case CM_SURFACE_FORMAT_Y16_UNORM:
case CM_SURFACE_FORMAT_IRW0:
case CM_SURFACE_FORMAT_IRW1:
case CM_SURFACE_FORMAT_IRW2:
case CM_SURFACE_FORMAT_IRW3:
case CM_SURFACE_FORMAT_R16_FLOAT:
case CM_SURFACE_FORMAT_V8U8:
case CM_SURFACE_FORMAT_A8P8:
case CM_SURFACE_FORMAT_R16_TYPELESS:
sizePerPixel = 2;
break;
case CM_SURFACE_FORMAT_A8:
case CM_SURFACE_FORMAT_P8:
case CM_SURFACE_FORMAT_R8_UINT:
case CM_SURFACE_FORMAT_Y8_UNORM:
case CM_SURFACE_FORMAT_L8:
case CM_SURFACE_FORMAT_IA44:
case CM_SURFACE_FORMAT_AI44:
case CM_SURFACE_FORMAT_400P:
case CM_SURFACE_FORMAT_BUFFER_2D:
case CM_SURFACE_FORMAT_R8_UNORM:
sizePerPixel = 1;
break;
// 2 planes
//_________________________
//|Y0|Y1| |
//|__|__| |
//| |
//| |
//| |
//| |
//| |
//|________________________|
//|U0|V0| |
//|__|__| |
//| |
//|________________________|
case CM_SURFACE_FORMAT_P016:
case CM_SURFACE_FORMAT_P010:
sizePerPixel = 2;
UVheight = (inParam.height + 1) / 2;
UVpitch = inParam.pitch;
UVwidth = inParam.width;
planes = 2;
break;
case CM_SURFACE_FORMAT_NV12: //NV12
sizePerPixel = 1;
//To support NV12 format with odd height here.
//if original height is even, the UV plane's height is set as updatedHeight/2, which equals to (updatedHeight+1)/2
//if original height is odd, the UV plane's height is set as roundup(updatedHeight/2), which equals to (updatedHeight+1)/2 too
UVheight = (inParam.height + 1) / 2;
UVpitch = inParam.pitch;
UVwidth = inParam.width;
planes = 2;
break;
case CM_SURFACE_FORMAT_P208:
sizePerPixel = 1;
UVheight = inParam.height;
UVpitch = inParam.pitch;
UVwidth = inParam.width;
planes = 2;
break;
// 3 planes
// 4:1:1 (12-bits per pixel) // 4:2:2 (16-bits per pixel)
// 411P // 422H
// -----------------> // ----------------->
// ________________________ // ________________________
//|Y0|Y1| | //|Y0|Y1| |
//|__|__| | //|__|__| |
//| | //| |
//| | //| |
//| | //| |
//| | //| |
//| | //| |
//|________________________| //|________________________|
//|U0|U1|| | //|U0|U1| | |
//|__|__|| | //|__|__| | |
//| | | //| | |
//| | PAD | //| | PAD |
//| | | //| | |
//| | | //| | |
//| | | //| | |
//|______|_________________| //|____________|___________|
//|V0|V1|| | //|V0|V1| | |
//|__|__|| | //|__|__| | |
//| | | //| | |
//| | PAD | //| | PAD |
//| | | //| | |
//| | | //| | |
//| | | //| | |
//|______|_________________| //|____________|___________|
// 4:4:4 (24-bits per pixel)
// 444P
// ----------------->
// ________________________
//|Y0|Y1| |
//|__|__| |
//| |
//| |
//| |
//| |
//| |
//|________________________|
//|U0|U1| |
//|__|__| |
//| |
//| |
//| |
//| |
//| |
//|________________________|
//|V0|V1| |
//|__|__| |
//| |
//| |
//| |
//| |
//| |
//|________________________|
case CM_SURFACE_FORMAT_411P:
case CM_SURFACE_FORMAT_422H:
case CM_SURFACE_FORMAT_444P:
case CM_SURFACE_FORMAT_RGBP:
case CM_SURFACE_FORMAT_BGRP:
sizePerPixel = 1;
UVheight = inParam.height;
UVpitch = inParam.pitch;
UVwidth = inParam.width;
planes = 3;
break;
// 4:2:0 (12-bits per pixel)
// IMC1 // IMC3
// -----------------> // ----------------->
// ________________________ // ________________________
//|Y0|Y1| | //|Y0|Y1| |
//|__|__| | //|__|__| |
//| | //| |
//| | //| |
//| | //| |
//| | //| |
//| | //| |
//|________________________| //|________________________|
//|V0|V1| | | //|U0|U1| | |
//|__|__| | | //|__|__| | |
//| | | //| | |
//|____________| PAD | //|____________| PAD |
//|U0|U1| | | //|V0|V1| | |
//|__|__| | | //|__|__| | |
//| | | //| | |
//|____________|___________| //|____________|___________|
case CM_SURFACE_FORMAT_IMC3:
sizePerPixel = 1;
UVheight = (inParam.height + 1) / 2;
UVpitch = inParam.pitch;
UVwidth = inParam.width;
planes = 3;
break;
// 4:2:2V (16-bits per pixel)
// 422V
// ----------------->
// ________________________
//|Y0|Y1| |
//|__|__| |
//| |
//| |
//| |
//| |
//| |
//|________________________|
//|U0|U1| |
//|__|__| |
//| |
//|________________________|
//|V0|V1| |
//|__|__| |
//| |
//|________________________|
case CM_SURFACE_FORMAT_422V:
sizePerPixel = 1;
UVheight = (inParam.height + 1) / 2;
UVpitch = inParam.pitch;
UVwidth = inParam.width;
planes = 3;
break;
// 4:2:0 (12-bits per pixel)
// I420
// ----------------->
// ________________________
//|Y0|Y1| |
//|__|__| |
//| |
//| |
//| |
//| |
//| |
//|________________________|
//|U0|U1| |
//|__|__| |
//| |
//|____________|
//|V0|V1| |
//|__|__| |
//| |
//|____________|
case CM_SURFACE_FORMAT_YV12:
case CM_SURFACE_FORMAT_I420: //I420
sizePerPixel = 1;
UVheight = (inParam.height + 1) / 2;
UVpitch = inParam.pitch / 2;
UVwidth = inParam.width / 2;
planes = 3;
break;
case CM_SURFACE_FORMAT_411R://411R
sizePerPixel = 1;
UVheight = inParam.height;
UVpitch = inParam.pitch / 4;
UVwidth = inParam.width / 4;
planes = 3;
break;
default:
CM_ASSERTMESSAGE("Error: Unsupported surface format.");
return CM_SURFACE_FORMAT_NOT_SUPPORTED;
}
return CM_SUCCESS;
}
//*-----------------------------------------------------------------------------
//| Purpose: Get the index of CmSurface2D
//| Returns: Result of the operation.
//*-----------------------------------------------------------------------------
CM_RT_API int32_t CmSurface2DRTBase::GetIndex(SurfaceIndex*& index)
{
index = m_index;
return CM_SUCCESS;
}
CM_RT_API int32_t CmSurface2DRTBase::SetCompressionMode(MEMCOMP_STATE mmcMode)
{
INSERT_API_CALL_LOG();
CM_RETURN_CODE hr = CM_SUCCESS;
CM_HAL_SURFACE2D_COMPRESSIOM_PARAM mmcModeParam;
CmDeviceRT * cmDevice = nullptr;
m_surfaceMgr->GetCmDevice(cmDevice);
CM_ASSERT(cmDevice);
mmcModeParam.handle = m_handle;
mmcModeParam.mmcMode = mmcMode;
PCM_CONTEXT_DATA cmData = (PCM_CONTEXT_DATA)cmDevice->GetAccelData();
CM_ASSERT(cmData);
CM_CHK_NULL_RETURN_CMERROR(cmData->cmHalState);
CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnSetCompressionMode(cmData->cmHalState, mmcModeParam));
++ m_propertyIndex;
finish:
return hr;
}
//*-----------------------------------------------------------------------------
//| Purpose: Write data from system memory to Surface 2D to with stride
//| It clips larger picture frame content into smaller gfx surface size
//| horizontalStride >= surface width * sizePerPixel
//| verticalStride >= surface height
//| Arguments :
//| sysMem [in] Pointer to system memory
//| event [in] Pointer to CmEvent
//| horizontalStride [in] Stride in system memory in bytes
//| verticalStride[in] Height Stride in system memory in rows
//| sysMemSize [out] Size of Memory need to read
//|
//| Returns: Result of the operation.
//*-----------------------------------------------------------------------------
CM_RT_API int32_t CmSurface2DRTBase::WriteSurfaceFullStride(
const unsigned char* sysMem, CmEvent* event, const uint32_t horizontalStride,
const uint32_t verticalStride, uint64_t sysMemSize)
{
INSERT_API_CALL_LOG();
CM_RETURN_CODE hr = CM_SUCCESS;
uint8_t *dst = nullptr;
uint8_t *src = nullptr;
uint32_t sizePerPixel = 0;
uint32_t updatedHeight = 0;
uint32_t widthInByte = 0;
uint32_t pitch = 0;
uint32_t row = 0;
uint32_t UVHeight = 0;
uint32_t UVpitch = 0;
uint32_t UVwidth = 0;
uint32_t planeHeight = 0;
uint32_t planes = 0;
uint32_t offset0 = 0;
uint32_t offset1 = 0;
uint32_t offset2 = 0;
uint32_t offsetn = 0;
uint32_t tmp = 0;
UNUSED(sysMemSize);
if (sysMem == nullptr)
{
CM_ASSERTMESSAGE("Error: Pointer to system memory is null.")
return CM_INVALID_ARG_VALUE;
}
if (event)
{
CmEventRT *eventRT = dynamic_cast<CmEventRT *>(event);
if (eventRT)
{
FlushDeviceQueue(eventRT);
}
else
{
event->WaitForTaskFinished();
}
}
WaitForReferenceFree(); // wait all owner task finished
CmDeviceRT * cmDevice = nullptr;
m_surfaceMgr->GetCmDevice(cmDevice);
CM_CHK_NULL_RETURN_CMERROR(cmDevice);
uint32_t platform = 0;
cmDevice->GetGenPlatform(platform);
//Lock for surface read/write
CSync* surfaceLock = cmDevice->GetSurfaceLock();
CM_ASSERT(surfaceLock);
CLock locker(*surfaceLock);
PCM_CONTEXT_DATA cmData = (PCM_CONTEXT_DATA)cmDevice->GetAccelData();
CM_CHK_NULL_RETURN_CMERROR(cmData);
CM_CHK_NULL_RETURN_CMERROR(cmData->cmHalState);
CM_HAL_SURFACE2D_LOCK_UNLOCK_PARAM inParam;
CmSafeMemSet(&inParam, 0, sizeof(CM_HAL_SURFACE2D_LOCK_UNLOCK_PARAM));
inParam.width = m_width;
inParam.height = m_height;
inParam.handle = m_handle;
inParam.lockFlag = CM_HAL_LOCKFLAG_WRITEONLY;
inParam.useGmmOffset = true;
// Lock Surface Resource
CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnLock2DResource(cmData->cmHalState, &inParam));
CM_CHK_NULL_GOTOFINISH_CMERROR(inParam.data);
//make sure format is set correctly
inParam.format = m_format;
// Get planar memory layout information according to the format
CM_CHK_CMSTATUS_GOTOFINISH(GetPlanarInfomation(inParam, sizePerPixel, UVwidth, UVHeight, UVpitch, planes));
// Write copy surface content data
widthInByte = m_width * sizePerPixel;
pitch = m_pitch;
planeHeight = inParam.height;
// convert gmmlib plane offset to linear offset
offset0 = inParam.YSurfaceOffset.iSurfaceOffset + (inParam.YSurfaceOffset.iXOffset * sizePerPixel) + (inParam.YSurfaceOffset.iYOffset * pitch);
offset1 = inParam.USurfaceOffset.iSurfaceOffset + (inParam.USurfaceOffset.iXOffset * sizePerPixel) + (inParam.USurfaceOffset.iYOffset * UVpitch);
offset2 = inParam.VSurfaceOffset.iSurfaceOffset + (inParam.VSurfaceOffset.iXOffset * sizePerPixel) + (inParam.VSurfaceOffset.iYOffset * UVpitch);
tmp = offset1;
if (offset1 > offset2)
{
offset1 = offset2;
offset2 = tmp;
// some VSurfaceOffset.iSurfaceOffset could be 0 from gmm resource info
if (offset1 == 0)
offset1 = offset2;
}
// write copy Y plane or single plane format
dst = (uint8_t *)(inParam.data);
src = (uint8_t *)sysMem;
if ((pitch > widthInByte) || (horizontalStride != pitch))
{
// scan line copy
for (row = 0; row < planeHeight; row++)
{
CmFastMemCopyWC(dst, src, widthInByte);
src += horizontalStride;
dst += pitch;
}
}
else
{ // block copy
CmFastMemCopyWC(dst, src, widthInByte * planeHeight);
}
if (UVHeight > 0)
{
// Write copy 2nd plane
if (planes > 1)
{
offsetn = offset1;
// Limit the Gmm offset usage to after Gen11
if ((platform <= IGFX_GEN11LP_CORE) || !inParam.useGmmOffset)
{
offsetn = (planeHeight * pitch);
}
dst = (uint8_t *)(inParam.data) + offsetn;
src = (uint8_t *)sysMem + horizontalStride * verticalStride;
for (row = 0; row < UVHeight; row++)
{
CmFastMemCopyWC(dst, src, UVwidth * sizePerPixel);
src += horizontalStride * UVwidth / m_width;
dst += UVpitch;
}
}
// Write copy 3rd plane
if (planes > 2)
{
offsetn = offset2;
// Limit the Gmm offset usage to after Gen11
if ((platform <= IGFX_GEN11LP_CORE) || !inParam.useGmmOffset)
{
offsetn = (planeHeight * pitch) + (UVHeight * UVpitch);
}
dst = (uint8_t *)(inParam.data) + offsetn;
// calculate system memory frame buffer UV plain width and height with ratio of video surface UV plane vs Y plane
// UVwidth / m_width is horizontal ratio; UVHeight / m_height is vertical ratio
// system memory frame buffer 3rd plane offset is Y plane size + 2nd Plane size
src = (uint8_t *)sysMem + (horizontalStride * verticalStride) +
(horizontalStride * UVwidth / m_width * verticalStride * UVHeight / m_height);
for (row = 0; row < UVHeight; row++)
{
CmFastMemCopyWC(dst, src, UVwidth * sizePerPixel);
src += horizontalStride * UVwidth / m_width;
dst += UVpitch;
}
}
}
//Unlock Surface2D
inParam.data = nullptr;
CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnUnlock2DResource(cmData->cmHalState, &inParam));
finish:
return hr;
}
//*-----------------------------------------------------------------------------
//| Purpose: Write data from system memory to Surface 2D to with stride
//| It clips larger picture frame content into smaller gfx surface size
//| horizontalStride >= surface width * sizePerPixel
//| verticalStride == surface height
//| Arguments :
//| sysMem [in] Pointer to system memory
//| event [in] Pointer to CmEvent
//| Stride [in] Stride in system memory in bytes
//| sysMemSize [out] Size of Memory need to read
//|
//| Returns: Result of the operation.
//*-----------------------------------------------------------------------------
CM_RT_API int32_t CmSurface2DRTBase::WriteSurfaceStride(const unsigned char* sysMem, CmEvent* event, const uint32_t stride, uint64_t sysMemSize)
{
INSERT_API_CALL_LOG();
return WriteSurfaceFullStride(sysMem, event, stride, m_height, sysMemSize);
}
//*-----------------------------------------------------------------------------
//| Purpose: Write data from system memory to Surface 2D
//| picture frame content size equals gfx surface size
//| Arguments :
//| sysMem [in] Pointer to system memory
//| event [in] Pointer to CmEvent
//| sysMemSize [out] Size of Memory need to write
//|
//| Returns: Result of the operation.
//*-----------------------------------------------------------------------------
CM_RT_API int32_t CmSurface2DRTBase::WriteSurface(const unsigned char* sysMem, CmEvent* event, uint64_t sysMemSize)
{
INSERT_API_CALL_LOG();
uint32_t sizePerPixel = 0;
uint32_t UVHeight = 0;
uint32_t UVpitch = 0;
uint32_t UVwidth = 0;
uint32_t planes = 0;
CM_HAL_SURFACE2D_LOCK_UNLOCK_PARAM inParam;
CmSafeMemSet(&inParam, 0, sizeof(CM_HAL_SURFACE2D_LOCK_UNLOCK_PARAM));
inParam.width = m_width;
inParam.height = m_height;
inParam.format = m_format;
// Get planar memory layout information according to the format
GetPlanarInfomation(inParam, sizePerPixel, UVwidth, UVHeight, UVpitch, planes);
return WriteSurfaceFullStride(sysMem, event, sizePerPixel * m_width, m_height, sysMemSize);
}
//*-----------------------------------------------------------------------------
//| Purpose: Hybrid memory copy from system memory to Surface 2D to with stride
//| Arguments :
//| sysMem [in] Pointer to system memory
//| event [in] Pointer to CmEvent
//| horizontalStride [in] Stride in system memory in bytes
//| verticalStride[in] Height Stride in system memory in rows
//| sysMemSize [in] Size of Memory need to read
//| option [in] Option to disable/enable hybrid memory copy
//| Returns: Result of the operation.
//*-----------------------------------------------------------------------------
CM_RT_API int32_t CmSurface2DRTBase::WriteSurfaceHybridStrides( const unsigned char* sysMem, CmEvent* event, const uint32_t horizontalStride, const uint32_t verticalStride, uint64_t sysMemSize, uint32_t option )
{
INSERT_API_CALL_LOG();
int32_t hr = CM_SUCCESS;
uint32_t sizePerPixel = 0;
uint32_t updatedHeight = 0;
uint32_t widthInBytes = 0;
CmQueue *cmQueue = nullptr;
CmDeviceRT *cmDevice = nullptr;
CmQueueRT *cmQueueRT = nullptr;
bool forceCPUCopy = COPY_OPTION(option);
CM_STATUS status;
m_surfaceMgr->GetCmDevice(cmDevice);
CM_CHK_NULL_RETURN_CMERROR(cmDevice);
int32_t result = m_surfaceMgr->GetPixelBytesAndHeight(m_width, m_height, m_format, sizePerPixel, updatedHeight);
if (result != CM_SUCCESS)
{
CM_ASSERTMESSAGE("Error: Failed to get correct surface info.")
return result;
}
widthInBytes = m_width * sizePerPixel;
WaitForReferenceFree(); // wait all owner task finished
if (forceCPUCopy)
{
CM_CHK_CMSTATUS_GOTOFINISH(WriteSurfaceFullStride(sysMem, event, horizontalStride, verticalStride, sysMemSize));
}
else
{
CM_CHK_CMSTATUS_GOTOFINISH(cmDevice->CreateQueue(cmQueue));
if(IsGPUCopy((void*)sysMem, widthInBytes, m_height, horizontalStride))
{
CmEvent *tempEvent = CM_NO_EVENT;
CM_CHK_CMSTATUS_GOTOFINISH(cmQueue->EnqueueCopyCPUToGPUFullStride(this, sysMem, horizontalStride, verticalStride, CM_FASTCOPY_OPTION_BLOCKING, tempEvent));
}
else if (IsUnalignedGPUCopy(widthInBytes, m_height))
{
cmQueueRT = static_cast<CmQueueRT *>(cmQueue);
CmSurface2DRT * cmSurface2DRT = dynamic_cast<CmSurface2DRT *>(this);
CM_CHK_NULL_RETURN_CMERROR(cmSurface2DRT);
CM_CHK_CMSTATUS_GOTOFINISH(cmQueueRT->EnqueueUnalignedCopyInternal(cmSurface2DRT, (unsigned char*)sysMem, horizontalStride, verticalStride, CM_FASTCOPY_CPU2GPU));
}
else
{
CM_CHK_CMSTATUS_GOTOFINISH(WriteSurfaceFullStride(sysMem, event, horizontalStride, verticalStride, sysMemSize));
}
}
finish:
return hr;
}
//*-----------------------------------------------------------------------------
//| Purpose: Read data from Surface 2D to system memory with stride
//| It copies smaller gfx surface content into larger system memory picture frame
//| horizontalStride >= surface width * sizePerPixel
//| verticalStride == surface height
//| Arguments :
//| sysMem [in] Pointer to system memory
//| event [in] Pointer to CmEvent
//| Stride [in] Stride in system memory in bytes
//| sysMemSize [out] Size of Memory need to read
//|
//| Returns: Result of the operation.
//*-----------------------------------------------------------------------------
CM_RT_API int32_t CmSurface2DRTBase::ReadSurfaceStride( unsigned char* sysMem, CmEvent* event, const uint32_t stride, uint64_t sysMemSize )
{
INSERT_API_CALL_LOG();
return ReadSurfaceFullStride(sysMem, event, stride, m_height, sysMemSize);
}
//*-----------------------------------------------------------------------------
//| Purpose: Read data from Surface 2D to system memory with stride
//| It copies smaller gfx surface content into larger system memory picture frame
//| horizontalStride >= surface width * sizePerPixel
//| verticalStride >= surface height
//| Arguments :
//| sysMem [in] Pointer to system memory
//| event [in] Pointer to CmEvent
//| horizontalStride [in] Width Stride in system memory in bytes
//| verticalStride[in] Height Stride in system memory in rows
//| sysMemSize [out] Size of Memory need to read
//|
//| Returns: Result of the operation.
//*-----------------------------------------------------------------------------
CM_RT_API int32_t CmSurface2DRTBase::ReadSurfaceFullStride( unsigned char* sysMem, CmEvent* event,
const uint32_t horizontalStride, const uint32_t verticalStride, uint64_t sysMemSize )
{
INSERT_API_CALL_LOG();
CM_RETURN_CODE hr = CM_SUCCESS;
uint8_t *dst = nullptr;
uint8_t *src = nullptr;
uint32_t sizePerPixel = 0;
uint32_t UVHeight = 0;
uint32_t UVwidth = 0;
uint32_t UVpitch = 0;
uint32_t updatedHeight = 0;
uint32_t widthInByte = 0;
uint32_t pitch = 0;
uint32_t row = 0;
uint32_t planeHeight = 0;
uint32_t planes = 0;
uint32_t offset0 = 0;
uint32_t offset1 = 0;
uint32_t offset2 = 0;
uint32_t tmp = 0;
UNUSED(sysMemSize);
if (sysMem == nullptr)
{
CM_ASSERTMESSAGE("Error: Pointer to system memory is null.")
return CM_INVALID_ARG_VALUE;
}
if (event)
{
CmEventRT *eventRT = dynamic_cast<CmEventRT *>(event);
if (eventRT)
{
FlushDeviceQueue(eventRT);
}
else
{
event->WaitForTaskFinished();
}
}
WaitForReferenceFree(); // wait all owner task finished
CmDeviceRT * cmDevice = nullptr;
m_surfaceMgr->GetCmDevice(cmDevice);
CM_CHK_NULL_RETURN_CMERROR(cmDevice);
uint32_t platform = 0;
cmDevice->GetGenPlatform(platform);
//Lock for surface read/write
CSync* surfaceLock = cmDevice->GetSurfaceLock();
CM_ASSERT(surfaceLock);
CLock locker(*surfaceLock);
PCM_CONTEXT_DATA cmData = (PCM_CONTEXT_DATA)cmDevice->GetAccelData();
CM_CHK_NULL_RETURN_CMERROR(cmData);
CM_CHK_NULL_RETURN_CMERROR(cmData->cmHalState);
CM_HAL_SURFACE2D_LOCK_UNLOCK_PARAM inParam;
CmSafeMemSet(&inParam, 0, sizeof(CM_HAL_SURFACE2D_LOCK_UNLOCK_PARAM));
inParam.width = m_width;
inParam.height = m_height;
inParam.handle = m_handle;
inParam.lockFlag = CM_HAL_LOCKFLAG_READONLY;
inParam.useGmmOffset = true;
// Lock Surface Resource
CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnLock2DResource(cmData->cmHalState, &inParam));
CM_CHK_NULL_GOTOFINISH_CMERROR(inParam.data);
//make sure format is set correctly
inParam.format = m_format;
// Get planar memory layout information according to the format
CM_CHK_CMSTATUS_GOTOFINISH(GetPlanarInfomation(inParam, sizePerPixel, UVwidth, UVHeight, UVpitch, planes));
// Read copy surface content data
widthInByte = m_width * sizePerPixel;
pitch = m_pitch;
planeHeight = inParam.height;
// convert gmmlib plane offset to linear offset
offset0 = inParam.YSurfaceOffset.iSurfaceOffset + (inParam.YSurfaceOffset.iXOffset * sizePerPixel) + (inParam.YSurfaceOffset.iYOffset * pitch);
offset1 = inParam.USurfaceOffset.iSurfaceOffset + (inParam.USurfaceOffset.iXOffset * sizePerPixel) + (inParam.USurfaceOffset.iYOffset * UVpitch);
offset2 = inParam.VSurfaceOffset.iSurfaceOffset + (inParam.VSurfaceOffset.iXOffset * sizePerPixel) + (inParam.VSurfaceOffset.iYOffset * UVpitch);
tmp = offset1;
if (offset1 > offset2)
{
offset1 = offset2;
offset2 = tmp;
if (offset1 == 0)
offset1 = offset2;
}
dst = (uint8_t *)sysMem;
src = (uint8_t *)(inParam.data);
// Read copy Y plane
if ((pitch > widthInByte) || (horizontalStride != pitch))
{
// scan line copy
for (row = 0; row < planeHeight; row++)
{
CmFastMemCopyFromWC(dst, src, widthInByte, GetCpuInstructionLevel());
dst += horizontalStride;
src += pitch;
}
}
else
{ // block copy
CmFastMemCopyFromWC(dst, src, pitch * planeHeight, GetCpuInstructionLevel());
}
// Read copy 2nd plane
if (UVHeight > 0)
{
if (planes > 1)
{
int offsetn = offset1;
// Limit the Gmm offset usage to after Gen11
if ((platform <= IGFX_GEN11LP_CORE) || !inParam.useGmmOffset)
{
offsetn = planeHeight * pitch;
}
src = (uint8_t *)(inParam.data) + offsetn;
dst = (uint8_t *)sysMem + (horizontalStride * verticalStride);
for (row = 0; row < UVHeight; row++)
{
CmFastMemCopyFromWC(dst, src, UVwidth * sizePerPixel, GetCpuInstructionLevel());
dst += horizontalStride * UVwidth / m_width;
src += UVpitch;
}
}
// Read copy 3rd plane
if (planes > 2)
{
int offsetn = offset2;
// Limit the Gmm offset usage to after Gen11
if ((platform <= IGFX_GEN11LP_CORE) || !inParam.useGmmOffset)
{
offsetn = (planeHeight * pitch) + (UVHeight * UVpitch);
}
src = (uint8_t *)(inParam.data) + offsetn;
// calculate system memory frame buffer UV plain width and height with ratio of video surface UV plane vs Y plane
// UVwidth / m_width is horizontal ratio; UVHeight / m_height is vertical ratio
// system memory frame buffer 3rd plane offset is Y plane size + 2nd Plane size
dst = (uint8_t *)sysMem + (horizontalStride * verticalStride) +
(horizontalStride * UVwidth / m_width * verticalStride * UVHeight / m_height);
for (row = 0; row < UVHeight; row++)
{
CmFastMemCopyFromWC(dst, src, UVwidth * sizePerPixel, GetCpuInstructionLevel());
dst += horizontalStride * UVwidth / m_width;
src += UVpitch;
}
}
}
//Unlock
inParam.data = nullptr;
CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnUnlock2DResource(cmData->cmHalState, &inParam));
finish:
return hr;
}
//*-----------------------------------------------------------------------------
//| Purpose: Read data from Surface 2D to system memory
//| Arguments :
//| sysMem [in] Pointer to system memory
//| event [in] Pointer to CmEvent
//| sysMemSize [out] Size of Memory need to read
//|
//| Returns: Result of the operation.
//*-----------------------------------------------------------------------------
CM_RT_API int32_t CmSurface2DRTBase::ReadSurface(unsigned char* sysMem, CmEvent* event, uint64_t sysMemSize)
{
INSERT_API_CALL_LOG();
uint32_t sizePerPixel = 0;
uint32_t UVHeight = 0;
uint32_t UVpitch = 0;
uint32_t UVwidth = 0;
uint32_t planes = 0;
CM_HAL_SURFACE2D_LOCK_UNLOCK_PARAM inParam;
CmSafeMemSet(&inParam, 0, sizeof(CM_HAL_SURFACE2D_LOCK_UNLOCK_PARAM));
inParam.width = m_width;
inParam.height = m_height;
inParam.format = m_format;
// Get planar memory layout information according to the format
GetPlanarInfomation(inParam, sizePerPixel, UVwidth, UVHeight, UVpitch, planes);
return ReadSurfaceFullStride(sysMem, event, sizePerPixel * m_width, m_height, sysMemSize);
}
//*-----------------------------------------------------------------------------
//| Purpose: Hybrid memory copy from Surface 2D to system memory with stride
//| Arguments :
//| sysMem [out] Pointer to system memory
//| event [in] Pointer to CmEvent
//| horizontalStride [in] Width Stride in system memory in bytes
//| verticalStride[in] Height Stride in system memory in rows
//| sysMemSize [in] Size of Memory need to read
//| option [in] Option to disable/enable hybrid memory copy
//| Returns: Result of the operation.
//*-----------------------------------------------------------------------------
CM_RT_API int32_t CmSurface2DRTBase::ReadSurfaceHybridStrides(unsigned char* sysMem, CmEvent* event, const uint32_t horizontalStride, const uint32_t verticalStride, uint64_t sysMemSize, uint32_t option)
{
INSERT_API_CALL_LOG();
int32_t hr = CM_SUCCESS;
uint32_t sizePerPixel = 0;
uint32_t updatedHeight = 0;
uint32_t widthInBytes = 0;
CmQueue *cmQueue = nullptr;
CmDeviceRT *cmDevice = nullptr;
CmQueueRT *cmQueueRT = nullptr;
bool forceCPUCopy = COPY_OPTION(option);
CM_STATUS status;
m_surfaceMgr->GetCmDevice(cmDevice);
CM_CHK_NULL_RETURN_CMERROR(cmDevice);
int32_t result = m_surfaceMgr->GetPixelBytesAndHeight(m_width, m_height, m_format, sizePerPixel, updatedHeight);
if (result != CM_SUCCESS)
{
CM_ASSERTMESSAGE("Error: Failed to get correct surface info.")
return result;
}
widthInBytes = m_width * sizePerPixel;
WaitForReferenceFree(); // wait all owner task finished
if (forceCPUCopy)
{
CM_CHK_CMSTATUS_GOTOFINISH(ReadSurfaceFullStride(sysMem, event, horizontalStride, verticalStride, sysMemSize));
}
else
{
CM_CHK_CMSTATUS_GOTOFINISH(cmDevice->CreateQueue(cmQueue));
if (IsGPUCopy((void*)sysMem, widthInBytes, m_height, horizontalStride))
{
CmEvent *tempEvent = CM_NO_EVENT;
CM_CHK_CMSTATUS_GOTOFINISH(cmQueue->EnqueueCopyGPUToCPUFullStride(this, sysMem, horizontalStride, verticalStride, CM_FASTCOPY_OPTION_BLOCKING, tempEvent));
}
else if (IsUnalignedGPUCopy(widthInBytes, m_height))
{
cmQueueRT = static_cast<CmQueueRT *>(cmQueue);
CmSurface2DRT * cmSurface2DRT = dynamic_cast<CmSurface2DRT *>(this);
CM_CHK_NULL_RETURN_CMERROR(cmSurface2DRT);
CM_CHK_CMSTATUS_GOTOFINISH(cmQueueRT->EnqueueUnalignedCopyInternal(cmSurface2DRT, (unsigned char*)sysMem, horizontalStride, verticalStride, CM_FASTCOPY_GPU2CPU));
}
else
{
CM_CHK_CMSTATUS_GOTOFINISH(ReadSurfaceFullStride(sysMem, event, horizontalStride, verticalStride, sysMemSize));
}
}
finish:
return hr;
}
//*-----------------------------------------------------------------------------
//| Purpose: Let CM know that the UMD resource of current CmSurface2D
// wrapper was changed. This change may happen at the CmSurface2D
// creation and destroy time or changed from outside of CM. This
// should be called immediately after the UMD resource changed.
//
//| Arguments :
//| umdResource [in] Pointer to the UMD resource for the CM
//| wrapper. Set it to nullptr when the
//| third party MosResource was deleted
//| before the CmSurface2D.
//| updateMosResource [in] 1: will update the MosResource.
//| 0: will not update the MosResource.
//| mosResource [in] Pointer to the new valid MosResource
//| that the CMSurface2D will be based on.
//| Do not set this parameter if the
//| MosResource is already deleted.
//| Returns: Result of the operation.
//*-----------------------------------------------------------------------------
CMRT_UMD_API int32_t
CmSurface2DRTBase::NotifyUmdResourceChanged(UMD_RESOURCE umdResource,
int updateMosResource,
PMOS_RESOURCE mosResource)
{
m_umdResource = umdResource;
//
if ( updateMosResource )
{
m_surfaceMgr->UpdateSurface2DTableMosResource( m_handle, mosResource );
}
return CM_SUCCESS;
}
//*-----------------------------------------------------------------------------
//| Purpose: Get the handle of CmSurface2D
//| Returns: Result of the operation.
//*-----------------------------------------------------------------------------
int32_t CmSurface2DRTBase::GetHandle( uint32_t& handle)
{
handle = m_handle;
return CM_SUCCESS;
}
//*-----------------------------------------------------------------------------
//| Purpose: Get the handle of CmSurface2D
//| Returns: Result of the operation.
//*-----------------------------------------------------------------------------
int32_t CmSurface2DRTBase::GetIndexFor2D( uint32_t& index )
{
index = m_handle;
return CM_SUCCESS;
}
int32_t CmSurface2DRTBase::SetSurfaceProperties(uint32_t width, uint32_t height, CM_SURFACE_FORMAT format)
{
if (format == CM_SURFACE_FORMAT_NV12)
{
m_pitch = MOS_ALIGN_CEIL(width * m_pitch /m_width , 2);
}
m_width = width;
m_height = height;
m_format = format;
return CM_SUCCESS;
}
//*-----------------------------------------------------------------------------
//| Purpose: Get the description of surface 2d, width,height,format and the size of pixel .
//| Arguments :
//| width [out] Reference to width of surface
//| height [out] Reference to height of surface
//| format [out] Reference to format of surface
//| sizeperpixel [out] Reference to the pixel's size in bytes
//|
//| Returns: Result of the operation.
//*-----------------------------------------------------------------------------
CM_RT_API int32_t CmSurface2DRTBase::GetSurfaceDesc(uint32_t &width, uint32_t &height, CM_SURFACE_FORMAT &format,uint32_t &sizeperpixel)
{
int ret = CM_SUCCESS;
uint32_t updatedHeight = 0 ;
width = m_width;
height = m_height;
format = m_format;
// Get size per pixel
ret = m_surfaceMgr->GetPixelBytesAndHeight(width, height, format, sizeperpixel, updatedHeight);
return ret;
}
CM_RT_API int32_t CmSurface2DRTBase::InitSurface(const unsigned int initValue, CmEvent* event)
{
INSERT_API_CALL_LOG();
CM_RETURN_CODE hr = CM_SUCCESS;
CmDeviceRT* cmDevice = nullptr;
PCM_CONTEXT_DATA cmData = nullptr;
CM_HAL_SURFACE2D_LOCK_UNLOCK_PARAM inParam;
uint32_t pitch = 0;
uint32_t *surf = nullptr;
uint32_t widthInBytes = 0;
if( event )
{
CmEventRT *eventRT = dynamic_cast<CmEventRT *>(event);
if (eventRT)
{
FlushDeviceQueue(eventRT);
}
else
{
event->WaitForTaskFinished();
}
}
WaitForReferenceFree(); // wait all owner task finished
uint32_t sizePerPixel = 0;
uint32_t updatedHeight = 0;
CM_CHK_CMSTATUS_GOTOFINISH(m_surfaceMgr->GetPixelBytesAndHeight(m_width, m_height, m_format, sizePerPixel, updatedHeight));
m_surfaceMgr->GetCmDevice(cmDevice);
CM_CHK_NULL_RETURN_CMERROR(cmDevice);
cmData = (PCM_CONTEXT_DATA)cmDevice->GetAccelData();
CM_CHK_NULL_RETURN_CMERROR(cmData);
CM_CHK_NULL_RETURN_CMERROR(cmData->cmHalState);
CmSafeMemSet( &inParam, 0, sizeof( CM_HAL_SURFACE2D_LOCK_UNLOCK_PARAM ) );
inParam.width = m_width;
inParam.height = m_height;
inParam.handle = m_handle;
inParam.lockFlag = CM_HAL_LOCKFLAG_WRITEONLY;
CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnLock2DResource(cmData->cmHalState, &inParam));
CM_CHK_NULL_GOTOFINISH_CMERROR(inParam.data);
pitch = inParam.pitch;
surf = ( uint32_t *)inParam.data;
widthInBytes = m_width * sizePerPixel;
if(widthInBytes != pitch)
{
for (uint32_t i=0; i < updatedHeight; i++)
{
if (widthInBytes % sizeof(uint32_t) == 0)
{
CmDwordMemSet(surf, initValue, widthInBytes);
}
else
{
CmDwordMemSet(surf, initValue, widthInBytes + sizeof(uint32_t));
}
surf += (pitch >> 2); // divide by 4 byte to dword
}
}
else
{
CmDwordMemSet(surf, initValue, pitch * updatedHeight);
}
//Unlock Surface2D
inParam.data = nullptr;
CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnUnlock2DResource(cmData->cmHalState, &inParam));
finish:
return hr;
}
int32_t CmSurface2DRTBase::SetMemoryObjectControl( MEMORY_OBJECT_CONTROL memCtrl, MEMORY_TYPE memType, uint32_t age)
{
int32_t hr = CM_SUCCESS;
uint16_t mocs = 0;
hr = CmSurface::SetMemoryObjectControl(memCtrl, memType, age);
CmDeviceRT *cmDevice = nullptr;
m_surfaceMgr->GetCmDevice(cmDevice);
CM_CHK_NULL_RETURN_CMERROR(cmDevice);
PCM_CONTEXT_DATA cmData = (PCM_CONTEXT_DATA)cmDevice->GetAccelData();
CM_CHK_NULL_RETURN_CMERROR(cmData);
CM_CHK_NULL_RETURN_CMERROR(cmData->cmHalState);
mocs = (m_memObjCtrl.mem_ctrl << 8) | (m_memObjCtrl.mem_type<<4) | m_memObjCtrl.age;
CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnSetSurfaceMOCS(cmData->cmHalState, m_handle, mocs, ARG_KIND_SURFACE_2D));
++ m_propertyIndex;
finish:
return hr;
}
CM_RT_API int32_t CmSurface2DRTBase::SelectMemoryObjectControlSetting(MEMORY_OBJECT_CONTROL memCtrl)
{
INSERT_API_CALL_LOG();
++ m_propertyIndex;
return SetMemoryObjectControl(memCtrl, CM_USE_PTE, 0);
}
CMRT_UMD_API int32_t CmSurface2DRTBase::SetResourceUsage(const MOS_HW_RESOURCE_DEF mosUsage)
{
INSERT_API_CALL_LOG();
int32_t hr = CM_SUCCESS;
uint16_t mocs = 0;
hr = CmSurface::SetResourceUsage(mosUsage);
CmDeviceRT *cmDevice = nullptr;
m_surfaceMgr->GetCmDevice(cmDevice);
CM_CHK_NULL_RETURN_CMERROR(cmDevice);
PCM_CONTEXT_DATA cmData = (PCM_CONTEXT_DATA)cmDevice->GetAccelData();
CM_CHK_NULL_RETURN_CMERROR(cmData);
CM_CHK_NULL_RETURN_CMERROR(cmData->cmHalState);
mocs = (m_memObjCtrl.mem_ctrl << 8) | (m_memObjCtrl.mem_type << 4) | m_memObjCtrl.age;
CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR(cmData->cmHalState->pfnSetSurfaceMOCS(cmData->cmHalState, m_handle, mocs, ARG_KIND_SURFACE_2D));
++ m_propertyIndex;
finish:
return hr;
}
int32_t CmSurface2DRTBase::Create2DAlias(SurfaceIndex* & aliasIndex)
{
INSERT_API_CALL_LOG();
uint32_t surfArraySize = 0;
if( m_numAliases < CM_HAL_MAX_NUM_2D_ALIASES )
{
uint32_t origIndex = m_index->get_data();
m_surfaceMgr->GetSurfaceArraySize(surfArraySize);
uint32_t newIndex = origIndex + ( (m_numAliases + 1) * surfArraySize);
m_aliasIndexes[m_numAliases] = MOS_New(SurfaceIndex, newIndex);
if( m_aliasIndexes[m_numAliases] )
{
aliasIndex = m_aliasIndexes[m_numAliases];
m_numAliases++;
return CM_SUCCESS;
}
else
{
CM_ASSERTMESSAGE("Error: Failed to create surface 2d alias due to out of system memory.");
return CM_OUT_OF_HOST_MEMORY;
}
}
else
{
return CM_EXCEED_MAX_NUM_2D_ALIASES;
}
}
CM_RT_API int32_t CmSurface2DRTBase::GetNumAliases(uint32_t& numAliases)
{
numAliases = m_numAliases;
return CM_SUCCESS;
}
CM_RT_API int32_t CmSurface2DRTBase::SetSurfaceStateParam( SurfaceIndex *surfIndex, const CM_SURFACE2D_STATE_PARAM *surfStateParam )
{
CM_RETURN_CODE hr = CM_SUCCESS;
CmDeviceRT * cmDevice = nullptr;
PCM_CONTEXT_DATA cmData = nullptr;
CM_HAL_SURFACE2D_SURFACE_STATE_PARAM inParam;
uint32_t aliasIndex = 0;
m_surfaceMgr->GetCmDevice( cmDevice );
CM_CHK_NULL_GOTOFINISH_CMERROR(cmDevice);
cmData = ( PCM_CONTEXT_DATA )cmDevice->GetAccelData();
CM_CHK_NULL_GOTOFINISH_CMERROR(cmData);
CM_CHK_NULL_GOTOFINISH_CMERROR(cmData->cmHalState);
CmSafeMemSet( &inParam, 0, sizeof( inParam ) );
inParam.width = surfStateParam->width;
inParam.height = surfStateParam->height;
if (surfStateParam->format)
{
inParam.format = surfStateParam->format;
}
inParam.depth = surfStateParam->depth;
inParam.pitch = surfStateParam->pitch;
inParam.memoryObjectControl = surfStateParam->memory_object_control;
inParam.surfaceXOffset = surfStateParam->surface_x_offset;
inParam.surfaceYOffset = surfStateParam->surface_y_offset;
inParam.surfaceOffset = surfStateParam->surface_offset;
if (surfIndex)
{
aliasIndex = surfIndex->get_data();
}
else
{
aliasIndex = m_index->get_data();
}
CM_CHK_MOSSTATUS_GOTOFINISH_CMERROR( cmData->cmHalState->pfnSet2DSurfaceStateParam(cmData->cmHalState, &inParam, aliasIndex, m_handle) );
++ m_propertyIndex;
finish:
return hr;
}
CMRT_UMD_API int32_t CmSurface2DRTBase::SetReadSyncFlag(bool readSync, CmQueue *cmQueue)
{
int32_t hr = CM_SUCCESS;
CmDeviceRT *cmDevice = nullptr;
m_surfaceMgr->GetCmDevice(cmDevice);
CM_CHK_NULL_RETURN_CMERROR(cmDevice);
PCM_CONTEXT_DATA cmData = (PCM_CONTEXT_DATA)cmDevice->GetAccelData();
CM_CHK_NULL_RETURN_CMERROR(cmData);
CM_CHK_NULL_RETURN_CMERROR(cmData->cmHalState);
CmQueueRT *cmQueueRT = static_cast<CmQueueRT *>(cmQueue);
CM_CHK_NULL_RETURN_CMERROR(cmQueueRT);
hr = cmData->cmHalState->pfnSetSurfaceReadFlag(cmData->cmHalState, m_handle, readSync,
(MOS_GPU_CONTEXT)cmQueueRT->GetQueueOption().GPUContext);
if( FAILED(hr) )
{
CM_ASSERTMESSAGE("Error: Set read sync flag failure.")
return CM_FAILURE;
}
return hr;
}
void CmSurface2DRTBase::Log(std::ostringstream &oss)
{
#if CM_LOG_ON
oss << " Surface2D Info "
<< " Width:" << m_width
<< " Height:"<< m_height
<< " Format:"<< GetFormatString(m_format)
<< " Pitch:" << m_pitch
<< " Handle:" << m_handle
<< " SurfaceIndex:" << m_index->get_data()
<< " IsCmCreated:"<<m_isCmCreated
<< std::endl;
#endif
}
void CmSurface2DRTBase::DumpContent(uint32_t kernelNumber, char *kernelName, int32_t taskId, uint32_t argIndex, uint32_t vectorIndex)
{
#if MDF_SURFACE_CONTENT_DUMP
std::ostringstream outputFileName;
outputFileName << "t_" << taskId
<< "_k_" << kernelNumber
<< "_" << kernelName
<< "_argi_" << argIndex
<< "_vector_index_" << vectorIndex;
DumpContentToFile(outputFileName.str().c_str());
#endif
}
void CmSurface2DRTBase::DumpContentToFile(const char *filename)
{
#if MDF_SURFACE_CONTENT_DUMP
static uint32_t surface2DDumpNumber = 0;
std::ostringstream outputFileName;
char fileNamePrefix[MAX_PATH] = {0};
outputFileName << filename
<< "_surf2d_surfi_"<< m_index->get_data()
<< "_w_" << m_width
<< "_h_" << m_height
<< "_p_" << m_pitch
<< "_f_" << GetFormatString(m_format)
<< "_" << surface2DDumpNumber;
GetLogFileLocation(outputFileName.str().c_str(), fileNamePrefix);
std::ofstream outputFileStream;
// Open file
outputFileStream.open(fileNamePrefix, std::ios::app);
CM_ASSERT(outputFileStream);
CmDeviceRT * cmDevice = nullptr;
m_surfaceMgr->GetCmDevice(cmDevice);
CM_ASSERT(cmDevice);
CSync* surfaceLock = cmDevice->GetSurfaceLock();
CM_ASSERT(surfaceLock);
CLock locker(*surfaceLock);
uint32_t sizePerPixel = 0;
uint32_t updatedHeight = 0;
uint32_t surfaceSize = 0;
uint32_t widthInByte = 0;
uint8_t *dst = nullptr;
uint8_t *surf = nullptr;
m_surfaceMgr->GetPixelBytesAndHeight(m_width, m_height, m_format, sizePerPixel, updatedHeight);
surfaceSize = m_width*sizePerPixel*updatedHeight;
widthInByte = m_width * sizePerPixel;
std::vector<char>surface(surfaceSize);
PCM_CONTEXT_DATA cmData = (PCM_CONTEXT_DATA)cmDevice->GetAccelData();
CM_ASSERT(cmData);
CM_ASSERT(cmData->cmHalState);
PCM_HAL_SURFACE2D_ENTRY pEntry = &cmData->cmHalState->umdSurf2DTable[m_handle];
CM_ASSERT(pEntry);
PMOS_RESOURCE pOsResource = &pEntry->osResource;
CM_ASSERT(pOsResource->pGmmResInfo);
GMM_RESOURCE_FLAG gmmFlags = pOsResource->pGmmResInfo->GetResFlags();
if (gmmFlags.Info.NotLockable == true)
{
size_t alignSize = 4096;
unsigned char* system = (unsigned char*)MOS_AlignedAllocMemory(surfaceSize, alignSize);
CM_CHK_NULL_RETURN_VOID(system);
CmQueue* queue = nullptr;
int ret = cmDevice->CreateQueue(queue);
if (ret != 0)
{
CM_ASSERTMESSAGE("Error: CreateQueue failure in dump.")
return;
}
CmSurface2D* cmSurface2D = static_cast<CmSurface2D*>(this);
CmQueueRT* queueRT = dynamic_cast<CmQueueRT*>(queue);
CmEvent* event = nullptr;
cmData->cmHalState->dumpSurfaceContent = false;
ret = queueRT->EnqueueCopyGPUToCPU(cmSurface2D, system, event);
if (ret != 0)
{
CM_ASSERTMESSAGE("Error: EnqueueCopyGPUToCPU failure in surface content dump.")
}
ret = event->WaitForTaskFinished();
if (ret != 0)
{
CM_ASSERTMESSAGE("Error: WaitForTaskFinished failure in surface content dump.")
}
outputFileStream.write((char*)system, surfaceSize);
cmData->cmHalState->dumpSurfaceContent = true;
MOS_AlignedFreeMemory(system);
if (queueRT)
{
CmQueueRT::Destroy(queueRT);
}
}
else
{
int ret = ReadSurface((unsigned char*)&surface[0],nullptr);
if (ret != 0)
{
CM_ASSERTMESSAGE("Error: ReadSurface failure in surface content dump.")
}
outputFileStream.write(&surface[0], surfaceSize);
}
outputFileStream.close();
surface2DDumpNumber++;
#endif
}
CM_RT_API int32_t CmSurface2DRTBase::SetProperty(CM_FRAME_TYPE frameType)
{
m_frameType = frameType;
m_surfaceMgr->UpdateSurface2DTableFrameType(m_handle, frameType);
++ m_propertyIndex;
return CM_SUCCESS;
}
int32_t CmSurface2DRTBase::UpdateResource(MOS_RESOURCE *resource)
{
// get index
int index = m_index->get_data();
return m_surfaceMgr->UpdateSurface2D(resource, index, m_handle);
}
int32_t CmSurface2DRTBase::UpdateSurfaceProperty(uint32_t width, uint32_t height, uint32_t pitch, CM_SURFACE_FORMAT format)
{
int result = m_surfaceMgr->Surface2DSanityCheck(width, height, format);
if( result != CM_SUCCESS )
{
CM_ASSERTMESSAGE("Error: Surface 2D sanity check failure.");
return result;
}
m_width = width;
m_height = height;
m_pitch = pitch;
m_format = format;
++ m_propertyIndex;
return CM_SUCCESS;
}
}