xref: /aosp_15_r20/external/intel-media-driver/media_driver/linux/common/cm/hal/cm_surface_manager.cpp (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
1 /*
2 * Copyright (c) 2007-2017, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file      cm_surface_manager_os.cpp
24 //! \brief     Contains Class CmSurfaceManager  definitions
25 //!
26 #include "cm_surface_manager.h"
27 
28 #include "cm_surface_2d_rt.h"
29 
30 #include "cm_surface_2d_rt.h"
31 #include "cm_device_rt.h"
32 #include "cm_mem.h"
33 
34 namespace CMRT_UMD
35 {
36 //*-----------------------------------------------------------------------------
37 //| Purpose:    Create Surface Manager
38 //| Arguments :
39 //|               device         [in]       Pointer to Cm Device
40 //|               halMaxValues   [in]       Cm Max values
41 //|               surfaceManager [out]      Reference to pointer to CmSurfaceManager
42 //|
43 //| Returns:    Result of the operation.
44 //*-----------------------------------------------------------------------------
Create(CmDeviceRT * device,CM_HAL_MAX_VALUES halMaxValues,CM_HAL_MAX_VALUES_EX halMaxValuesEx,CmSurfaceManager * & surfaceManager)45 int32_t CmSurfaceManager::Create(
46     CmDeviceRT* device,
47     CM_HAL_MAX_VALUES halMaxValues,
48     CM_HAL_MAX_VALUES_EX halMaxValuesEx,
49     CmSurfaceManager* &surfaceManager)
50 {
51     int32_t result = CM_SUCCESS;
52 
53     surfaceManager = new (std::nothrow) CmSurfaceManager(device);
54     if (surfaceManager)
55     {
56         result = surfaceManager->Initialize(halMaxValues, halMaxValuesEx);
57         if (result != CM_SUCCESS)
58         {
59             CmSurfaceManager::Destroy(surfaceManager);
60         }
61     }
62     else
63     {
64         CM_ASSERTMESSAGE("Error: Failed to create CmSurfaceManager due to out of system memory.");
65         result = CM_OUT_OF_HOST_MEMORY;
66     }
67     return result;
68 }
69 
70 //*-----------------------------------------------------------------------------
71 //| Purpose:    Destroy CmSurfaceManager
72 //| Returns:    Result of the operation.
73 //*-----------------------------------------------------------------------------
Destroy(CmSurfaceManager * & surfaceManager)74 int32_t CmSurfaceManager::Destroy(CmSurfaceManager* &surfaceManager)
75 {
76     if (surfaceManager)
77     {
78         delete surfaceManager;
79         surfaceManager = nullptr;
80     }
81     return CM_SUCCESS;
82 }
83 
84 //*-----------------------------------------------------------------------------
85 //| Purpose:    Constructor of CmSurfaceManager
86 //| Returns:    None
87 //*-----------------------------------------------------------------------------
CmSurfaceManager(CmDeviceRT * device)88 CmSurfaceManager::CmSurfaceManager(CmDeviceRT* device) :CmSurfaceManagerBase(device) {}
89 
90 //*-----------------------------------------------------------------------------
91 //| Purpose:    Destructor of CmSurfaceManager
92 //| Returns:    None
93 //*-----------------------------------------------------------------------------
~CmSurfaceManager()94 CmSurfaceManager::~CmSurfaceManager() {}
95 
96 //*-----------------------------------------------------------------------------
97 //| Purpose:    Create surface 2d with mos info
98 //| Arguments :
99 //|               mosResource        [in]       pointer to mos resource
100 //|               createdByCm        [in]       if this surface created by thin layer
101 //|               surface          [IN/out]   Reference to CmSurface2D
102 //|
103 //| Returns:    Result of the operation.
104 //*-----------------------------------------------------------------------------
CreateSurface2DFromMosResource(MOS_RESOURCE * mosResource,bool createdByCm,CmSurface2DRT * & surface)105  int32_t CmSurfaceManager::CreateSurface2DFromMosResource(MOS_RESOURCE * mosResource, bool createdByCm, CmSurface2DRT* & surface)
106  {
107     uint32_t handle         = 0;
108     uint32_t index          = ValidSurfaceIndexStart();
109     int32_t result         = 0;
110     uint32_t width          = 0;
111     uint32_t height         = 0;
112     uint32_t pitch          = 0;
113     CM_SURFACE_FORMAT   format = CM_SURFACE_FORMAT_INVALID;
114 
115     surface = nullptr;
116 
117     //Get width, height, pitch, format from mosResource
118     result = GetSurfaceInfo(mosResource, width, height, pitch, format);
119     if( result != CM_SUCCESS )
120     {
121         CM_ASSERTMESSAGE("Error: Failed to get surface info from mosResource.");
122         return result;
123     }
124 
125     //Sanity check
126     result = Surface2DSanityCheck(width, height, format);
127     if( result != CM_SUCCESS )
128     {
129         CM_ASSERTMESSAGE("Error: Sanity check for surface 2D failure.");
130         return result;
131     }
132 
133     // For 2D surface, since the real memory buffer is not allocated in CMRT@UMD, no reuse/manager can be done
134     // Real reuse is controlled by the CMRT library.
135     if (GetFreeSurfaceIndex(index) != CM_SUCCESS)
136     {
137         CM_ASSERTMESSAGE("Error: Exceed the maximum surface amount.");
138         return CM_EXCEED_SURFACE_AMOUNT;
139     }
140 
141     if( m_2DSurfaceCount >= m_max2DSurfaceCount )
142     {
143         CM_ASSERTMESSAGE("Error: Exceed the maximum surface amount.");
144         return CM_EXCEED_SURFACE_AMOUNT;
145     }
146 
147     result = AllocateSurface2D( width, height, format, mosResource, handle);
148     if( result != CM_SUCCESS )
149     {
150         CM_ASSERTMESSAGE("Error: Failed to allocate surface.");
151         return result;
152     }
153 
154     result = CmSurface2DRT::Create( index, handle, width, height, pitch, format, createdByCm, this, surface );
155     if( result != CM_SUCCESS )
156     {
157         FreeSurface2D( handle );
158         CM_ASSERTMESSAGE("Error: Failed to create CmSurface2D.");
159         return result;
160     }
161 
162     m_surfaceArray[ index ] = surface;
163     UpdateProfileFor2DSurface(index, width, height, format);
164 
165     return CM_SUCCESS;
166  }
167 
168 //*-----------------------------------------------------------------------------
169 //| Purpose:    Check the legality of surface's width,height and format
170 //| Returns:    Result of the operation.
171 //*-----------------------------------------------------------------------------
Surface2DSanityCheck(uint32_t width,uint32_t height,CM_SURFACE_FORMAT format)172 int32_t CmSurfaceManager::Surface2DSanityCheck(uint32_t width, uint32_t height, CM_SURFACE_FORMAT format)
173 {
174     if( ( width < CM_MIN_SURF_WIDTH ) || ( width > CM_MAX_2D_SURF_WIDTH ) )
175     {
176         CM_ASSERTMESSAGE("Error: Invalid surface width.");
177         return CM_INVALID_WIDTH;
178     }
179 
180     if( ( height < CM_MIN_SURF_HEIGHT ) || ( height > CM_MAX_2D_SURF_HEIGHT ) )
181     {
182         CM_ASSERTMESSAGE("Error: Invalid surface height.");
183         return CM_INVALID_HEIGHT;
184     }
185 
186     switch( format )
187     {
188         case CM_SURFACE_FORMAT_X8R8G8B8:
189         case CM_SURFACE_FORMAT_A8R8G8B8:
190         case CM_SURFACE_FORMAT_A8B8G8R8:
191         case CM_SURFACE_FORMAT_R32F:
192         case CM_SURFACE_FORMAT_A8:
193         case CM_SURFACE_FORMAT_P8:
194         case CM_SURFACE_FORMAT_R8G8_SNORM:
195         case CM_SURFACE_FORMAT_Y8_UNORM:
196         case CM_SURFACE_FORMAT_Y16_UNORM:
197         case CM_SURFACE_FORMAT_Y16_SNORM:
198         case CM_SURFACE_FORMAT_A16B16G16R16:
199         case CM_SURFACE_FORMAT_R10G10B10A2:
200         case CM_SURFACE_FORMAT_A16B16G16R16F:
201         case CM_SURFACE_FORMAT_V8U8:
202         case CM_SURFACE_FORMAT_R16_FLOAT:
203         case CM_SURFACE_FORMAT_L8:
204         case CM_SURFACE_FORMAT_R32_SINT:
205         case CM_SURFACE_FORMAT_R32_UINT:
206         case CM_SURFACE_FORMAT_BUFFER_2D:
207         case CM_SURFACE_FORMAT_Y216:
208         case CM_SURFACE_FORMAT_Y416:
209         case CM_SURFACE_FORMAT_AYUV:
210         case CM_SURFACE_FORMAT_Y210:
211         case CM_SURFACE_FORMAT_Y410:
212         case CM_SURFACE_FORMAT_R32G32B32A32F:
213         case CM_SURFACE_FORMAT_400P:
214             break;
215 
216         case CM_SURFACE_FORMAT_R8_UINT:
217         case CM_SURFACE_FORMAT_R16_UINT:
218         case CM_SURFACE_FORMAT_L16:
219             break;
220 
221         case CM_SURFACE_FORMAT_UYVY:
222         case CM_SURFACE_FORMAT_YUY2:
223             if( width & 0x1 )
224             {
225                 CM_ASSERTMESSAGE("Error: Invalid surface width.");
226                 return CM_INVALID_WIDTH;
227             }
228             break;
229 
230         case CM_SURFACE_FORMAT_NV12:
231             if (width & 0x1)
232             {
233                 CM_ASSERTMESSAGE("Error: Invalid surface width.");
234                 return CM_INVALID_WIDTH;
235             }
236             break;
237 
238         case CM_SURFACE_FORMAT_P010:
239         case CM_SURFACE_FORMAT_P016:
240         case CM_SURFACE_FORMAT_YV12:
241             if( width & 0x1 )
242             {
243                 CM_ASSERTMESSAGE("Error: Invalid surface width.");
244                 return CM_INVALID_WIDTH;
245             }
246             if( height & 0x1 )
247             {
248                 CM_ASSERTMESSAGE("Error: Invalid surface height.");
249                 return CM_INVALID_HEIGHT;
250             }
251             break;
252 
253         case CM_SURFACE_FORMAT_411P:
254         case CM_SURFACE_FORMAT_411R:
255         case CM_SURFACE_FORMAT_IMC3:
256         case CM_SURFACE_FORMAT_422H:
257         case CM_SURFACE_FORMAT_422V:
258         case CM_SURFACE_FORMAT_444P:
259         case CM_SURFACE_FORMAT_RGBP:
260         case CM_SURFACE_FORMAT_BGRP:
261         case CM_SURFACE_FORMAT_P208:
262             if( width & 0x1 )
263             {
264                 CM_ASSERTMESSAGE("Error: Invalid surface width.");
265                 return CM_INVALID_WIDTH;
266             }
267             if( height & 0x1 )
268             {
269                 CM_ASSERTMESSAGE("Error: Invalid surface height.");
270                 return CM_INVALID_HEIGHT;
271             }
272             break;
273 
274         default:
275             CM_ASSERTMESSAGE("Error: Unsupported surface format.");
276             return CM_SURFACE_FORMAT_NOT_SUPPORTED;
277     }
278 
279     return CM_SUCCESS;
280 }
281 
282 //!
283 //! \brief    Get mos surface's information (width, height, pitch and format)
284 //! \details  This function calls mos interface pfnGetResourceInfo to get details of surface.
285 //! \param    [in] mosResource
286 //!           pointer to mos resource
287 //! \param    [in,out] width
288 //!           reference to surface's width
289 //! \param    [in,out] height
290 //!           reference to surface's height
291 //! \param    [in,out] pitch
292 //!           reference to surface's lock pitch
293 //! \param    [in,out] format
294 //!           reference to surface's format
295 //! \return   MOS_STATUS
296 //!
GetSurfaceInfo(MOS_RESOURCE * mosResource,uint32_t & width,uint32_t & height,uint32_t & pitch,CM_SURFACE_FORMAT & format)297 int32_t CmSurfaceManager::GetSurfaceInfo( MOS_RESOURCE * mosResource, uint32_t &width, uint32_t &height, uint32_t &pitch, CM_SURFACE_FORMAT &format)
298 {
299     PCM_CONTEXT_DATA cmData = (PCM_CONTEXT_DATA)m_device->GetAccelData();
300     PCM_HAL_STATE state  = cmData->cmHalState;
301 
302     MOS_SURFACE          surfaceDetails;
303     MOS_ZeroMemory(&surfaceDetails, sizeof(surfaceDetails));
304     surfaceDetails.Format = CM_SURFACE_FORMAT_INVALID;
305     state->osInterface->pfnGetResourceInfo(state->osInterface, mosResource, &surfaceDetails);
306 
307     width    = surfaceDetails.dwWidth;
308     height   = surfaceDetails.dwHeight;
309     format   = surfaceDetails.Format;
310     pitch    = surfaceDetails.dwLockPitch;
311 
312     return CM_SUCCESS;
313 }
314 
UpdateSurface2D(MOS_RESOURCE * mosResource,int index,uint32_t handle)315 int32_t CmSurfaceManager::UpdateSurface2D(MOS_RESOURCE * mosResource, int index, uint32_t handle)
316 {
317     PCM_CONTEXT_DATA cmData = (PCM_CONTEXT_DATA)m_device->GetAccelData();
318     PCM_HAL_STATE state = cmData->cmHalState;
319 
320     CM_SURFACE_FORMAT format;
321     uint32_t width          = 0;
322     uint32_t height         = 0;
323     uint32_t pitch          = 0;
324     int result = GetSurfaceInfo(mosResource, width, height, pitch, format);
325     if( result != CM_SUCCESS )
326     {
327         CM_ASSERTMESSAGE("Error: Failed to get surface info from pMosResource.");
328         return result;
329     }
330 
331     CM_HAL_SURFACE2D_PARAM inParam;
332     CmSafeMemSet( &inParam, 0, sizeof( CM_HAL_SURFACE2D_PARAM ) );
333     inParam.width                  = width;
334     inParam.height                 = height;
335     inParam.format                 = format;
336     inParam.mosResource            = mosResource;
337     inParam.isAllocatedbyCmrtUmd   = false;
338     inParam.handle                 = handle;
339 
340     state->pfnUpdateSurface2D(state, &inParam);
341 
342     CmSurface2DRT *surface = static_cast<CmSurface2DRT *>(m_surfaceArray[index]);
343 
344     int ret = surface->UpdateSurfaceProperty(width, height, pitch, format);
345 
346     return ret;
347 
348 }
349 
350 }  // namespace
351