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]                 = &target;
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