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