1 /*
2 * Copyright (c) 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 #include "cm_surface_manager.h"
23 #include "cm_debug.h"
24 #include "cm_def.h"
25 #include "cm_device.h"
26 #include "cm_mem.h"
27
Surface2DSanityCheck(uint32_t width,uint32_t height,CM_SURFACE_FORMAT format)28 int32_t CmSurfaceManager::Surface2DSanityCheck(uint32_t width,
29 uint32_t height,
30 CM_SURFACE_FORMAT format)
31 {
32 if ((width < CM_MIN_SURF_WIDTH) || (width > CM_MAX_2D_SURF_WIDTH))
33 {
34 CmAssert(0);
35 return CM_INVALID_WIDTH;
36 }
37 if ((height < CM_MIN_SURF_HEIGHT) || (height > CM_MAX_2D_SURF_HEIGHT))
38 {
39 CmAssert(0);
40 return CM_INVALID_HEIGHT;
41 }
42
43 switch (format)
44 {
45 case CM_SURFACE_FORMAT_X8R8G8B8:
46 case CM_SURFACE_FORMAT_A8R8G8B8:
47 case CM_SURFACE_FORMAT_A8B8G8R8:
48 case CM_SURFACE_FORMAT_R32F:
49 case CM_SURFACE_FORMAT_A16B16G16R16:
50 case CM_SURFACE_FORMAT_R10G10B10A2:
51 case CM_SURFACE_FORMAT_A16B16G16R16F:
52 case CM_SURFACE_FORMAT_L16:
53 case CM_SURFACE_FORMAT_D16:
54 case CM_SURFACE_FORMAT_A8:
55 case CM_SURFACE_FORMAT_P8:
56 case CM_SURFACE_FORMAT_V8U8:
57 case CM_SURFACE_FORMAT_R16_UINT:
58 case CM_SURFACE_FORMAT_R8_UINT:
59 case CM_SURFACE_FORMAT_Y216:
60 case CM_SURFACE_FORMAT_Y416:
61 case CM_SURFACE_FORMAT_AYUV:
62 case CM_SURFACE_FORMAT_Y210:
63 case CM_SURFACE_FORMAT_Y410:
64 case CM_SURFACE_FORMAT_R32G32B32A32F:
65 break;
66
67 case CM_SURFACE_FORMAT_UYVY:
68 case CM_SURFACE_FORMAT_YUY2:
69 if (width & 0x1)
70 {
71 CmAssert(0);
72 return CM_INVALID_WIDTH;
73 }
74 break;
75
76 case CM_SURFACE_FORMAT_P016:
77 case CM_SURFACE_FORMAT_P010:
78 case CM_SURFACE_FORMAT_YV12:
79 case CM_SURFACE_FORMAT_422H:
80 case CM_SURFACE_FORMAT_444P:
81 case CM_SURFACE_FORMAT_422V:
82 case CM_SURFACE_FORMAT_411P:
83 case CM_SURFACE_FORMAT_411R:
84 case CM_SURFACE_FORMAT_RGBP:
85 case CM_SURFACE_FORMAT_BGRP:
86 case CM_SURFACE_FORMAT_IMC3:
87 case CM_SURFACE_FORMAT_P208:
88 if (width & 0x1)
89 {
90 CmAssert(0);
91 return CM_INVALID_WIDTH;
92 }
93 if (height & 0x1)
94 {
95 CmAssert(0);
96 return CM_INVALID_HEIGHT;
97 }
98 break;
99
100 case CM_SURFACE_FORMAT_NV12:
101 if (width & 0x1)
102 {
103 CmAssert(0);
104 return CM_INVALID_WIDTH;
105 }
106 if (height & 0x1)
107 {
108 CmAssert(0);
109 return CM_INVALID_HEIGHT;
110 }
111 break;
112
113 default:
114 CmAssert(0);
115 return CM_SURFACE_FORMAT_NOT_SUPPORTED;
116 }
117
118 return CM_SUCCESS;
119 }
120
121
CreateSurface2D(uint32_t width,uint32_t height,CM_SURFACE_FORMAT format,CmSurface2D * & surface)122 int32_t CmSurfaceManager::CreateSurface2D(uint32_t width,
123 uint32_t height,
124 CM_SURFACE_FORMAT format,
125 CmSurface2D *&surface)
126 {
127 int32_t result = CM_SUCCESS;
128
129 //Sanity check
130 CHK_RET(Surface2DSanityCheck(width, height, format));
131
132 // Passes the reference to CMRT@UMD to create a CmSurface.
133 CHK_RET(AllocateSurface2DInUmd(width, height, format, true, false, 0, surface));
134 CHK_NULL(surface);
135
136 finish:
137 if (FAILED(result))
138 {
139 surface = nullptr;
140 }
141
142 return result;
143 }
144
CreateSurface2D(VASurfaceID vaSurface,CmSurface2D * & surface)145 int32_t CmSurfaceManager::CreateSurface2D(VASurfaceID vaSurface,
146 CmSurface2D *&surface)
147 { // Not created by Cm , but it is created through Libva
148 return CreateSurface2D(vaSurface, false, true, surface);
149 }
150
CreateSurface2D(VASurfaceID * vaSurfaceArray,const uint32_t surfaceCount,CmSurface2D ** surfaceArray)151 int32_t CmSurfaceManager::CreateSurface2D(VASurfaceID *vaSurfaceArray,
152 const uint32_t surfaceCount,
153 CmSurface2D **surfaceArray)
154 {
155 int32_t result = CM_FAILURE;
156 uint32_t surfIndex = 0;
157 for (surfIndex = 0; surfIndex < surfaceCount; surfIndex++)
158 {
159 CHK_RET(CreateSurface2D(vaSurfaceArray[surfIndex], surfaceArray[surfIndex]));
160 CHK_NULL(surfaceArray[surfIndex]);
161 }
162
163 finish:
164 if (result != CM_SUCCESS)
165 {
166 for (uint32_t j = 0; j < surfIndex; j++)
167 {
168 DestroySurface(surfaceArray[j]);
169 }
170 }
171 return result;
172 }
173
CreateVaSurface2D(uint32_t width,uint32_t height,CM_SURFACE_FORMAT format,VASurfaceID & vaSurface,CmSurface2D * & surface)174 int32_t CmSurfaceManager::CreateVaSurface2D(uint32_t width,
175 uint32_t height,
176 CM_SURFACE_FORMAT format,
177 VASurfaceID &vaSurface,
178 CmSurface2D *&surface)
179 {
180 int32_t hr = CM_SUCCESS;
181 VAStatus vaStatus = VA_STATUS_SUCCESS;
182 VADisplay *dpy = nullptr;
183 uint32_t vaFormat = 0;
184
185 vaFormat = ConvertToLibvaFormat(format);
186
187 //Create Va Surface
188 m_device->GetVaDpy(dpy);
189 if(dpy == nullptr)
190 {
191 CmAssert(0);
192 return CM_INVALID_LIBVA_INITIALIZE;
193 }
194
195 // Set attribute for vaCreateSurfaces
196 VASurfaceAttrib surfaceAttrib;
197 surfaceAttrib.type = VASurfaceAttribPixelFormat;
198 surfaceAttrib.value.type = VAGenericValueTypeInteger;
199 surfaceAttrib.flags = VA_SURFACE_ATTRIB_SETTABLE;
200 surfaceAttrib.value.value.i = vaFormat;
201
202 // since no 10-bit format is supported in MDF,
203 // the VA_RT_FORMAT_YUV420 will be overwritten
204 // by the format in attribute
205 vaStatus = vaCreateSurfaces(*dpy, VA_RT_FORMAT_YUV420, width, height, &vaSurface, 1,
206 &surfaceAttrib, 1);
207 if (vaStatus != VA_STATUS_SUCCESS)
208 {
209 CmAssert(0);
210 return CM_VA_SURFACE_NOT_SUPPORTED;
211 }
212
213 //Create Cm Surface
214 hr = CreateSurface2D(vaSurface, true, true, surface);
215 if (hr != CM_SUCCESS)
216 {
217 CmAssert(0);
218 vaStatus = vaDestroySurfaces(*dpy, &vaSurface, 1);
219 return hr;
220 }
221
222 return CM_SUCCESS;
223 }
224
CreateSurface2D(VASurfaceID & vaSurface,bool cmCreated,bool createdbyLibva,CmSurface2D * & surface)225 int32_t CmSurfaceManager::CreateSurface2D(VASurfaceID &vaSurface,
226 bool cmCreated,
227 bool createdbyLibva,
228 CmSurface2D *&surface)
229 {
230 int32_t result = CM_SUCCESS;
231 //Pass it to CMRT@UMD to create CmSurface
232 CHK_RET(AllocateSurface2DInUmd(0, 0, (CM_SURFACE_FORMAT)0, cmCreated, createdbyLibva,
233 vaSurface, surface));
234 CHK_NULL(surface);
235
236 finish:
237 return result;
238 }
239
ConvertToLibvaFormat(int32_t format)240 int32_t CmSurfaceManager::ConvertToLibvaFormat(int32_t format)
241 {
242 int32_t vaFmt = format;
243 switch (format)
244 {
245 case VA_CM_FMT_A8R8G8B8:
246 vaFmt = VA_FOURCC_ARGB;
247 break;
248
249 default:
250 vaFmt = format;
251 break;
252 }
253 return vaFmt;
254 }
255
AllocateSurface2DInUmd(uint32_t width,uint32_t height,CM_SURFACE_FORMAT format,bool cmCreated,bool createdbyLibva,VASurfaceID vaSurface,CmSurface2D * & surface)256 int32_t CmSurfaceManager::AllocateSurface2DInUmd(uint32_t width,
257 uint32_t height,
258 CM_SURFACE_FORMAT format,
259 bool cmCreated,
260 bool createdbyLibva,
261 VASurfaceID vaSurface,
262 CmSurface2D *&surface)
263 {
264 VADisplay *display = nullptr;
265 m_device->GetVaDpy(display);
266
267 CM_CREATESURFACE2D_PARAM inParam;
268 CmSafeMemSet(&inParam, 0, sizeof(CM_CREATESURFACE2D_PARAM));
269 inParam.width = width;
270 inParam.height = height;
271 inParam.format = format;
272 inParam.isCmCreated = cmCreated;
273 inParam.isLibvaCreated = createdbyLibva;
274 inParam.vaSurfaceID = vaSurface;
275 inParam.vaDpy = display;
276
277 int32_t hr = m_device->OSALExtensionExecute(CM_FN_CMDEVICE_CREATESURFACE2D,
278 &inParam, sizeof(inParam),
279 nullptr, 0);
280 CHK_FAILURE_RETURN(hr);
281 CHK_FAILURE_RETURN(inParam.returnValue);
282 surface = (CmSurface2D *)inParam.cmSurface2DHandle;
283
284 return hr;
285 }
286