1 /*****************************************************************************
2 * vlc_vdpau.c: VDPAU helper for VLC
3 *****************************************************************************
4 * Copyright (C) 2013 RĂ©mi Denis-Courmont
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
26 #include <vlc_common.h>
27 #include "vlc_vdpau.h"
29 #pragma GCC visibility push(default)
33 VdpGetErrorString *get_error_string;
34 VdpGetProcAddress *get_proc_address;
35 VdpGetApiVersion *get_api_version;
37 VdpGetInformationString *get_information_string;
38 VdpDeviceDestroy *device_destroy;
39 VdpGenerateCSCMatrix *generate_csc_matrix;
40 VdpVideoSurfaceQueryCapabilities *video_surface_query_capabilities;
41 VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *video_surface_query_get_put_bits_y_cb_cr_capabilities;
42 VdpVideoSurfaceCreate *video_surface_create;
43 VdpVideoSurfaceDestroy *video_surface_destroy;
44 VdpVideoSurfaceGetParameters *video_surface_get_parameters;
45 VdpVideoSurfaceGetBitsYCbCr *video_surface_get_bits_y_cb_cr;
46 VdpVideoSurfacePutBitsYCbCr *video_surface_put_bits_y_cb_cr;
47 VdpOutputSurfaceQueryCapabilities *output_surface_query_capabilities;
48 VdpOutputSurfaceQueryGetPutBitsNativeCapabilities *output_surface_query_get_put_bits_native_capabilities;
49 VdpOutputSurfaceQueryPutBitsIndexedCapabilities *output_surface_query_put_bits_indexed_capabilities;
50 VdpOutputSurfaceQueryPutBitsYCbCrCapabilities *output_surface_query_put_bits_y_cb_cr_capabilities;
51 VdpOutputSurfaceCreate *output_surface_create;
52 VdpOutputSurfaceDestroy *output_surface_destroy;
53 VdpOutputSurfaceGetParameters *output_surface_get_parameters;
54 VdpOutputSurfaceGetBitsNative *output_surface_get_bits_native;
55 VdpOutputSurfacePutBitsNative *output_surface_put_bits_native;
56 VdpOutputSurfacePutBitsIndexed *output_surface_put_bits_indexed;
57 VdpOutputSurfacePutBitsYCbCr *output_surface_put_bits_y_cb_cr;
58 VdpBitmapSurfaceQueryCapabilities *bitmap_surface_query_capabilities;
59 VdpBitmapSurfaceCreate *bitmap_surface_create;
60 VdpBitmapSurfaceDestroy *bitmap_surface_destroy;
61 VdpBitmapSurfaceGetParameters *bitmap_surface_get_parameters;
62 VdpBitmapSurfacePutBitsNative *bitmap_surface_put_bits_native;
66 VdpOutputSurfaceRenderOutputSurface *output_surface_render_output_surface;
67 VdpOutputSurfaceRenderBitmapSurface *output_surface_render_bitmap_surface;
68 void *output_surface_render_video_surface_luma;
69 VdpDecoderQueryCapabilities *decoder_query_capabilities;
70 VdpDecoderCreate *decoder_create;
71 VdpDecoderDestroy *decoder_destroy;
72 VdpDecoderGetParameters *decoder_get_parameters;
73 VdpDecoderRender *decoder_render;
74 VdpVideoMixerQueryFeatureSupport *video_mixer_query_feature_support;
75 VdpVideoMixerQueryParameterSupport *video_mixer_query_parameter_support;
76 VdpVideoMixerQueryAttributeSupport *video_mixer_query_attribute_support;
77 VdpVideoMixerQueryParameterValueRange *video_mixer_query_parameter_value_range;
78 VdpVideoMixerQueryAttributeValueRange *video_mixer_query_attribute_value_range;
79 VdpVideoMixerCreate *video_mixer_create;
80 VdpVideoMixerSetFeatureEnables *video_mixer_set_feature_enables;
81 VdpVideoMixerSetAttributeValues *video_mixer_set_attribute_values;
82 VdpVideoMixerGetFeatureSupport *video_mixer_get_feature_support;
83 VdpVideoMixerGetFeatureEnables *video_mixer_get_feature_enables;
84 VdpVideoMixerGetParameterValues *video_mixer_get_parameter_values;
85 VdpVideoMixerGetAttributeValues *video_mixer_get_attribute_values;
86 VdpVideoMixerDestroy *video_mixer_destroy;
87 VdpVideoMixerRender *video_mixer_render;
88 VdpPresentationQueueTargetDestroy *presentation_queue_target_destroy;
89 VdpPresentationQueueCreate *presentation_queue_create;
90 VdpPresentationQueueDestroy *presentation_queue_destroy;
91 VdpPresentationQueueSetBackgroundColor *presentation_queue_set_background_color;
92 VdpPresentationQueueGetBackgroundColor *presentation_queue_get_background_color;
95 VdpPresentationQueueGetTime *presentation_queue_get_time;
96 VdpPresentationQueueDisplay *presentation_queue_display;
97 VdpPresentationQueueBlockUntilSurfaceIdle *presentation_queue_block_until_surface_idle;
98 VdpPresentationQueueQuerySurfaceStatus *presentation_queue_query_surface_status;
99 VdpPreemptionCallbackRegister *preemption_callback_register;
108 }; /**< VDPAU function pointers table */
109 void *handle; /**< Shared library handle */
112 const char *vdp_get_error_string(const vdp_t *vdp, VdpStatus status)
114 return vdp->vt.get_error_string(status);
117 static const char *vdp_get_error_string_fallback(const vdp_t *vdp,
121 return (status != VDP_STATUS_OK) ? "Unknown error" : "No error";
124 VdpStatus vdp_get_proc_address(const vdp_t *vdp, VdpDevice device,
125 VdpFuncId func_id, void **func_ptr)
127 return vdp->vt.get_proc_address(device, func_id, func_ptr);
130 VdpStatus vdp_get_api_version(const vdp_t *vdp, uint32_t *ver)
132 return vdp->vt.get_api_version(ver);
135 VdpStatus vdp_get_information_string(const vdp_t *vdp, const char **str)
137 return vdp->vt.get_information_string(str);
141 VdpStatus vdp_device_destroy(const vdp_t *vdp, VdpDevice device)
143 return vdp->vt.device_destroy(device);
146 VdpStatus vdp_generate_csc_matrix(const vdp_t *vdp, const VdpProcamp *procamp,
147 VdpColorStandard standard, VdpCSCMatrix *csc_matrix)
149 VdpProcamp buf, *copy = NULL;
156 return vdp->vt.generate_csc_matrix(copy, standard, csc_matrix);
159 /*** Video surface ***/
160 VdpStatus vdp_video_surface_query_capabilities(const vdp_t *vdp, VdpDevice dev,
161 VdpChromaType type, VdpBool *ok, uint32_t *mw, uint32_t *mh)
163 return vdp->vt.video_surface_query_capabilities(dev, type, ok, mw, mh);
166 VdpStatus vdp_video_surface_query_get_put_bits_y_cb_cr_capabilities(
167 const vdp_t *vdp, VdpDevice device, VdpChromaType type, VdpYCbCrFormat fmt,
170 return vdp->vt.video_surface_query_get_put_bits_y_cb_cr_capabilities(
171 device, type, fmt, ok);
174 VdpStatus vdp_video_surface_create(const vdp_t *vdp, VdpDevice device,
175 VdpChromaType chroma, uint32_t w, uint32_t h, VdpVideoSurface *surface)
177 return vdp->vt.video_surface_create(device, chroma, w, h, surface);
180 VdpStatus vdp_video_surface_destroy(const vdp_t *vdp, VdpVideoSurface surface)
182 return vdp->vt.video_surface_destroy(surface);
185 VdpStatus vdp_video_surface_get_parameters(const vdp_t *vdp,
186 VdpVideoSurface surface, VdpChromaType *type, uint32_t *w, uint32_t *h)
188 return vdp->vt.video_surface_get_parameters(surface, type, w, h);
191 VdpStatus vdp_video_surface_get_bits_y_cb_cr(const vdp_t *vdp,
192 VdpVideoSurface surface, VdpYCbCrFormat fmt,
193 void *const *data, uint32_t const *pitches)
195 return vdp->vt.video_surface_get_bits_y_cb_cr(surface, fmt, data, pitches);
198 VdpStatus vdp_video_surface_put_bits_y_cb_cr(const vdp_t *vdp,
199 VdpVideoSurface surface, VdpYCbCrFormat fmt,
200 const void *const *data, uint32_t const *pitches)
202 return vdp->vt.video_surface_put_bits_y_cb_cr(surface, fmt, data, pitches);
205 /*** Output surface ***/
206 VdpStatus vdp_output_surface_query_capabilities(const vdp_t *vdp,
207 VdpDevice device, VdpRGBAFormat fmt, VdpBool *ok,
208 uint32_t *max_width, uint32_t *max_height)
210 return vdp->vt.output_surface_query_capabilities(device, fmt, ok,
211 max_width, max_height);
214 VdpStatus vdp_output_surface_query_get_put_bits_native_capabilities(
215 const vdp_t *vdp, VdpDevice device, VdpRGBAFormat fmt, VdpBool *ok)
217 return vdp->vt.output_surface_query_get_put_bits_native_capabilities(
221 VdpStatus vdp_output_surface_query_put_bits_indexed_capabilities(
222 const vdp_t *vdp, VdpDevice device, VdpRGBAFormat fmt,
223 VdpIndexedFormat idxfmt, VdpColorTableFormat colfmt, VdpBool *ok)
225 return vdp->vt.output_surface_query_put_bits_indexed_capabilities(device,
226 fmt, idxfmt, colfmt, ok);
229 VdpStatus vdp_output_surface_query_put_bits_y_cb_cr_capabilities(
230 const vdp_t *vdp, VdpDevice device,
231 VdpRGBAFormat fmt, VdpYCbCrFormat yccfmt, VdpBool *ok)
233 return vdp->vt.output_surface_query_put_bits_y_cb_cr_capabilities(device,
237 VdpStatus vdp_output_surface_create(const vdp_t *vdp, VdpDevice device,
238 VdpRGBAFormat fmt, uint32_t w, uint32_t h, VdpOutputSurface *surface)
240 return vdp->vt.output_surface_create(device, fmt, w, h, surface);
243 VdpStatus vdp_output_surface_destroy(const vdp_t *vdp,
244 VdpOutputSurface surface)
246 return vdp->vt.output_surface_destroy(surface);
249 VdpStatus vdp_output_surface_get_parameters(const vdp_t *vdp,
250 VdpOutputSurface surface, VdpRGBAFormat *fmt, uint32_t *w, uint32_t *h)
252 return vdp->vt.output_surface_get_parameters(surface, fmt, w, h);
255 VdpStatus vdp_output_surface_get_bits_native(const vdp_t *vdp,
256 VdpOutputSurface surface, const VdpRect *src,
257 void *const *data, uint32_t const *pitches)
259 return vdp->vt.output_surface_get_bits_native(surface, src, data, pitches);
262 VdpStatus vdp_output_surface_put_bits_native(const vdp_t *vdp,
263 VdpOutputSurface surface, const void *const *data, uint32_t const *pitches,
266 return vdp->vt.output_surface_put_bits_native(surface, data, pitches, dst);
269 VdpStatus vdp_output_surface_put_bits_indexed(const vdp_t *vdp,
270 VdpOutputSurface surface, VdpIndexedFormat fmt, const void *const *data,
271 const uint32_t *pitch, const VdpRect *dst,
272 VdpColorTableFormat tabfmt, const void *tab)
274 return vdp->vt.output_surface_put_bits_indexed(surface, fmt, data, pitch,
278 VdpStatus vdp_output_surface_put_bits_y_cb_cr(const vdp_t *vdp,
279 VdpOutputSurface surface, VdpYCbCrFormat fmt, const void *const *data,
280 const uint32_t *pitches, const VdpRect *dst, const VdpCSCMatrix *mtx)
282 return vdp->vt.output_surface_put_bits_y_cb_cr(surface, fmt, data,
286 /*** Bitmap surface ***/
287 VdpStatus vdp_bitmap_surface_query_capabilities(const vdp_t *vdp,
288 VdpDevice device, VdpRGBAFormat fmt, VdpBool *ok, uint32_t *w, uint32_t *h)
290 return vdp->vt.bitmap_surface_query_capabilities(device, fmt, ok, w, h);
293 VdpStatus vdp_bitmap_surface_create(const vdp_t *vdp, VdpDevice device,
294 VdpRGBAFormat fmt, uint32_t w, uint32_t h, VdpBool fq,
295 VdpBitmapSurface *surface)
297 return vdp->vt.bitmap_surface_create(device, fmt, w, h, fq, surface);
300 VdpStatus vdp_bitmap_surface_destroy(const vdp_t *vdp,
301 VdpBitmapSurface surface)
303 return vdp->vt.bitmap_surface_destroy(surface);
306 VdpStatus vdp_bitmap_surface_get_parameters(const vdp_t *vdp,
307 VdpBitmapSurface surface, VdpRGBAFormat *fmt, uint32_t *w, uint32_t *h,
310 return vdp->vt.bitmap_surface_get_parameters(surface, fmt, w, h, fq);
313 VdpStatus vdp_bitmap_surface_put_bits_native(const vdp_t *vdp,
314 VdpBitmapSurface surface, const void *const *data, const uint32_t *pitch,
317 return vdp->vt.bitmap_surface_put_bits_native(surface, data, pitch, rect);
320 VdpStatus vdp_output_surface_render_output_surface(const vdp_t *vdp,
321 VdpOutputSurface dst_surface, const VdpRect *dst_rect,
322 VdpOutputSurface src_surface, const VdpRect *src_rect,
323 const VdpColor *colors,
324 const VdpOutputSurfaceRenderBlendState const *state, uint32_t flags)
326 return vdp->vt.output_surface_render_output_surface(dst_surface, dst_rect,
327 src_surface, src_rect, colors, state, flags);
330 VdpStatus vdp_output_surface_render_bitmap_surface(const vdp_t *vdp,
331 VdpOutputSurface dst_surface, const VdpRect *dst_rect,
332 VdpBitmapSurface src_surface, const VdpRect *src_rect,
333 const VdpColor *colors,
334 const VdpOutputSurfaceRenderBlendState *state, uint32_t flags)
336 return vdp->vt.output_surface_render_bitmap_surface(dst_surface, dst_rect,
337 src_surface, src_rect, colors, state, flags);
341 VdpStatus vdp_decoder_query_capabilities(const vdp_t *vdp, VdpDevice device,
342 VdpDecoderProfile profile, VdpBool *ok, uint32_t *l, uint32_t *m,
343 uint32_t *w, uint32_t *h)
345 return vdp->vt.decoder_query_capabilities(device, profile, ok, l, m, w, h);
348 VdpStatus vdp_decoder_create(const vdp_t *vdp, VdpDevice device,
349 VdpDecoderProfile profile, uint32_t w, uint32_t h, uint32_t refs,
352 return vdp->vt.decoder_create(device, profile, w, h, refs, decoder);
355 VdpStatus vdp_decoder_destroy(const vdp_t *vdp, VdpDecoder decoder)
357 return vdp->vt.decoder_destroy(decoder);
360 VdpStatus vdp_decoder_get_parameters(const vdp_t *vdp, VdpDecoder decoder,
361 VdpDecoderProfile *profile, uint32_t *w, uint32_t *h)
363 return vdp->vt.decoder_get_parameters(decoder, profile, w, h);
366 VdpStatus vdp_decoder_render(const vdp_t *vdp, VdpDecoder decoder,
367 VdpVideoSurface target, const VdpPictureInfo *info,
368 uint32_t bufv, const VdpBitstreamBuffer *bufc)
371 return vdp->vt.decoder_render(decoder, target, info, bufv, bufc);
374 /*** Video mixer ***/
375 VdpStatus vdp_video_mixer_query_feature_support(const vdp_t *vdp,
376 VdpDevice device, VdpVideoMixerFeature feature, VdpBool *ok)
378 return vdp->vt.video_mixer_query_feature_support(device, feature, ok);
381 VdpStatus vdp_video_mixer_query_parameter_support(const vdp_t *vdp,
382 VdpDevice device, VdpVideoMixerParameter parameter, VdpBool *ok)
384 return vdp->vt.video_mixer_query_parameter_support(device, parameter, ok);
387 VdpStatus vdp_video_mixer_query_attribute_support(const vdp_t *vdp,
388 VdpDevice device, VdpVideoMixerAttribute attribute, VdpBool *ok)
390 return vdp->vt.video_mixer_query_attribute_support(device, attribute, ok);
393 VdpStatus vdp_video_mixer_query_parameter_value_range(const vdp_t *vdp,
394 VdpDevice device, VdpVideoMixerParameter parameter, void *min, void *max)
396 return vdp->vt.video_mixer_query_parameter_value_range(device, parameter,
400 VdpStatus vdp_video_mixer_query_attribute_value_range(const vdp_t *vdp,
401 VdpDevice device, VdpVideoMixerAttribute attribute, void *min, void *max)
403 return vdp->vt.video_mixer_query_attribute_value_range(device, attribute,
407 VdpStatus vdp_video_mixer_create(const vdp_t *vdp, VdpDevice device,
408 uint32_t featc, const VdpVideoMixerFeature *featv,
409 uint32_t parmc, const VdpVideoMixerParameter *parmv,
410 const void *const *parmvalv, VdpVideoMixer *mixer)
412 return vdp->vt.video_mixer_create(device, featc, featv, parmc, parmv,
416 VdpStatus vdp_video_mixer_set_feature_enables(const vdp_t *vdp,
417 VdpVideoMixer mixer, uint32_t count, const VdpVideoMixerFeature *ids,
418 const VdpBool *values)
420 return vdp->vt.video_mixer_set_feature_enables(mixer, count, ids, values);
423 VdpStatus vdp_video_mixer_set_attribute_values(const vdp_t *vdp,
424 VdpVideoMixer mixer, uint32_t count,
425 const VdpVideoMixerAttribute const *ids, const void *const *values)
427 return vdp->vt.video_mixer_set_attribute_values(mixer, count, ids, values);
430 VdpStatus vdp_video_mixer_get_feature_support(const vdp_t *vdp,
431 VdpVideoMixer mixer, uint32_t count, const VdpVideoMixerFeature *ids,
434 return vdp->vt.video_mixer_get_feature_support(mixer, count, ids, values);
437 VdpStatus vdp_video_mixer_get_feature_enables(const vdp_t *vdp,
438 VdpVideoMixer mixer, uint32_t count, const VdpVideoMixerFeature *ids,
441 return vdp->vt.video_mixer_get_feature_enables(mixer, count, ids, values);
444 VdpStatus vdp_video_mixer_get_parameter_values(const vdp_t *vdp,
445 VdpVideoMixer mixer, uint32_t count, const VdpVideoMixerParameter *ids,
448 return vdp->vt.video_mixer_get_parameter_values(mixer, count, ids, values);
451 VdpStatus vdp_video_mixer_get_attribute_values(const vdp_t *vdp,
452 VdpVideoMixer mixer, uint32_t count, const VdpVideoMixerAttribute *ids,
455 return vdp->vt.video_mixer_get_attribute_values(mixer, count, ids, values);
458 VdpStatus vdp_video_mixer_destroy(const vdp_t *vdp, VdpVideoMixer mixer)
460 return vdp->vt.video_mixer_destroy(mixer);
463 VdpStatus vdp_video_mixer_render(const vdp_t *vdp, VdpVideoMixer mixer,
464 VdpOutputSurface bgsurface, const VdpRect *bgrect,
465 VdpVideoMixerPictureStructure pic_struct, uint32_t prev_count,
466 const VdpVideoSurface *prev, VdpVideoSurface cur, uint32_t next_count,
467 const VdpVideoSurface *next, const VdpRect *src_rect,
468 VdpOutputSurface dst, const VdpRect *dst_rect, const VdpRect *dst_v_rect,
469 uint32_t layerc, const VdpLayer *layerv)
471 return vdp->vt.video_mixer_render(mixer, bgsurface, bgrect, pic_struct,
472 prev_count, prev, cur, next_count, next, src_rect, dst, dst_rect,
473 dst_v_rect, layerc, layerv);
476 /*** Presentation queue ***/
477 VdpStatus vdp_presentation_queue_target_destroy(const vdp_t *vdp,
478 VdpPresentationQueueTarget target)
480 return vdp->vt.presentation_queue_target_destroy(target);
483 VdpStatus vdp_presentation_queue_create(const vdp_t *vdp, VdpDevice device,
484 VdpPresentationQueueTarget target, VdpPresentationQueue *queue)
486 return vdp->vt.presentation_queue_create(device, target, queue);
489 VdpStatus vdp_presentation_queue_destroy(const vdp_t *vdp,
490 VdpPresentationQueue queue)
492 return vdp->vt.presentation_queue_destroy(queue);
495 VdpStatus vdp_presentation_queue_set_background_color(const vdp_t *vdp,
496 VdpPresentationQueue queue, const VdpColor *color)
498 VdpColor bak = *color;
499 return vdp->vt.presentation_queue_set_background_color(queue, &bak);
502 VdpStatus vdp_presentation_queue_get_background_color(const vdp_t *vdp,
503 VdpPresentationQueue queue, VdpColor *color)
505 return vdp->vt.presentation_queue_get_background_color(queue, color);
508 VdpStatus vdp_presentation_queue_get_time(const vdp_t *vdp,
509 VdpPresentationQueue queue, VdpTime *current_time)
511 return vdp->vt.presentation_queue_get_time(queue, current_time);
514 VdpStatus vdp_presentation_queue_display(const vdp_t *vdp,
515 VdpPresentationQueue queue, VdpOutputSurface surface, uint32_t clip_width,
516 uint32_t clip_height, VdpTime pts)
518 return vdp->vt.presentation_queue_display(queue, surface, clip_width,
522 VdpStatus vdp_presentation_queue_block_until_surface_idle(const vdp_t *vdp,
523 VdpPresentationQueue queue, VdpOutputSurface surface, VdpTime *pts)
525 return vdp->vt.presentation_queue_block_until_surface_idle(queue, surface,
529 VdpStatus vdp_presentation_queue_query_surface_status(const vdp_t *vdp,
530 VdpPresentationQueue queue, VdpOutputSurface surface,
531 VdpPresentationQueueStatus *status, VdpTime *pts)
533 return vdp->vt.presentation_queue_query_surface_status(queue, surface,
538 VdpStatus vdp_preemption_callback_register(const vdp_t *vdp, VdpDevice device,
539 VdpPreemptionCallback cb, void *ctx)
541 return vdp->vt.preemption_callback_register(device, cb, ctx);
544 static VdpStatus vdp_fallback(/* UNDEFINED - LEAVE EMPTY */)
546 return VDP_STATUS_NO_IMPLEMENTATION;
551 #include <vdpau/vdpau_x11.h>
553 VdpStatus vdp_presentation_queue_target_create_x11(const vdp_t *vdp,
554 VdpDevice device, uint32_t drawable, VdpPresentationQueueTarget *target)
557 VdpStatus err = vdp_get_proc_address(vdp, device,
558 VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11, &ptr);
559 if (err != VDP_STATUS_OK)
562 VdpPresentationQueueTargetCreateX11 *f = ptr;
563 return f(device, drawable, target);
566 VdpStatus vdp_create_x11(void *dpy, int snum,
567 vdp_t **restrict vdpp, VdpDevice *restrict devp)
569 vdp_t *vdp = malloc(sizeof (*vdp));
570 if (unlikely(vdp == NULL))
571 return VDP_STATUS_RESOURCES;
574 VdpStatus err = VDP_STATUS_NO_IMPLEMENTATION;
576 vdp->handle = dlopen("libvdpau.so.1", RTLD_LAZY|RTLD_LOCAL);
577 if (vdp->handle == NULL)
583 VdpDeviceCreateX11 *create = dlsym(vdp->handle, "vdp_device_create_x11");
587 VdpGetProcAddress *gpa;
588 err = create(dpy, snum, devp, &gpa);
589 if (err != VDP_STATUS_OK)
592 for (VdpFuncId i = 0; i < sizeof (vdp->vt) / sizeof (void *); i++)
593 if (gpa(*devp, i, vdp->funcs + i) != VDP_STATUS_OK)
595 void *fallback = vdp_fallback;
596 if (unlikely(i == VDP_FUNC_ID_GET_ERROR_STRING))
597 fallback = vdp_get_error_string_fallback;
598 vdp->funcs[i] = fallback;
601 return VDP_STATUS_OK;
603 vdp_destroy_x11(vdp);
607 void vdp_destroy_x11(vdp_t *vdp)
609 dlclose(vdp->handle);