xref: /aosp_15_r20/external/mesa3d/src/gallium/frontends/va/context.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /**************************************************************************
2  *
3  * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian.
4  * Copyright 2014 Advanced Micro Devices, Inc.
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sub license, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice and this permission notice (including the
16  * next paragraph) shall be included in all copies or substantial portions
17  * of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22  * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
23  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  *
27  **************************************************************************/
28 
29 #include "pipe/p_screen.h"
30 #include "pipe/p_video_codec.h"
31 #include "util/u_memory.h"
32 #include "util/u_handle_table.h"
33 #include "util/u_video.h"
34 #include "util/set.h"
35 #include "vl/vl_deint_filter.h"
36 #include "vl/vl_winsys.h"
37 
38 #include "va_private.h"
39 #ifdef HAVE_DRISW_KMS
40 #include "loader/loader.h"
41 #endif
42 
43 #include <va/va_drmcommon.h>
44 
45 static struct VADriverVTable vtable =
46 {
47    &vlVaTerminate,
48    &vlVaQueryConfigProfiles,
49    &vlVaQueryConfigEntrypoints,
50    &vlVaGetConfigAttributes,
51    &vlVaCreateConfig,
52    &vlVaDestroyConfig,
53    &vlVaQueryConfigAttributes,
54    &vlVaCreateSurfaces,
55    &vlVaDestroySurfaces,
56    &vlVaCreateContext,
57    &vlVaDestroyContext,
58    &vlVaCreateBuffer,
59    &vlVaBufferSetNumElements,
60    &vlVaMapBuffer,
61    &vlVaUnmapBuffer,
62    &vlVaDestroyBuffer,
63    &vlVaBeginPicture,
64    &vlVaRenderPicture,
65    &vlVaEndPicture,
66    &vlVaSyncSurface,
67    &vlVaQuerySurfaceStatus,
68    &vlVaQuerySurfaceError,
69    &vlVaPutSurface,
70    &vlVaQueryImageFormats,
71    &vlVaCreateImage,
72    &vlVaDeriveImage,
73    &vlVaDestroyImage,
74    &vlVaSetImagePalette,
75    &vlVaGetImage,
76    &vlVaPutImage,
77    &vlVaQuerySubpictureFormats,
78    &vlVaCreateSubpicture,
79    &vlVaDestroySubpicture,
80    &vlVaSubpictureImage,
81    &vlVaSetSubpictureChromakey,
82    &vlVaSetSubpictureGlobalAlpha,
83    &vlVaAssociateSubpicture,
84    &vlVaDeassociateSubpicture,
85    &vlVaQueryDisplayAttributes,
86    &vlVaGetDisplayAttributes,
87    &vlVaSetDisplayAttributes,
88    &vlVaBufferInfo,
89    &vlVaLockSurface,
90    &vlVaUnlockSurface,
91    NULL, /* DEPRECATED VaGetSurfaceAttributes */
92    &vlVaCreateSurfaces2,
93    &vlVaQuerySurfaceAttributes,
94    &vlVaAcquireBufferHandle,
95    &vlVaReleaseBufferHandle,
96 #if VA_CHECK_VERSION(1, 1, 0)
97    NULL, /* vaCreateMFContext */
98    NULL, /* vaMFAddContext */
99    NULL, /* vaMFReleaseContext */
100    NULL, /* vaMFSubmit */
101    NULL, /* vaCreateBuffer2 */
102    NULL, /* vaQueryProcessingRate */
103    &vlVaExportSurfaceHandle,
104 #endif
105 #if VA_CHECK_VERSION(1, 15, 0)
106    &vlVaSyncSurface2,
107    &vlVaSyncBuffer,
108 #endif
109 #if VA_CHECK_VERSION(1, 21, 0)
110    NULL, /* vaCopy */
111    &vlVaMapBuffer2,
112 #endif
113 };
114 
115 static struct VADriverVTableVPP vtable_vpp =
116 {
117    1,
118    &vlVaQueryVideoProcFilters,
119    &vlVaQueryVideoProcFilterCaps,
120    &vlVaQueryVideoProcPipelineCaps
121 };
122 
123 VA_PUBLIC_API VAStatus
VA_DRIVER_INIT_FUNC(VADriverContextP ctx)124 VA_DRIVER_INIT_FUNC(VADriverContextP ctx)
125 {
126    vlVaDriver *drv;
127 #if !defined(_WIN32) && defined(GALLIUM_ZINK)
128    /* TODO: this should work on Windows too */
129    const char *drivername = os_get_option_cached("LIBVA_DRIVER_NAME");
130    bool zink = drivername && !strcmp(drivername, "zink");
131 #endif
132 
133    if (!ctx)
134       return VA_STATUS_ERROR_INVALID_CONTEXT;
135 
136    drv = CALLOC(1, sizeof(vlVaDriver));
137    if (!drv)
138       return VA_STATUS_ERROR_ALLOCATION_FAILED;
139 
140    switch (ctx->display_type) {
141 #ifdef _WIN32
142    case VA_DISPLAY_WIN32: {
143       drv->vscreen = vl_win32_screen_create(ctx->native_dpy);
144       break;
145    }
146 #else
147    case VA_DISPLAY_ANDROID:
148       FREE(drv);
149       return VA_STATUS_ERROR_UNIMPLEMENTED;
150    case VA_DISPLAY_GLX:
151    case VA_DISPLAY_X11:
152 #ifdef GALLIUM_ZINK
153       if (zink)
154          drv->vscreen = vl_kopper_screen_create(ctx->native_dpy, ctx->x11_screen);
155 #endif
156       if (!drv->vscreen)
157          drv->vscreen = vl_dri3_screen_create(ctx->native_dpy, ctx->x11_screen);
158 #ifdef HAVE_X11_DRI2
159       if (!drv->vscreen)
160          drv->vscreen = vl_dri2_screen_create(ctx->native_dpy, ctx->x11_screen);
161 #endif
162       if (!drv->vscreen)
163          drv->vscreen = vl_xlib_swrast_screen_create(ctx->native_dpy, ctx->x11_screen);
164       break;
165    case VA_DISPLAY_WAYLAND:
166    case VA_DISPLAY_DRM:
167    case VA_DISPLAY_DRM_RENDERNODES: {
168       const struct drm_state *drm_info = (struct drm_state *) ctx->drm_state;
169 
170       if (!drm_info || drm_info->fd < 0) {
171          FREE(drv);
172          return VA_STATUS_ERROR_INVALID_PARAMETER;
173       }
174 #ifdef HAVE_DRISW_KMS
175       char* drm_driver_name = loader_get_driver_for_fd(drm_info->fd);
176       if(drm_driver_name) {
177          if (strcmp(drm_driver_name, "vgem") == 0)
178             drv->vscreen = vl_vgem_drm_screen_create(drm_info->fd);
179          FREE(drm_driver_name);
180       }
181 #endif
182       if(!drv->vscreen) {
183          /* VA_DISPLAY_WAYLAND uses the compositor's fd, like VA_DISPLAY_X11 does.
184           * In this case, tell vl_drm_screen_create to consider the DRI_PRIME env
185           * variable to let the user select a different device.
186           * The other display types receive a fd explicitely picked by the application,
187           * so don't try to override them.
188           */
189          bool honor_dri_prime = ctx->display_type == VA_DISPLAY_WAYLAND;
190          drv->vscreen = vl_drm_screen_create(drm_info->fd, honor_dri_prime);
191       }
192       break;
193    }
194 #endif
195    default:
196       FREE(drv);
197       return VA_STATUS_ERROR_INVALID_DISPLAY;
198    }
199 
200    if (!drv->vscreen)
201       goto error_screen;
202 
203    drv->pipe = pipe_create_multimedia_context(drv->vscreen->pscreen);
204    if (!drv->pipe)
205       goto error_pipe;
206 
207    drv->htab = handle_table_create();
208    if (!drv->htab)
209       goto error_htab;
210 
211    bool can_init_compositor = (drv->vscreen->pscreen->get_param(drv->vscreen->pscreen, PIPE_CAP_GRAPHICS) ||
212                               drv->vscreen->pscreen->get_param(drv->vscreen->pscreen, PIPE_CAP_COMPUTE));
213 
214    if (can_init_compositor) {
215       if (!vl_compositor_init(&drv->compositor, drv->pipe))
216          goto error_compositor;
217       if (!vl_compositor_init_state(&drv->cstate, drv->pipe))
218          goto error_compositor_state;
219 
220       vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, true, &drv->csc);
221       if (!vl_compositor_set_csc_matrix(&drv->cstate, (const vl_csc_matrix *)&drv->csc, 1.0f, 0.0f))
222          goto error_csc_matrix;
223    }
224 
225    (void) mtx_init(&drv->mutex, mtx_plain);
226 
227    ctx->pDriverData = (void *)drv;
228    ctx->version_major = 0;
229    ctx->version_minor = 1;
230    *ctx->vtable = vtable;
231    *ctx->vtable_vpp = vtable_vpp;
232    ctx->max_profiles = PIPE_VIDEO_PROFILE_MAX - PIPE_VIDEO_PROFILE_UNKNOWN - 1;
233    ctx->max_entrypoints = 2;
234    ctx->max_attributes = 1;
235    ctx->max_image_formats = VL_VA_MAX_IMAGE_FORMATS;
236    ctx->max_subpic_formats = 1;
237 #if VA_CHECK_VERSION(1, 15, 0)
238    ctx->max_display_attributes = 1; /* VADisplayPCIID */
239 #else
240    ctx->max_display_attributes = 0;
241 #endif
242 
243    snprintf(drv->vendor_string, sizeof(drv->vendor_string),
244             "Mesa Gallium driver " PACKAGE_VERSION " for %s",
245             drv->vscreen->pscreen->get_name(drv->vscreen->pscreen));
246    ctx->str_vendor = drv->vendor_string;
247 
248    return VA_STATUS_SUCCESS;
249 
250 error_csc_matrix:
251    if (can_init_compositor)
252       vl_compositor_cleanup_state(&drv->cstate);
253 
254 error_compositor_state:
255    if (can_init_compositor)
256       vl_compositor_cleanup(&drv->compositor);
257 
258 error_compositor:
259    handle_table_destroy(drv->htab);
260 
261 error_htab:
262    drv->pipe->destroy(drv->pipe);
263 
264 error_pipe:
265    drv->vscreen->destroy(drv->vscreen);
266 
267 error_screen:
268    FREE(drv);
269    return VA_STATUS_ERROR_ALLOCATION_FAILED;
270 }
271 
272 VAStatus
vlVaCreateContext(VADriverContextP ctx,VAConfigID config_id,int picture_width,int picture_height,int flag,VASurfaceID * render_targets,int num_render_targets,VAContextID * context_id)273 vlVaCreateContext(VADriverContextP ctx, VAConfigID config_id, int picture_width,
274                   int picture_height, int flag, VASurfaceID *render_targets,
275                   int num_render_targets, VAContextID *context_id)
276 {
277    vlVaDriver *drv;
278    vlVaContext *context;
279    vlVaConfig *config;
280    int is_vpp;
281    int min_supported_width, min_supported_height;
282    int max_supported_width, max_supported_height;
283 
284    if (!ctx)
285       return VA_STATUS_ERROR_INVALID_CONTEXT;
286 
287    drv = VL_VA_DRIVER(ctx);
288    mtx_lock(&drv->mutex);
289    config = handle_table_get(drv->htab, config_id);
290    mtx_unlock(&drv->mutex);
291 
292    if (!config)
293       return VA_STATUS_ERROR_INVALID_CONFIG;
294 
295    is_vpp = config->profile == PIPE_VIDEO_PROFILE_UNKNOWN && !picture_width &&
296             !picture_height && !flag && !render_targets && !num_render_targets;
297 
298    if (!(picture_width && picture_height) && !is_vpp)
299       return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
300 
301    context = CALLOC(1, sizeof(vlVaContext));
302    if (!context)
303       return VA_STATUS_ERROR_ALLOCATION_FAILED;
304 
305    if (is_vpp && !drv->vscreen->pscreen->get_video_param(drv->vscreen->pscreen,
306                                                          PIPE_VIDEO_PROFILE_UNKNOWN,
307                                                          PIPE_VIDEO_ENTRYPOINT_PROCESSING,
308                                                          PIPE_VIDEO_CAP_SUPPORTED)) {
309       context->decoder = NULL;
310    } else {
311       if (config->entrypoint != PIPE_VIDEO_ENTRYPOINT_PROCESSING) {
312          min_supported_width = drv->vscreen->pscreen->get_video_param(drv->vscreen->pscreen,
313                         config->profile, config->entrypoint,
314                         PIPE_VIDEO_CAP_MIN_WIDTH);
315          min_supported_height = drv->vscreen->pscreen->get_video_param(drv->vscreen->pscreen,
316                         config->profile, config->entrypoint,
317                         PIPE_VIDEO_CAP_MIN_HEIGHT);
318          max_supported_width = drv->vscreen->pscreen->get_video_param(drv->vscreen->pscreen,
319                         config->profile, config->entrypoint,
320                         PIPE_VIDEO_CAP_MAX_WIDTH);
321          max_supported_height = drv->vscreen->pscreen->get_video_param(drv->vscreen->pscreen,
322                         config->profile, config->entrypoint,
323                         PIPE_VIDEO_CAP_MAX_HEIGHT);
324 
325          if (picture_width < min_supported_width || picture_height < min_supported_height ||
326              picture_width > max_supported_width || picture_height > max_supported_height) {
327             FREE(context);
328             return VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
329          }
330       }
331       context->templat.profile = config->profile;
332       context->templat.entrypoint = config->entrypoint;
333       context->templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
334       context->templat.width = picture_width;
335       context->templat.height = picture_height;
336       context->templat.expect_chunked_decode = true;
337 
338       switch (u_reduce_video_profile(context->templat.profile)) {
339       case PIPE_VIDEO_FORMAT_MPEG12:
340       case PIPE_VIDEO_FORMAT_VC1:
341       case PIPE_VIDEO_FORMAT_MPEG4:
342          context->templat.max_references = 2;
343          break;
344 
345       case PIPE_VIDEO_FORMAT_MPEG4_AVC:
346          context->templat.max_references = 0;
347          if (config->entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE) {
348             context->desc.h264.pps = CALLOC_STRUCT(pipe_h264_pps);
349             if (!context->desc.h264.pps) {
350                FREE(context);
351                return VA_STATUS_ERROR_ALLOCATION_FAILED;
352             }
353             context->desc.h264.pps->sps = CALLOC_STRUCT(pipe_h264_sps);
354             if (!context->desc.h264.pps->sps) {
355                FREE(context->desc.h264.pps);
356                FREE(context);
357                return VA_STATUS_ERROR_ALLOCATION_FAILED;
358             }
359          }
360          break;
361 
362      case PIPE_VIDEO_FORMAT_HEVC:
363          if (config->entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE) {
364             context->desc.h265.pps = CALLOC_STRUCT(pipe_h265_pps);
365             if (!context->desc.h265.pps) {
366                FREE(context);
367                return VA_STATUS_ERROR_ALLOCATION_FAILED;
368             }
369             context->desc.h265.pps->sps = CALLOC_STRUCT(pipe_h265_sps);
370             if (!context->desc.h265.pps->sps) {
371                FREE(context->desc.h265.pps);
372                FREE(context);
373                return VA_STATUS_ERROR_ALLOCATION_FAILED;
374             }
375          }
376          break;
377 
378       case PIPE_VIDEO_FORMAT_VP9:
379          break;
380 
381       default:
382          break;
383       }
384    }
385 
386    context->desc.base.profile = config->profile;
387    context->desc.base.entry_point = config->entrypoint;
388    if (config->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
389       switch (u_reduce_video_profile(context->templat.profile)) {
390       case PIPE_VIDEO_FORMAT_MPEG4_AVC:
391          context->templat.max_references = PIPE_H264_MAX_REFERENCES;
392          for (unsigned i = 0; i < ARRAY_SIZE(context->desc.h264enc.rate_ctrl); i++) {
393             context->desc.h264enc.rate_ctrl[i].rate_ctrl_method = config->rc;
394             context->desc.h264enc.rate_ctrl[i].vbv_buffer_size = 20000000;
395             context->desc.h264enc.rate_ctrl[i].vbv_buf_lv = 64;
396             context->desc.h264enc.rate_ctrl[i].fill_data_enable = 1;
397             context->desc.h264enc.rate_ctrl[i].enforce_hrd = 1;
398             context->desc.h264enc.rate_ctrl[i].max_qp = 51;
399             context->desc.h264enc.rate_ctrl[i].frame_rate_num = 30;
400             context->desc.h264enc.rate_ctrl[i].frame_rate_den = 1;
401          }
402          context->desc.h264enc.frame_idx = util_hash_table_create_ptr_keys();
403          util_dynarray_init(&context->desc.h264enc.raw_headers, NULL);
404          break;
405       case PIPE_VIDEO_FORMAT_HEVC:
406          context->templat.max_references = PIPE_H265_MAX_REFERENCES;
407          for (unsigned i = 0; i < ARRAY_SIZE(context->desc.h265enc.rc); i++) {
408             context->desc.h265enc.rc[i].rate_ctrl_method = config->rc;
409             context->desc.h265enc.rc[i].vbv_buffer_size = 20000000;
410             context->desc.h265enc.rc[i].vbv_buf_lv = 64;
411             context->desc.h265enc.rc[i].fill_data_enable = 1;
412             context->desc.h265enc.rc[i].enforce_hrd = 1;
413             context->desc.h265enc.rc[i].max_qp = 51;
414             context->desc.h265enc.rc[i].frame_rate_num = 30;
415             context->desc.h265enc.rc[i].frame_rate_den = 1;
416          }
417          context->desc.h265enc.frame_idx = util_hash_table_create_ptr_keys();
418          util_dynarray_init(&context->desc.h265enc.raw_headers, NULL);
419          break;
420       case PIPE_VIDEO_FORMAT_AV1:
421          context->templat.max_references = PIPE_AV1_MAX_REFERENCES;
422          for (unsigned i = 0; i < ARRAY_SIZE(context->desc.av1enc.rc); i++) {
423             context->desc.av1enc.rc[i].rate_ctrl_method = config->rc;
424             context->desc.av1enc.rc[i].vbv_buffer_size = 20000000;
425             context->desc.av1enc.rc[i].vbv_buf_lv = 64;
426             context->desc.av1enc.rc[i].fill_data_enable = 1;
427             context->desc.av1enc.rc[i].enforce_hrd = 1;
428             context->desc.av1enc.rc[i].max_qp = 255;
429             context->desc.av1enc.rc[i].min_qp = 1;
430             context->desc.av1enc.rc[i].frame_rate_num = 30;
431             context->desc.av1enc.rc[i].frame_rate_den = 1;
432          }
433          break;
434       default:
435          break;
436       }
437 
438       mtx_lock(&drv->mutex);
439       context->decoder = drv->pipe->create_video_codec(drv->pipe, &context->templat);
440       mtx_unlock(&drv->mutex);
441       if (!context->decoder)
442          return VA_STATUS_ERROR_ALLOCATION_FAILED;
443    }
444 
445    context->surfaces = _mesa_set_create(NULL, _mesa_hash_pointer, _mesa_key_pointer_equal);
446 
447    mtx_lock(&drv->mutex);
448    *context_id = handle_table_add(drv->htab, context);
449    mtx_unlock(&drv->mutex);
450 
451    return VA_STATUS_SUCCESS;
452 }
453 
454 VAStatus
vlVaDestroyContext(VADriverContextP ctx,VAContextID context_id)455 vlVaDestroyContext(VADriverContextP ctx, VAContextID context_id)
456 {
457    vlVaDriver *drv;
458    vlVaContext *context;
459 
460    if (!ctx)
461       return VA_STATUS_ERROR_INVALID_CONTEXT;
462 
463    if (context_id == 0)
464       return VA_STATUS_ERROR_INVALID_CONTEXT;
465 
466    drv = VL_VA_DRIVER(ctx);
467    mtx_lock(&drv->mutex);
468    context = handle_table_get(drv->htab, context_id);
469    if (!context) {
470       mtx_unlock(&drv->mutex);
471       return VA_STATUS_ERROR_INVALID_CONTEXT;
472    }
473 
474    set_foreach(context->surfaces, entry) {
475       vlVaSurface *surf = (vlVaSurface *)entry->key;
476       assert(surf->ctx == context);
477       surf->ctx = NULL;
478       if (surf->fence && context->decoder && context->decoder->destroy_fence) {
479          context->decoder->destroy_fence(context->decoder, surf->fence);
480          surf->fence = NULL;
481       }
482    }
483    _mesa_set_destroy(context->surfaces, NULL);
484 
485    if (context->decoder) {
486       if (context->desc.base.entry_point == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
487          if (u_reduce_video_profile(context->decoder->profile) ==
488              PIPE_VIDEO_FORMAT_MPEG4_AVC) {
489             if (context->desc.h264enc.frame_idx)
490                _mesa_hash_table_destroy(context->desc.h264enc.frame_idx, NULL);
491             util_dynarray_fini(&context->desc.h264enc.raw_headers);
492          }
493          if (u_reduce_video_profile(context->decoder->profile) ==
494              PIPE_VIDEO_FORMAT_HEVC) {
495             if (context->desc.h265enc.frame_idx)
496                _mesa_hash_table_destroy(context->desc.h265enc.frame_idx, NULL);
497             util_dynarray_fini(&context->desc.h265enc.raw_headers);
498          }
499       } else {
500          if (u_reduce_video_profile(context->decoder->profile) ==
501                PIPE_VIDEO_FORMAT_MPEG4_AVC) {
502             FREE(context->desc.h264.pps->sps);
503             FREE(context->desc.h264.pps);
504          }
505          if (u_reduce_video_profile(context->decoder->profile) ==
506                PIPE_VIDEO_FORMAT_HEVC) {
507             FREE(context->desc.h265.pps->sps);
508             FREE(context->desc.h265.pps);
509          }
510       }
511       context->decoder->destroy(context->decoder);
512    }
513    if (context->blit_cs)
514       drv->pipe->delete_compute_state(drv->pipe, context->blit_cs);
515    if (context->deint) {
516       vl_deint_filter_cleanup(context->deint);
517       FREE(context->deint);
518    }
519    FREE(context->desc.base.decrypt_key);
520    FREE(context->bs.buffers);
521    FREE(context->bs.sizes);
522    FREE(context);
523    handle_table_remove(drv->htab, context_id);
524    mtx_unlock(&drv->mutex);
525 
526    return VA_STATUS_SUCCESS;
527 }
528 
529 VAStatus
vlVaTerminate(VADriverContextP ctx)530 vlVaTerminate(VADriverContextP ctx)
531 {
532    vlVaDriver *drv;
533 
534    if (!ctx)
535       return VA_STATUS_ERROR_INVALID_CONTEXT;
536 
537    drv = ctx->pDriverData;
538    vl_compositor_cleanup_state(&drv->cstate);
539    vl_compositor_cleanup(&drv->compositor);
540    drv->pipe->destroy(drv->pipe);
541    drv->vscreen->destroy(drv->vscreen);
542    handle_table_destroy(drv->htab);
543    mtx_destroy(&drv->mutex);
544    FREE(drv);
545 
546    return VA_STATUS_SUCCESS;
547 }
548