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[sizeof (vdp_vtable_t) / sizeof (void *)];
108     }; /**< VDPAU function pointers table */
109     void *handle; /**< Shared library handle */
110 };
111 
112 #define CHECK_FUNC(id) \
113     if (unlikely(vdp->funcs[VDP_FUNC_ID_##id] == NULL)) \
114         return VDP_STATUS_NO_IMPLEMENTATION
115 
vdp_get_error_string(const vdp_t * vdp,VdpStatus status)116 const char *vdp_get_error_string(const vdp_t *vdp, VdpStatus status)
117 {
118     if (unlikely(vdp->funcs[VDP_FUNC_ID_GET_ERROR_STRING] == NULL))
119         return (status != VDP_STATUS_OK) ? "Unknown error" : "No error";
120     return vdp->vt.get_error_string(status);
121 }
122 
vdp_get_proc_address(const vdp_t * vdp,VdpDevice device,VdpFuncId func_id,void ** func_ptr)123 VdpStatus vdp_get_proc_address(const vdp_t *vdp, VdpDevice device,
124     VdpFuncId func_id, void **func_ptr)
125 {
126     CHECK_FUNC(GET_PROC_ADDRESS);
127     return vdp->vt.get_proc_address(device, func_id, func_ptr);
128 }
129 
vdp_get_api_version(const vdp_t * vdp,uint32_t * ver)130 VdpStatus vdp_get_api_version(const vdp_t *vdp, uint32_t *ver)
131 {
132     CHECK_FUNC(GET_API_VERSION);
133     return vdp->vt.get_api_version(ver);
134 }
135 
vdp_get_information_string(const vdp_t * vdp,const char ** str)136 VdpStatus vdp_get_information_string(const vdp_t *vdp, const char **str)
137 {
138     CHECK_FUNC(GET_INFORMATION_STRING);
139     return vdp->vt.get_information_string(str);
140 }
141 
142 /*** Device ***/
vdp_device_destroy(const vdp_t * vdp,VdpDevice device)143 VdpStatus vdp_device_destroy(const vdp_t *vdp, VdpDevice device)
144 {
145     CHECK_FUNC(DEVICE_DESTROY);
146     return vdp->vt.device_destroy(device);
147 }
148 
vdp_generate_csc_matrix(const vdp_t * vdp,const VdpProcamp * procamp,VdpColorStandard standard,VdpCSCMatrix * csc_matrix)149 VdpStatus vdp_generate_csc_matrix(const vdp_t *vdp, const VdpProcamp *procamp,
150     VdpColorStandard standard, VdpCSCMatrix *csc_matrix)
151 {
152     VdpProcamp buf, *copy = NULL;
153 
154     if (procamp != NULL)
155     {
156         buf = *procamp;
157         copy = &buf;
158     }
159     CHECK_FUNC(GENERATE_CSC_MATRIX);
160     return vdp->vt.generate_csc_matrix(copy, standard, csc_matrix);
161 }
162 
163 /*** Video surface ***/
vdp_video_surface_query_capabilities(const vdp_t * vdp,VdpDevice dev,VdpChromaType type,VdpBool * ok,uint32_t * mw,uint32_t * mh)164 VdpStatus vdp_video_surface_query_capabilities(const vdp_t *vdp, VdpDevice dev,
165     VdpChromaType type, VdpBool *ok, uint32_t *mw, uint32_t *mh)
166 {
167     CHECK_FUNC(VIDEO_SURFACE_QUERY_CAPABILITIES);
168     return vdp->vt.video_surface_query_capabilities(dev, type, ok, mw, mh);
169 }
170 
vdp_video_surface_query_get_put_bits_y_cb_cr_capabilities(const vdp_t * vdp,VdpDevice device,VdpChromaType type,VdpYCbCrFormat fmt,VdpBool * ok)171 VdpStatus vdp_video_surface_query_get_put_bits_y_cb_cr_capabilities(
172     const vdp_t *vdp, VdpDevice device, VdpChromaType type, VdpYCbCrFormat fmt,
173     VdpBool *ok)
174 {
175     CHECK_FUNC(VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES);
176     return vdp->vt.video_surface_query_get_put_bits_y_cb_cr_capabilities(
177         device, type, fmt, ok);
178 }
179 
vdp_video_surface_create(const vdp_t * vdp,VdpDevice device,VdpChromaType chroma,uint32_t w,uint32_t h,VdpVideoSurface * surface)180 VdpStatus vdp_video_surface_create(const vdp_t *vdp, VdpDevice device,
181     VdpChromaType chroma, uint32_t w, uint32_t h, VdpVideoSurface *surface)
182 {
183     CHECK_FUNC(VIDEO_SURFACE_CREATE);
184     return vdp->vt.video_surface_create(device, chroma, w, h, surface);
185 }
186 
vdp_video_surface_destroy(const vdp_t * vdp,VdpVideoSurface surface)187 VdpStatus vdp_video_surface_destroy(const vdp_t *vdp, VdpVideoSurface surface)
188 {
189     CHECK_FUNC(VIDEO_SURFACE_DESTROY);
190     return vdp->vt.video_surface_destroy(surface);
191 }
192 
vdp_video_surface_get_parameters(const vdp_t * vdp,VdpVideoSurface surface,VdpChromaType * type,uint32_t * w,uint32_t * h)193 VdpStatus vdp_video_surface_get_parameters(const vdp_t *vdp,
194     VdpVideoSurface surface, VdpChromaType *type, uint32_t *w, uint32_t *h)
195 {
196     CHECK_FUNC(VIDEO_SURFACE_GET_PARAMETERS);
197     return vdp->vt.video_surface_get_parameters(surface, type, w, h);
198 }
199 
vdp_video_surface_get_bits_y_cb_cr(const vdp_t * vdp,VdpVideoSurface surface,VdpYCbCrFormat fmt,void * const * data,uint32_t const * pitches)200 VdpStatus vdp_video_surface_get_bits_y_cb_cr(const vdp_t *vdp,
201     VdpVideoSurface surface, VdpYCbCrFormat fmt,
202     void *const *data, uint32_t const *pitches)
203 {
204     CHECK_FUNC(VIDEO_SURFACE_GET_BITS_Y_CB_CR);
205     return vdp->vt.video_surface_get_bits_y_cb_cr(surface, fmt, data, pitches);
206 }
207 
vdp_video_surface_put_bits_y_cb_cr(const vdp_t * vdp,VdpVideoSurface surface,VdpYCbCrFormat fmt,const void * const * data,uint32_t const * pitches)208 VdpStatus vdp_video_surface_put_bits_y_cb_cr(const vdp_t *vdp,
209     VdpVideoSurface surface, VdpYCbCrFormat fmt,
210     const void *const *data, uint32_t const *pitches)
211 {
212     CHECK_FUNC(VIDEO_SURFACE_PUT_BITS_Y_CB_CR);
213     return vdp->vt.video_surface_put_bits_y_cb_cr(surface, fmt, data, pitches);
214 }
215 
216 /*** Output surface ***/
vdp_output_surface_query_capabilities(const vdp_t * vdp,VdpDevice device,VdpRGBAFormat fmt,VdpBool * ok,uint32_t * max_width,uint32_t * max_height)217 VdpStatus vdp_output_surface_query_capabilities(const vdp_t *vdp,
218     VdpDevice device, VdpRGBAFormat fmt, VdpBool *ok,
219     uint32_t *max_width, uint32_t *max_height)
220 {
221     CHECK_FUNC(OUTPUT_SURFACE_QUERY_CAPABILITIES);
222     return vdp->vt.output_surface_query_capabilities(device, fmt, ok,
223                                                      max_width, max_height);
224 }
225 
vdp_output_surface_query_get_put_bits_native_capabilities(const vdp_t * vdp,VdpDevice device,VdpRGBAFormat fmt,VdpBool * ok)226 VdpStatus vdp_output_surface_query_get_put_bits_native_capabilities(
227     const vdp_t *vdp, VdpDevice device, VdpRGBAFormat fmt, VdpBool *ok)
228 {
229     CHECK_FUNC(OUTPUT_SURFACE_QUERY_GET_PUT_BITS_NATIVE_CAPABILITIES);
230     return vdp->vt.output_surface_query_get_put_bits_native_capabilities(
231                                                               device, fmt, ok);
232 }
233 
vdp_output_surface_query_put_bits_indexed_capabilities(const vdp_t * vdp,VdpDevice device,VdpRGBAFormat fmt,VdpIndexedFormat idxfmt,VdpColorTableFormat colfmt,VdpBool * ok)234 VdpStatus vdp_output_surface_query_put_bits_indexed_capabilities(
235     const vdp_t *vdp, VdpDevice device, VdpRGBAFormat fmt,
236     VdpIndexedFormat idxfmt, VdpColorTableFormat colfmt, VdpBool *ok)
237 {
238     CHECK_FUNC(OUTPUT_SURFACE_QUERY_PUT_BITS_INDEXED_CAPABILITIES);
239     return vdp->vt.output_surface_query_put_bits_indexed_capabilities(device,
240                                                       fmt, idxfmt, colfmt, ok);
241 }
242 
vdp_output_surface_query_put_bits_y_cb_cr_capabilities(const vdp_t * vdp,VdpDevice device,VdpRGBAFormat fmt,VdpYCbCrFormat yccfmt,VdpBool * ok)243 VdpStatus vdp_output_surface_query_put_bits_y_cb_cr_capabilities(
244     const vdp_t *vdp, VdpDevice device,
245     VdpRGBAFormat fmt, VdpYCbCrFormat yccfmt, VdpBool *ok)
246 {
247     CHECK_FUNC(OUTPUT_SURFACE_QUERY_PUT_BITS_Y_CB_CR_CAPABILITIES);
248     return vdp->vt.output_surface_query_put_bits_y_cb_cr_capabilities(device,
249                                                               fmt, yccfmt, ok);
250 }
251 
vdp_output_surface_create(const vdp_t * vdp,VdpDevice device,VdpRGBAFormat fmt,uint32_t w,uint32_t h,VdpOutputSurface * surface)252 VdpStatus vdp_output_surface_create(const vdp_t *vdp, VdpDevice device,
253     VdpRGBAFormat fmt, uint32_t w, uint32_t h, VdpOutputSurface *surface)
254 {
255     CHECK_FUNC(OUTPUT_SURFACE_CREATE);
256     return vdp->vt.output_surface_create(device, fmt, w, h, surface);
257 }
258 
vdp_output_surface_destroy(const vdp_t * vdp,VdpOutputSurface surface)259 VdpStatus vdp_output_surface_destroy(const vdp_t *vdp,
260                                      VdpOutputSurface surface)
261 {
262     CHECK_FUNC(OUTPUT_SURFACE_DESTROY);
263     return vdp->vt.output_surface_destroy(surface);
264 }
265 
vdp_output_surface_get_parameters(const vdp_t * vdp,VdpOutputSurface surface,VdpRGBAFormat * fmt,uint32_t * w,uint32_t * h)266 VdpStatus vdp_output_surface_get_parameters(const vdp_t *vdp,
267     VdpOutputSurface surface, VdpRGBAFormat *fmt, uint32_t *w, uint32_t *h)
268 {
269     CHECK_FUNC(OUTPUT_SURFACE_GET_PARAMETERS);
270     return vdp->vt.output_surface_get_parameters(surface, fmt, w, h);
271 }
272 
vdp_output_surface_get_bits_native(const vdp_t * vdp,VdpOutputSurface surface,const VdpRect * src,void * const * data,uint32_t const * pitches)273 VdpStatus vdp_output_surface_get_bits_native(const vdp_t *vdp,
274     VdpOutputSurface surface, const VdpRect *src,
275     void *const *data, uint32_t const *pitches)
276 {
277     CHECK_FUNC(OUTPUT_SURFACE_GET_BITS_NATIVE);
278     return vdp->vt.output_surface_get_bits_native(surface, src, data, pitches);
279 }
280 
vdp_output_surface_put_bits_native(const vdp_t * vdp,VdpOutputSurface surface,const void * const * data,uint32_t const * pitches,const VdpRect * dst)281 VdpStatus vdp_output_surface_put_bits_native(const vdp_t *vdp,
282     VdpOutputSurface surface, const void *const *data, uint32_t const *pitches,
283     const VdpRect *dst)
284 {
285     CHECK_FUNC(OUTPUT_SURFACE_PUT_BITS_NATIVE);
286     return vdp->vt.output_surface_put_bits_native(surface, data, pitches, dst);
287 }
288 
vdp_output_surface_put_bits_indexed(const vdp_t * vdp,VdpOutputSurface surface,VdpIndexedFormat fmt,const void * const * data,const uint32_t * pitch,const VdpRect * dst,VdpColorTableFormat tabfmt,const void * tab)289 VdpStatus vdp_output_surface_put_bits_indexed(const vdp_t *vdp,
290     VdpOutputSurface surface, VdpIndexedFormat fmt, const void *const *data,
291     const uint32_t *pitch, const VdpRect *dst,
292     VdpColorTableFormat tabfmt, const void *tab)
293 {
294     CHECK_FUNC(OUTPUT_SURFACE_PUT_BITS_INDEXED);
295     return vdp->vt.output_surface_put_bits_indexed(surface, fmt, data, pitch,
296                                                    dst, tabfmt, tab);
297 }
298 
vdp_output_surface_put_bits_y_cb_cr(const vdp_t * vdp,VdpOutputSurface surface,VdpYCbCrFormat fmt,const void * const * data,const uint32_t * pitches,const VdpRect * dst,const VdpCSCMatrix * mtx)299 VdpStatus vdp_output_surface_put_bits_y_cb_cr(const vdp_t *vdp,
300     VdpOutputSurface surface, VdpYCbCrFormat fmt, const void *const *data,
301     const uint32_t *pitches, const VdpRect *dst, const VdpCSCMatrix *mtx)
302 {
303     CHECK_FUNC(OUTPUT_SURFACE_PUT_BITS_Y_CB_CR);
304     return vdp->vt.output_surface_put_bits_y_cb_cr(surface, fmt, data,
305                                                    pitches, dst, mtx);
306 }
307 
308 /*** Bitmap surface ***/
vdp_bitmap_surface_query_capabilities(const vdp_t * vdp,VdpDevice device,VdpRGBAFormat fmt,VdpBool * ok,uint32_t * w,uint32_t * h)309 VdpStatus vdp_bitmap_surface_query_capabilities(const vdp_t *vdp,
310     VdpDevice device, VdpRGBAFormat fmt, VdpBool *ok, uint32_t *w, uint32_t *h)
311 {
312     CHECK_FUNC(BITMAP_SURFACE_QUERY_CAPABILITIES);
313     return vdp->vt.bitmap_surface_query_capabilities(device, fmt, ok, w, h);
314 }
315 
vdp_bitmap_surface_create(const vdp_t * vdp,VdpDevice device,VdpRGBAFormat fmt,uint32_t w,uint32_t h,VdpBool fq,VdpBitmapSurface * surface)316 VdpStatus vdp_bitmap_surface_create(const vdp_t *vdp, VdpDevice device,
317     VdpRGBAFormat fmt, uint32_t w, uint32_t h, VdpBool fq,
318     VdpBitmapSurface *surface)
319 {
320     CHECK_FUNC(BITMAP_SURFACE_CREATE);
321     return vdp->vt.bitmap_surface_create(device, fmt, w, h, fq, surface);
322 }
323 
vdp_bitmap_surface_destroy(const vdp_t * vdp,VdpBitmapSurface surface)324 VdpStatus vdp_bitmap_surface_destroy(const vdp_t *vdp,
325                                      VdpBitmapSurface surface)
326 {
327     CHECK_FUNC(BITMAP_SURFACE_DESTROY);
328     return vdp->vt.bitmap_surface_destroy(surface);
329 }
330 
vdp_bitmap_surface_get_parameters(const vdp_t * vdp,VdpBitmapSurface surface,VdpRGBAFormat * fmt,uint32_t * w,uint32_t * h,VdpBool * fq)331 VdpStatus vdp_bitmap_surface_get_parameters(const vdp_t *vdp,
332     VdpBitmapSurface surface, VdpRGBAFormat *fmt, uint32_t *w, uint32_t *h,
333     VdpBool *fq)
334 {
335     CHECK_FUNC(BITMAP_SURFACE_GET_PARAMETERS);
336     return vdp->vt.bitmap_surface_get_parameters(surface, fmt, w, h, fq);
337 }
338 
vdp_bitmap_surface_put_bits_native(const vdp_t * vdp,VdpBitmapSurface surface,const void * const * data,const uint32_t * pitch,const VdpRect * rect)339 VdpStatus vdp_bitmap_surface_put_bits_native(const vdp_t *vdp,
340     VdpBitmapSurface surface, const void *const *data, const uint32_t *pitch,
341     const VdpRect *rect)
342 {
343     CHECK_FUNC(BITMAP_SURFACE_PUT_BITS_NATIVE);
344     return vdp->vt.bitmap_surface_put_bits_native(surface, data, pitch, rect);
345 }
346 
vdp_output_surface_render_output_surface(const vdp_t * vdp,VdpOutputSurface dst_surface,const VdpRect * dst_rect,VdpOutputSurface src_surface,const VdpRect * src_rect,const VdpColor * colors,const VdpOutputSurfaceRenderBlendState * const state,uint32_t flags)347 VdpStatus vdp_output_surface_render_output_surface(const vdp_t *vdp,
348     VdpOutputSurface dst_surface, const VdpRect *dst_rect,
349     VdpOutputSurface src_surface, const VdpRect *src_rect,
350     const VdpColor *colors,
351     const VdpOutputSurfaceRenderBlendState *const state, uint32_t flags)
352 {
353     CHECK_FUNC(OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE);
354     return vdp->vt.output_surface_render_output_surface(dst_surface, dst_rect,
355         src_surface, src_rect, colors, state, flags);
356 }
357 
vdp_output_surface_render_bitmap_surface(const vdp_t * vdp,VdpOutputSurface dst_surface,const VdpRect * dst_rect,VdpBitmapSurface src_surface,const VdpRect * src_rect,const VdpColor * colors,const VdpOutputSurfaceRenderBlendState * state,uint32_t flags)358 VdpStatus vdp_output_surface_render_bitmap_surface(const vdp_t *vdp,
359     VdpOutputSurface dst_surface, const VdpRect *dst_rect,
360     VdpBitmapSurface src_surface, const VdpRect *src_rect,
361     const VdpColor *colors,
362     const VdpOutputSurfaceRenderBlendState *state, uint32_t flags)
363 {
364     CHECK_FUNC(OUTPUT_SURFACE_RENDER_BITMAP_SURFACE);
365     return vdp->vt.output_surface_render_bitmap_surface(dst_surface, dst_rect,
366         src_surface, src_rect, colors, state, flags);
367 }
368 
369 /*** Decoder ***/
vdp_decoder_query_capabilities(const vdp_t * vdp,VdpDevice device,VdpDecoderProfile profile,VdpBool * ok,uint32_t * l,uint32_t * m,uint32_t * w,uint32_t * h)370 VdpStatus vdp_decoder_query_capabilities(const vdp_t *vdp, VdpDevice device,
371     VdpDecoderProfile profile, VdpBool *ok, uint32_t *l, uint32_t *m,
372     uint32_t *w, uint32_t *h)
373 {
374     CHECK_FUNC(DECODER_QUERY_CAPABILITIES);
375     return vdp->vt.decoder_query_capabilities(device, profile, ok, l, m, w, h);
376 }
377 
vdp_decoder_create(const vdp_t * vdp,VdpDevice device,VdpDecoderProfile profile,uint32_t w,uint32_t h,uint32_t refs,VdpDecoder * decoder)378 VdpStatus vdp_decoder_create(const vdp_t *vdp, VdpDevice device,
379     VdpDecoderProfile profile, uint32_t w, uint32_t h, uint32_t refs,
380     VdpDecoder *decoder)
381 {
382     CHECK_FUNC(DECODER_CREATE);
383     return vdp->vt.decoder_create(device, profile, w, h, refs, decoder);
384 }
385 
vdp_decoder_destroy(const vdp_t * vdp,VdpDecoder decoder)386 VdpStatus vdp_decoder_destroy(const vdp_t *vdp, VdpDecoder decoder)
387 {
388     CHECK_FUNC(DECODER_DESTROY);
389     return vdp->vt.decoder_destroy(decoder);
390 }
391 
vdp_decoder_get_parameters(const vdp_t * vdp,VdpDecoder decoder,VdpDecoderProfile * profile,uint32_t * w,uint32_t * h)392 VdpStatus vdp_decoder_get_parameters(const vdp_t *vdp, VdpDecoder decoder,
393     VdpDecoderProfile *profile, uint32_t *w, uint32_t *h)
394 {
395     CHECK_FUNC(DECODER_GET_PARAMETERS);
396     return vdp->vt.decoder_get_parameters(decoder, profile, w, h);
397 }
398 
vdp_decoder_render(const vdp_t * vdp,VdpDecoder decoder,VdpVideoSurface target,const VdpPictureInfo * info,uint32_t bufv,const VdpBitstreamBuffer * bufc)399 VdpStatus vdp_decoder_render(const vdp_t *vdp, VdpDecoder decoder,
400     VdpVideoSurface target, const VdpPictureInfo *info,
401     uint32_t bufv, const VdpBitstreamBuffer *bufc)
402 {
403     CHECK_FUNC(DECODER_RENDER);
404     return vdp->vt.decoder_render(decoder, target, info, bufv, bufc);
405 }
406 
407 /*** Video mixer ***/
vdp_video_mixer_query_feature_support(const vdp_t * vdp,VdpDevice device,VdpVideoMixerFeature feature,VdpBool * ok)408 VdpStatus vdp_video_mixer_query_feature_support(const vdp_t *vdp,
409     VdpDevice device, VdpVideoMixerFeature feature, VdpBool *ok)
410 {
411     CHECK_FUNC(VIDEO_MIXER_QUERY_FEATURE_SUPPORT);
412     return vdp->vt.video_mixer_query_feature_support(device, feature, ok);
413 }
414 
vdp_video_mixer_query_parameter_support(const vdp_t * vdp,VdpDevice device,VdpVideoMixerParameter parameter,VdpBool * ok)415 VdpStatus vdp_video_mixer_query_parameter_support(const vdp_t *vdp,
416     VdpDevice device, VdpVideoMixerParameter parameter, VdpBool *ok)
417 {
418     CHECK_FUNC(VIDEO_MIXER_QUERY_PARAMETER_SUPPORT);
419     return vdp->vt.video_mixer_query_parameter_support(device, parameter, ok);
420 }
421 
vdp_video_mixer_query_attribute_support(const vdp_t * vdp,VdpDevice device,VdpVideoMixerAttribute attribute,VdpBool * ok)422 VdpStatus vdp_video_mixer_query_attribute_support(const vdp_t *vdp,
423     VdpDevice device, VdpVideoMixerAttribute attribute, VdpBool *ok)
424 {
425     CHECK_FUNC(VIDEO_MIXER_QUERY_ATTRIBUTE_SUPPORT);
426     return vdp->vt.video_mixer_query_attribute_support(device, attribute, ok);
427 }
428 
vdp_video_mixer_query_parameter_value_range(const vdp_t * vdp,VdpDevice device,VdpVideoMixerParameter parameter,void * min,void * max)429 VdpStatus vdp_video_mixer_query_parameter_value_range(const vdp_t *vdp,
430     VdpDevice device, VdpVideoMixerParameter parameter, void *min, void *max)
431 {
432     CHECK_FUNC(VIDEO_MIXER_QUERY_PARAMETER_VALUE_RANGE);
433     return vdp->vt.video_mixer_query_parameter_value_range(device, parameter,
434         min, max);
435 }
436 
vdp_video_mixer_query_attribute_value_range(const vdp_t * vdp,VdpDevice device,VdpVideoMixerAttribute attribute,void * min,void * max)437 VdpStatus vdp_video_mixer_query_attribute_value_range(const vdp_t *vdp,
438     VdpDevice device, VdpVideoMixerAttribute attribute, void *min, void *max)
439 {
440     CHECK_FUNC(VIDEO_MIXER_QUERY_ATTRIBUTE_VALUE_RANGE);
441     return vdp->vt.video_mixer_query_attribute_value_range(device, attribute,
442         min, max);
443 }
444 
vdp_video_mixer_create(const vdp_t * vdp,VdpDevice device,uint32_t featc,const VdpVideoMixerFeature * featv,uint32_t parmc,const VdpVideoMixerParameter * parmv,const void * const * parmvalv,VdpVideoMixer * mixer)445 VdpStatus vdp_video_mixer_create(const vdp_t *vdp, VdpDevice device,
446     uint32_t featc, const VdpVideoMixerFeature *featv,
447     uint32_t parmc, const VdpVideoMixerParameter *parmv,
448     const void *const *parmvalv, VdpVideoMixer *mixer)
449 {
450     CHECK_FUNC(VIDEO_MIXER_CREATE);
451     return vdp->vt.video_mixer_create(device, featc, featv, parmc, parmv,
452                                       parmvalv, mixer);
453 }
454 
vdp_video_mixer_set_feature_enables(const vdp_t * vdp,VdpVideoMixer mixer,uint32_t count,const VdpVideoMixerFeature * ids,const VdpBool * values)455 VdpStatus vdp_video_mixer_set_feature_enables(const vdp_t *vdp,
456     VdpVideoMixer mixer, uint32_t count, const VdpVideoMixerFeature *ids,
457     const VdpBool *values)
458 {
459     CHECK_FUNC(VIDEO_MIXER_SET_FEATURE_ENABLES);
460     return vdp->vt.video_mixer_set_feature_enables(mixer, count, ids, values);
461 }
462 
vdp_video_mixer_set_attribute_values(const vdp_t * vdp,VdpVideoMixer mixer,uint32_t count,const VdpVideoMixerAttribute * const ids,const void * const * values)463 VdpStatus vdp_video_mixer_set_attribute_values(const vdp_t *vdp,
464     VdpVideoMixer mixer, uint32_t count,
465     const VdpVideoMixerAttribute *const ids, const void *const *values)
466 {
467     CHECK_FUNC(VIDEO_MIXER_SET_ATTRIBUTE_VALUES);
468     return vdp->vt.video_mixer_set_attribute_values(mixer, count, ids, values);
469 }
470 
vdp_video_mixer_get_feature_support(const vdp_t * vdp,VdpVideoMixer mixer,uint32_t count,const VdpVideoMixerFeature * ids,VdpBool * values)471 VdpStatus vdp_video_mixer_get_feature_support(const vdp_t *vdp,
472     VdpVideoMixer mixer, uint32_t count, const VdpVideoMixerFeature *ids,
473     VdpBool *values)
474 {
475     CHECK_FUNC(VIDEO_MIXER_GET_FEATURE_SUPPORT);
476     return vdp->vt.video_mixer_get_feature_support(mixer, count, ids, values);
477 }
478 
vdp_video_mixer_get_feature_enables(const vdp_t * vdp,VdpVideoMixer mixer,uint32_t count,const VdpVideoMixerFeature * ids,VdpBool * values)479 VdpStatus vdp_video_mixer_get_feature_enables(const vdp_t *vdp,
480     VdpVideoMixer mixer, uint32_t count, const VdpVideoMixerFeature *ids,
481     VdpBool *values)
482 {
483     CHECK_FUNC(VIDEO_MIXER_GET_FEATURE_ENABLES);
484     return vdp->vt.video_mixer_get_feature_enables(mixer, count, ids, values);
485 }
486 
vdp_video_mixer_get_parameter_values(const vdp_t * vdp,VdpVideoMixer mixer,uint32_t count,const VdpVideoMixerParameter * ids,void * const * values)487 VdpStatus vdp_video_mixer_get_parameter_values(const vdp_t *vdp,
488     VdpVideoMixer mixer, uint32_t count, const VdpVideoMixerParameter *ids,
489     void *const *values)
490 {
491     CHECK_FUNC(VIDEO_MIXER_GET_PARAMETER_VALUES);
492     return vdp->vt.video_mixer_get_parameter_values(mixer, count, ids, values);
493 }
494 
vdp_video_mixer_get_attribute_values(const vdp_t * vdp,VdpVideoMixer mixer,uint32_t count,const VdpVideoMixerAttribute * ids,void * const * values)495 VdpStatus vdp_video_mixer_get_attribute_values(const vdp_t *vdp,
496     VdpVideoMixer mixer, uint32_t count, const VdpVideoMixerAttribute *ids,
497     void *const *values)
498 {
499     CHECK_FUNC(VIDEO_MIXER_GET_ATTRIBUTE_VALUES);
500     return vdp->vt.video_mixer_get_attribute_values(mixer, count, ids, values);
501 }
502 
vdp_video_mixer_destroy(const vdp_t * vdp,VdpVideoMixer mixer)503 VdpStatus vdp_video_mixer_destroy(const vdp_t *vdp, VdpVideoMixer mixer)
504 {
505     CHECK_FUNC(VIDEO_MIXER_DESTROY);
506     return vdp->vt.video_mixer_destroy(mixer);
507 }
508 
vdp_video_mixer_render(const vdp_t * vdp,VdpVideoMixer mixer,VdpOutputSurface bgsurface,const VdpRect * bgrect,VdpVideoMixerPictureStructure pic_struct,uint32_t prev_count,const VdpVideoSurface * prev,VdpVideoSurface cur,uint32_t next_count,const VdpVideoSurface * next,const VdpRect * src_rect,VdpOutputSurface dst,const VdpRect * dst_rect,const VdpRect * dst_v_rect,uint32_t layerc,const VdpLayer * layerv)509 VdpStatus vdp_video_mixer_render(const vdp_t *vdp, VdpVideoMixer mixer,
510     VdpOutputSurface bgsurface, const VdpRect *bgrect,
511     VdpVideoMixerPictureStructure pic_struct, uint32_t prev_count,
512     const VdpVideoSurface *prev, VdpVideoSurface cur, uint32_t next_count,
513     const VdpVideoSurface *next, const VdpRect *src_rect,
514     VdpOutputSurface dst, const VdpRect *dst_rect, const VdpRect *dst_v_rect,
515     uint32_t layerc, const VdpLayer *layerv)
516 {
517     CHECK_FUNC(VIDEO_MIXER_RENDER);
518     return vdp->vt.video_mixer_render(mixer, bgsurface, bgrect, pic_struct,
519         prev_count, prev, cur, next_count, next, src_rect, dst, dst_rect,
520         dst_v_rect, layerc, layerv);
521 }
522 
523 /*** Presentation queue ***/
vdp_presentation_queue_target_destroy(const vdp_t * vdp,VdpPresentationQueueTarget target)524 VdpStatus vdp_presentation_queue_target_destroy(const vdp_t *vdp,
525     VdpPresentationQueueTarget target)
526 {
527     CHECK_FUNC(PRESENTATION_QUEUE_TARGET_DESTROY);
528     return vdp->vt.presentation_queue_target_destroy(target);
529 }
530 
vdp_presentation_queue_create(const vdp_t * vdp,VdpDevice device,VdpPresentationQueueTarget target,VdpPresentationQueue * queue)531 VdpStatus vdp_presentation_queue_create(const vdp_t *vdp, VdpDevice device,
532     VdpPresentationQueueTarget target, VdpPresentationQueue *queue)
533 {
534     CHECK_FUNC(PRESENTATION_QUEUE_CREATE);
535     return vdp->vt.presentation_queue_create(device, target, queue);
536 }
537 
vdp_presentation_queue_destroy(const vdp_t * vdp,VdpPresentationQueue queue)538 VdpStatus vdp_presentation_queue_destroy(const vdp_t *vdp,
539     VdpPresentationQueue queue)
540 {
541     CHECK_FUNC(PRESENTATION_QUEUE_DESTROY);
542     return vdp->vt.presentation_queue_destroy(queue);
543 }
544 
vdp_presentation_queue_set_background_color(const vdp_t * vdp,VdpPresentationQueue queue,const VdpColor * color)545 VdpStatus vdp_presentation_queue_set_background_color(const vdp_t *vdp,
546     VdpPresentationQueue queue, const VdpColor *color)
547 {
548     VdpColor bak = *color;
549     CHECK_FUNC(PRESENTATION_QUEUE_SET_BACKGROUND_COLOR);
550     return vdp->vt.presentation_queue_set_background_color(queue, &bak);
551 }
552 
vdp_presentation_queue_get_background_color(const vdp_t * vdp,VdpPresentationQueue queue,VdpColor * color)553 VdpStatus vdp_presentation_queue_get_background_color(const vdp_t *vdp,
554     VdpPresentationQueue queue, VdpColor *color)
555 {
556     CHECK_FUNC(PRESENTATION_QUEUE_GET_BACKGROUND_COLOR);
557     return vdp->vt.presentation_queue_get_background_color(queue, color);
558 }
559 
vdp_presentation_queue_get_time(const vdp_t * vdp,VdpPresentationQueue queue,VdpTime * current_time)560 VdpStatus vdp_presentation_queue_get_time(const vdp_t *vdp,
561     VdpPresentationQueue queue, VdpTime *current_time)
562 {
563     CHECK_FUNC(PRESENTATION_QUEUE_GET_TIME);
564     return vdp->vt.presentation_queue_get_time(queue, current_time);
565 }
566 
vdp_presentation_queue_display(const vdp_t * vdp,VdpPresentationQueue queue,VdpOutputSurface surface,uint32_t clip_width,uint32_t clip_height,VdpTime pts)567 VdpStatus vdp_presentation_queue_display(const vdp_t *vdp,
568     VdpPresentationQueue queue, VdpOutputSurface surface, uint32_t clip_width,
569     uint32_t clip_height, VdpTime pts)
570 {
571     CHECK_FUNC(PRESENTATION_QUEUE_DISPLAY);
572     return vdp->vt.presentation_queue_display(queue, surface, clip_width,
573                                               clip_height, pts);
574 }
575 
vdp_presentation_queue_block_until_surface_idle(const vdp_t * vdp,VdpPresentationQueue queue,VdpOutputSurface surface,VdpTime * pts)576 VdpStatus vdp_presentation_queue_block_until_surface_idle(const vdp_t *vdp,
577     VdpPresentationQueue queue, VdpOutputSurface surface, VdpTime *pts)
578 {
579     CHECK_FUNC(PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE);
580     return vdp->vt.presentation_queue_block_until_surface_idle(queue, surface,
581                                                                pts);
582 }
583 
vdp_presentation_queue_query_surface_status(const vdp_t * vdp,VdpPresentationQueue queue,VdpOutputSurface surface,VdpPresentationQueueStatus * status,VdpTime * pts)584 VdpStatus vdp_presentation_queue_query_surface_status(const vdp_t *vdp,
585     VdpPresentationQueue queue, VdpOutputSurface surface,
586     VdpPresentationQueueStatus *status, VdpTime *pts)
587 {
588     CHECK_FUNC(PRESENTATION_QUEUE_QUERY_SURFACE_STATUS);
589     return vdp->vt.presentation_queue_query_surface_status(queue, surface,
590                                                            status, pts);
591 }
592 
593 /*** Preemption ***/
vdp_preemption_callback_register(const vdp_t * vdp,VdpDevice device,VdpPreemptionCallback cb,void * ctx)594 VdpStatus vdp_preemption_callback_register(const vdp_t *vdp, VdpDevice device,
595     VdpPreemptionCallback cb, void *ctx)
596 {
597     CHECK_FUNC(PREEMPTION_CALLBACK_REGISTER);
598     return vdp->vt.preemption_callback_register(device, cb, ctx);
599 }
600 
601 /*** X11 & VLC ***/
602 #include <dlfcn.h>
603 #include <vdpau/vdpau_x11.h>
604 
vdp_presentation_queue_target_create_x11(const vdp_t * vdp,VdpDevice device,uint32_t drawable,VdpPresentationQueueTarget * target)605 VdpStatus vdp_presentation_queue_target_create_x11(const vdp_t *vdp,
606     VdpDevice device, uint32_t drawable, VdpPresentationQueueTarget *target)
607 {
608     void *ptr;
609     VdpStatus err = vdp_get_proc_address(vdp, device,
610                        VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11, &ptr);
611     if (err != VDP_STATUS_OK)
612         return err;
613 
614     VdpPresentationQueueTargetCreateX11 *f = ptr;
615     return f(device, drawable, target);
616 }
617 
vdp_create_x11(void * dpy,int snum,vdp_t ** restrict vdpp,VdpDevice * restrict devp)618 VdpStatus vdp_create_x11(void *dpy, int snum,
619                          vdp_t **restrict vdpp, VdpDevice *restrict devp)
620 {
621     vdp_t *vdp = malloc(sizeof (*vdp));
622     if (unlikely(vdp == NULL))
623         return VDP_STATUS_RESOURCES;
624     *vdpp = vdp;
625 
626     VdpStatus err = VDP_STATUS_NO_IMPLEMENTATION;
627 
628     vdp->handle = dlopen("libvdpau.so.1", RTLD_LAZY|RTLD_LOCAL);
629     if (vdp->handle == NULL)
630     {
631         free(vdp);
632         return err;
633     }
634 
635     VdpDeviceCreateX11 *create = dlsym(vdp->handle, "vdp_device_create_x11");
636     if (create == NULL)
637         goto error;
638 
639     VdpGetProcAddress *gpa;
640     err = create(dpy, snum, devp, &gpa);
641     if (err != VDP_STATUS_OK)
642         goto error;
643 
644     for (VdpFuncId i = 0; i < sizeof (vdp->vt) / sizeof (void *); i++)
645         if (gpa(*devp, i, vdp->funcs + i) != VDP_STATUS_OK)
646             vdp->funcs[i] = NULL;
647 
648     return VDP_STATUS_OK;
649 error:
650     vdp_destroy_x11(vdp);
651     return err;
652 }
653 
vdp_destroy_x11(vdp_t * vdp)654 void vdp_destroy_x11(vdp_t *vdp)
655 {
656     dlclose(vdp->handle);
657     free(vdp);
658 }
659