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