OSDN Git Service

Initial commit of libva
[android-x86/hardware-intel-common-libva.git] / src / va.c
1 /*
2  * @COPYRIGHT@ Intel Confidential - Unreleased Software
3  */
4
5 #include "X11/Xlib.h"
6 #include "va.h"
7 #include "va_backend.h"
8
9 #include "assert.h"
10 #include <stdarg.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <dlfcn.h>
14 #include <unistd.h>
15 #include <xf86dri.h>
16
17 #define DEFAULT_DRIVER_DIR      "/usr/X11R6/lib/modules/dri"
18 #define DRIVER_EXTENSION        "_drv_video.so"
19 #define DRIVER_INIT_FUNC        "__vaDriverInit_0_18"
20
21 #define CTX(dpy) ((VADriverContextP) dpy );
22 #define ASSERT_CONTEXT(dpy) assert( vaDbgContextIsValid(dpy) )
23 #define ASSERT          assert
24 #define CHECK_VTABLE(s, ctx, func) if (!va_checkVtable(ctx->vtable.va##func, #func)) s = VA_STATUS_ERROR_UNKNOWN;
25 #define CHECK_MAXIMUM(s, ctx, var) if (!va_checkMaximum(ctx->max_##var, #var)) s = VA_STATUS_ERROR_UNKNOWN;
26
27 #define TRACE(func) if (va_debug_trace) va_infoMessage("[TR] %s\n", #func);
28
29 static VADriverContextP pDriverContexts = NULL;
30 static int va_debug_trace = 0;
31
32 static Bool vaDbgContextIsValid(VADriverContextP arg_ctx)
33 {
34   VADriverContextP ctx = pDriverContexts;
35   
36   while (ctx)
37   {
38       if (ctx == arg_ctx)
39       {
40           return True;
41       }
42       ctx = ctx->pNext;
43   }
44   return False;
45 }
46
47 VADisplay vaGetDisplay (
48     NativeDisplay native_dpy    /* implementation specific */
49 )
50 {
51   VADisplay dpy = NULL;
52   VADriverContextP ctx = pDriverContexts;
53   
54   while (ctx)
55   {
56       if (ctx->x11_dpy == (Display *)native_dpy)
57       {
58           dpy = (VADisplay) ctx;
59           break;
60       }
61       ctx = ctx->pNext;
62   }
63   
64   if (!dpy)
65   {
66       /* create new entry */
67       ctx = (VADriverContextP) calloc(1, sizeof(struct VADriverContext));
68       ctx->pNext = pDriverContexts;
69       ctx->x11_dpy = (Display *) native_dpy;
70       pDriverContexts = ctx;
71       dpy = (VADisplay) ctx;
72   }
73   
74   return dpy;
75 }
76
77 static void va_errorMessage(const char *msg, ...)
78 {
79     va_list args;
80
81     fprintf(stderr, "libva error: ");
82     va_start(args, msg);
83     vfprintf(stderr, msg, args);
84     va_end(args);
85 }
86
87 static void va_infoMessage(const char *msg, ...)
88 {
89     va_list args;
90
91     fprintf(stderr, "libva: ");
92     va_start(args, msg);
93     vfprintf(stderr, msg, args);
94     va_end(args);
95 }
96
97 static Bool va_checkVtable(void *ptr, char *function)
98 {
99     if (!ptr)
100     {
101         va_errorMessage("No valid vtable entry for va%s\n", function);
102         return False;
103     }
104     return True;
105 }
106
107 static Bool va_checkMaximum(int value, char *variable)
108 {
109     if (!value)
110     {
111         va_errorMessage("Failed to define max_%s in init\n", variable);
112         return False;
113     }
114     return True;
115 }
116
117 static VAStatus va_getDriverName(VADriverContextP ctx, char **driver_name)
118 {
119     VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
120     int direct_capable;
121     int driver_major;
122     int driver_minor;
123     int driver_patch;
124     Bool result = True;
125     
126     *driver_name = NULL;
127     if (geteuid() == getuid())
128     {
129         /* don't allow setuid apps to use LIBVA_DRIVER_NAME */
130         if (getenv("LIBVA_DRIVER_NAME"))
131         {
132             /* For easier debugging */
133             *driver_name = strdup(getenv("LIBVA_DRIVER_NAME"));
134             return VA_STATUS_SUCCESS;
135         }
136     }
137     if (result)
138     {
139         result = XF86DRIQueryDirectRenderingCapable(ctx->x11_dpy, ctx->x11_screen, &direct_capable);
140         if (!result)
141         {
142             va_errorMessage("XF86DRIQueryDirectRenderingCapable failed\n");
143         }
144     }
145     if (result)
146     {
147         result = direct_capable;
148         if (!result)
149         {
150             va_errorMessage("XF86DRIQueryDirectRenderingCapable returned false\n");
151         }
152     }
153     if (result)
154     {
155         result = XF86DRIGetClientDriverName(ctx->x11_dpy, ctx->x11_screen, &driver_major, &driver_minor,
156                                             &driver_patch, driver_name);
157         if (!result)
158         {
159             va_errorMessage("XF86DRIGetClientDriverName returned false\n");
160         }
161     }
162     if (result)
163     {
164         vaStatus = VA_STATUS_SUCCESS;
165         va_infoMessage("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n",
166              driver_major, driver_minor, driver_patch, *driver_name, ctx->x11_screen);
167     }
168
169     return vaStatus;
170 }
171
172 static VAStatus va_openDriver(VADriverContextP ctx, char *driver_name)
173 {
174     VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN;
175     char *search_path;
176     char *saveptr;
177     char *driver_dir;
178     
179     if (geteuid() == getuid())
180     {
181         /* don't allow setuid apps to use LIBVA_DRIVERS_PATH */
182         search_path = getenv("LIBVA_DRIVERS_PATH");
183         if (!search_path)
184         {
185             search_path = getenv("LIBGL_DRIVERS_PATH");
186         }
187     }
188     if (!search_path)
189     {
190         search_path = DEFAULT_DRIVER_DIR;
191     }
192
193     search_path = strdup(search_path);
194     driver_dir = strtok_r(search_path, ":", &saveptr);
195     while(driver_dir)
196     {
197         void *handle = NULL;
198         char *driver_path = (char *) malloc( strlen(driver_dir) +
199                                              strlen(driver_name) +
200                                              strlen(DRIVER_EXTENSION) + 2 );
201         strcpy( driver_path, driver_dir );
202         strcat( driver_path, "/" );
203         strcat( driver_path, driver_name );
204         strcat( driver_path, DRIVER_EXTENSION );
205         
206         va_infoMessage("Trying to open %s\n", driver_path);
207
208         handle = dlopen( driver_path, RTLD_NOW | RTLD_GLOBAL );
209         if (!handle)
210         {
211             /* Don't give errors for non-existing files */
212             if (0 == access( driver_path, F_OK))
213             {   
214                 va_errorMessage("dlopen of %s failed: %s\n", driver_path, dlerror());
215             }
216         }
217         else
218         {
219             VADriverInit init_func;
220             init_func = (VADriverInit) dlsym(handle, DRIVER_INIT_FUNC);
221             if (!init_func)
222             {
223                 va_errorMessage("%s has no function %s\n", driver_path, DRIVER_INIT_FUNC);
224                 dlclose(handle);
225             }
226             else
227             {
228                 vaStatus = (*init_func)(ctx);
229
230                 if (VA_STATUS_SUCCESS == vaStatus)
231                 {
232                     CHECK_MAXIMUM(vaStatus, ctx, profiles);
233                     CHECK_MAXIMUM(vaStatus, ctx, entrypoints);
234                     CHECK_MAXIMUM(vaStatus, ctx, attributes);
235                     CHECK_VTABLE(vaStatus, ctx, Terminate);
236                     CHECK_VTABLE(vaStatus, ctx, QueryConfigProfiles);
237                     CHECK_VTABLE(vaStatus, ctx, QueryConfigEntrypoints);
238                     CHECK_VTABLE(vaStatus, ctx, QueryConfigAttributes);
239                     CHECK_VTABLE(vaStatus, ctx, CreateConfig);
240                     CHECK_VTABLE(vaStatus, ctx, GetConfigAttributes);
241                     CHECK_VTABLE(vaStatus, ctx, CreateSurfaces);
242                     CHECK_VTABLE(vaStatus, ctx, DestroySurface);
243                     CHECK_VTABLE(vaStatus, ctx, CreateContext);
244                     CHECK_VTABLE(vaStatus, ctx, DestroyContext);
245                     CHECK_VTABLE(vaStatus, ctx, CreateBuffer);
246                     CHECK_VTABLE(vaStatus, ctx, BufferData);
247                     CHECK_VTABLE(vaStatus, ctx, BufferSetNumElements);
248                     CHECK_VTABLE(vaStatus, ctx, MapBuffer);
249                     CHECK_VTABLE(vaStatus, ctx, UnmapBuffer);
250                     CHECK_VTABLE(vaStatus, ctx, DestroyBuffer);
251                     CHECK_VTABLE(vaStatus, ctx, BeginPicture);
252                     CHECK_VTABLE(vaStatus, ctx, RenderPicture);
253                     CHECK_VTABLE(vaStatus, ctx, EndPicture);
254                     CHECK_VTABLE(vaStatus, ctx, SyncSurface);
255                     CHECK_VTABLE(vaStatus, ctx, QuerySurfaceStatus);
256                     CHECK_VTABLE(vaStatus, ctx, PutSurface);
257                     CHECK_VTABLE(vaStatus, ctx, DbgCopySurfaceToBuffer);
258                 }
259                 if (VA_STATUS_SUCCESS != vaStatus)
260                 {
261                     va_errorMessage("%s init failed\n", driver_path);
262                     dlclose(handle);
263                 }
264                 if (VA_STATUS_SUCCESS == vaStatus)
265                 {
266                     ctx->handle = handle;
267                 }
268                 free(driver_path);
269                 break;
270             }
271         }
272         free(driver_path);
273         
274         driver_dir = strtok_r(NULL, ":", &saveptr);
275     }
276     
277     free(search_path);    
278     
279     return vaStatus;
280 }
281
282
283 /*
284  * Returns a short english description of error_status
285  */
286 const char *vaErrorStr(VAStatus error_status)
287 {
288     switch(error_status)
289     {
290         case VA_STATUS_SUCCESS:
291             return "success (no error)";
292         case VA_STATUS_ERROR_ALLOCATION_FAILED:
293             return "resource allocation failed";
294         case VA_STATUS_ERROR_INVALID_CONFIG:
295             return "invalid VAConfigID";
296         case VA_STATUS_ERROR_INVALID_CONTEXT:
297             return "invalid VAContextID";
298         case VA_STATUS_ERROR_INVALID_SURFACE:
299             return "invalid VASurfaceID";
300         case VA_STATUS_ERROR_INVALID_BUFFER:
301             return "invalid VABufferID";
302         case VA_STATUS_ERROR_ATTR_NOT_SUPPORTED:
303             return "attribute not supported";
304         case VA_STATUS_ERROR_MAX_NUM_EXCEEDED:
305             return "list argument exceeds maximum number";
306         case VA_STATUS_ERROR_UNSUPPORTED_PROFILE:
307             return "the requested VAProfile is not supported";
308         case VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT:
309             return "the requested VAEntryPoint is not supported";
310         case VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT:
311             return "the requested RT Format is not supported";
312         case VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE:
313             return "the requested VABufferType is not supported";
314         case VA_STATUS_ERROR_UNKNOWN:
315             return "unknown libva error";
316     }
317     return "unknwon libva error / description missing";
318 }
319       
320 VAStatus vaInitialize (
321     VADisplay dpy,
322     int *major_version,  /* out */
323     int *minor_version   /* out */
324 )
325 {
326   VADriverContextP ctx = CTX(dpy);
327   char *driver_name = NULL;
328   VAStatus vaStatus;
329   
330   ASSERT_CONTEXT(ctx);
331
332   va_debug_trace = (getenv("LIBVA_DEBUG_TRACE") != NULL);
333
334   vaStatus = va_getDriverName(ctx, &driver_name);
335   va_infoMessage("va_getDriverName() returns %d\n", vaStatus);
336   
337   if (VA_STATUS_SUCCESS == vaStatus)
338   {
339       vaStatus = va_openDriver(ctx, driver_name);
340       va_infoMessage("va_openDriver() returns %d\n", vaStatus);
341       
342       *major_version = ctx->version_major;
343       *minor_version = ctx->version_minor;
344   }
345
346   if (driver_name)
347   {
348       XFree(driver_name);
349   }
350   return vaStatus;
351 }
352
353
354 /*
355  * After this call, all library internal resources will be cleaned up
356  */ 
357 VAStatus vaTerminate (
358     VADisplay dpy
359 )
360 {
361   VAStatus vaStatus = VA_STATUS_SUCCESS;
362   VADriverContextP old_ctx = CTX(dpy);
363   ASSERT_CONTEXT(old_ctx);
364
365   if (old_ctx->handle)
366   {
367       vaStatus = old_ctx->vtable.vaTerminate(old_ctx);
368       dlclose(old_ctx->handle);
369       old_ctx->handle = NULL;
370   }
371
372   if (VA_STATUS_SUCCESS == vaStatus)
373   {
374       VADriverContextP *ctx = &pDriverContexts;
375
376       /* Throw away old_ctx */
377       while (*ctx)
378       {
379           if (*ctx == old_ctx)
380           {
381               *ctx = old_ctx->pNext;
382               old_ctx->pNext = NULL;
383               break;
384           }
385           ctx = &((*ctx)->pNext);
386       }
387       free(old_ctx);
388   }
389   return vaStatus;
390 }
391
392 /* Get maximum number of profiles supported by the implementation */
393 int vaMaxNumProfiles (
394     VADisplay dpy
395 )
396 {
397   VADriverContextP ctx = CTX(dpy);
398   ASSERT_CONTEXT(ctx);
399   
400   return ctx->max_profiles;
401 }
402
403 /* Get maximum number of entrypoints supported by the implementation */
404 int vaMaxNumEntrypoints (
405     VADisplay dpy
406 )
407 {
408   VADriverContextP ctx = CTX(dpy);
409   ASSERT_CONTEXT(ctx);
410   
411   return ctx->max_entrypoints;
412 }
413
414 /* Get maximum number of attributs supported by the implementation */
415 int vaMaxNumConfigAttributes (
416     VADisplay dpy
417 )
418 {
419   VADriverContextP ctx = CTX(dpy);
420   ASSERT_CONTEXT(ctx);
421   
422   return ctx->max_attributes;
423 }
424
425
426 VAStatus vaQueryConfigEntrypoints (
427     VADisplay dpy,
428     VAProfile profile,
429     VAEntrypoint *entrypoints,  /* out */
430     int *num_entrypoints        /* out */
431 )
432 {
433   VADriverContextP ctx = CTX(dpy);
434   ASSERT_CONTEXT(ctx);
435
436   TRACE(vaQueryConfigEntrypoints);
437   return ctx->vtable.vaQueryConfigEntrypoints ( ctx, profile, entrypoints, num_entrypoints);
438 }
439
440 VAStatus vaQueryConfigAttributes (
441     VADisplay dpy,
442     VAProfile profile,
443     VAEntrypoint entrypoint,
444     VAConfigAttrib *attrib_list, /* in/out */
445     int num_attribs
446 )
447 {
448   VADriverContextP ctx = CTX(dpy);
449   ASSERT_CONTEXT(ctx);
450
451   TRACE(vaQueryConfigAttributes);
452   return ctx->vtable.vaQueryConfigAttributes ( ctx, profile, entrypoint, attrib_list, num_attribs );
453 }
454
455 VAStatus vaQueryConfigProfiles (
456     VADisplay dpy,
457     VAProfile *profile_list,    /* out */
458     int *num_profiles           /* out */
459 )
460 {
461   VADriverContextP ctx = CTX(dpy);
462   ASSERT_CONTEXT(ctx);
463
464   TRACE(vaQueryConfigProfiles);
465   return ctx->vtable.vaQueryConfigProfiles ( ctx, profile_list, num_profiles );
466 }
467
468 VAStatus vaCreateConfig (
469     VADisplay dpy,
470     VAProfile profile, 
471     VAEntrypoint entrypoint, 
472     VAConfigAttrib *attrib_list,
473     int num_attribs,
474     VAConfigID *config_id /* out */
475 )
476 {
477   VADriverContextP ctx = CTX(dpy);
478   ASSERT_CONTEXT(ctx);
479
480   TRACE(vaCreateConfig);
481   return ctx->vtable.vaCreateConfig ( ctx, profile, entrypoint, attrib_list, num_attribs, config_id );
482 }
483
484 VAStatus vaGetConfigAttributes (
485     VADisplay dpy,
486     VAConfigID config_id, 
487     VAProfile *profile,         /* out */
488     VAEntrypoint *entrypoint,   /* out */
489     VAConfigAttrib *attrib_list,/* out */
490     int *num_attribs            /* out */
491 )
492 {
493   VADriverContextP ctx = CTX(dpy);
494   ASSERT_CONTEXT(ctx);
495
496   TRACE(vaGetConfigAttributes);
497   return ctx->vtable.vaGetConfigAttributes( ctx, config_id, profile, entrypoint, attrib_list, num_attribs);
498 }
499
500 VAStatus vaCreateSurfaces (
501     VADisplay dpy,
502     int width,
503     int height,
504     int format,
505     int num_surfaces,
506     VASurface *surfaces /* out */
507 )
508 {
509   VADriverContextP ctx = CTX(dpy);
510   ASSERT_CONTEXT(ctx);
511
512   TRACE(vaCreateSurfaces);
513   return ctx->vtable.vaCreateSurfaces( ctx, width, height, format, num_surfaces, surfaces );
514 }
515
516 VAStatus vaDestroySurface (
517     VADisplay dpy,
518     VASurface *surface_list,
519     int num_surfaces
520 )
521 {
522   VADriverContextP ctx = CTX(dpy);
523   ASSERT_CONTEXT(ctx);
524
525   TRACE(vaDestroySurface);
526   return ctx->vtable.vaDestroySurface( ctx, surface_list, num_surfaces );
527 }
528
529 VAStatus vaCreateContext (
530     VADisplay dpy,
531     VAConfigID config_id,
532     int picture_width,
533     int picture_height,
534     int flag,
535     VASurface *render_targets,
536     int num_render_targets,
537     VAContext *context          /* out */
538 )
539 {
540   VADriverContextP ctx = CTX(dpy);
541   ASSERT_CONTEXT(ctx);
542
543   TRACE(vaCreateContext);
544   return ctx->vtable.vaCreateContext( ctx, config_id, picture_width, picture_height,
545                                       flag, render_targets, num_render_targets, context );
546 }
547
548 VAStatus vaDestroyContext (
549     VADisplay dpy,
550     VAContext *context
551 )
552 {
553   VADriverContextP ctx = CTX(dpy);
554   ASSERT_CONTEXT(ctx);
555
556   TRACE(vaDestroyContext);
557   return ctx->vtable.vaDestroyContext( ctx, context );
558 }
559
560 VAStatus vaCreateBuffer (
561     VADisplay dpy,
562     VABufferType type,  /* in */
563     VABufferID *buf_id  /* out */
564 )
565 {
566   VADriverContextP ctx = CTX(dpy);
567   ASSERT_CONTEXT(ctx);
568
569   TRACE(vaCreateBuffer);
570   return ctx->vtable.vaCreateBuffer( ctx, type, buf_id);
571 }
572
573 VAStatus vaBufferData (
574     VADisplay dpy,
575     VABufferID buf_id,  /* in */
576     unsigned int size,  /* in */
577     unsigned int num_elements, /* in */
578     void *data          /* in */
579 )
580 {
581   VADriverContextP ctx = CTX(dpy);
582   ASSERT_CONTEXT(ctx);
583
584   TRACE(vaBufferData);
585   return ctx->vtable.vaBufferData( ctx, buf_id, size, num_elements, data);
586 }
587
588 VAStatus vaBufferSetNumElements (
589     VADisplay dpy,
590     VABufferID buf_id,  /* in */
591     unsigned int num_elements /* in */
592 )
593 {
594   VADriverContextP ctx = CTX(dpy);
595   ASSERT_CONTEXT(ctx);
596
597   TRACE(vaBufferSetNumElements);
598   return ctx->vtable.vaBufferSetNumElements( ctx, buf_id, num_elements );
599 }
600
601
602 VAStatus vaMapBuffer (
603     VADisplay dpy,
604     VABufferID buf_id,  /* in */
605     void **pbuf         /* out */
606 )
607 {
608   VADriverContextP ctx = CTX(dpy);
609   ASSERT_CONTEXT(ctx);
610
611   TRACE(vaMapBuffer);
612   return ctx->vtable.vaMapBuffer( ctx, buf_id, pbuf );
613 }
614
615 VAStatus vaUnmapBuffer (
616     VADisplay dpy,
617     VABufferID buf_id   /* in */
618 )
619 {
620   VADriverContextP ctx = CTX(dpy);
621   ASSERT_CONTEXT(ctx);
622
623   TRACE(vaUnmapBuffer);
624   return ctx->vtable.vaUnmapBuffer( ctx, buf_id );
625 }
626
627 VAStatus vaDestroyBuffer (
628     VADisplay dpy,
629     VABufferID buffer_id
630 )
631 {
632   VADriverContextP ctx = CTX(dpy);
633   ASSERT_CONTEXT(ctx);
634
635   TRACE(vaDestroyBuffer);
636   return ctx->vtable.vaDestroyBuffer( ctx, buffer_id );
637 }
638
639 VAStatus vaBeginPicture (
640     VADisplay dpy,
641     VAContext *context,
642     VASurface *render_target
643 )
644 {
645   VADriverContextP ctx = CTX(dpy);
646   ASSERT_CONTEXT(ctx);
647
648   TRACE(vaBeginPicture);
649   return ctx->vtable.vaBeginPicture( ctx, context, render_target );
650 }
651
652 VAStatus vaRenderPicture (
653     VADisplay dpy,
654     VAContext *context,
655     VABufferID *buffers,
656     int num_buffers
657 )
658 {
659   VADriverContextP ctx = CTX(dpy);
660   ASSERT_CONTEXT(ctx);
661
662   TRACE(vaRenderPicture);
663   return ctx->vtable.vaRenderPicture( ctx, context, buffers, num_buffers );
664 }
665
666 VAStatus vaEndPicture (
667     VADisplay dpy,
668     VAContext *context
669 )
670 {
671   VADriverContextP ctx = CTX(dpy);
672   ASSERT_CONTEXT(ctx);
673
674   TRACE(vaEndPicture);
675   return ctx->vtable.vaEndPicture( ctx, context );
676 }
677
678 VAStatus vaSyncSurface (
679     VADisplay dpy,
680     VAContext *context,
681     VASurface *render_target
682 )
683 {
684   VADriverContextP ctx = CTX(dpy);
685   ASSERT_CONTEXT(ctx);
686
687   TRACE(vaSyncSurface);
688   return ctx->vtable.vaSyncSurface( ctx, context, render_target );
689 }
690
691 VAStatus vaQuerySurfaceStatus (
692     VADisplay dpy,
693     VAContext *context,
694     VASurface *render_target,
695     VASurfaceStatus *status     /* out */
696 )
697 {
698   VADriverContextP ctx = CTX(dpy);
699   ASSERT_CONTEXT(ctx);
700
701   TRACE(vaQuerySurfaceStatus);
702   return ctx->vtable.vaQuerySurfaceStatus( ctx, context, render_target, status );
703 }
704
705 VAStatus vaPutSurface (
706     VADisplay dpy,
707     VASurface *surface,
708     Drawable draw, /* X Drawable */
709     short srcx,
710     short srcy,
711     unsigned short srcw,
712     unsigned short srch,
713     short destx,
714     short desty,
715     unsigned short destw,
716     unsigned short desth,
717     int flags /* de-interlacing flags */
718 )
719 {
720   VADriverContextP ctx = CTX(dpy);
721   ASSERT_CONTEXT(ctx);
722
723   TRACE(vaPutSurface);
724   return ctx->vtable.vaPutSurface( ctx, surface, draw, srcx, srcy, srcw, srch,
725                                    destx, desty, destw, desth, flags );
726 }
727
728 VAStatus vaDbgCopySurfaceToBuffer(VADisplay dpy,
729     VASurface *surface,
730     void **buffer, /* out */
731     unsigned int *stride /* out */
732 )
733 {
734   VADriverContextP ctx = CTX(dpy);
735   ASSERT_CONTEXT(ctx);
736
737   TRACE(vaDbgCopySurfaceToBuffer);
738   return ctx->vtable.vaDbgCopySurfaceToBuffer( ctx, surface, buffer, stride );
739 }
740