]> git.sesse.net Git - vlc/blob - modules/hw/vdpau/vlc_vdpau.c
vdpau: chroma filter cleanup
[vlc] / modules / hw / vdpau / vlc_vdpau.c
1 /*****************************************************************************
2  * vlc_vdpau.c: VDPAU helper for VLC
3  *****************************************************************************
4  * Copyright (C) 2013 RĂ©mi Denis-Courmont
5  *
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.
10  *
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.
15  *
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  *****************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
24
25 #include <stdlib.h>
26 #include <vlc_common.h>
27 #include "vlc_vdpau.h"
28
29 #pragma GCC visibility push(default)
30
31 typedef struct
32 {
33     VdpGetErrorString *get_error_string;
34     VdpGetProcAddress *get_proc_address;
35     VdpGetApiVersion *get_api_version;
36     void *dummy3;
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;
63     void *dummy30;
64     void *dummy31;
65     void *dummy32;
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;
93     void *dummy60;
94     void *dummy61;
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;
100 } vdp_vtable_t;
101
102 struct vdp_s
103 {
104     union
105     {
106         vdp_vtable_t vt;
107         void *funcs[1];
108     }; /**< VDPAU function pointers table */
109     void *handle; /**< Shared library handle */
110 };
111
112 const char *vdp_get_error_string(const vdp_t *vdp, VdpStatus status)
113 {
114     return vdp->vt.get_error_string(status);
115 }
116
117 static const char *vdp_get_error_string_fallback(const vdp_t *vdp,
118                                                  VdpStatus status)
119 {
120     (void) vdp;
121     return (status != VDP_STATUS_OK) ? "Unknown error" : "No error";
122 }
123
124 VdpStatus vdp_get_proc_address(const vdp_t *vdp, VdpDevice device,
125     VdpFuncId func_id, void **func_ptr)
126 {
127     return vdp->vt.get_proc_address(device, func_id, func_ptr);
128 }
129
130 VdpStatus vdp_get_api_version(const vdp_t *vdp, uint32_t *ver)
131 {
132     return vdp->vt.get_api_version(ver);
133 }
134
135 VdpStatus vdp_get_information_string(const vdp_t *vdp, const char **str)
136 {
137     return vdp->vt.get_information_string(str);
138 }
139
140 /*** Device ***/
141 VdpStatus vdp_device_destroy(const vdp_t *vdp, VdpDevice device)
142 {
143     return vdp->vt.device_destroy(device);
144 }
145
146 VdpStatus vdp_generate_csc_matrix(const vdp_t *vdp, const VdpProcamp *procamp,
147     VdpColorStandard standard, VdpCSCMatrix *csc_matrix)
148 {
149     VdpProcamp buf, *copy = NULL;
150
151     if (procamp != NULL)
152     {
153         buf = *procamp;
154         copy = &buf;
155     }
156     return vdp->vt.generate_csc_matrix(copy, standard, csc_matrix);
157 }
158
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)
162 {
163     return vdp->vt.video_surface_query_capabilities(dev, type, ok, mw, mh);
164 }
165
166 VdpStatus vdp_video_surface_query_get_put_bits_y_cb_cr_capabilities(
167     const vdp_t *vdp, VdpDevice device, VdpChromaType type, VdpYCbCrFormat fmt,
168     VdpBool *ok)
169 {
170     return vdp->vt.video_surface_query_get_put_bits_y_cb_cr_capabilities(
171         device, type, fmt, ok);
172 }
173
174 VdpStatus vdp_video_surface_create(const vdp_t *vdp, VdpDevice device,
175     VdpChromaType chroma, uint32_t w, uint32_t h, VdpVideoSurface *surface)
176 {
177     return vdp->vt.video_surface_create(device, chroma, w, h, surface);
178 }
179
180 VdpStatus vdp_video_surface_destroy(const vdp_t *vdp, VdpVideoSurface surface)
181 {
182     return vdp->vt.video_surface_destroy(surface);
183 }
184
185 VdpStatus vdp_video_surface_get_parameters(const vdp_t *vdp,
186     VdpVideoSurface surface, VdpChromaType *type, uint32_t *w, uint32_t *h)
187 {
188     return vdp->vt.video_surface_get_parameters(surface, type, w, h);
189 }
190
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)
194 {
195     return vdp->vt.video_surface_get_bits_y_cb_cr(surface, fmt, data, pitches);
196 }
197
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)
201 {
202     return vdp->vt.video_surface_put_bits_y_cb_cr(surface, fmt, data, pitches);
203 }
204
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)
209 {
210     return vdp->vt.output_surface_query_capabilities(device, fmt, ok,
211                                                      max_width, max_height);
212 }
213
214 VdpStatus vdp_output_surface_query_get_put_bits_native_capabilities(
215     const vdp_t *vdp, VdpDevice device, VdpRGBAFormat fmt, VdpBool *ok)
216 {
217     return vdp->vt.output_surface_query_get_put_bits_native_capabilities(
218                                                               device, fmt, ok);
219 }
220
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)
224 {
225     return vdp->vt.output_surface_query_put_bits_indexed_capabilities(device,
226                                                       fmt, idxfmt, colfmt, ok);
227 }
228
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)
232 {
233     return vdp->vt.output_surface_query_put_bits_y_cb_cr_capabilities(device,
234                                                               fmt, yccfmt, ok);
235 }
236
237 VdpStatus vdp_output_surface_create(const vdp_t *vdp, VdpDevice device,
238     VdpRGBAFormat fmt, uint32_t w, uint32_t h, VdpOutputSurface *surface)
239 {
240     return vdp->vt.output_surface_create(device, fmt, w, h, surface);
241 }
242
243 VdpStatus vdp_output_surface_destroy(const vdp_t *vdp,
244                                      VdpOutputSurface surface)
245 {
246     return vdp->vt.output_surface_destroy(surface);
247 }
248
249 VdpStatus vdp_output_surface_get_parameters(const vdp_t *vdp,
250     VdpOutputSurface surface, VdpRGBAFormat *fmt, uint32_t *w, uint32_t *h)
251 {
252     return vdp->vt.output_surface_get_parameters(surface, fmt, w, h);
253 }
254
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)
258 {
259     return vdp->vt.output_surface_get_bits_native(surface, src, data, pitches);
260 }
261
262 VdpStatus vdp_output_surface_put_bits_native(const vdp_t *vdp,
263     VdpOutputSurface surface, const void *const *data, uint32_t const *pitches,
264     const VdpRect *dst)
265 {
266     return vdp->vt.output_surface_put_bits_native(surface, data, pitches, dst);
267 }
268
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)
273 {
274     return vdp->vt.output_surface_put_bits_indexed(surface, fmt, data, pitch,
275                                                    dst, tabfmt, tab);
276 }
277
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)
281 {
282     return vdp->vt.output_surface_put_bits_y_cb_cr(surface, fmt, data,
283                                                    pitches, dst, mtx);
284 }
285
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)
289 {
290     return vdp->vt.bitmap_surface_query_capabilities(device, fmt, ok, w, h);
291 }
292
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)
296 {
297     return vdp->vt.bitmap_surface_create(device, fmt, w, h, fq, surface);
298 }
299
300 VdpStatus vdp_bitmap_surface_destroy(const vdp_t *vdp,
301                                      VdpBitmapSurface surface)
302 {
303     return vdp->vt.bitmap_surface_destroy(surface);
304 }
305
306 VdpStatus vdp_bitmap_surface_get_parameters(const vdp_t *vdp,
307     VdpBitmapSurface surface, VdpRGBAFormat *fmt, uint32_t *w, uint32_t *h,
308     VdpBool *fq)
309 {
310     return vdp->vt.bitmap_surface_get_parameters(surface, fmt, w, h, fq);
311 }
312
313 VdpStatus vdp_bitmap_surface_put_bits_native(const vdp_t *vdp,
314     VdpBitmapSurface surface, const void *const *data, const uint32_t *pitch,
315     const VdpRect *rect)
316 {
317     return vdp->vt.bitmap_surface_put_bits_native(surface, data, pitch, rect);
318 }
319
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)
325 {
326     return vdp->vt.output_surface_render_output_surface(dst_surface, dst_rect,
327         src_surface, src_rect, colors, state, flags);
328 }
329
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)
335 {
336     return vdp->vt.output_surface_render_bitmap_surface(dst_surface, dst_rect,
337         src_surface, src_rect, colors, state, flags);
338 }
339
340 /*** Decoder ***/
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)
344 {
345     return vdp->vt.decoder_query_capabilities(device, profile, ok, l, m, w, h);
346 }
347
348 VdpStatus vdp_decoder_create(const vdp_t *vdp, VdpDevice device,
349     VdpDecoderProfile profile, uint32_t w, uint32_t h, uint32_t refs,
350     VdpDecoder *decoder)
351 {
352     return vdp->vt.decoder_create(device, profile, w, h, refs, decoder);
353 }
354
355 VdpStatus vdp_decoder_destroy(const vdp_t *vdp, VdpDecoder decoder)
356 {
357     return vdp->vt.decoder_destroy(decoder);
358 }
359
360 VdpStatus vdp_decoder_get_parameters(const vdp_t *vdp, VdpDecoder decoder,
361     VdpDecoderProfile *profile, uint32_t *w, uint32_t *h)
362 {
363     return vdp->vt.decoder_get_parameters(decoder, profile, w, h);
364 }
365
366 VdpStatus vdp_decoder_render(const vdp_t *vdp, VdpDecoder decoder,
367     VdpVideoSurface target, const VdpPictureInfo *info,
368     uint32_t bufv, const VdpBitstreamBuffer *bufc)
369
370 {
371     return vdp->vt.decoder_render(decoder, target, info, bufv, bufc);
372 }
373
374 /*** Video mixer ***/
375 VdpStatus vdp_video_mixer_query_feature_support(const vdp_t *vdp,
376     VdpDevice device, VdpVideoMixerFeature feature, VdpBool *ok)
377 {
378     return vdp->vt.video_mixer_query_feature_support(device, feature, ok);
379 }
380
381 VdpStatus vdp_video_mixer_query_parameter_support(const vdp_t *vdp,
382     VdpDevice device, VdpVideoMixerParameter parameter, VdpBool *ok)
383 {
384     return vdp->vt.video_mixer_query_parameter_support(device, parameter, ok);
385 }
386
387 VdpStatus vdp_video_mixer_query_attribute_support(const vdp_t *vdp,
388     VdpDevice device, VdpVideoMixerAttribute attribute, VdpBool *ok)
389 {
390     return vdp->vt.video_mixer_query_attribute_support(device, attribute, ok);
391 }
392
393 VdpStatus vdp_video_mixer_query_parameter_value_range(const vdp_t *vdp,
394     VdpDevice device, VdpVideoMixerParameter parameter, void *min, void *max)
395 {
396     return vdp->vt.video_mixer_query_parameter_value_range(device, parameter,
397         min, max);
398 }
399
400 VdpStatus vdp_video_mixer_query_attribute_value_range(const vdp_t *vdp,
401     VdpDevice device, VdpVideoMixerAttribute attribute, void *min, void *max)
402 {
403     return vdp->vt.video_mixer_query_attribute_value_range(device, attribute,
404         min, max);
405 }
406
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)
411 {
412     return vdp->vt.video_mixer_create(device, featc, featv, parmc, parmv,
413                                       parmvalv, mixer);
414 }
415
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)
419 {
420     return vdp->vt.video_mixer_set_feature_enables(mixer, count, ids, values);
421 }
422
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)
426 {
427     return vdp->vt.video_mixer_set_attribute_values(mixer, count, ids, values);
428 }
429
430 VdpStatus vdp_video_mixer_get_feature_support(const vdp_t *vdp,
431     VdpVideoMixer mixer, uint32_t count, const VdpVideoMixerFeature *ids,
432     VdpBool *values)
433 {
434     return vdp->vt.video_mixer_get_feature_support(mixer, count, ids, values);
435 }
436
437 VdpStatus vdp_video_mixer_get_feature_enables(const vdp_t *vdp,
438     VdpVideoMixer mixer, uint32_t count, const VdpVideoMixerFeature *ids,
439     VdpBool *values)
440 {
441     return vdp->vt.video_mixer_get_feature_enables(mixer, count, ids, values);
442 }
443
444 VdpStatus vdp_video_mixer_get_parameter_values(const vdp_t *vdp,
445     VdpVideoMixer mixer, uint32_t count, const VdpVideoMixerParameter *ids,
446     void *const *values)
447 {
448     return vdp->vt.video_mixer_get_parameter_values(mixer, count, ids, values);
449 }
450
451 VdpStatus vdp_video_mixer_get_attribute_values(const vdp_t *vdp,
452     VdpVideoMixer mixer, uint32_t count, const VdpVideoMixerAttribute *ids,
453     void *const *values)
454 {
455     return vdp->vt.video_mixer_get_attribute_values(mixer, count, ids, values);
456 }
457
458 VdpStatus vdp_video_mixer_destroy(const vdp_t *vdp, VdpVideoMixer mixer)
459 {
460     return vdp->vt.video_mixer_destroy(mixer);
461 }
462
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)
470 {
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);
474 }
475
476 /*** Presentation queue ***/
477 VdpStatus vdp_presentation_queue_target_destroy(const vdp_t *vdp,
478     VdpPresentationQueueTarget target)
479 {
480     return vdp->vt.presentation_queue_target_destroy(target);
481 }
482
483 VdpStatus vdp_presentation_queue_create(const vdp_t *vdp, VdpDevice device,
484     VdpPresentationQueueTarget target, VdpPresentationQueue *queue)
485 {
486     return vdp->vt.presentation_queue_create(device, target, queue);
487 }
488
489 VdpStatus vdp_presentation_queue_destroy(const vdp_t *vdp,
490     VdpPresentationQueue queue)
491 {
492     return vdp->vt.presentation_queue_destroy(queue);
493 }
494
495 VdpStatus vdp_presentation_queue_set_background_color(const vdp_t *vdp,
496     VdpPresentationQueue queue, const VdpColor *color)
497 {
498     VdpColor bak = *color;
499     return vdp->vt.presentation_queue_set_background_color(queue, &bak);
500 }
501
502 VdpStatus vdp_presentation_queue_get_background_color(const vdp_t *vdp,
503     VdpPresentationQueue queue, VdpColor *color)
504 {
505     return vdp->vt.presentation_queue_get_background_color(queue, color);
506 }
507
508 VdpStatus vdp_presentation_queue_get_time(const vdp_t *vdp,
509     VdpPresentationQueue queue, VdpTime *current_time)
510 {
511     return vdp->vt.presentation_queue_get_time(queue, current_time);
512 }
513
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)
517 {
518     return vdp->vt.presentation_queue_display(queue, surface, clip_width,
519                                               clip_height, pts);
520 }
521
522 VdpStatus vdp_presentation_queue_block_until_surface_idle(const vdp_t *vdp,
523     VdpPresentationQueue queue, VdpOutputSurface surface, VdpTime *pts)
524 {
525     return vdp->vt.presentation_queue_block_until_surface_idle(queue, surface,
526                                                                pts);
527 }
528
529 VdpStatus vdp_presentation_queue_query_surface_status(const vdp_t *vdp,
530     VdpPresentationQueue queue, VdpOutputSurface surface,
531     VdpPresentationQueueStatus *status, VdpTime *pts)
532 {
533     return vdp->vt.presentation_queue_query_surface_status(queue, surface,
534                                                            status, pts);
535 }
536
537 /*** Preemption ***/
538 VdpStatus vdp_preemption_callback_register(const vdp_t *vdp, VdpDevice device,
539     VdpPreemptionCallback cb, void *ctx)
540 {
541     return vdp->vt.preemption_callback_register(device, cb, ctx);
542 }
543
544 static VdpStatus vdp_fallback(/* UNDEFINED - LEAVE EMPTY */)
545 {
546     return VDP_STATUS_NO_IMPLEMENTATION;
547 }
548
549 /*** X11 & VLC ***/
550 #include <dlfcn.h>
551 #include <vdpau/vdpau_x11.h>
552
553 VdpStatus vdp_presentation_queue_target_create_x11(const vdp_t *vdp,
554     VdpDevice device, uint32_t drawable, VdpPresentationQueueTarget *target)
555 {
556     void *ptr;
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)
560         return err;
561
562     VdpPresentationQueueTargetCreateX11 *f = ptr;
563     return f(device, drawable, target);
564 }
565
566 VdpStatus vdp_create_x11(void *dpy, int snum,
567                          vdp_t **restrict vdpp, VdpDevice *restrict devp)
568 {
569     vdp_t *vdp = malloc(sizeof (*vdp));
570     if (unlikely(vdp == NULL))
571         return VDP_STATUS_RESOURCES;
572     *vdpp = vdp;
573
574     VdpStatus err = VDP_STATUS_NO_IMPLEMENTATION;
575
576     vdp->handle = dlopen("libvdpau.so.1", RTLD_LAZY|RTLD_LOCAL);
577     if (vdp->handle == NULL)
578     {
579         free(vdp);
580         return err;
581     }
582
583     VdpDeviceCreateX11 *create = dlsym(vdp->handle, "vdp_device_create_x11");
584     if (create == NULL)
585         goto error;
586
587     VdpGetProcAddress *gpa;
588     err = create(dpy, snum, devp, &gpa);
589     if (err != VDP_STATUS_OK)
590         goto error;
591
592     for (VdpFuncId i = 0; i < sizeof (vdp->vt) / sizeof (void *); i++)
593         if (gpa(*devp, i, vdp->funcs + i) != VDP_STATUS_OK)
594         {
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;
599         }
600
601     return VDP_STATUS_OK;
602 error:
603     vdp_destroy_x11(vdp);
604     return err;
605 }
606
607 void vdp_destroy_x11(vdp_t *vdp)
608 {
609     dlclose(vdp->handle);
610     free(vdp);
611 }