1 /*
2 * Copyright (c) 2015-2019, 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 //! \file     media_libva_common.cpp
23 //! \brief    libva(and its extension) interface implemantation common functions
24 //!
25 
26 #include "media_libva.h"
27 #include "media_libva_util.h"
28 #include "mos_solo_generic.h"
29 #include "mos_interface.h"
30 
DdiMedia_GetVaContextFromHeap(PDDI_MEDIA_HEAP mediaHeap,uint32_t index,PMEDIA_MUTEX_T mutex)31 static void* DdiMedia_GetVaContextFromHeap(PDDI_MEDIA_HEAP  mediaHeap, uint32_t index, PMEDIA_MUTEX_T mutex)
32 {
33     PDDI_MEDIA_VACONTEXT_HEAP_ELEMENT  vaCtxHeapElmt = nullptr;
34     void                              *context = nullptr;
35 
36     DdiMediaUtil_LockMutex(mutex);
37     if(nullptr == mediaHeap || index >= mediaHeap->uiAllocatedHeapElements)
38     {
39         DdiMediaUtil_UnLockMutex(mutex);
40         return nullptr;
41     }
42     vaCtxHeapElmt  = (PDDI_MEDIA_VACONTEXT_HEAP_ELEMENT)mediaHeap->pHeapBase;
43     vaCtxHeapElmt += index;
44     context        = vaCtxHeapElmt->pVaContext;
45     DdiMediaUtil_UnLockMutex(mutex);
46 
47     return context;
48 }
49 
DdiMedia_MediaSurfaceToMosResource(DDI_MEDIA_SURFACE * mediaSurface,MOS_RESOURCE * mosResource)50 void DdiMedia_MediaSurfaceToMosResource(DDI_MEDIA_SURFACE *mediaSurface, MOS_RESOURCE  *mosResource)
51 {
52     DDI_CHK_NULL(mediaSurface, "nullptr mediaSurface",);
53     DDI_CHK_NULL(mosResource, "nullptr mosResource",);
54     DDI_ASSERT(mosResource->bo);
55 
56     if (g_apoMosEnabled)
57     {
58         MosInterface::ConvertResourceFromDdi(mediaSurface, mosResource, OS_SPECIFIC_RESOURCE_SURFACE, 0);
59         return;
60     }
61 
62     switch (mediaSurface->format)
63     {
64         case Media_Format_NV12:
65             mosResource->Format    = Format_NV12;
66             break;
67         case Media_Format_NV21:
68             mosResource->Format    = Format_NV21;
69             break;
70         case Media_Format_YUY2:
71             mosResource->Format    = Format_YUY2;
72             break;
73         case Media_Format_X8R8G8B8:
74             mosResource->Format    = Format_X8R8G8B8;
75             break;
76         case Media_Format_X8B8G8R8:
77             mosResource->Format    = Format_X8B8G8R8;
78             break;
79         case Media_Format_A8B8G8R8:
80         case Media_Format_R8G8B8A8:
81             mosResource->Format    = Format_A8B8G8R8;
82             break;
83         case Media_Format_A8R8G8B8:
84             mosResource->Format    = Format_A8R8G8B8;
85             break;
86         case Media_Format_R5G6B5:
87             mosResource->Format    = Format_R5G6B5;
88             break;
89         case Media_Format_R8G8B8:
90             mosResource->Format    = Format_R8G8B8;
91             break;
92         case Media_Format_RGBP:
93             mosResource->Format    = Format_RGBP;
94             break;
95         case Media_Format_BGRP:
96             mosResource->Format    = Format_BGRP;
97             break;
98         case Media_Format_444P:
99             mosResource->Format    = Format_444P;
100             break;
101         case Media_Format_411P:
102             mosResource->Format    = Format_411P;
103             break;
104         case Media_Format_IMC3:
105             mosResource->Format    = Format_IMC3;
106             break;
107         case Media_Format_400P:
108             mosResource->Format    = Format_400P;
109             break;
110         case Media_Format_422H:
111             mosResource->Format    = Format_422H;
112             break;
113         case Media_Format_422V:
114             mosResource->Format    = Format_422V;
115             break;
116         case Media_Format_Buffer:
117             mosResource->Format    = Format_Any;
118         case Media_Format_P010:
119             mosResource->Format    = Format_P010;
120             break;
121         case Media_Format_P016:
122             mosResource->Format    = Format_P016;
123             break;
124         case Media_Format_Y210:
125             mosResource->Format    = Format_Y210;
126             break;
127         case Media_Format_Y216:
128             mosResource->Format    = Format_Y216;
129             break;
130         case Media_Format_AYUV:
131             mosResource->Format    = Format_AYUV;
132             break;
133         case Media_Format_Y410:
134             mosResource->Format    = Format_Y410;
135             break;
136         case Media_Format_Y416:
137             mosResource->Format    = Format_Y416;
138             break;
139         case Media_Format_Y8:
140             mosResource->Format    = Format_Y8;
141             break;
142         case Media_Format_Y16S:
143             mosResource->Format    = Format_Y16S;
144             break;
145         case Media_Format_Y16U:
146             mosResource->Format    = Format_Y16U;
147             break;
148         case Media_Format_R10G10B10A2:
149         case Media_Format_R10G10B10X2:
150             mosResource->Format    = Format_R10G10B10A2;
151             break;
152         case Media_Format_B10G10R10A2:
153         case Media_Format_B10G10R10X2:
154             mosResource->Format    = Format_B10G10R10A2;
155             break;
156         case Media_Format_UYVY:
157             mosResource->Format    = Format_UYVY;
158             break;
159         case Media_Format_VYUY:
160             mosResource->Format    = Format_VYUY;
161             break;
162         case Media_Format_YVYU:
163             mosResource->Format    = Format_YVYU;
164             break;
165         case Media_Format_A16R16G16B16:
166             mosResource->Format    = Format_A16R16G16B16;
167             break;
168         case Media_Format_A16B16G16R16:
169             mosResource->Format    = Format_A16B16G16R16;
170             break;
171         default:
172             DDI_ASSERTMESSAGE("DDI: unsupported media format for surface.");
173             break;
174     }
175     mosResource->iWidth    = mediaSurface->iWidth;
176     mosResource->iHeight   = mediaSurface->iHeight;
177     mosResource->iPitch    = mediaSurface->iPitch;
178     mosResource->iCount    = mediaSurface->iRefCount;
179     mosResource->isTiled   = mediaSurface->isTiled;
180     mosResource->TileType  = LinuxToMosTileType(mediaSurface->TileType);
181     mosResource->bo        = mediaSurface->bo;
182     mosResource->name      = mediaSurface->name;
183 
184     mosResource->ppCurrentFrameSemaphore   = &mediaSurface->pCurrentFrameSemaphore;
185     mosResource->ppReferenceFrameSemaphore = &mediaSurface->pReferenceFrameSemaphore;
186     mosResource->bSemInitialized           = false;
187     mosResource->bMapped                   = false;
188 
189     if(mediaSurface->bMapped == true)
190     {
191         mosResource->pData     = mediaSurface->pData;
192     }
193     else
194     {
195         mosResource->pData     = nullptr;
196     }
197     mosResource->pGmmResInfo   = mediaSurface->pGmmResourceInfo;
198     mosResource->dwGfxAddress  = 0;
199 
200     // for MOS wrapper
201     mosResource->bConvertedFromDDIResource = true;
202 
203     Mos_Solo_SetOsResource(mediaSurface->pGmmResourceInfo, mosResource);
204 
205 }
206 
DdiMedia_MediaBufferToMosResource(DDI_MEDIA_BUFFER * mediaBuffer,MOS_RESOURCE * mosResource)207 void DdiMedia_MediaBufferToMosResource(DDI_MEDIA_BUFFER *mediaBuffer, MOS_RESOURCE *mosResource)
208 {
209     DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer",);
210     DDI_CHK_NULL(mosResource, "nullptr mosResource",);
211     DDI_ASSERT(mediaBuffer->bo);
212 
213     if (g_apoMosEnabled)
214     {
215         MosInterface::ConvertResourceFromDdi(mediaBuffer, mosResource, OS_SPECIFIC_RESOURCE_BUFFER, 0);
216         return;
217     }
218 
219     switch (mediaBuffer->format)
220     {
221         case Media_Format_Buffer:
222             mosResource->Format  = Format_Buffer;
223             mosResource->iWidth    = mediaBuffer->iSize;
224             mosResource->iHeight   = 1;
225             mosResource->iPitch    = mediaBuffer->iSize;
226             break;
227         case Media_Format_Perf_Buffer:
228             mosResource->Format  = Format_Buffer;
229             mosResource->iWidth    = mediaBuffer->iSize;
230             mosResource->iHeight   = 1;
231             mosResource->iPitch    = mediaBuffer->iSize;
232             break;
233         case Media_Format_2DBuffer:
234             mosResource->Format  = Format_Buffer_2D;
235             mosResource->iWidth    = mediaBuffer->uiWidth;
236             mosResource->iHeight   = mediaBuffer->uiHeight;
237             mosResource->iPitch    = mediaBuffer->uiPitch;
238             break;
239         case Media_Format_CPU:
240             return;
241         default:
242             mosResource->iWidth    = mediaBuffer->iSize;
243             mosResource->iHeight   = 1;
244             mosResource->iPitch    = mediaBuffer->iSize;
245             DDI_ASSERTMESSAGE("DDI: unsupported media format for surface.");
246             break;
247     }
248     mosResource->iCount    = mediaBuffer->iRefCount;
249     mosResource->isTiled   = 0;
250     mosResource->TileType  = LinuxToMosTileType(mediaBuffer->TileType);
251     mosResource->bo        = mediaBuffer->bo;
252     mosResource->name      = mediaBuffer->name;
253     mosResource->bMapped   = false;
254 
255     if(mediaBuffer->bMapped == true)
256     {
257         mosResource->pData     = mediaBuffer->pData;
258     }
259     else
260     {
261         mosResource->pData     = nullptr;
262     }
263     mosResource->dwGfxAddress  = 0;
264     mosResource->pGmmResInfo   = mediaBuffer->pGmmResourceInfo;
265 
266     // for MOS wrapper
267     mosResource->bConvertedFromDDIResource = true;
268 
269     Mos_Solo_SetOsResource(mediaBuffer->pGmmResourceInfo, mosResource);
270 }
271 
DdiMedia_GetContextFromContextID(VADriverContextP ctx,VAContextID vaCtxID,uint32_t * ctxType)272 void* DdiMedia_GetContextFromContextID (VADriverContextP ctx, VAContextID vaCtxID, uint32_t *ctxType)
273 {
274     PDDI_MEDIA_CONTEXT       mediaCtx = nullptr;
275     uint32_t                 index = 0;
276 
277     DDI_CHK_NULL(ctx, "nullptr ctx", nullptr);
278     DDI_CHK_NULL(ctxType, "nullptr ctxType", nullptr);
279 
280     mediaCtx  = DdiMedia_GetMediaContext(ctx);
281     index    = vaCtxID & DDI_MEDIA_MASK_VACONTEXTID;
282 
283     if (index >= DDI_MEDIA_MAX_INSTANCE_NUMBER)
284         return nullptr;
285     if ((vaCtxID&DDI_MEDIA_MASK_VACONTEXT_TYPE) == DDI_MEDIA_VACONTEXTID_OFFSET_CENC)
286     {
287         DDI_VERBOSEMESSAGE("Cenc context detected: 0x%x", vaCtxID);
288         *ctxType = DDI_MEDIA_CONTEXT_TYPE_CENC_DECODER;
289         return DdiMedia_GetVaContextFromHeap(mediaCtx->pDecoderCtxHeap, index, &mediaCtx->DecoderMutex);
290     }
291     else if ((vaCtxID&DDI_MEDIA_MASK_VACONTEXT_TYPE) == DDI_MEDIA_VACONTEXTID_OFFSET_DECODER)
292     {
293         DDI_VERBOSEMESSAGE("Decode context detected: 0x%x", vaCtxID);
294         *ctxType = DDI_MEDIA_CONTEXT_TYPE_DECODER;
295         return DdiMedia_GetVaContextFromHeap(mediaCtx->pDecoderCtxHeap, index, &mediaCtx->DecoderMutex);
296     }
297     else if ((vaCtxID&DDI_MEDIA_MASK_VACONTEXT_TYPE) == DDI_MEDIA_VACONTEXTID_OFFSET_ENCODER)
298     {
299         *ctxType = DDI_MEDIA_CONTEXT_TYPE_ENCODER;
300         return DdiMedia_GetVaContextFromHeap(mediaCtx->pEncoderCtxHeap, index, &mediaCtx->EncoderMutex);
301     }
302     else if ((vaCtxID & DDI_MEDIA_MASK_VACONTEXT_TYPE) == DDI_MEDIA_VACONTEXTID_OFFSET_VP)
303     {
304         *ctxType = DDI_MEDIA_CONTEXT_TYPE_VP;
305         return DdiMedia_GetVaContextFromHeap(mediaCtx->pVpCtxHeap, index, &mediaCtx->VpMutex);
306     }
307     else if ((vaCtxID & DDI_MEDIA_MASK_VACONTEXT_TYPE) == DDI_MEDIA_VACONTEXTID_OFFSET_CM)
308     {
309         *ctxType = DDI_MEDIA_CONTEXT_TYPE_CM;
310         return DdiMedia_GetVaContextFromHeap(mediaCtx->pCmCtxHeap, index, &mediaCtx->CmMutex);
311     }
312     else if ((vaCtxID & DDI_MEDIA_MASK_VACONTEXT_TYPE) == DDI_MEDIA_VACONTEXTID_OFFSET_MFE)
313     {
314         *ctxType = DDI_MEDIA_CONTEXT_TYPE_MFE;
315         return DdiMedia_GetVaContextFromHeap(mediaCtx->pMfeCtxHeap, index, &mediaCtx->MfeMutex);
316     }
317     else
318     {
319         DDI_ASSERTMESSAGE("Invalid context: 0x%x", vaCtxID);
320         *ctxType = DDI_MEDIA_CONTEXT_TYPE_NONE;
321         return nullptr;
322     }
323 
324 }
325 
DdiMedia_GetSurfaceFromVASurfaceID(PDDI_MEDIA_CONTEXT mediaCtx,VASurfaceID surfaceID)326 DDI_MEDIA_SURFACE* DdiMedia_GetSurfaceFromVASurfaceID (PDDI_MEDIA_CONTEXT mediaCtx, VASurfaceID surfaceID)
327 {
328     uint32_t                         i = 0;
329     PDDI_MEDIA_SURFACE_HEAP_ELEMENT  surfaceElement = nullptr;
330     PDDI_MEDIA_SURFACE               surface = nullptr;
331 
332     DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", nullptr);
333 
334     i                = (uint32_t)surfaceID;
335     bool validSurface = (i != VA_INVALID_SURFACE);
336     if(validSurface)
337     {
338         DDI_CHK_LESS(i, mediaCtx->pSurfaceHeap->uiAllocatedHeapElements, "invalid surface id", nullptr);
339         DdiMediaUtil_LockMutex(&mediaCtx->SurfaceMutex);
340         surfaceElement  = (PDDI_MEDIA_SURFACE_HEAP_ELEMENT)mediaCtx->pSurfaceHeap->pHeapBase;
341         surfaceElement += i;
342         surface         = surfaceElement->pSurface;
343         DdiMediaUtil_UnLockMutex(&mediaCtx->SurfaceMutex);
344     }
345 
346     return surface;
347 }
348 
DdiMedia_GetVASurfaceIDFromSurface(PDDI_MEDIA_SURFACE surface)349 VASurfaceID DdiMedia_GetVASurfaceIDFromSurface(PDDI_MEDIA_SURFACE surface)
350 {
351     DDI_CHK_NULL(surface, "nullptr surface", VA_INVALID_SURFACE);
352 
353     PDDI_MEDIA_SURFACE_HEAP_ELEMENT  surfaceElement = (PDDI_MEDIA_SURFACE_HEAP_ELEMENT)surface->pMediaCtx->pSurfaceHeap->pHeapBase;
354     for(uint32_t i = 0; i < surface->pMediaCtx->pSurfaceHeap->uiAllocatedHeapElements; i ++)
355     {
356         if(surface == surfaceElement->pSurface)
357         {
358             return surfaceElement->uiVaSurfaceID;
359         }
360         surfaceElement ++;
361     }
362     return VA_INVALID_SURFACE;
363 }
364 
DdiMedia_ReplaceSurfaceWithNewFormat(PDDI_MEDIA_SURFACE surface,DDI_MEDIA_FORMAT expectedFormat)365 PDDI_MEDIA_SURFACE DdiMedia_ReplaceSurfaceWithNewFormat(PDDI_MEDIA_SURFACE surface, DDI_MEDIA_FORMAT expectedFormat)
366 {
367     DDI_CHK_NULL(surface, "nullptr surface", nullptr);
368 
369     PDDI_MEDIA_SURFACE_HEAP_ELEMENT  surfaceElement = (PDDI_MEDIA_SURFACE_HEAP_ELEMENT)surface->pMediaCtx->pSurfaceHeap->pHeapBase;
370     PDDI_MEDIA_CONTEXT mediaCtx = surface->pMediaCtx;
371 
372     //check some conditions
373     if(expectedFormat == surface->format)
374     {
375         return surface;
376     }
377     //create new dst surface and copy the structure
378     PDDI_MEDIA_SURFACE dstSurface = (DDI_MEDIA_SURFACE *)MOS_AllocAndZeroMemory(sizeof(DDI_MEDIA_SURFACE));
379     if (nullptr == surfaceElement)
380     {
381         MOS_FreeMemory(dstSurface);
382         return nullptr;
383     }
384 
385     MOS_SecureMemcpy(dstSurface,sizeof(DDI_MEDIA_SURFACE),surface,sizeof(DDI_MEDIA_SURFACE));
386     DDI_CHK_NULL(dstSurface, "nullptr dstSurface", nullptr);
387     dstSurface->format = expectedFormat;
388     dstSurface->uiLockedBufID = VA_INVALID_ID;
389     dstSurface->uiLockedImageID = VA_INVALID_ID;
390     dstSurface->pSurfDesc = nullptr;
391     //lock surface heap
392     DdiMediaUtil_LockMutex(&mediaCtx->SurfaceMutex);
393     uint32_t i;
394     //get current element heap and index
395     for(i = 0; i < mediaCtx->pSurfaceHeap->uiAllocatedHeapElements; i ++)
396     {
397         if(surface == surfaceElement->pSurface)
398         {
399             break;
400         }
401         surfaceElement ++;
402     }
403     //if cant find
404     if(i == surface->pMediaCtx->pSurfaceHeap->uiAllocatedHeapElements)
405     {
406         DdiMediaUtil_LockMutex(&mediaCtx->SurfaceMutex);
407         MOS_FreeMemory(dstSurface);
408         return nullptr;
409     }
410     //FreeSurface
411     DdiMediaUtil_FreeSurface(surface);
412     MOS_FreeMemory(surface);
413     //CreateNewSurface
414     DdiMediaUtil_CreateSurface(dstSurface,mediaCtx);
415     surfaceElement->pSurface = dstSurface;
416 
417     DdiMediaUtil_UnLockMutex(&mediaCtx->SurfaceMutex);
418 
419     return dstSurface;
420 }
421 
DdiMedia_GetBufferFromVABufferID(PDDI_MEDIA_CONTEXT mediaCtx,VABufferID bufferID)422 DDI_MEDIA_BUFFER* DdiMedia_GetBufferFromVABufferID (PDDI_MEDIA_CONTEXT mediaCtx, VABufferID bufferID)
423 {
424     uint32_t                       i = 0;
425     PDDI_MEDIA_BUFFER_HEAP_ELEMENT bufHeapElement = nullptr;
426     PDDI_MEDIA_BUFFER              buf = nullptr;
427 
428     i                = (uint32_t)bufferID;
429     DDI_CHK_LESS(i, mediaCtx->pBufferHeap->uiAllocatedHeapElements, "invalid buffer id", nullptr);
430     DdiMediaUtil_LockMutex(&mediaCtx->BufferMutex);
431     bufHeapElement  = (PDDI_MEDIA_BUFFER_HEAP_ELEMENT)mediaCtx->pBufferHeap->pHeapBase;
432     bufHeapElement += i;
433     buf             = bufHeapElement->pBuffer;
434     DdiMediaUtil_UnLockMutex(&mediaCtx->BufferMutex);
435 
436     return buf;
437 }
438 
DdiMedia_DestroyBufFromVABufferID(PDDI_MEDIA_CONTEXT mediaCtx,VABufferID bufferID)439 bool DdiMedia_DestroyBufFromVABufferID (PDDI_MEDIA_CONTEXT mediaCtx, VABufferID bufferID)
440 {
441     DdiMediaUtil_LockMutex(&mediaCtx->BufferMutex);
442     DdiMediaUtil_ReleasePMediaBufferFromHeap(mediaCtx->pBufferHeap, bufferID);
443     mediaCtx->uiNumBufs--;
444     DdiMediaUtil_UnLockMutex(&mediaCtx->BufferMutex);
445     return true;
446 }
447 
DdiMedia_GetContextFromVABufferID(PDDI_MEDIA_CONTEXT mediaCtx,VABufferID bufferID)448 void* DdiMedia_GetContextFromVABufferID (PDDI_MEDIA_CONTEXT mediaCtx, VABufferID bufferID)
449 {
450     uint32_t                       i;
451     PDDI_MEDIA_BUFFER_HEAP_ELEMENT bufHeapElement;
452     void *                         ctx;
453 
454     i                = (uint32_t)bufferID;
455     DDI_CHK_LESS(i, mediaCtx->pBufferHeap->uiAllocatedHeapElements, "invalid buffer id", nullptr);
456     DdiMediaUtil_LockMutex(&mediaCtx->BufferMutex);
457     bufHeapElement  = (PDDI_MEDIA_BUFFER_HEAP_ELEMENT)mediaCtx->pBufferHeap->pHeapBase;
458     ctx            = bufHeapElement->pCtx;
459     DdiMediaUtil_UnLockMutex(&mediaCtx->BufferMutex);
460 
461     return ctx;
462 }
463