1 /*
2 * Copyright (c) 2009-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 media_libva_putsurface_linux.cpp
24 //! \brief libva(and its extension) putsurface linux implementaion
25 //!
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <stdarg.h>
31
32 #include <fcntl.h> //open
33 #include <sys/stat.h> //fstat
34 #include <unistd.h> //read, lseek
35 #include <dlfcn.h> //dlopen,dlsym,dlclose
36 #include <time.h> //get_clocktime
37 #include <errno.h> //errno
38 #include <assert.h> //assert
39
40 #include <sys/mman.h>
41 #include <dlfcn.h>
42 #include <sys/ioctl.h>
43 #include <X11/Xlib.h>
44 #include <X11/Xutil.h>
45
46 #include "media_libva_putsurface_linux.h"
47 #include "media_libva_util.h"
48 #include "media_libva_common.h"
49 #include "media_libva_vp.h"
50
51 extern MOS_FORMAT VpGetFormatFromMediaFormat(DDI_MEDIA_FORMAT mf);
52 extern VPHAL_CSPACE DdiVp_GetColorSpaceFromMediaFormat(DDI_MEDIA_FORMAT mf);
53 extern MOS_TILE_TYPE VpGetTileTypeFromMediaTileType(uint32_t mediaTileType);
54
55 /* Closes and disposed any allocated data */
dso_close(struct dso_handle * h)56 void dso_close(struct dso_handle *h)
57 {
58 if (!h){
59 return;
60 }
61
62 if (h->handle) {
63 if (h->handle != RTLD_DEFAULT)
64 dlclose(h->handle);
65 h->handle = nullptr;
66 }
67 free(h);
68 }
69
70 /* Opens the named shared library */
dso_open(const char * path)71 struct dso_handle * dso_open(const char *path)
72 {
73 struct dso_handle *h = nullptr;
74
75 h = (dso_handle *)calloc(1, sizeof(*h));
76 if (!h){
77 return nullptr;
78 }
79
80 if (path) {
81 h->handle = dlopen(path, RTLD_LAZY|RTLD_LOCAL);
82 if (!h->handle)
83 goto error;
84 }
85 else{
86 h->handle = RTLD_DEFAULT;
87 }
88 return h;
89
90 error:
91 dso_close(h);
92 return nullptr;
93 }
94
95 /* Load function name from one dynamic lib */
get_symbol(struct dso_handle * h,void * func_vptr,const char * name)96 static bool get_symbol(struct dso_handle *h, void *func_vptr, const char *name)
97 {
98 DDI_CHK_NULL(h, "nullptr h", false);
99 DDI_CHK_NULL(func_vptr, "nullptr func_vptr", false);
100
101 dso_generic_func func;
102 dso_generic_func * const func_ptr = (dso_generic_func*) func_vptr;
103 const char *error = nullptr;
104
105 dlerror();
106 func = (dso_generic_func)dlsym(h->handle, name);
107 error = dlerror();
108 if (error) {
109 fprintf(stderr, "error: failed to resolve %s(): %s\n", name, error);
110 return false;
111 }
112 *func_ptr = func;
113 return true;
114 }
115
116 //!
117 //! \brief Loads function name from vtable
118 //!
119 //! \param [in] h
120 //! Dso handle
121 //! \param [in] vtable
122 //! VA api table
123 //! \param [in] vtable_length
124 //! Length of VA api table
125 //! \param [in] symbols
126 //! Dso symbol
127 //!
128 //! \return bool
129 //! true if call success, else false
130 //!
131 bool
dso_get_symbols(struct dso_handle * h,void * vtable,uint32_t vtable_length,const struct dso_symbol * symbols)132 dso_get_symbols(
133 struct dso_handle *h,
134 void *vtable,
135 uint32_t vtable_length,
136 const struct dso_symbol *symbols
137 )
138 {
139 DDI_CHK_NULL(h, "nullptr h", false);
140
141 const struct dso_symbol *s = nullptr;
142 if (nullptr == symbols)
143 {
144 return VA_STATUS_ERROR_INVALID_PARAMETER;
145 }
146 for (s = symbols; s->name != nullptr; s++) {
147 if (s->offset + sizeof(dso_generic_func) > vtable_length)
148 return false;
149 if (!get_symbol(h, ((char *)vtable) + s->offset, s->name))
150 return false;
151 }
152 return true;
153 }
154
output_dri_init(VADriverContextP ctx)155 bool output_dri_init(VADriverContextP ctx)
156 {
157 DDI_CHK_NULL(ctx, "nullptr ctx", false);
158
159 PDDI_MEDIA_CONTEXT mediaDrvCtx = nullptr;
160 mediaDrvCtx = DdiMedia_GetMediaContext(ctx);
161 DDI_CHK_NULL(mediaDrvCtx, "nullptr ctx", false);
162
163 struct dso_handle *dso_handle = nullptr;
164 struct dri_vtable *dri_vtable = nullptr;
165
166 mediaDrvCtx->dri_output = nullptr;
167
168 static const struct dso_symbol symbols[] = {
169 { "va_dri_get_drawable",
170 offsetof(struct dri_vtable, get_drawable) },
171 { "va_dri_get_rendering_buffer",
172 offsetof(struct dri_vtable, get_rendering_buffer) },
173 { "va_dri_swap_buffer",
174 offsetof(struct dri_vtable, swap_buffer) },
175 { nullptr, }
176 };
177
178 mediaDrvCtx->dri_output = (va_dri_output*) calloc(1, sizeof(struct va_dri_output));
179 if (!mediaDrvCtx->dri_output){
180 goto error;
181 }
182
183 mediaDrvCtx->dri_output->handle = dso_open(LIBVA_X11_NAME);
184 if (!mediaDrvCtx->dri_output->handle){
185 free(mediaDrvCtx->dri_output);
186 mediaDrvCtx->dri_output = nullptr;
187 goto error;
188 }
189
190 dso_handle = mediaDrvCtx->dri_output->handle;
191 dri_vtable = &mediaDrvCtx->dri_output->vtable;
192 if (!dso_get_symbols(dso_handle, dri_vtable, sizeof(*dri_vtable), symbols)){
193 dso_close(mediaDrvCtx->dri_output->handle);
194 free(mediaDrvCtx->dri_output);
195 mediaDrvCtx->dri_output = nullptr;
196 goto error;
197 }
198 return true;
199
200 error:
201 return false;
202 }
203
204 void
Rect_init(RECT * rect,int16_t destx,int16_t desty,uint16_t destw,uint16_t desth)205 inline Rect_init(
206 RECT *rect,
207 int16_t destx,
208 int16_t desty,
209 uint16_t destw,
210 uint16_t desth
211 )
212 {
213 if (nullptr == rect)
214 {
215 return;
216 }
217 rect->left = destx;
218 rect->top = desty;
219 rect->right = destx + destw;
220 rect->bottom = desty + desth;
221 }
222
DdiCodec_PutSurfaceLinuxVphalExt(VADriverContextP ctx,VASurfaceID surface,void * draw,int16_t srcx,int16_t srcy,uint16_t srcw,uint16_t srch,int16_t destx,int16_t desty,uint16_t destw,uint16_t desth,VARectangle * cliprects,uint32_t number_cliprects,uint32_t flags)223 VAStatus DdiCodec_PutSurfaceLinuxVphalExt(
224 VADriverContextP ctx,
225 VASurfaceID surface,
226 void *draw, /* Drawable of window system */
227 int16_t srcx,
228 int16_t srcy,
229 uint16_t srcw,
230 uint16_t srch,
231 int16_t destx,
232 int16_t desty,
233 uint16_t destw,
234 uint16_t desth,
235 VARectangle *cliprects, /* client supplied clip list */
236 uint32_t number_cliprects, /* number of clip rects in the clip list */
237 uint32_t flags /* de-interlacing flags */
238 )
239 {
240 GC gc;
241 int32_t depth;
242 Visual* visual;
243 XImage* ximg;
244 int32_t surf_width;
245 int32_t surf_height;
246 PDDI_MEDIA_CONTEXT mediaDrvCtx;
247 PDDI_MEDIA_SURFACE dstSurfBuffObj;
248
249 TypeXCreateGC pfn_XCreateGC = nullptr;
250 TypeXFreeGC pfn_XFreeGC = nullptr;
251 TypeXCreateImage pfn_XCreateImage = nullptr;
252 TypeXDestroyImage pfn_XDestroyImage = nullptr;
253 TypeXPutImage pfn_XPutImage = nullptr;
254
255 if (nullptr == draw)
256 {
257 return VA_STATUS_ERROR_UNKNOWN;
258 }
259
260 visual = nullptr;
261 ximg = nullptr;
262 mediaDrvCtx = DdiMedia_GetMediaContext(ctx);
263 dstSurfBuffObj = DdiMedia_GetSurfaceFromVASurfaceID(mediaDrvCtx, surface);
264
265 if (nullptr == dstSurfBuffObj)
266 {
267 return VA_STATUS_ERROR_UNKNOWN;
268 }
269
270 if (nullptr == mediaDrvCtx->X11FuncTable ||
271 nullptr == mediaDrvCtx->X11FuncTable->pfnXCreateGC ||
272 nullptr == mediaDrvCtx->X11FuncTable->pfnXFreeGC ||
273 nullptr == mediaDrvCtx->X11FuncTable->pfnXCreateImage ||
274 nullptr == mediaDrvCtx->X11FuncTable->pfnXDestroyImage ||
275 nullptr == mediaDrvCtx->X11FuncTable->pfnXPutImage)
276 {
277 return VA_STATUS_ERROR_UNKNOWN;
278 }
279
280 pfn_XCreateGC = (TypeXCreateGC)(mediaDrvCtx->X11FuncTable->pfnXCreateGC);
281 pfn_XFreeGC = (TypeXFreeGC)(mediaDrvCtx->X11FuncTable->pfnXFreeGC);
282 pfn_XCreateImage = (TypeXCreateImage)(mediaDrvCtx->X11FuncTable->pfnXCreateImage);
283 pfn_XDestroyImage = (TypeXDestroyImage)(mediaDrvCtx->X11FuncTable->pfnXDestroyImage);
284 pfn_XPutImage = (TypeXPutImage)(mediaDrvCtx->X11FuncTable->pfnXPutImage);
285
286 surf_width = dstSurfBuffObj->iWidth;
287 surf_height = dstSurfBuffObj->iHeight;
288
289 visual = DefaultVisual(ctx->native_dpy, ctx->x11_screen);
290 gc = (*pfn_XCreateGC)((Display*)ctx->native_dpy, (Drawable)draw, 0, nullptr);
291 depth = DefaultDepth(ctx->native_dpy, ctx->x11_screen);
292
293 if (TrueColor != visual->c_class)
294 {
295 DDI_ASSERTMESSAGE("Default visual of X display must be TrueColor.");
296 (*pfn_XFreeGC)((Display*)ctx->native_dpy, gc);
297 return VA_STATUS_ERROR_UNKNOWN;
298 }
299
300 ximg = (*pfn_XCreateImage)((Display*)ctx->native_dpy, visual, depth, ZPixmap, 0, nullptr,surf_width, surf_height, 32, 0 );
301
302 if (nullptr == ximg)
303 {
304 return VA_STATUS_ERROR_ALLOCATION_FAILED;
305 }
306
307 if (ximg->bits_per_pixel != 32)
308 {
309 DDI_ASSERTMESSAGE("Display uses %d bits/pixel this not supported.",ximg->bits_per_pixel);
310 (*pfn_XDestroyImage)(ximg);
311 (*pfn_XFreeGC)((Display*)ctx->native_dpy, gc);
312 return VA_STATUS_ERROR_UNKNOWN;
313 }
314
315 ximg->data = (char *)DdiMediaUtil_LockSurface(dstSurfBuffObj, (MOS_LOCKFLAG_READONLY | MOS_LOCKFLAG_WRITEONLY));
316
317 if (nullptr == ximg->data)
318 {
319 DdiMediaUtil_UnlockSurface(dstSurfBuffObj);
320 (*pfn_XDestroyImage)(ximg);
321 (*pfn_XFreeGC)((Display*)ctx->native_dpy, gc);
322 return VA_STATUS_ERROR_ALLOCATION_FAILED;
323 }
324
325 (*pfn_XPutImage)((Display*)ctx->native_dpy, (Drawable)draw, gc, ximg, 0, 0, destx, desty, surf_width, surf_height);
326
327 DdiMediaUtil_UnlockSurface(dstSurfBuffObj);
328 ximg->data = nullptr;
329
330 if (nullptr != ximg)
331 {
332 (*pfn_XDestroyImage)(ximg);
333 }
334
335 (*pfn_XFreeGC)((Display*)ctx->native_dpy, gc);
336
337 return VA_STATUS_SUCCESS;
338 }
339
DdiCodec_PutSurfaceLinuxHW(VADriverContextP ctx,VASurfaceID surface,void * draw,int16_t srcx,int16_t srcy,uint16_t srcw,uint16_t srch,int16_t destx,int16_t desty,uint16_t destw,uint16_t desth,VARectangle * cliprects,uint32_t number_cliprects,uint32_t flags)340 VAStatus DdiCodec_PutSurfaceLinuxHW(
341 VADriverContextP ctx,
342 VASurfaceID surface,
343 void* draw, /* Drawable of window system */
344 int16_t srcx,
345 int16_t srcy,
346 uint16_t srcw,
347 uint16_t srch,
348 int16_t destx,
349 int16_t desty,
350 uint16_t destw,
351 uint16_t desth,
352 VARectangle *cliprects, /* client supplied clip list */
353 uint32_t number_cliprects, /* number of clip rects in the clip list */
354 uint32_t flags /* de-interlacing flags */
355 )
356 {
357 VphalState *vpHal = nullptr;
358 int32_t ovRenderIndex = 0;
359 VPHAL_SURFACE Surf;
360 VPHAL_SURFACE target;
361 VPHAL_RENDER_PARAMS renderParams;
362 VPHAL_COLORFILL_PARAMS colorFill;
363
364 MOS_STATUS eStatus = MOS_STATUS_INVALID_PARAMETER;
365 RECT srcRect = { 0, 0, 0, 0 };
366 RECT dstRect = { 0, 0, 0, 0 };
367 PDDI_MEDIA_CONTEXT mediaCtx;
368 PDDI_MEDIA_SURFACE bufferObject;
369 uint32_t width,height,pitch;
370 uint32_t drawable_tiling_mode;
371 uint32_t drawable_swizzle_mode;
372 MOS_ALLOC_GFXRES_PARAMS allocParams;
373 MOS_TILE_TYPE tileType;
374
375 uint32_t ctxType;
376 PDDI_VP_CONTEXT vpCtx;
377 struct dri_drawable* dri_drawable = nullptr;
378 union dri_buffer* buffer = nullptr;
379
380 GMM_RESCREATE_PARAMS gmmParams;
381
382 mediaCtx = DdiMedia_GetMediaContext(ctx);
383 DDI_CHK_NULL(mediaCtx, "Null mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
384 DDI_CHK_NULL(mediaCtx->dri_output, "Null mediaDrvCtx->dri_output", VA_STATUS_ERROR_INVALID_PARAMETER);
385 DDI_CHK_NULL(mediaCtx->pSurfaceHeap, "Null mediaDrvCtx->pSurfaceHeap", VA_STATUS_ERROR_INVALID_PARAMETER);
386 DDI_CHK_NULL(mediaCtx->pGmmClientContext, "Null mediaCtx->pGmmClientContext", VA_STATUS_ERROR_INVALID_PARAMETER);
387 DDI_CHK_LESS((uint32_t)surface, mediaCtx->pSurfaceHeap->uiAllocatedHeapElements, "Invalid surfaceId", VA_STATUS_ERROR_INVALID_SURFACE);
388
389 struct dri_vtable * const dri_vtable = &mediaCtx->dri_output->vtable;
390 DDI_CHK_NULL(dri_vtable, "Null dri_vtable", VA_STATUS_ERROR_INVALID_PARAMETER);
391
392 dri_drawable = dri_vtable->get_drawable(ctx, (Drawable)draw);
393 assert(dri_drawable);
394 buffer = dri_vtable->get_rendering_buffer(ctx, dri_drawable);
395 assert(buffer);
396
397 bufferObject = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, surface);
398 DDI_CHK_NULL(bufferObject, "Null bufferObject", VA_STATUS_ERROR_INVALID_SURFACE);
399 DdiMediaUtil_MediaPrintFps();
400 pitch = bufferObject->iPitch;
401
402 vpCtx = nullptr;
403 if (nullptr != mediaCtx->pVpCtxHeap->pHeapBase)
404 {
405 vpCtx = (PDDI_VP_CONTEXT)DdiMedia_GetContextFromContextID(ctx, (VAContextID)(0 + DDI_MEDIA_VACONTEXTID_OFFSET_VP), &ctxType);
406 DDI_CHK_NULL(vpCtx, "Null vpCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
407 vpHal = vpCtx->pVpHal;
408 DDI_CHK_NULL(vpHal, "Null vpHal", VA_STATUS_ERROR_INVALID_PARAMETER);
409 }
410 else
411 {
412 return VA_STATUS_ERROR_INVALID_CONTEXT;
413 }
414
415 // Zero memory
416 MOS_ZeroMemory(&Surf, sizeof(Surf));
417 MOS_ZeroMemory(&target, sizeof(target));
418 MOS_ZeroMemory(&renderParams, sizeof(renderParams));
419 MOS_ZeroMemory(&gmmParams, sizeof(gmmParams));
420
421 renderParams.Component = COMPONENT_LibVA;
422
423 //Init source rectangle
424 Rect_init(&srcRect, srcx, srcy, srcw, srch);
425 Rect_init(&dstRect, destx, desty, destw, desth);
426
427 // Source Surface Information
428 Surf.Format = VpGetFormatFromMediaFormat(bufferObject->format); // Surface format
429 Surf.SurfType = SURF_IN_PRIMARY; // Surface type (context)
430 Surf.SampleType = SAMPLE_PROGRESSIVE;
431 Surf.ScalingMode = VPHAL_SCALING_AVS;
432
433 Surf.OsResource.Format = VpGetFormatFromMediaFormat(bufferObject->format);
434 Surf.OsResource.iWidth = bufferObject->iWidth;
435 Surf.OsResource.iHeight = bufferObject->iHeight;
436 Surf.OsResource.iPitch = bufferObject->iPitch;
437 Surf.OsResource.iCount = 0;
438 Surf.OsResource.TileType = VpGetTileTypeFromMediaTileType(bufferObject->TileType);
439 Surf.OsResource.bMapped = bufferObject->bMapped;
440 Surf.OsResource.bo = bufferObject->bo;
441 Surf.OsResource.pGmmResInfo = bufferObject->pGmmResourceInfo;
442
443 Surf.dwWidth = bufferObject->iWidth;
444 Surf.dwHeight = bufferObject->iHeight;
445 Surf.dwPitch = bufferObject->iPitch;
446 Surf.TileType = VpGetTileTypeFromMediaTileType(bufferObject->TileType);
447 Surf.ColorSpace = DdiVp_GetColorSpaceFromMediaFormat(bufferObject->format);
448 Surf.ExtendedGamut = false;
449 Surf.rcSrc = srcRect;
450 Surf.rcDst = dstRect;
451
452 MOS_LINUX_BO* drawable_bo = mos_bo_gem_create_from_name(mediaCtx->pDrmBufMgr, "rendering buffer", buffer->dri2.name);
453 if (nullptr == drawable_bo)
454 {
455 return VA_STATUS_ERROR_ALLOCATION_FAILED;
456 }
457
458 if (!mos_bo_get_tiling(drawable_bo, &drawable_tiling_mode, &drawable_swizzle_mode))
459 {
460 switch (drawable_tiling_mode)
461 {
462 case I915_TILING_Y:
463 tileType = MOS_TILE_Y;
464 break;
465 case I915_TILING_X:
466 tileType = MOS_TILE_X;
467 gmmParams.Flags.Info.TiledX = true;
468 break;
469 case I915_TILING_NONE:
470 tileType = MOS_TILE_LINEAR;
471 gmmParams.Flags.Info.Linear = true;
472 break;
473 default:
474 drawable_tiling_mode = I915_TILING_NONE;
475 tileType = MOS_TILE_LINEAR;
476 gmmParams.Flags.Info.Linear = true;
477 break;
478 target.OsResource.TileType = (MOS_TILE_TYPE)drawable_tiling_mode;
479 }
480 }
481 else
482 {
483 target.OsResource.TileType = (MOS_TILE_TYPE)I915_TILING_NONE;
484 tileType = MOS_TILE_LINEAR;
485 gmmParams.Flags.Info.Linear = true;
486 }
487 gmmParams.Flags.Info.LocalOnly = MEDIA_IS_SKU(&mediaCtx->SkuTable, FtrLocalMemory);
488
489 target.Format = Format_A8R8G8B8;
490 target.SurfType = SURF_OUT_RENDERTARGET;
491
492 //init target retangle
493 Rect_init(&srcRect, dri_drawable->x, dri_drawable->y, dri_drawable->width, dri_drawable->height);
494 Rect_init(&dstRect, dri_drawable->x, dri_drawable->y, dri_drawable->width, dri_drawable->height);
495
496 // Create GmmResourceInfo
497 gmmParams.Flags.Gpu.Video = true;
498 gmmParams.BaseWidth = dri_drawable->width;
499 gmmParams.BaseHeight = dri_drawable->height;
500 gmmParams.ArraySize = 1;
501 gmmParams.Type = RESOURCE_2D;
502 gmmParams.Format = GMM_FORMAT_R8G8B8A8_UNORM_TYPE;
503 //gmmParams.Format = GMM_FORMAT_B8G8R8A8_UNORM_TYPE;
504 target.OsResource.pGmmResInfo = mediaCtx->pGmmClientContext->CreateResInfoObject(&gmmParams);
505 if (nullptr == target.OsResource.pGmmResInfo)
506 {
507 mos_bo_unreference(drawable_bo);
508 return VA_STATUS_ERROR_ALLOCATION_FAILED;
509 }
510
511 target.OsResource.iWidth = dri_drawable->width;
512 target.OsResource.iHeight = dri_drawable->height;
513 target.OsResource.iPitch = buffer->dri2.pitch;
514 target.OsResource.Format = Format_A8R8G8B8;
515 target.OsResource.iCount = 0;
516 target.OsResource.bo = drawable_bo;
517 target.OsResource.pData = (uint8_t *)drawable_bo->virt;
518 target.OsResource.TileType = tileType;
519 target.TileType = tileType;
520 target.dwWidth = dri_drawable->width;
521 target.dwHeight = dri_drawable->height;
522 target.dwPitch = target.OsResource.iPitch;
523 target.ColorSpace = CSpace_sRGB;
524 target.ExtendedGamut = false;
525 target.rcSrc = srcRect;
526 target.rcDst = dstRect;
527
528 renderParams.uSrcCount = 1;
529 renderParams.uDstCount = 1;
530 renderParams.pSrc[0] = &Surf;
531 renderParams.pTarget[0] = ⌖
532 renderParams.pColorFillParams = &colorFill;
533 renderParams.pColorFillParams->Color = 0xFF000000;
534 renderParams.pColorFillParams->bYCbCr = false;
535 renderParams.pColorFillParams->CSpace = CSpace_sRGB;
536
537 DdiMediaUtil_LockMutex(&mediaCtx->PutSurfaceRenderMutex);
538 eStatus = vpHal->Render(&renderParams);
539 if (MOS_FAILED(eStatus))
540 {
541 DdiMediaUtil_UnLockMutex(&mediaCtx->PutSurfaceRenderMutex);
542 mos_bo_unreference(drawable_bo);
543 return VA_STATUS_ERROR_OPERATION_FAILED;
544 }
545
546 DdiMediaUtil_UnLockMutex(&mediaCtx->PutSurfaceRenderMutex);
547 mos_bo_unreference(drawable_bo);
548 target.OsResource.bo = nullptr;
549 DdiMediaUtil_LockMutex(&mediaCtx->PutSurfaceSwapBufferMutex);
550 dri_vtable->swap_buffer(ctx, dri_drawable);
551 DdiMediaUtil_UnLockMutex(&mediaCtx->PutSurfaceSwapBufferMutex);
552
553 mediaCtx->pGmmClientContext->DestroyResInfoObject(target.OsResource.pGmmResInfo);
554 target.OsResource.pGmmResInfo = nullptr;
555
556 return VA_STATUS_SUCCESS;
557 }
558
559 #ifndef ANDROID
560 // move from media_libva_putsurface_linux.c
DdiMedia_mask2shift(unsigned long mask)561 static unsigned long DdiMedia_mask2shift(unsigned long mask)
562 {
563 unsigned long shift = 0;
564 while((mask & 0x1) == 0)
565 {
566 mask = mask >> 1;
567 shift++;
568 }
569 return shift;
570 }
DdiMedia_yuv2pixel(uint32_t * pixel,int32_t y,int32_t u,int32_t v,unsigned long rshift,unsigned long rmask,unsigned long gshift,unsigned long gmask,unsigned long bshift,unsigned long bmask)571 static void DdiMedia_yuv2pixel(uint32_t *pixel, int32_t y, int32_t u, int32_t v,
572 unsigned long rshift, unsigned long rmask,
573 unsigned long gshift, unsigned long gmask,
574 unsigned long bshift, unsigned long bmask)
575 {
576 DDI_CHK_NULL(pixel, "nullptr pixel", );
577 /* Warning, magic values ahead */
578 int32_t r = y + ((351 * (v-128)) >> 8);
579 int32_t g = y - (((179 * (v-128)) + (86 * (u-128))) >> 8);
580 int32_t b = y + ((444 * (u-128)) >> 8);
581
582 if (r > 255) r = 255;
583 if (g > 255) g = 255;
584 if (b > 255) b = 255;
585 if (r < 0) r = 0;
586 if (g < 0) g = 0;
587 if (b < 0) b = 0;
588
589 *pixel = (uint32_t)(((r << rshift) & rmask) | ((g << gshift) & gmask) |((b << bshift) & bmask));
590 }
591
592 #define YUV_444P_TO_ARGB() \
593 srcY = umdContextY + pitch * srcy;\
594 srcU = srcY + pitch * ((mediaSurface->iHeight));\
595 srcV = srcU + pitch * ((mediaSurface->iHeight));\
596 \
597 for(y = srcy; y < (srcy + height); y += 1) \
598 {\
599 for(x = srcx; x < (srcx + width); x += 1) \
600 {\
601 y1 = *(srcY + x); \
602 u1 = *(srcU + x);\
603 v1 = *(srcV + x);\
604 \
605 pixel = (uint32_t *)(ximg->data + (y * ximg->bytes_per_line) + (x * (ximg->bits_per_pixel >> 3)));\
606 DdiMedia_yuv2pixel(pixel, y1, u1, v1, rshift, rmask, gshift, gmask, bshift, bmask);\
607 \
608 }\
609 srcY += pitch;\
610 srcU += pitch;\
611 srcV += pitch;\
612 }
613
614 #define YUV_422H_TO_ARGB()\
615 srcY = umdContextY + pitch * srcy;\
616 srcU = srcY + pitch * mediaSurface->iHeight;\
617 srcV = srcU + pitch * mediaSurface->iHeight;\
618 \
619 for(y = srcy; y < (srcy + height); y += 1)\
620 {\
621 for(x = srcx; x < (srcx + width); x += 2)\
622 {\
623 y1 = *(srcY + x);\
624 y2 = *(srcY + x + 1);\
625 u1 = *(srcU + x / 2);\
626 v1 = *(srcV + x / 2);\
627 \
628 pixel = (uint32_t *)(ximg->data + (y * ximg->bytes_per_line) + (x * (ximg->bits_per_pixel >> 3)));\
629 DdiMedia_yuv2pixel(pixel, y1, u1, v1, rshift, rmask, gshift, gmask, bshift, bmask);\
630 pixel = (uint32_t *)(ximg->data + (y * ximg->bytes_per_line) + ((x + 1) * (ximg->bits_per_pixel >> 3)));\
631 DdiMedia_yuv2pixel(pixel, y2, u1, v1, rshift, rmask, gshift, gmask, bshift, bmask);\
632 }\
633 srcY += pitch;\
634 srcU += pitch;\
635 srcV += pitch;\
636 }
637
638 #define YUV_422V_TO_ARGB() \
639 srcY = umdContextY + pitch * srcy;\
640 srcU = srcY + pitch * mediaSurface->iHeight;\
641 srcV = srcU + pitch * mediaSurface->iHeight / 2;\
642 \
643 for(y = srcy; y < (srcy + width); y += 1)\
644 {\
645 for(x = srcx; x < (srcx + height); x += 2)\
646 {\
647 y1 = *(srcY + x * pitch);\
648 y2 = *(srcY + (x + 1) * pitch);\
649 u1 = *(srcU + (x / 2) * pitch);\
650 v1 = *(srcV + (x / 2) * pitch);\
651 \
652 pixel = (uint32_t *)(ximg->data + (x * ximg->bytes_per_line) + (y * (ximg->bits_per_pixel >> 3)));\
653 DdiMedia_yuv2pixel(pixel, y1, u1, v1, rshift, rmask, gshift, gmask, bshift, bmask);\
654 pixel = (uint32_t *)(ximg->data + (x* ximg->bytes_per_line) + ((y + 1) * (ximg->bits_per_pixel >> 3)));\
655 DdiMedia_yuv2pixel(pixel, y2, u1, v1, rshift, rmask, gshift, gmask, bshift, bmask);\
656 \
657 }\
658 \
659 srcY += 1;\
660 srcU += 1;\
661 srcV += 1;\
662 }
663
664 #define YUV_IMC3_TO_ARGB() \
665 srcY = umdContextY + pitch * srcy;\
666 srcU = srcY + pitch * mediaSurface->iHeight;\
667 srcV = srcU + pitch * mediaSurface->iHeight / 2;\
668 \
669 for(y = srcy; y < (srcy + height); y += 2) \
670 {\
671 for(x = srcx; x < (srcx + width); x += 2) \
672 {\
673 y1 = *(srcY + x);\
674 y2 = *(srcY + x + 1);\
675 y3 = *(srcY + x + pitch);\
676 y4 = *(srcY + x + pitch + 1);\
677 \
678 u1 = *(srcU + x / 2);\
679 v1 = *(srcV + x / 2);\
680 \
681 pixel = (uint32_t *)(ximg->data + (y * ximg->bytes_per_line) + (x * (ximg->bits_per_pixel >> 3)));\
682 DdiMedia_yuv2pixel(pixel, y1, u1, v1, rshift, rmask, gshift, gmask, bshift, bmask);\
683 pixel = (uint32_t *)(ximg->data + (y * ximg->bytes_per_line) + ((x + 1) * (ximg->bits_per_pixel >> 3)));\
684 DdiMedia_yuv2pixel(pixel, y2, u1, v1, rshift, rmask, gshift, gmask, bshift, bmask);\
685 pixel = (uint32_t *)(ximg->data + ((y + 1) * ximg->bytes_per_line) + (x * (ximg->bits_per_pixel >> 3)));\
686 DdiMedia_yuv2pixel(pixel, y3, u1, v1, rshift, rmask, gshift, gmask, bshift, bmask);\
687 pixel = (uint32_t *)(ximg->data + ((y + 1) * ximg->bytes_per_line) + ((x + 1) * (ximg->bits_per_pixel >> 3)));\
688 DdiMedia_yuv2pixel(pixel, y4, u1, v1, rshift, rmask, gshift, gmask, bshift, bmask); \
689 }\
690 srcY += pitch * 2;\
691 srcU += pitch;\
692 srcV += pitch;\
693 }
694
695 #define YUV_411P_TO_ARGB() \
696 srcY = umdContextY + pitch * srcy;\
697 srcU = srcY + pitch * mediaSurface->iHeight;\
698 srcV = srcU + pitch * mediaSurface->iHeight;\
699 \
700 for(y = srcy; y < (srcy + height); y += 1)\
701 {\
702 for(x = srcx; x < (srcx + width); x += 4)\
703 {\
704 y1 = *(srcY + x);\
705 y2 = *(srcY + x + 1);\
706 y3 = *(srcY + x + 2);\
707 y4 = *(srcY + x + 3);\
708 \
709 u1 = *(srcU + x / 4);\
710 v1 = *(srcV + x / 4);\
711 \
712 pixel = (uint32_t *)(ximg->data + (y * ximg->bytes_per_line) + (x * (ximg->bits_per_pixel >> 3)));\
713 DdiMedia_yuv2pixel(pixel, y1, u1, v1, rshift, rmask, gshift, gmask, bshift, bmask);\
714 pixel = (uint32_t *)(ximg->data + (y * ximg->bytes_per_line) + ((x + 1) * (ximg->bits_per_pixel >> 3)));\
715 DdiMedia_yuv2pixel(pixel, y2, u1, v1, rshift, rmask, gshift, gmask, bshift, bmask);\
716 pixel = (uint32_t *)(ximg->data + ((y ) * ximg->bytes_per_line) + ((x+2) * (ximg->bits_per_pixel >> 3)));\
717 DdiMedia_yuv2pixel(pixel, y3, u1, v1, rshift, rmask, gshift, gmask, bshift, bmask);\
718 pixel = (uint32_t *)(ximg->data + ((y) * ximg->bytes_per_line) + ((x + 3) * (ximg->bits_per_pixel >> 3)));\
719 DdiMedia_yuv2pixel(pixel, y4, u1, v1, rshift, rmask, gshift, gmask, bshift, bmask);\
720 }\
721 srcY += pitch;\
722 srcU += pitch;\
723 srcV += pitch;\
724 }
725
726 #define YUV_400P_TO_ARGB()\
727 srcY = umdContextY + pitch * srcy;\
728 srcU = srcY;\
729 srcV = srcY;\
730 \
731 for(y = srcy; y < (srcy + height); y += 2)\
732 {\
733 for(x = srcx; x < (srcx + width); x += 2)\
734 {\
735 y1 = *(srcY + x);\
736 y2 = *(srcY + x + 1);\
737 y3 = *(srcY + x + pitch);\
738 y4 = *(srcY + x + pitch + 1);\
739 \
740 u1 = 128;\
741 v1 = 128;\
742 pixel = (uint32_t *)(ximg->data + (y * ximg->bytes_per_line) + (x * (ximg->bits_per_pixel >> 3)));\
743 DdiMedia_yuv2pixel(pixel, y1, u1, v1, rshift, rmask, gshift, gmask, bshift, bmask);\
744 pixel = (uint32_t *)(ximg->data + (y * ximg->bytes_per_line) + ((x + 1) * (ximg->bits_per_pixel >> 3)));\
745 DdiMedia_yuv2pixel(pixel, y2, u1, v1, rshift, rmask, gshift, gmask, bshift, bmask);\
746 pixel = (uint32_t *)(ximg->data + ((y + 1) * ximg->bytes_per_line) + (x * (ximg->bits_per_pixel >> 3)));\
747 DdiMedia_yuv2pixel(pixel, y3, u1, v1, rshift, rmask, gshift, gmask, bshift, bmask);\
748 pixel = (uint32_t *)(ximg->data + ((y + 1) * ximg->bytes_per_line) + ((x + 1) * (ximg->bits_per_pixel >> 3)));\
749 DdiMedia_yuv2pixel(pixel, y4, u1, v1, rshift, rmask, gshift, gmask, bshift, bmask);\
750 }\
751 srcY += pitch * 2;\
752 srcU += pitch;\
753 srcV += pitch;\
754 }
755
756 #define YUV_NV12_TO_ARGB()\
757 srcY = umdContextY + pitch * srcy;\
758 srcU = srcY + pitch * mediaSurface->iHeight;\
759 srcV = srcU + 1;\
760 \
761 for(y = srcy; y < (srcy + height); y += 2)\
762 {\
763 for(x = srcx; x < (srcx + width); x += 2)\
764 {\
765 y1 = *(srcY + x);\
766 y2 = *(srcY + x + 1);\
767 y3 = *(srcY + x + pitch);\
768 y4 = *(srcY + x + pitch + 1);\
769 \
770 u1 = *(srcU + x);\
771 v1 = *(srcU + x +1);\
772 pixel = (uint32_t *)(ximg->data + (y * ximg->bytes_per_line) + (x * (ximg->bits_per_pixel >> 3)));\
773 DdiMedia_yuv2pixel(pixel, y1, u1, v1, rshift, rmask, gshift, gmask, bshift, bmask);\
774 pixel = (uint32_t *)(ximg->data + (y * ximg->bytes_per_line) + ((x + 1) * (ximg->bits_per_pixel >> 3)));\
775 DdiMedia_yuv2pixel(pixel, y2, u1, v1, rshift, rmask, gshift, gmask, bshift, bmask);\
776 pixel = (uint32_t *)(ximg->data + ((y + 1) * ximg->bytes_per_line) + (x * (ximg->bits_per_pixel >> 3)));\
777 DdiMedia_yuv2pixel(pixel, y3, u1, v1, rshift, rmask, gshift, gmask, bshift, bmask);\
778 pixel = (uint32_t *)(ximg->data + ((y + 1) * ximg->bytes_per_line) + ((x + 1) * (ximg->bits_per_pixel >> 3)));\
779 DdiMedia_yuv2pixel(pixel, y4, u1, v1, rshift, rmask, gshift, gmask, bshift, bmask);\
780 }\
781 srcY += pitch * 2;\
782 srcU += pitch;\
783 }
784
DdiMedia_PutSurfaceLinuxSW(VADriverContextP ctx,VASurfaceID surface,void * draw,int16_t srcx,int16_t srcy,uint16_t srcw,uint16_t srch,int16_t destx,int16_t desty,uint16_t destw,uint16_t desth,VARectangle * cliprects,uint32_t number_cliprects,uint32_t flags)785 VAStatus DdiMedia_PutSurfaceLinuxSW(
786 VADriverContextP ctx,
787 VASurfaceID surface,
788 void* draw, /* Drawable of window system */
789 int16_t srcx,
790 int16_t srcy,
791 uint16_t srcw,
792 uint16_t srch,
793 int16_t destx,
794 int16_t desty,
795 uint16_t destw,
796 uint16_t desth,
797 VARectangle *cliprects, /* client supplied clip list */
798 uint32_t number_cliprects, /* number of clip rects in the clip list */
799 uint32_t flags /* de-interlacing flags */
800 )
801 {
802 PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
803 DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx.", VA_STATUS_ERROR_INVALID_CONTEXT);
804
805 DDI_CHK_NULL(mediaCtx->X11FuncTable, "nullptr X11FuncTable", VA_STATUS_ERROR_INVALID_CONTEXT);
806 DDI_CHK_NULL(mediaCtx->X11FuncTable->pfnXCreateGC, "nullptr pfnXCreateGC", VA_STATUS_ERROR_INVALID_CONTEXT);
807 DDI_CHK_NULL(mediaCtx->X11FuncTable->pfnXFreeGC, "nullptr pfnXFreeGC", VA_STATUS_ERROR_INVALID_CONTEXT);
808 DDI_CHK_NULL(mediaCtx->X11FuncTable->pfnXCreateImage, "nullptr pfnXCreateImage", VA_STATUS_ERROR_INVALID_CONTEXT);
809 DDI_CHK_NULL(mediaCtx->X11FuncTable->pfnXDestroyImage, "nullptr pfnXDestroyImage", VA_STATUS_ERROR_INVALID_CONTEXT);
810 DDI_CHK_NULL(mediaCtx->X11FuncTable->pfnXPutImage, "nullptr pfnXPutImage", VA_STATUS_ERROR_INVALID_CONTEXT);
811
812 TypeXCreateGC pfn_XCreateGC = (TypeXCreateGC)(mediaCtx->X11FuncTable->pfnXCreateGC);
813 TypeXFreeGC pfn_XFreeGC = (TypeXFreeGC)(mediaCtx->X11FuncTable->pfnXFreeGC);
814 TypeXCreateImage pfn_XCreateImage = (TypeXCreateImage)(mediaCtx->X11FuncTable->pfnXCreateImage);
815 TypeXDestroyImage pfn_XDestroyImage = (TypeXDestroyImage)(mediaCtx->X11FuncTable->pfnXDestroyImage);
816 TypeXPutImage pfn_XPutImage = (TypeXPutImage)(mediaCtx->X11FuncTable->pfnXPutImage);
817
818 DDI_MEDIA_SURFACE *mediaSurface = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, surface);
819 DDI_CHK_NULL(mediaSurface, "nullptr mediaSurface.", VA_STATUS_ERROR_INVALID_SURFACE);
820
821 uint16_t width = 0;
822 if (srcw <= destw)
823 width = srcw;
824 else
825 width = destw;
826
827 uint16_t height = 0;
828 if (srch <= desth)
829 height = srch;
830 else
831 height = desth;
832
833 int32_t pitch = mediaSurface->iPitch;
834 uint32_t adjustU = 1;
835 uint32_t adjustD = 1;
836 switch(mediaSurface->format)
837 {
838 case Media_Format_422H:
839 case Media_Format_444P:
840 case Media_Format_411P:
841 adjustU = 3;
842 adjustD = 1;
843 break;
844 case Media_Format_400P:
845 adjustU = 1;
846 adjustD = 1;
847 break;
848 case Media_Format_422V:
849 case Media_Format_IMC3:
850 adjustU = 2;
851 adjustD = 1;
852 break;
853 case Media_Format_NV12:
854 adjustU = 3;
855 adjustD = 2;
856 break;
857 default:
858 DDI_ASSERTMESSAGE("Color Format is not supported: %d",mediaSurface->format);
859 return VA_STATUS_ERROR_INVALID_VALUE;
860 }
861
862 uint32_t surfaceSize = pitch * mediaSurface->iHeight * adjustU / adjustD;
863 uint8_t *dispTempBuffer = (uint8_t *)malloc(surfaceSize);
864 if (dispTempBuffer == nullptr)
865 {
866 DdiMediaUtil_UnlockSurface(mediaSurface);
867 return VA_STATUS_ERROR_ALLOCATION_FAILED;
868 }
869
870 uint8_t *umdContextY = dispTempBuffer;
871 uint8_t *ptr = (uint8_t*)DdiMediaUtil_LockSurface(mediaSurface, (MOS_LOCKFLAG_READONLY | MOS_LOCKFLAG_WRITEONLY));
872 MOS_STATUS eStatus = MOS_SecureMemcpy(umdContextY, surfaceSize, ptr, surfaceSize);
873
874 if (eStatus != MOS_STATUS_SUCCESS)
875 {
876 MOS_FreeMemory(dispTempBuffer);
877 DDI_ASSERTMESSAGE("DDI:Failed to copy surface buffer data!");
878 return VA_STATUS_ERROR_OPERATION_FAILED;
879 }
880
881 Visual *visual = DefaultVisual(ctx->native_dpy, ctx->x11_screen);
882 GC gc = (*pfn_XCreateGC)((Display*)ctx->native_dpy, (Drawable)draw, 0, nullptr);
883
884 if (TrueColor != visual->c_class)
885 {
886 (*pfn_XFreeGC)((Display*)ctx->native_dpy, gc);
887 MOS_FreeMemory(dispTempBuffer);
888 return VA_STATUS_ERROR_UNKNOWN;
889 }
890
891 unsigned long rmask = visual->red_mask;
892 unsigned long gmask = visual->green_mask;
893 unsigned long bmask = visual->blue_mask;
894
895 unsigned long rshift = DdiMedia_mask2shift(rmask);
896 unsigned long gshift = DdiMedia_mask2shift(gmask);
897 unsigned long bshift = DdiMedia_mask2shift(bmask);
898
899 int32_t depth = DefaultDepth(ctx->native_dpy, ctx->x11_screen);
900 XImage *ximg = (*pfn_XCreateImage)((Display*)ctx->native_dpy, visual, depth, ZPixmap, 0, nullptr,width, height, 32, 0 );
901 if (ximg == nullptr)
902 {
903 MOS_FreeMemory(dispTempBuffer);
904 return VA_STATUS_ERROR_ALLOCATION_FAILED;
905 }
906
907 if (ximg->bits_per_pixel != 32)
908 {
909 (*pfn_XDestroyImage)(ximg);
910 (*pfn_XFreeGC)((Display*)ctx->native_dpy, gc);
911 MOS_FreeMemory(dispTempBuffer);
912 return VA_STATUS_ERROR_UNKNOWN;
913 }
914
915 ximg->data = (char *) malloc(ximg->bytes_per_line * MOS_ALIGN_CEIL(height, 2)); // If height is odd, need to add it by one for we process two lines per iteration
916 if (nullptr == ximg->data)
917 {
918 (*pfn_XDestroyImage)(ximg);
919 (*pfn_XFreeGC)((Display*)ctx->native_dpy, gc);
920 MOS_FreeMemory(dispTempBuffer);
921 return VA_STATUS_ERROR_ALLOCATION_FAILED;
922 }
923
924 int32_t x = 0;
925 int32_t y = 0;
926 uint8_t *srcY = nullptr;
927 uint8_t *srcU = nullptr;
928 uint8_t *srcV = nullptr;
929 uint32_t *pixel = nullptr;
930 int32_t y1 = 0, y2 = 0, y3 = 0, y4 = 0, u1 = 0, v1 = 0;
931 switch(mediaSurface->format)
932 {
933 case Media_Format_444P:
934 YUV_444P_TO_ARGB();
935 break;
936 case Media_Format_422H:
937 YUV_422H_TO_ARGB();
938 break;
939 case Media_Format_422V:
940 YUV_422V_TO_ARGB();
941 break;
942 case Media_Format_IMC3:
943 YUV_IMC3_TO_ARGB();
944 break;
945 case Media_Format_411P:
946 YUV_411P_TO_ARGB();
947 break;
948 case Media_Format_400P:
949 YUV_400P_TO_ARGB();
950 break;
951 case Media_Format_NV12:
952 YUV_NV12_TO_ARGB();
953 break;
954 default:
955 DDI_ASSERTMESSAGE("Color Format is not supported: %d", mediaSurface->format);
956 }
957
958 DdiMediaUtil_UnlockSurface(mediaSurface);
959
960 (*pfn_XPutImage)((Display*)ctx->native_dpy,(Drawable)draw, gc, ximg, 0, 0, destx, desty, destw, desth);
961
962 if (ximg != nullptr)
963 {
964 (*pfn_XDestroyImage)(ximg);
965 }
966 (*pfn_XFreeGC)((Display*)ctx->native_dpy, gc);
967 MOS_FreeMemory(dispTempBuffer);
968 return VA_STATUS_SUCCESS;
969 }
970
DdiMedia_PutSurfaceDummy(VADriverContextP ctx,VASurfaceID surface,void * draw,int16_t srcx,int16_t srcy,uint16_t srcw,uint16_t srch,int16_t destx,int16_t desty,uint16_t destw,uint16_t desth,VARectangle * cliprects,uint32_t number_cliprects,uint32_t flags)971 VAStatus DdiMedia_PutSurfaceDummy(
972 VADriverContextP ctx,
973 VASurfaceID surface,
974 void *draw, /* Drawable of window system */
975 int16_t srcx,
976 int16_t srcy,
977 uint16_t srcw,
978 uint16_t srch,
979 int16_t destx,
980 int16_t desty,
981 uint16_t destw,
982 uint16_t desth,
983 VARectangle *cliprects, /* client supplied clip list */
984 uint32_t number_cliprects, /* number of clip rects in the clip list */
985 uint32_t flags /* de-interlacing flags */
986 )
987 {
988 return VA_STATUS_ERROR_UNIMPLEMENTED;
989 }
990
991 #endif
992