vdpau_trace.cpp revision a4f78def
1/*
2 * Copyright (c) 2008-2015 NVIDIA Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24#define __STDC_FORMAT_MACROS
25#define __STDC_LIMIT_MACROS
26#include <inttypes.h>
27
28#include <dlfcn.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <vdpau/vdpau_x11.h>
33
34#include "../src/util.h"
35
36#define _VDP_TRACE_ARSIZE(_x_) ((sizeof (_x_)) / (sizeof ((_x_)[0])))
37
38#if DEBUG
39
40static void _vdp_trace_error_breakpoint(char const * file, int line, char const * function)
41{
42    fprintf(stderr, "VDPAU trace: Error detected at %s:%d %s()\n", file, line, function);
43}
44
45#define _VDP_TRACE_ERROR_BREAKPOINT() _vdp_trace_error_breakpoint(__FILE__, __LINE__, __FUNCTION__)
46
47#else
48
49#define _VDP_TRACE_ERROR_BREAKPOINT()
50
51#endif
52
53#define LEVEL_PARAMS 1
54#define LEVEL_DATA   2
55
56struct _VdpCapData {
57    void * dll;
58
59    int    level;
60    FILE * fp;
61
62    VdpDevice           vdp_device;
63    VdpGetProcAddress * vdp_get_proc_address;
64
65    VdpGetErrorString * vdp_get_error_string;
66    VdpGetApiVersion * vdp_get_api_version;
67    VdpGetInformationString * vdp_get_information_string;
68    VdpDeviceDestroy * vdp_device_destroy;
69    VdpGenerateCSCMatrix * vdp_generate_csc_matrix;
70    VdpVideoSurfaceQueryCapabilities * vdp_video_surface_query_capabilities;
71    VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities * vdp_video_surface_query_get_put_bits_y_cb_cr_capabilities;
72    VdpVideoSurfaceCreate * vdp_video_surface_create;
73    VdpVideoSurfaceDestroy * vdp_video_surface_destroy;
74    VdpVideoSurfaceGetParameters * vdp_video_surface_get_parameters;
75    VdpVideoSurfaceGetBitsYCbCr * vdp_video_surface_get_bits_y_cb_cr;
76    VdpVideoSurfacePutBitsYCbCr * vdp_video_surface_put_bits_y_cb_cr;
77    VdpOutputSurfaceQueryCapabilities * vdp_output_surface_query_capabilities;
78    VdpOutputSurfaceQueryGetPutBitsNativeCapabilities * vdp_output_surface_query_get_put_bits_native_capabilities;
79    VdpOutputSurfaceQueryPutBitsIndexedCapabilities * vdp_output_surface_query_put_bits_indexed_capabilities;
80    VdpOutputSurfaceQueryPutBitsYCbCrCapabilities * vdp_output_surface_query_put_bits_y_cb_cr_capabilities;
81    VdpOutputSurfaceCreate * vdp_output_surface_create;
82    VdpOutputSurfaceDestroy * vdp_output_surface_destroy;
83    VdpOutputSurfaceGetParameters * vdp_output_surface_get_parameters;
84    VdpOutputSurfaceGetBitsNative * vdp_output_surface_get_bits_native;
85    VdpOutputSurfacePutBitsNative * vdp_output_surface_put_bits_native;
86    VdpOutputSurfacePutBitsIndexed * vdp_output_surface_put_bits_indexed;
87    VdpOutputSurfacePutBitsYCbCr * vdp_output_surface_put_bits_y_cb_cr;
88    VdpBitmapSurfaceQueryCapabilities * vdp_bitmap_surface_query_capabilities;
89    VdpBitmapSurfaceCreate * vdp_bitmap_surface_create;
90    VdpBitmapSurfaceDestroy * vdp_bitmap_surface_destroy;
91    VdpBitmapSurfaceGetParameters * vdp_bitmap_surface_get_parameters;
92    VdpBitmapSurfacePutBitsNative * vdp_bitmap_surface_put_bits_native;
93    VdpOutputSurfaceRenderOutputSurface * vdp_output_surface_render_output_surface;
94    VdpOutputSurfaceRenderBitmapSurface * vdp_output_surface_render_bitmap_surface;
95    VdpDecoderQueryCapabilities * vdp_decoder_query_capabilities;
96    VdpDecoderCreate * vdp_decoder_create;
97    VdpDecoderDestroy * vdp_decoder_destroy;
98    VdpDecoderGetParameters * vdp_decoder_get_parameters;
99    VdpDecoderRender * vdp_decoder_render;
100    VdpVideoMixerQueryFeatureSupport * vdp_video_mixer_query_feature_support;
101    VdpVideoMixerQueryParameterSupport * vdp_video_mixer_query_parameter_support;
102    VdpVideoMixerQueryAttributeSupport * vdp_video_mixer_query_attribute_support;
103    VdpVideoMixerQueryParameterValueRange * vdp_video_mixer_query_parameter_value_range;
104    VdpVideoMixerQueryAttributeValueRange * vdp_video_mixer_query_attribute_value_range;
105    VdpVideoMixerCreate * vdp_video_mixer_create;
106    VdpVideoMixerSetFeatureEnables * vdp_video_mixer_set_feature_enables;
107    VdpVideoMixerSetAttributeValues * vdp_video_mixer_set_attribute_values;
108    VdpVideoMixerGetFeatureSupport * vdp_video_mixer_get_feature_support;
109    VdpVideoMixerGetFeatureEnables * vdp_video_mixer_get_feature_enables;
110    VdpVideoMixerGetParameterValues * vdp_video_mixer_get_parameter_values;
111    VdpVideoMixerGetAttributeValues * vdp_video_mixer_get_attribute_values;
112    VdpVideoMixerDestroy * vdp_video_mixer_destroy;
113    VdpVideoMixerRender * vdp_video_mixer_render;
114    VdpPresentationQueueTargetDestroy * vdp_presentation_queue_target_destroy;
115    VdpPresentationQueueCreate * vdp_presentation_queue_create;
116    VdpPresentationQueueDestroy * vdp_presentation_queue_destroy;
117    VdpPresentationQueueSetBackgroundColor * vdp_presentation_queue_set_background_color;
118    VdpPresentationQueueGetBackgroundColor * vdp_presentation_queue_get_background_color;
119    VdpPresentationQueueGetTime * vdp_presentation_queue_get_time;
120    VdpPresentationQueueDisplay * vdp_presentation_queue_display;
121    VdpPresentationQueueBlockUntilSurfaceIdle * vdp_presentation_queue_block_until_surface_idle;
122    VdpPresentationQueueQuerySurfaceStatus * vdp_presentation_queue_query_surface_status;
123    VdpPreemptionCallbackRegister * vdp_preemption_callback_register;
124    VdpPresentationQueueTargetCreateX11 * vdp_presentation_queue_target_create_x11;
125};
126
127static _VdpCapData _vdp_cap_data;
128
129template<class T> static inline T const delta(T const & a, T const & b)
130{
131    if (a < b) {
132        return b - a;
133    }
134    else {
135        return a - b;
136    }
137}
138
139static void _vdp_cap_dump_procamp(VdpProcamp * procamp)
140{
141    if (!procamp) {
142        fprintf(_vdp_cap_data.fp, "NULL");
143        return;
144    }
145
146    fprintf(
147        _vdp_cap_data.fp,
148        "{(ver=%d)%s %f, %f, %f, %f}",
149        procamp->struct_version,
150        (procamp->struct_version > 0)
151            ? "(unsupported; cannot dump all fields)"
152            : "",
153        procamp->brightness,
154        procamp->contrast,
155        procamp->saturation,
156        procamp->hue
157    );
158}
159
160static void _vdp_cap_dump_color(
161    VdpColor const * color
162)
163{
164    if (!color) {
165        fputs("NULL", _vdp_cap_data.fp);
166        return;
167    }
168
169    fprintf(
170        _vdp_cap_data.fp,
171        "{%f, %f, %f, %f}",
172        color->red,
173        color->green,
174        color->blue,
175        color->alpha
176    );
177}
178
179static void _vdp_cap_dump_rect(
180    VdpRect const * rect
181)
182{
183    if (!rect) {
184        fprintf(_vdp_cap_data.fp, "NULL");
185        return;
186    }
187
188    fprintf(
189        _vdp_cap_data.fp,
190        "{%u, %u, %u, %u}",
191        rect->x0,
192        rect->y0,
193        rect->x1,
194        rect->y1
195    );
196}
197
198static void _vdp_cap_dump_csc_matrix(
199    VdpCSCMatrix const * matrix
200)
201{
202    if (!matrix) {
203        fprintf(_vdp_cap_data.fp, "NULL");
204        return;
205    }
206
207    fprintf(
208        _vdp_cap_data.fp,
209        "{{%f, %f, %f, %f}, {%f, %f, %f, %f}, {%f, %f, %f, %f}}",
210        (*matrix)[0][0],
211        (*matrix)[0][1],
212        (*matrix)[0][2],
213        (*matrix)[0][3],
214        (*matrix)[1][0],
215        (*matrix)[1][1],
216        (*matrix)[1][2],
217        (*matrix)[1][3],
218        (*matrix)[2][0],
219        (*matrix)[2][1],
220        (*matrix)[2][2],
221        (*matrix)[2][3]
222    );
223}
224
225static void _vdp_cap_dump_blend_state(
226    VdpOutputSurfaceRenderBlendState const * blend_state
227)
228{
229    if (!blend_state) {
230        fprintf(_vdp_cap_data.fp, "NULL");
231        return;
232    }
233
234    fprintf(
235        _vdp_cap_data.fp,
236        "{(ver=%d)%s %u, %u, %u, %u, %u, %u, ",
237        blend_state->struct_version,
238        (blend_state->struct_version > 0)
239            ? "(unsupported; cannot dump all fields)"
240            : "",
241        blend_state->blend_factor_source_color,
242        blend_state->blend_factor_destination_color,
243        blend_state->blend_factor_source_alpha,
244        blend_state->blend_factor_destination_alpha,
245        blend_state->blend_equation_color,
246        blend_state->blend_equation_alpha
247    );
248    _vdp_cap_dump_color(&(blend_state->blend_constant));
249    fputs("}", _vdp_cap_data.fp);
250}
251
252static void _vdp_cap_dump_picture_info(
253    VdpDecoderProfile      profile,
254    VdpPictureInfo const * picture_info
255)
256{
257    switch (profile) {
258    case VDP_DECODER_PROFILE_MPEG1:
259    case VDP_DECODER_PROFILE_MPEG2_SIMPLE:
260    case VDP_DECODER_PROFILE_MPEG2_MAIN:
261        {
262            VdpPictureInfoMPEG1Or2 const * picture_info_mpeg1or2 =
263                (VdpPictureInfoMPEG1Or2 const *)picture_info;
264
265            fprintf(
266                _vdp_cap_data.fp,
267                "{%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, {{%u, %u}, {%u, %u}}, {",
268                picture_info_mpeg1or2->forward_reference,
269                picture_info_mpeg1or2->backward_reference,
270                picture_info_mpeg1or2->slice_count,
271                (uint32_t)picture_info_mpeg1or2->picture_structure,
272                (uint32_t)picture_info_mpeg1or2->picture_coding_type,
273                (uint32_t)picture_info_mpeg1or2->intra_dc_precision,
274                (uint32_t)picture_info_mpeg1or2->frame_pred_frame_dct,
275                (uint32_t)picture_info_mpeg1or2->concealment_motion_vectors,
276                (uint32_t)picture_info_mpeg1or2->intra_vlc_format,
277                (uint32_t)picture_info_mpeg1or2->alternate_scan,
278                (uint32_t)picture_info_mpeg1or2->q_scale_type,
279                (uint32_t)picture_info_mpeg1or2->top_field_first,
280                (uint32_t)picture_info_mpeg1or2->full_pel_forward_vector,
281                (uint32_t)picture_info_mpeg1or2->full_pel_backward_vector,
282                (uint32_t)picture_info_mpeg1or2->f_code[0][0],
283                (uint32_t)picture_info_mpeg1or2->f_code[0][1],
284                (uint32_t)picture_info_mpeg1or2->f_code[1][0],
285                (uint32_t)picture_info_mpeg1or2->f_code[1][1]
286            );
287            for (uint32_t i = 0; i < _VDP_TRACE_ARSIZE(picture_info_mpeg1or2->intra_quantizer_matrix); ++i) {
288                fprintf(
289                    _vdp_cap_data.fp,
290                    "%s%u",
291                    (i == 0) ? "" : ", ",
292                    (uint32_t)picture_info_mpeg1or2->intra_quantizer_matrix[i]
293                );
294            }
295            fputs("}, {", _vdp_cap_data.fp);
296            for (uint32_t i = 0; i < _VDP_TRACE_ARSIZE(picture_info_mpeg1or2->non_intra_quantizer_matrix); ++i) {
297                fprintf(
298                    _vdp_cap_data.fp,
299                    "%s%u",
300                    (i == 0) ? "" : ", ",
301                    (uint32_t)picture_info_mpeg1or2->non_intra_quantizer_matrix[i]
302                );
303            }
304            fputs("}}", _vdp_cap_data.fp);
305        }
306        break;
307    case VDP_DECODER_PROFILE_H264_BASELINE:
308    case VDP_DECODER_PROFILE_H264_MAIN:
309    case VDP_DECODER_PROFILE_H264_HIGH:
310        {
311            VdpPictureInfoH264 const * picture_info_h264 =
312                (VdpPictureInfoH264 const *)picture_info;
313
314            fprintf(
315                _vdp_cap_data.fp,
316                "{%u, {%d, %d}, %d, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %d, %d, %d, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, {",
317                picture_info_h264->slice_count,
318                picture_info_h264->field_order_cnt[0],
319                picture_info_h264->field_order_cnt[1],
320                (int32_t)picture_info_h264->is_reference,
321                (uint32_t)picture_info_h264->frame_num,
322                (uint32_t)picture_info_h264->field_pic_flag,
323                (uint32_t)picture_info_h264->bottom_field_flag,
324                (uint32_t)picture_info_h264->num_ref_frames,
325                (uint32_t)picture_info_h264->mb_adaptive_frame_field_flag,
326                (uint32_t)picture_info_h264->constrained_intra_pred_flag,
327                (uint32_t)picture_info_h264->weighted_pred_flag,
328                (uint32_t)picture_info_h264->weighted_bipred_idc,
329                (uint32_t)picture_info_h264->frame_mbs_only_flag,
330                (uint32_t)picture_info_h264->transform_8x8_mode_flag,
331                (int32_t)picture_info_h264->chroma_qp_index_offset,
332                (int32_t)picture_info_h264->second_chroma_qp_index_offset,
333                (int32_t)picture_info_h264->pic_init_qp_minus26,
334                (uint32_t)picture_info_h264->num_ref_idx_l0_active_minus1,
335                (uint32_t)picture_info_h264->num_ref_idx_l1_active_minus1,
336                (uint32_t)picture_info_h264->log2_max_frame_num_minus4,
337                (uint32_t)picture_info_h264->pic_order_cnt_type,
338                (uint32_t)picture_info_h264->log2_max_pic_order_cnt_lsb_minus4,
339                (uint32_t)picture_info_h264->delta_pic_order_always_zero_flag,
340                (uint32_t)picture_info_h264->direct_8x8_inference_flag,
341                (uint32_t)picture_info_h264->entropy_coding_mode_flag,
342                (uint32_t)picture_info_h264->pic_order_present_flag,
343                (uint32_t)picture_info_h264->deblocking_filter_control_present_flag,
344                (uint32_t)picture_info_h264->redundant_pic_cnt_present_flag
345            );
346            for (uint32_t i = 0; i < _VDP_TRACE_ARSIZE(picture_info_h264->scaling_lists_4x4); ++i) {
347                fputs((i == 0) ? "{" : "}, {", _vdp_cap_data.fp);
348                for (uint32_t j = 0; j < _VDP_TRACE_ARSIZE(picture_info_h264->scaling_lists_4x4[0]); ++j) {
349                    fprintf(
350                        _vdp_cap_data.fp,
351                        "%s%u",
352                        (j == 0) ? "" : ", ",
353                        (uint32_t)picture_info_h264->scaling_lists_4x4[i][j]
354                    );
355                }
356            }
357            fputs("}}, {", _vdp_cap_data.fp);
358            for (uint32_t i = 0; i < _VDP_TRACE_ARSIZE(picture_info_h264->scaling_lists_8x8); ++i) {
359                fputs((i == 0) ? "{" : "}, {", _vdp_cap_data.fp);
360                for (uint32_t j = 0; j < _VDP_TRACE_ARSIZE(picture_info_h264->scaling_lists_8x8[0]); ++j) {
361                    fprintf(
362                        _vdp_cap_data.fp,
363                        "%s%u",
364                        (j == 0) ? "" : ", ",
365                        (uint32_t)picture_info_h264->scaling_lists_8x8[i][j]
366                    );
367                }
368            }
369            fputs("}}, {", _vdp_cap_data.fp);
370            for (uint32_t i = 0; i < _VDP_TRACE_ARSIZE(picture_info_h264->referenceFrames); ++i) {
371                VdpReferenceFrameH264 const * rf = &(picture_info_h264->referenceFrames[i]);
372                fprintf(
373                    _vdp_cap_data.fp,
374                    "%s{%u, %d, %d, %d, {%d, %d}, %u}",
375                    (i == 0) ? "" : ", ",
376                    rf->surface,
377                    (int32_t)rf->is_long_term,
378                    (int32_t)rf->top_is_reference,
379                    (int32_t)rf->bottom_is_reference,
380                    (int32_t)rf->field_order_cnt[0],
381                    (int32_t)rf->field_order_cnt[1],
382                    (uint32_t)rf->frame_idx
383                );
384            }
385            fputs("}}", _vdp_cap_data.fp);
386        }
387        break;
388    case VDP_DECODER_PROFILE_VC1_SIMPLE:
389    case VDP_DECODER_PROFILE_VC1_MAIN:
390    case VDP_DECODER_PROFILE_VC1_ADVANCED:
391        {
392            VdpPictureInfoVC1 const * picture_info_vc1 =
393                (VdpPictureInfoVC1 const *)picture_info;
394
395            fprintf(
396                _vdp_cap_data.fp,
397                "{%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u}",
398                picture_info_vc1->forward_reference,
399                picture_info_vc1->backward_reference,
400                picture_info_vc1->slice_count,
401                (uint32_t)picture_info_vc1->picture_type,
402                (uint32_t)picture_info_vc1->frame_coding_mode,
403                (uint32_t)picture_info_vc1->postprocflag,
404                (uint32_t)picture_info_vc1->pulldown,
405                (uint32_t)picture_info_vc1->interlace,
406                (uint32_t)picture_info_vc1->tfcntrflag,
407                (uint32_t)picture_info_vc1->finterpflag,
408                (uint32_t)picture_info_vc1->psf,
409                (uint32_t)picture_info_vc1->dquant,
410                (uint32_t)picture_info_vc1->panscan_flag,
411                (uint32_t)picture_info_vc1->refdist_flag,
412                (uint32_t)picture_info_vc1->quantizer,
413                (uint32_t)picture_info_vc1->extended_mv,
414                (uint32_t)picture_info_vc1->extended_dmv,
415                (uint32_t)picture_info_vc1->overlap,
416                (uint32_t)picture_info_vc1->vstransform,
417                (uint32_t)picture_info_vc1->loopfilter,
418                (uint32_t)picture_info_vc1->fastuvmc,
419                (uint32_t)picture_info_vc1->range_mapy_flag,
420                (uint32_t)picture_info_vc1->range_mapy,
421                (uint32_t)picture_info_vc1->range_mapuv_flag,
422                (uint32_t)picture_info_vc1->range_mapuv,
423                (uint32_t)picture_info_vc1->multires,
424                (uint32_t)picture_info_vc1->syncmarker,
425                (uint32_t)picture_info_vc1->rangered,
426                (uint32_t)picture_info_vc1->maxbframes,
427                (uint32_t)picture_info_vc1->deblockEnable,
428                (uint32_t)picture_info_vc1->pquant
429            );
430        }
431        break;
432    case VDP_DECODER_PROFILE_MPEG4_PART2_SP:
433    case VDP_DECODER_PROFILE_MPEG4_PART2_ASP:
434    case VDP_DECODER_PROFILE_DIVX4_QMOBILE:
435    case VDP_DECODER_PROFILE_DIVX4_MOBILE:
436    case VDP_DECODER_PROFILE_DIVX4_HOME_THEATER:
437    case VDP_DECODER_PROFILE_DIVX4_HD_1080P:
438    case VDP_DECODER_PROFILE_DIVX5_QMOBILE:
439    case VDP_DECODER_PROFILE_DIVX5_MOBILE:
440    case VDP_DECODER_PROFILE_DIVX5_HOME_THEATER:
441    case VDP_DECODER_PROFILE_DIVX5_HD_1080P:
442        {
443            VdpPictureInfoMPEG4Part2 const * picture_info_mpeg4 =
444                (VdpPictureInfoMPEG4Part2 const *)picture_info;
445
446            fprintf(
447                _vdp_cap_data.fp,
448                "{%u, %u, {%d, %d}, {%d, %d}, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, {",
449                picture_info_mpeg4->forward_reference,
450                picture_info_mpeg4->backward_reference,
451                (int32_t)picture_info_mpeg4->trd[0],
452                (int32_t)picture_info_mpeg4->trd[1],
453                (int32_t)picture_info_mpeg4->trb[0],
454                (int32_t)picture_info_mpeg4->trb[1],
455                (uint32_t)picture_info_mpeg4->vop_time_increment_resolution,
456                (uint32_t)picture_info_mpeg4->vop_coding_type,
457                (uint32_t)picture_info_mpeg4->vop_fcode_forward,
458                (uint32_t)picture_info_mpeg4->vop_fcode_backward,
459                (uint32_t)picture_info_mpeg4->resync_marker_disable,
460                (uint32_t)picture_info_mpeg4->interlaced,
461                (uint32_t)picture_info_mpeg4->quant_type,
462                (uint32_t)picture_info_mpeg4->quarter_sample,
463                (uint32_t)picture_info_mpeg4->short_video_header,
464                (uint32_t)picture_info_mpeg4->rounding_control,
465                (uint32_t)picture_info_mpeg4->alternate_vertical_scan_flag,
466                (uint32_t)picture_info_mpeg4->top_field_first
467            );
468            for (uint32_t i = 0; i < _VDP_TRACE_ARSIZE(picture_info_mpeg4->intra_quantizer_matrix); ++i) {
469                fprintf(
470                    _vdp_cap_data.fp,
471                    "%s%u",
472                    (i == 0) ? "" : ", ",
473                    (uint32_t)picture_info_mpeg4->intra_quantizer_matrix[i]
474                );
475            }
476            fputs("}, {", _vdp_cap_data.fp);
477            for (uint32_t i = 0; i < _VDP_TRACE_ARSIZE(picture_info_mpeg4->non_intra_quantizer_matrix); ++i) {
478                fprintf(
479                    _vdp_cap_data.fp,
480                    "%s%u",
481                    (i == 0) ? "" : ", ",
482                    (uint32_t)picture_info_mpeg4->non_intra_quantizer_matrix[i]
483                );
484            }
485            fputs("}}", _vdp_cap_data.fp);
486        }
487        break;
488    case VDP_DECODER_PROFILE_HEVC_MAIN:
489    case VDP_DECODER_PROFILE_HEVC_MAIN_10:
490    case VDP_DECODER_PROFILE_HEVC_MAIN_STILL:
491    case VDP_DECODER_PROFILE_HEVC_MAIN_12:
492    case VDP_DECODER_PROFILE_HEVC_MAIN_444:
493        {
494            VdpPictureInfoHEVC const * picture_info_hevc =
495                (VdpPictureInfoHEVC const *)picture_info;
496
497            fprintf(
498                _vdp_cap_data.fp,
499                "{%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, {",
500                (uint32_t)picture_info_hevc->chroma_format_idc,
501                (uint32_t)picture_info_hevc->separate_colour_plane_flag,
502                (uint32_t)picture_info_hevc->pic_width_in_luma_samples,
503                (uint32_t)picture_info_hevc->pic_height_in_luma_samples,
504                (uint32_t)picture_info_hevc->bit_depth_luma_minus8,
505                (uint32_t)picture_info_hevc->bit_depth_chroma_minus8,
506                (uint32_t)picture_info_hevc->log2_max_pic_order_cnt_lsb_minus4,
507                (uint32_t)picture_info_hevc->sps_max_dec_pic_buffering_minus1,
508                (uint32_t)picture_info_hevc->log2_min_luma_coding_block_size_minus3,
509                (uint32_t)picture_info_hevc->log2_diff_max_min_luma_coding_block_size,
510                (uint32_t)picture_info_hevc->log2_min_transform_block_size_minus2,
511                (uint32_t)picture_info_hevc->log2_diff_max_min_transform_block_size,
512                (uint32_t)picture_info_hevc->max_transform_hierarchy_depth_inter,
513                (uint32_t)picture_info_hevc->max_transform_hierarchy_depth_intra,
514                (uint32_t)picture_info_hevc->scaling_list_enabled_flag
515            );
516            for (uint32_t i = 0; i < _VDP_TRACE_ARSIZE(picture_info_hevc->ScalingList4x4); ++i) {
517                fputs((i == 0) ? "{" : "}, {", _vdp_cap_data.fp);
518                for (uint32_t j = 0; j < _VDP_TRACE_ARSIZE(picture_info_hevc->ScalingList4x4[0]); ++j) {
519                    fprintf(
520                        _vdp_cap_data.fp,
521                        "%s%u",
522                        (j == 0) ? "" : ", ",
523                        (uint32_t)picture_info_hevc->ScalingList4x4[i][j]
524                    );
525                }
526            }
527            fputs("}}, {", _vdp_cap_data.fp);
528            for (uint32_t i = 0; i < _VDP_TRACE_ARSIZE(picture_info_hevc->ScalingList8x8); ++i) {
529                fputs((i == 0) ? "{" : "}, {", _vdp_cap_data.fp);
530                for (uint32_t j = 0; j < _VDP_TRACE_ARSIZE(picture_info_hevc->ScalingList8x8[0]); ++j) {
531                    fprintf(
532                        _vdp_cap_data.fp,
533                        "%s%u",
534                        (j == 0) ? "" : ", ",
535                        (uint32_t)picture_info_hevc->ScalingList8x8[i][j]
536                    );
537                }
538            }
539            fputs("}}, {", _vdp_cap_data.fp);
540            for (uint32_t i = 0; i < _VDP_TRACE_ARSIZE(picture_info_hevc->ScalingList16x16); ++i) {
541                fputs((i == 0) ? "{" : "}, {", _vdp_cap_data.fp);
542                for (uint32_t j = 0; j < _VDP_TRACE_ARSIZE(picture_info_hevc->ScalingList16x16[0]); ++j) {
543                    fprintf(
544                        _vdp_cap_data.fp,
545                        "%s%u",
546                        (j == 0) ? "" : ", ",
547                        (uint32_t)picture_info_hevc->ScalingList16x16[i][j]
548                    );
549                }
550            }
551            fputs("}}, {", _vdp_cap_data.fp);
552            for (uint32_t i = 0; i < _VDP_TRACE_ARSIZE(picture_info_hevc->ScalingList32x32); ++i) {
553                fputs((i == 0) ? "{" : "}, {", _vdp_cap_data.fp);
554                for (uint32_t j = 0; j < _VDP_TRACE_ARSIZE(picture_info_hevc->ScalingList32x32[0]); ++j) {
555                    fprintf(
556                        _vdp_cap_data.fp,
557                        "%s%u",
558                        (j == 0) ? "" : ", ",
559                        (uint32_t)picture_info_hevc->ScalingList32x32[i][j]
560                    );
561                }
562            }
563            fputs("}}, {", _vdp_cap_data.fp);
564            for (uint32_t i = 0; i < _VDP_TRACE_ARSIZE(picture_info_hevc->ScalingListDCCoeff16x16); ++i) {
565                fprintf(
566                    _vdp_cap_data.fp,
567                    "%s%u",
568                    (i == 0) ? "" : ", ",
569                    (uint32_t)picture_info_hevc->ScalingListDCCoeff16x16[i]
570                );
571            }
572            fputs("}, {", _vdp_cap_data.fp);
573            for (uint32_t i = 0; i < _VDP_TRACE_ARSIZE(picture_info_hevc->ScalingListDCCoeff32x32); ++i) {
574                fprintf(
575                    _vdp_cap_data.fp,
576                    "%s%u",
577                    (i == 0) ? "" : ", ",
578                    (uint32_t)picture_info_hevc->ScalingListDCCoeff32x32[i]
579                );
580            }
581            fputs("}, ", _vdp_cap_data.fp);
582            fprintf(
583                _vdp_cap_data.fp,
584                "%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %d, %u, %u, %u, %u, %d, %d, %u, %u, %u, %u, %u, %u, %u, %u, %u, {",
585                (uint32_t)picture_info_hevc->amp_enabled_flag,
586                (uint32_t)picture_info_hevc->sample_adaptive_offset_enabled_flag,
587                (uint32_t)picture_info_hevc->pcm_enabled_flag,
588                (uint32_t)picture_info_hevc->pcm_sample_bit_depth_luma_minus1,
589                (uint32_t)picture_info_hevc->pcm_sample_bit_depth_chroma_minus1,
590                (uint32_t)picture_info_hevc->log2_min_pcm_luma_coding_block_size_minus3,
591                (uint32_t)picture_info_hevc->log2_diff_max_min_pcm_luma_coding_block_size,
592                (uint32_t)picture_info_hevc->pcm_loop_filter_disabled_flag,
593                (uint32_t)picture_info_hevc->num_short_term_ref_pic_sets,
594                (uint32_t)picture_info_hevc->long_term_ref_pics_present_flag,
595                (uint32_t)picture_info_hevc->num_long_term_ref_pics_sps,
596                (uint32_t)picture_info_hevc->sps_temporal_mvp_enabled_flag,
597                (uint32_t)picture_info_hevc->strong_intra_smoothing_enabled_flag,
598                (uint32_t)picture_info_hevc->dependent_slice_segments_enabled_flag,
599                (uint32_t)picture_info_hevc->output_flag_present_flag,
600                (uint32_t)picture_info_hevc->num_extra_slice_header_bits,
601                (uint32_t)picture_info_hevc->sign_data_hiding_enabled_flag,
602                (uint32_t)picture_info_hevc->cabac_init_present_flag,
603                (uint32_t)picture_info_hevc->num_ref_idx_l0_default_active_minus1,
604                (uint32_t)picture_info_hevc->num_ref_idx_l1_default_active_minus1,
605                (int32_t)picture_info_hevc->init_qp_minus26,
606                (uint32_t)picture_info_hevc->constrained_intra_pred_flag,
607                (uint32_t)picture_info_hevc->transform_skip_enabled_flag,
608                (uint32_t)picture_info_hevc->cu_qp_delta_enabled_flag,
609                (uint32_t)picture_info_hevc->diff_cu_qp_delta_depth,
610                (int32_t)picture_info_hevc->pps_cb_qp_offset,
611                (int32_t)picture_info_hevc->pps_cr_qp_offset,
612                (uint32_t)picture_info_hevc->pps_slice_chroma_qp_offsets_present_flag,
613                (uint32_t)picture_info_hevc->weighted_pred_flag,
614                (uint32_t)picture_info_hevc->weighted_bipred_flag,
615                (uint32_t)picture_info_hevc->transquant_bypass_enabled_flag,
616                (uint32_t)picture_info_hevc->tiles_enabled_flag,
617                (uint32_t)picture_info_hevc->entropy_coding_sync_enabled_flag,
618                (uint32_t)picture_info_hevc->num_tile_columns_minus1,
619                (uint32_t)picture_info_hevc->num_tile_rows_minus1,
620                (uint32_t)picture_info_hevc->uniform_spacing_flag
621            );
622            for (uint32_t i = 0; i < _VDP_TRACE_ARSIZE(picture_info_hevc->column_width_minus1); ++i) {
623                fprintf(
624                    _vdp_cap_data.fp,
625                    "%s%u",
626                    (i == 0) ? "" : ", ",
627                    (uint32_t)picture_info_hevc->column_width_minus1[i]
628                );
629            }
630            fputs("}, {", _vdp_cap_data.fp);
631            for (uint32_t i = 0; i < _VDP_TRACE_ARSIZE(picture_info_hevc->row_height_minus1); ++i) {
632                fprintf(
633                    _vdp_cap_data.fp,
634                    "%s%u",
635                    (i == 0) ? "" : ", ",
636                    (uint32_t)picture_info_hevc->row_height_minus1[i]
637                );
638            }
639            fputs("}, ", _vdp_cap_data.fp);
640            fprintf(
641                _vdp_cap_data.fp,
642                "%u, %u, %u, %u, %u, %d, %d, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %d, {",
643                (uint32_t)picture_info_hevc->loop_filter_across_tiles_enabled_flag,
644                (uint32_t)picture_info_hevc->pps_loop_filter_across_slices_enabled_flag,
645                (uint32_t)picture_info_hevc->deblocking_filter_control_present_flag,
646                (uint32_t)picture_info_hevc->deblocking_filter_override_enabled_flag,
647                (uint32_t)picture_info_hevc->pps_deblocking_filter_disabled_flag,
648                (int32_t)picture_info_hevc->pps_beta_offset_div2,
649                (int32_t)picture_info_hevc->pps_tc_offset_div2,
650                (uint32_t)picture_info_hevc->lists_modification_present_flag,
651                (uint32_t)picture_info_hevc->log2_parallel_merge_level_minus2,
652                (uint32_t)picture_info_hevc->slice_segment_header_extension_present_flag,
653                (uint32_t)picture_info_hevc->IDRPicFlag,
654                (uint32_t)picture_info_hevc->RAPPicFlag,
655                (uint32_t)picture_info_hevc->CurrRpsIdx,
656                (uint32_t)picture_info_hevc->NumPocTotalCurr,
657                (uint32_t)picture_info_hevc->NumDeltaPocsOfRefRpsIdx,
658                (uint32_t)picture_info_hevc->NumShortTermPictureSliceHeaderBits,
659                (uint32_t)picture_info_hevc->NumLongTermPictureSliceHeaderBits,
660                (int32_t)picture_info_hevc->CurrPicOrderCntVal
661            );
662            for (uint32_t i = 0; i < _VDP_TRACE_ARSIZE(picture_info_hevc->RefPics); ++i) {
663                fprintf(
664                    _vdp_cap_data.fp,
665                    "%s%u",
666                    (i == 0) ? "" : ", ",
667                    (uint32_t)picture_info_hevc->RefPics[i]
668                );
669            }
670            fputs("}, {", _vdp_cap_data.fp);
671            for (uint32_t i = 0; i < _VDP_TRACE_ARSIZE(picture_info_hevc->PicOrderCntVal); ++i) {
672                fprintf(
673                    _vdp_cap_data.fp,
674                    "%s%d",
675                    (i == 0) ? "" : ", ",
676                    (int32_t)picture_info_hevc->PicOrderCntVal[i]
677                );
678            }
679            fputs("}, {", _vdp_cap_data.fp);
680            for (uint32_t i = 0; i < _VDP_TRACE_ARSIZE(picture_info_hevc->IsLongTerm); ++i) {
681                fprintf(
682                    _vdp_cap_data.fp,
683                    "%s%u",
684                    (i == 0) ? "" : ", ",
685                    (uint32_t)picture_info_hevc->IsLongTerm[i]
686                );
687            }
688            fputs("}, ", _vdp_cap_data.fp);
689            fprintf(
690                _vdp_cap_data.fp,
691                "%u, %u, %u, {",
692                (uint32_t)picture_info_hevc->NumPocStCurrBefore,
693                (uint32_t)picture_info_hevc->NumPocStCurrAfter,
694                (uint32_t)picture_info_hevc->NumPocLtCurr
695            );
696            for (uint32_t i = 0; i < _VDP_TRACE_ARSIZE(picture_info_hevc->RefPicSetStCurrBefore); ++i) {
697                fprintf(
698                    _vdp_cap_data.fp,
699                    "%s%u",
700                    (i == 0) ? "" : ", ",
701                    (uint32_t)picture_info_hevc->RefPicSetStCurrBefore[i]
702                );
703            }
704            fputs("}, {", _vdp_cap_data.fp);
705            for (uint32_t i = 0; i < _VDP_TRACE_ARSIZE(picture_info_hevc->RefPicSetStCurrAfter); ++i) {
706                fprintf(
707                    _vdp_cap_data.fp,
708                    "%s%u",
709                    (i == 0) ? "" : ", ",
710                    (uint32_t)picture_info_hevc->RefPicSetStCurrAfter[i]
711                );
712            }
713            fputs("}, {", _vdp_cap_data.fp);
714            for (uint32_t i = 0; i < _VDP_TRACE_ARSIZE(picture_info_hevc->RefPicSetLtCurr); ++i) {
715                fprintf(
716                    _vdp_cap_data.fp,
717                    "%s%u",
718                    (i == 0) ? "" : ", ",
719                    (uint32_t)picture_info_hevc->RefPicSetLtCurr[i]
720                );
721            }
722            fputs("}}", _vdp_cap_data.fp);
723        }
724        break;
725    default:
726        fputs("{...}", _vdp_cap_data.fp);
727        break;
728    }
729}
730
731static void _vdp_cap_dump_video_mixer_parameter_value(
732    VdpVideoMixerParameter parameter,
733    void const *           value
734)
735{
736    switch (parameter) {
737    case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH:
738    case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT:
739    case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE:
740    case VDP_VIDEO_MIXER_PARAMETER_LAYERS:
741        if (!value) {
742            fputs("???", _vdp_cap_data.fp);
743        }
744        else {
745            fprintf(_vdp_cap_data.fp, "%u", *(uint32_t const *)value);
746        }
747        break;
748    default:
749        fputs("???", _vdp_cap_data.fp);
750        break;
751    }
752}
753
754static void _vdp_cap_dump_video_mixer_attribute_value(
755    VdpVideoMixerAttribute attribute,
756    void const *           value,
757    bool                   get_operation
758)
759{
760    if (!value) {
761        fputs("NULL", _vdp_cap_data.fp);
762        return;
763    }
764
765    switch (attribute) {
766    case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR:
767        _vdp_cap_dump_color((VdpColor const *)value);
768        break;
769    case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX:
770        {
771            VdpCSCMatrix const * ptr;
772
773            // For some objects, the "default" value is a NULL pointer.
774            // So, VdpVideoMixerGetAttributeValues expects a double pointer to
775            // the value, so it can either fill in the value, or NULL out the
776            // pointer.
777            if (get_operation) {
778                ptr = *(VdpCSCMatrix const * const *)value;
779            }
780            else {
781                ptr = (VdpCSCMatrix const *)value;
782            }
783            _vdp_cap_dump_csc_matrix(ptr);
784        }
785        break;
786    case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL:
787    case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL:
788    case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA:
789    case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA:
790        fprintf(_vdp_cap_data.fp, "%f", *(float const *)value);
791        break;
792    case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE:
793        fprintf(_vdp_cap_data.fp, "%u", *(uint8_t const *)value);
794        break;
795    default:
796        fputs("???", _vdp_cap_data.fp);
797        break;
798    }
799}
800
801static void _vdp_cap_dump_uint8_t_stream(
802    uint32_t        count,
803    uint8_t const * values
804)
805{
806    if (!values) {
807        fputs("NULL", _vdp_cap_data.fp);
808        return;
809    }
810
811    fputs("{", _vdp_cap_data.fp);
812    while (count) {
813        fprintf(
814            _vdp_cap_data.fp,
815            "%02x",
816            values[0]
817        );
818
819        --count;
820        ++values;
821    }
822    fputs("}", _vdp_cap_data.fp);
823}
824
825static void _vdp_cap_dump_uint32_t_stream(
826    uint32_t         count,
827    uint32_t const * values
828)
829{
830    if (!values) {
831        fputs("NULL", _vdp_cap_data.fp);
832        return;
833    }
834
835    fputs("{", _vdp_cap_data.fp);
836    while (count) {
837        fprintf(
838            _vdp_cap_data.fp,
839            "%08x%s",
840            values[0],
841            (count > 1) ? " " : ""
842        );
843
844        --count;
845        ++values;
846    }
847    fputs("}", _vdp_cap_data.fp);
848}
849
850struct _VdpcapPlane {
851    void const * data;
852    uint32_t     pitch;
853    uint32_t     item_count;
854    uint32_t     item_size;
855    uint32_t     lines;
856};
857
858typedef void _VdpcapPlaneDumper(uint32_t count, void const * values);
859
860static void _vdp_cap_dump_plane_list(
861    uint32_t             plane_count,
862    _VdpcapPlane const * planes
863)
864{
865    if (!planes) {
866        fputs("NULL", _vdp_cap_data.fp);
867        return;
868    }
869
870    fputs("{", _vdp_cap_data.fp);
871    while (plane_count) {
872        uint32_t lines = planes[0].lines;
873
874        _VdpcapPlaneDumper * dumper;
875        if (planes[0].item_size == 4) {
876            dumper = (_VdpcapPlaneDumper*)_vdp_cap_dump_uint32_t_stream;
877        }
878        else {
879            dumper = (_VdpcapPlaneDumper*)_vdp_cap_dump_uint8_t_stream;
880        }
881
882        fputs("{", _vdp_cap_data.fp);
883        uint8_t const * ptr = (uint8_t const *)planes[0].data;
884        while (lines) {
885            dumper(planes[0].item_count, ptr);
886            if (lines > 1) {
887                fputs(", ", _vdp_cap_data.fp);
888            }
889
890            ptr += planes[0].pitch;
891            --lines;
892        }
893        fputs("}", _vdp_cap_data.fp);
894
895        if (plane_count > 1) {
896            fputs(", ", _vdp_cap_data.fp);
897        }
898
899        --plane_count;
900        ++planes;
901    }
902    fputs("}", _vdp_cap_data.fp);
903}
904
905static bool _vdp_cap_init_planes_for_ycbcr_format(
906    uint32_t *     plane_count,
907    _VdpcapPlane * planes,
908    VdpYCbCrFormat format,
909    uint32_t       region_width,
910    uint32_t       region_height
911)
912{
913    switch (format) {
914    case VDP_YCBCR_FORMAT_NV12:
915        if (*plane_count < 2) {
916            return false;
917        }
918        *plane_count = 2;
919        planes[0].item_size = 1;
920        planes[0].item_count = region_width;
921        planes[0].lines = region_height;
922        planes[1].item_size = 1;
923        planes[1].item_count = region_width;
924        planes[1].lines = region_height / 2;
925        break;
926    case VDP_YCBCR_FORMAT_YV12:
927        if (*plane_count < 3) {
928            return false;
929        }
930        *plane_count = 3;
931        planes[0].item_size = 1;
932        planes[0].item_count = region_width;
933        planes[0].lines = region_height;
934        planes[1].item_size = 1;
935        planes[1].item_count = region_width / 2;
936        planes[1].lines = region_height / 2;
937        planes[2].item_size = 1;
938        planes[2].item_count = region_width / 2;
939        planes[2].lines = region_height / 2;
940        break;
941    case VDP_YCBCR_FORMAT_UYVY:
942    case VDP_YCBCR_FORMAT_YUYV:
943        if (*plane_count < 1) {
944            return false;
945        }
946        *plane_count = 1;
947        planes[0].item_size = 1;
948        planes[0].item_count = region_width * 2;
949        planes[0].lines = region_height;
950        break;
951    case VDP_YCBCR_FORMAT_Y8U8V8A8:
952    case VDP_YCBCR_FORMAT_V8U8Y8A8:
953        if (*plane_count < 1) {
954            return false;
955        }
956        *plane_count = 1;
957        planes[0].item_size = 4;
958        planes[0].item_count = region_width;
959        planes[0].lines = region_height;
960        break;
961    default:
962        return false;
963    }
964
965    return true;
966}
967
968static bool _vdp_cap_init_planes_for_rgba_format(
969    uint32_t *     plane_count,
970    _VdpcapPlane * planes,
971    VdpRGBAFormat  format,
972    uint32_t       region_width,
973    uint32_t       region_height
974)
975{
976    switch (format) {
977    case VDP_RGBA_FORMAT_B8G8R8A8:
978    case VDP_RGBA_FORMAT_R8G8B8A8:
979    case VDP_RGBA_FORMAT_R10G10B10A2:
980    case VDP_RGBA_FORMAT_B10G10R10A2:
981        if (*plane_count < 1) {
982            return false;
983        }
984        *plane_count = 1;
985        planes[0].item_size = 4;
986        break;
987    case VDP_RGBA_FORMAT_A8:
988        if (*plane_count < 1) {
989            return false;
990        }
991        *plane_count = 1;
992        planes[0].item_size = 1;
993        break;
994    default:
995        return false;
996    }
997    planes[0].item_count = region_width;
998    planes[0].lines = region_height;
999
1000    return true;
1001}
1002
1003static bool _vdp_cap_init_planes_for_indexed_format(
1004    uint32_t *       plane_count,
1005    _VdpcapPlane *   planes,
1006    VdpIndexedFormat format,
1007    uint32_t         region_width,
1008    uint32_t         region_height
1009)
1010{
1011    uint32_t width_multiplier;
1012
1013    switch (format) {
1014    case VDP_INDEXED_FORMAT_A4I4:
1015    case VDP_INDEXED_FORMAT_I4A4:
1016        width_multiplier = 1;
1017        break;
1018    case VDP_INDEXED_FORMAT_A8I8:
1019    case VDP_INDEXED_FORMAT_I8A8:
1020        width_multiplier = 2;
1021        break;
1022    default:
1023        return false;
1024    }
1025
1026    if (*plane_count < 1) {
1027        return false;
1028    }
1029    *plane_count = 1;
1030    planes[0].item_size = 1;
1031    planes[0].item_count = region_width * width_multiplier;
1032    planes[0].lines = region_height;
1033
1034    return true;
1035}
1036
1037static bool _vdp_cap_init_planes_adapt_format_bits_ycbcr(
1038    uint32_t *     plane_count,
1039    _VdpcapPlane * planes,
1040    uint32_t       surface_format,
1041    uint32_t       bits_format,
1042    uint32_t       region_width,
1043    uint32_t       region_height
1044)
1045{
1046    return _vdp_cap_init_planes_for_ycbcr_format(
1047        plane_count,
1048        planes,
1049        bits_format,
1050        region_width,
1051        region_height
1052    );
1053}
1054
1055static bool _vdp_cap_init_planes_adapt_format_surface_rgba(
1056    uint32_t *     plane_count,
1057    _VdpcapPlane * planes,
1058    uint32_t       surface_format,
1059    uint32_t       bits_format,
1060    uint32_t       region_width,
1061    uint32_t       region_height
1062)
1063{
1064    return _vdp_cap_init_planes_for_rgba_format(
1065        plane_count,
1066        planes,
1067        surface_format,
1068        region_width,
1069        region_height
1070    );
1071}
1072
1073static bool _vdp_cap_init_planes_adapt_format_bits_indexed(
1074    uint32_t *     plane_count,
1075    _VdpcapPlane * planes,
1076    uint32_t       surface_format,
1077    uint32_t       bits_format,
1078    uint32_t       region_width,
1079    uint32_t       region_height
1080)
1081{
1082    return _vdp_cap_init_planes_for_indexed_format(
1083        plane_count,
1084        planes,
1085        bits_format,
1086        region_width,
1087        region_height
1088    );
1089}
1090
1091static bool _vdp_cap_init_planes_adapt_surface_video(
1092    uint32_t   surface,
1093    uint32_t * surface_format,
1094    uint32_t * width,
1095    uint32_t * height
1096)
1097{
1098    VdpStatus ret;
1099
1100    VdpChromaType chroma_type;
1101    ret = _vdp_cap_data.vdp_video_surface_get_parameters(
1102        surface,
1103        &chroma_type,
1104        width,
1105        height
1106    );
1107    if (ret != VDP_STATUS_OK) {
1108        return false;
1109    }
1110
1111    *surface_format = chroma_type;
1112
1113    return true;
1114}
1115
1116static bool _vdp_cap_init_planes_adapt_surface_output(
1117    uint32_t   surface,
1118    uint32_t * surface_format,
1119    uint32_t * width,
1120    uint32_t * height
1121)
1122{
1123    VdpStatus ret;
1124
1125    VdpRGBAFormat rgba_format;
1126    ret = _vdp_cap_data.vdp_output_surface_get_parameters(
1127        surface,
1128        &rgba_format,
1129        width,
1130        height
1131    );
1132    if (ret != VDP_STATUS_OK) {
1133        return false;
1134    }
1135
1136    *surface_format = rgba_format;
1137
1138    return true;
1139}
1140
1141static bool _vdp_cap_init_planes_adapt_surface_bitmap(
1142    uint32_t   surface,
1143    uint32_t * surface_format,
1144    uint32_t * width,
1145    uint32_t * height
1146)
1147{
1148    VdpStatus ret;
1149
1150    VdpRGBAFormat rgba_format;
1151    VdpBool       frequently_accessed;
1152    ret = _vdp_cap_data.vdp_bitmap_surface_get_parameters(
1153        surface,
1154        &rgba_format,
1155        width,
1156        height,
1157        &frequently_accessed
1158    );
1159    if (ret != VDP_STATUS_OK) {
1160        return false;
1161    }
1162
1163    *surface_format = rgba_format;
1164
1165    return true;
1166}
1167
1168typedef bool _Vdpcap_Init_Planes_Adapt_Format(
1169    uint32_t *     plane_count,
1170    _VdpcapPlane * planes,
1171    uint32_t       surface_format,
1172    uint32_t       bits_format,
1173    uint32_t       region_width,
1174    uint32_t       region_height
1175);
1176
1177typedef bool _Vdpcap_Init_Planes_Adapt_Surface(
1178    uint32_t   surface,
1179    uint32_t * surface_format,
1180    uint32_t * width,
1181    uint32_t * height
1182);
1183
1184static bool _vdp_cap_init_planes(
1185    uint32_t                            surface,
1186    void const * const *                source_data,
1187    uint32_t const *                    source_pitches,
1188    VdpRect const *                     destination_rect,
1189    uint32_t *                          plane_count,
1190    _VdpcapPlane *                      planes,
1191    _Vdpcap_Init_Planes_Adapt_Surface * adapt_surface,
1192    _Vdpcap_Init_Planes_Adapt_Format *  adapt_format,
1193    uint32_t                            adapt_format_bits_format
1194)
1195{
1196    bool ok;
1197
1198    if (!source_data || !source_pitches) {
1199        return false;
1200    }
1201
1202    if (_vdp_cap_data.level < LEVEL_PARAMS) {
1203        return false;
1204    }
1205
1206    uint32_t surface_format;
1207    uint32_t width;
1208    uint32_t height;
1209    ok = adapt_surface(
1210        surface,
1211        &surface_format,
1212        &width,
1213        &height
1214    );
1215    if (!ok) {
1216        return false;
1217    }
1218
1219    if (destination_rect) {
1220        width = delta<uint32_t>(destination_rect->x0, destination_rect->x1);
1221        height = delta<uint32_t>(destination_rect->y0, destination_rect->y1);
1222    }
1223
1224    ok = adapt_format(
1225        plane_count,
1226        planes,
1227        surface_format,
1228        adapt_format_bits_format,
1229        width,
1230        height
1231    );
1232    if (!ok) {
1233        return false;
1234    }
1235
1236    for (uint32_t i = 0; i < *plane_count; ++i) {
1237        planes[i].data = source_data[i];
1238        planes[i].pitch = source_pitches[i];
1239    }
1240
1241    return true;
1242}
1243
1244static void _vdp_cap_dump_bool_list(
1245    uint32_t        count,
1246    VdpBool const * values
1247)
1248{
1249    if (!values) {
1250        fputs("NULL", _vdp_cap_data.fp);
1251        return;
1252    }
1253
1254    fputs("{", _vdp_cap_data.fp);
1255    while (count) {
1256        fprintf(
1257            _vdp_cap_data.fp,
1258            "%d%s",
1259            (int)values[0],
1260            (count > 1) ? ", " : ""
1261        );
1262
1263        --count;
1264        ++values;
1265    }
1266    fputs("}", _vdp_cap_data.fp);
1267}
1268
1269static void _vdp_cap_dump_void_pointer_list(
1270    uint32_t             count,
1271    void const * const * values,
1272    bool                 zero_count_question_marks
1273)
1274{
1275    if (!values) {
1276        fputs("NULL", _vdp_cap_data.fp);
1277        return;
1278    }
1279
1280    fputs("{", _vdp_cap_data.fp);
1281    if (!count && zero_count_question_marks) {
1282        fputs("???", _vdp_cap_data.fp);
1283    }
1284    while (count) {
1285        fprintf(
1286            _vdp_cap_data.fp,
1287            "%p%s",
1288            values[0],
1289            (count > 1) ? ", " : ""
1290        );
1291
1292        --count;
1293        ++values;
1294    }
1295    fputs("}", _vdp_cap_data.fp);
1296}
1297
1298static void _vdp_cap_dump_uint32_t_list(
1299    uint32_t         count,
1300    uint32_t const * values,
1301    bool             zero_count_question_marks
1302)
1303{
1304    if (!values) {
1305        fputs("NULL", _vdp_cap_data.fp);
1306        return;
1307    }
1308
1309    fputs("{", _vdp_cap_data.fp);
1310    if (!count && zero_count_question_marks) {
1311        fputs("???", _vdp_cap_data.fp);
1312    }
1313    while (count) {
1314        fprintf(
1315            _vdp_cap_data.fp,
1316            "%u%s",
1317            values[0],
1318            (count > 1) ? ", " : ""
1319        );
1320
1321        --count;
1322        ++values;
1323    }
1324    fputs("}", _vdp_cap_data.fp);
1325}
1326
1327static void _vdp_cap_dump_color_list(
1328    uint32_t         count,
1329    VdpColor const * colors
1330)
1331{
1332    if (!colors) {
1333        fputs("NULL", _vdp_cap_data.fp);
1334        return;
1335    }
1336
1337    fputs("{", _vdp_cap_data.fp);
1338    while (count) {
1339        _vdp_cap_dump_color(&colors[0]);
1340        fputs(
1341            (count > 1) ? ", " : "",
1342            _vdp_cap_data.fp
1343        );
1344
1345        --count;
1346        ++colors;
1347    }
1348    fputs("}", _vdp_cap_data.fp);
1349}
1350
1351static void _vdp_cap_dump_color_table(
1352    VdpIndexedFormat    indexed_format,
1353    VdpColorTableFormat format,
1354    void const *        table
1355)
1356{
1357    if (!table) {
1358        fprintf(_vdp_cap_data.fp, "NULL");
1359        return;
1360    }
1361
1362    uint32_t count;
1363    switch (indexed_format) {
1364    case VDP_INDEXED_FORMAT_A4I4:
1365    case VDP_INDEXED_FORMAT_I4A4:
1366        count = 1 << 4;
1367        break;
1368    case VDP_INDEXED_FORMAT_A8I8:
1369    case VDP_INDEXED_FORMAT_I8A8:
1370        count = 1 << 8;
1371        break;
1372    default:
1373        fprintf(_vdp_cap_data.fp, "???");
1374        return;
1375    }
1376
1377    switch (format) {
1378    case VDP_COLOR_TABLE_FORMAT_B8G8R8X8:
1379        break;
1380    default:
1381        fprintf(_vdp_cap_data.fp, "???");
1382        return;
1383    }
1384
1385    _vdp_cap_dump_uint32_t_list(
1386        count,
1387        (uint32_t const *)table,
1388        true
1389    );
1390}
1391
1392static void _vdp_cap_dump_bitstream_buffer_list(
1393    uint32_t                   count,
1394    VdpBitstreamBuffer const * buffers
1395)
1396{
1397    if (!buffers) {
1398        fputs("NULL", _vdp_cap_data.fp);
1399        return;
1400    }
1401
1402    fputs("{", _vdp_cap_data.fp);
1403    while (count) {
1404        fprintf(
1405            _vdp_cap_data.fp,
1406             "{(ver %d)%s %u, ",
1407            buffers[0].struct_version,
1408            (buffers[0].struct_version > 0)
1409                ? "(unsupported; cannot dump all fields)"
1410                : "",
1411            buffers[0].bitstream_bytes
1412        );
1413        if (_vdp_cap_data.level >= LEVEL_DATA) {
1414            const uint8_t * ptr = (const uint8_t * )buffers[0].bitstream;
1415            for (uint32_t i = 0; i < buffers[0].bitstream_bytes; ++i) {
1416                fprintf(_vdp_cap_data.fp, "%02x ", ptr[i]);
1417            }
1418        }
1419        else {
1420            fputs("...", _vdp_cap_data.fp);
1421        }
1422        fputs(
1423            (count > 1) ? "}, " : "}",
1424            _vdp_cap_data.fp
1425        );
1426
1427        --count;
1428        ++buffers;
1429    }
1430    fputs("}", _vdp_cap_data.fp);
1431}
1432
1433static void _vdp_cap_dump_video_mixer_feature_list(
1434    uint32_t                     feature_count,
1435    VdpVideoMixerFeature const * features
1436)
1437{
1438    _vdp_cap_dump_uint32_t_list(
1439        feature_count,
1440        features,
1441        false
1442    );
1443}
1444
1445static void _vdp_cap_dump_video_mixer_parameter_list(
1446    uint32_t                       parameter_count,
1447    VdpVideoMixerParameter const * parameters
1448)
1449{
1450    _vdp_cap_dump_uint32_t_list(
1451        parameter_count,
1452        parameters,
1453        false
1454    );
1455}
1456
1457static void _vdp_cap_dump_video_mixer_attribute_list(
1458    uint32_t                       attribute_count,
1459    VdpVideoMixerAttribute const * attributes
1460)
1461{
1462    _vdp_cap_dump_uint32_t_list(
1463        attribute_count,
1464        attributes,
1465        false
1466    );
1467}
1468
1469static void _vdp_cap_dump_video_mixer_parameter_value_list(
1470    uint32_t                       parameter_count,
1471    VdpVideoMixerParameter const * parameters,
1472    void const * const *           parameter_values
1473)
1474{
1475    if (!parameters || !parameter_values) {
1476        fputs("NULL", _vdp_cap_data.fp);
1477        return;
1478    }
1479
1480    fputs("{", _vdp_cap_data.fp);
1481    while (parameter_count) {
1482        _vdp_cap_dump_video_mixer_parameter_value(parameters[0], parameter_values[0]);
1483        fputs((parameter_count > 1) ? ", " : "", _vdp_cap_data.fp);
1484
1485        --parameter_count;
1486        ++parameters;
1487        ++parameter_values;
1488    }
1489    fputs("}", _vdp_cap_data.fp);
1490}
1491
1492static void _vdp_cap_dump_video_mixer_attribute_value_list(
1493    uint32_t                       attribute_count,
1494    VdpVideoMixerAttribute const * attributes,
1495    void const * const *           attribute_values,
1496    bool                           get_operation
1497)
1498{
1499    if (!attributes || !attribute_values) {
1500        fputs("NULL", _vdp_cap_data.fp);
1501        return;
1502    }
1503
1504    fputs("{", _vdp_cap_data.fp);
1505    while (attribute_count) {
1506        _vdp_cap_dump_video_mixer_attribute_value(
1507            attributes[0],
1508            attribute_values[0],
1509            get_operation
1510        );
1511        fputs((attribute_count > 1) ? ", " : "", _vdp_cap_data.fp);
1512
1513        --attribute_count;
1514        ++attributes;
1515        ++attribute_values;
1516    }
1517    fputs("}", _vdp_cap_data.fp);
1518}
1519
1520static void _vdp_cap_dump_layers_list(
1521    uint32_t         layer_count,
1522    VdpLayer const * layers
1523)
1524{
1525    if (!layers) {
1526        fputs("NULL", _vdp_cap_data.fp);
1527        return;
1528    }
1529
1530    fputs("{", _vdp_cap_data.fp);
1531    while (layer_count) {
1532        fprintf(
1533            _vdp_cap_data.fp,
1534            "{(ver %d)%s %u,",
1535            layers[0].struct_version,
1536            (layers[0].struct_version > 0)
1537                ? "(unsupported; cannot dump all fields)"
1538                : "",
1539            layers[0].source_surface
1540        );
1541
1542        _vdp_cap_dump_rect(layers[0].source_rect);
1543        fputs(", ", _vdp_cap_data.fp);
1544        _vdp_cap_dump_rect(layers[0].destination_rect);
1545
1546        fputs((layer_count > 1) ? "}, " : "}", _vdp_cap_data.fp);
1547
1548        --layer_count;
1549        ++layers;
1550    }
1551    fputs("}", _vdp_cap_data.fp);
1552}
1553
1554static char const * _vdp_cap_get_error_string(
1555    VdpStatus status
1556)
1557{
1558    char const * ret;
1559
1560    fputs("vdp_get_error_string(", _vdp_cap_data.fp);
1561    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
1562        fprintf(
1563            _vdp_cap_data.fp,
1564            "%d",
1565            status
1566        );
1567    }
1568    fputs(")\n", _vdp_cap_data.fp);
1569
1570    ret = _vdp_cap_data.vdp_get_error_string(
1571        status
1572    );
1573
1574    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
1575        if (ret) {
1576            fprintf(_vdp_cap_data.fp, "    -> '%s'\n", ret);
1577        }
1578        else {
1579            fprintf(_vdp_cap_data.fp, "    -> NULL\n");
1580        }
1581    }
1582
1583    return ret;
1584}
1585
1586static VdpStatus _vdp_cap_get_api_version(
1587    /* output parameters follow */
1588    uint32_t * api_version
1589)
1590{
1591    VdpStatus ret;
1592
1593    fputs("vdp_get_api_version(", _vdp_cap_data.fp);
1594    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
1595        fprintf(
1596            _vdp_cap_data.fp,
1597            "%s",
1598            api_version ? "-" : "NULL"
1599        );
1600    }
1601    fputs(")\n", _vdp_cap_data.fp);
1602
1603    ret = _vdp_cap_data.vdp_get_api_version(
1604        api_version
1605    );
1606
1607    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
1608        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
1609        if (ret == VDP_STATUS_OK) {
1610            if (api_version) {
1611                fprintf(_vdp_cap_data.fp, ", %u", *api_version);
1612            }
1613            else {
1614                fputs(", ???", _vdp_cap_data.fp);
1615            }
1616        }
1617        fputs("\n", _vdp_cap_data.fp);
1618    }
1619
1620    return ret;
1621}
1622
1623static VdpStatus _vdp_cap_get_information_string(
1624    /* output parameters follow */
1625    char const * * information_string
1626)
1627{
1628    VdpStatus ret;
1629
1630    fputs("vdp_get_information_string(", _vdp_cap_data.fp);
1631    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
1632        fprintf(
1633            _vdp_cap_data.fp,
1634            "%s",
1635            information_string ? "-" : "NULL"
1636        );
1637    }
1638    fputs(")\n", _vdp_cap_data.fp);
1639
1640    ret = _vdp_cap_data.vdp_get_information_string(
1641        information_string
1642    );
1643
1644    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
1645        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
1646        if (ret == VDP_STATUS_OK) {
1647            if (information_string && *information_string) {
1648                fprintf(_vdp_cap_data.fp, ", \"%s\"", *information_string);
1649            }
1650            else if (information_string) {
1651                fputs(", (null)", _vdp_cap_data.fp);
1652            }
1653            else {
1654                fputs(", ???", _vdp_cap_data.fp);
1655            }
1656        }
1657        fputs("\n", _vdp_cap_data.fp);
1658    }
1659
1660    return ret;
1661}
1662
1663static VdpStatus _vdp_cap_device_destroy(
1664    VdpDevice device
1665)
1666{
1667    VdpStatus ret;
1668
1669    fputs("vdp_device_destroy(", _vdp_cap_data.fp);
1670    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
1671        fprintf(
1672            _vdp_cap_data.fp,
1673            "%u",
1674            device
1675        );
1676    }
1677    fputs(")\n", _vdp_cap_data.fp);
1678
1679    ret = _vdp_cap_data.vdp_device_destroy(
1680        device
1681    );
1682
1683    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
1684        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
1685    }
1686
1687    return ret;
1688}
1689
1690static VdpStatus _vdp_cap_generate_csc_matrix(
1691    VdpProcamp *     procamp,
1692    VdpColorStandard standard,
1693    /* output parameters follow */
1694    VdpCSCMatrix *   csc_matrix
1695)
1696{
1697    VdpStatus ret;
1698
1699    fputs("vdp_generate_csc_matrix(", _vdp_cap_data.fp);
1700    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
1701        _vdp_cap_dump_procamp(procamp);
1702        fprintf(
1703            _vdp_cap_data.fp,
1704            ", %u, %s",
1705            standard,
1706            csc_matrix ? "-" : "NULL"
1707        );
1708    }
1709    fputs(")\n", _vdp_cap_data.fp);
1710
1711    ret = _vdp_cap_data.vdp_generate_csc_matrix(
1712        procamp,
1713        standard,
1714        csc_matrix
1715    );
1716
1717    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
1718        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
1719        if (ret == VDP_STATUS_OK) {
1720            if (csc_matrix) {
1721                fputs(", ", _vdp_cap_data.fp);
1722                _vdp_cap_dump_csc_matrix(csc_matrix);
1723            }
1724            else {
1725                fputs(", ???", _vdp_cap_data.fp);
1726            }
1727        }
1728        fputs("\n", _vdp_cap_data.fp);
1729    }
1730
1731    return ret;
1732}
1733
1734static VdpStatus _vdp_cap_video_surface_query_capabilities(
1735    VdpDevice     device,
1736    VdpChromaType surface_chroma_type,
1737    /* output parameters follow */
1738    VdpBool *     is_supported,
1739    uint32_t *    max_width,
1740    uint32_t *    max_height
1741)
1742{
1743    VdpStatus ret;
1744
1745    fputs("vdp_video_surface_query_capabilities(", _vdp_cap_data.fp);
1746    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
1747        fprintf(
1748            _vdp_cap_data.fp,
1749            "%u, %u, %s, %s, %s",
1750            device,
1751            surface_chroma_type,
1752            is_supported ? "-" : "NULL",
1753            max_width ? "-" : "NULL",
1754            max_height ? "-" : "NULL"
1755        );
1756    }
1757    fputs(")\n", _vdp_cap_data.fp);
1758
1759    ret = _vdp_cap_data.vdp_video_surface_query_capabilities(
1760        device,
1761        surface_chroma_type,
1762        is_supported,
1763        max_width,
1764        max_height
1765    );
1766
1767    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
1768        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
1769        if (ret == VDP_STATUS_OK) {
1770            if (is_supported) {
1771                fprintf(_vdp_cap_data.fp, ", %d", *is_supported);
1772            }
1773            else {
1774                fputs(", ???", _vdp_cap_data.fp);
1775            }
1776            if (max_width) {
1777                fprintf(_vdp_cap_data.fp, ", %u", *max_width);
1778            }
1779            else {
1780                fputs(", ???", _vdp_cap_data.fp);
1781            }
1782            if (max_height) {
1783                fprintf(_vdp_cap_data.fp, ", %u", *max_height);
1784            }
1785            else {
1786                fputs(", ???", _vdp_cap_data.fp);
1787            }
1788        }
1789        fputs("\n", _vdp_cap_data.fp);
1790    }
1791
1792    return ret;
1793}
1794
1795static VdpStatus _vdp_cap_video_surface_query_get_put_bits_y_cb_cr_capabilities(
1796    VdpDevice      device,
1797    VdpChromaType  surface_chroma_type,
1798    VdpYCbCrFormat bits_ycbcr_format,
1799    /* output parameters follow */
1800    VdpBool *      is_supported
1801)
1802{
1803    VdpStatus ret;
1804
1805    fputs("vdp_video_surface_query_get_put_bits_y_cb_cr_capabilities(", _vdp_cap_data.fp);
1806    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
1807        fprintf(
1808            _vdp_cap_data.fp,
1809            "%u, %u, %u, %s",
1810            device,
1811            surface_chroma_type,
1812            bits_ycbcr_format,
1813            is_supported ? "-" : "NULL"
1814        );
1815    }
1816    fputs(")\n", _vdp_cap_data.fp);
1817
1818    ret = _vdp_cap_data.vdp_video_surface_query_get_put_bits_y_cb_cr_capabilities(
1819        device,
1820        surface_chroma_type,
1821        bits_ycbcr_format,
1822        is_supported
1823    );
1824
1825    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
1826        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
1827        if (ret == VDP_STATUS_OK) {
1828            if (is_supported) {
1829                fprintf(_vdp_cap_data.fp, ", %d", *is_supported);
1830            }
1831            else {
1832                fputs(", ???", _vdp_cap_data.fp);
1833            }
1834        }
1835        fputs("\n", _vdp_cap_data.fp);
1836    }
1837
1838    return ret;
1839}
1840
1841static VdpStatus _vdp_cap_video_surface_create(
1842    VdpDevice         device,
1843    VdpChromaType     chroma_type,
1844    uint32_t          width,
1845    uint32_t          height,
1846    /* output parameters follow */
1847    VdpVideoSurface * surface
1848)
1849{
1850    VdpStatus ret;
1851
1852    fputs("vdp_video_surface_create(", _vdp_cap_data.fp);
1853    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
1854        fprintf(
1855            _vdp_cap_data.fp,
1856            "%u, %u, %u, %u, %s",
1857            device,
1858            chroma_type,
1859            width,
1860            height,
1861            surface ? "-" : "NULL"
1862        );
1863    }
1864    fputs(")\n", _vdp_cap_data.fp);
1865
1866    ret = _vdp_cap_data.vdp_video_surface_create(
1867        device,
1868        chroma_type,
1869        width,
1870        height,
1871        surface
1872    );
1873
1874    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
1875        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
1876        if (ret == VDP_STATUS_OK) {
1877            if (surface) {
1878                fprintf(_vdp_cap_data.fp, ", %u", *surface);
1879            }
1880            else {
1881                fputs(", ???", _vdp_cap_data.fp);
1882            }
1883        }
1884        fputs("\n", _vdp_cap_data.fp);
1885    }
1886
1887    return ret;
1888}
1889
1890static VdpStatus _vdp_cap_video_surface_destroy(
1891    VdpVideoSurface surface
1892)
1893{
1894    VdpStatus ret;
1895
1896    fputs("vdp_video_surface_destroy(", _vdp_cap_data.fp);
1897    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
1898        fprintf(
1899            _vdp_cap_data.fp,
1900            "%u",
1901            surface
1902        );
1903    }
1904    fputs(")\n", _vdp_cap_data.fp);
1905
1906    ret = _vdp_cap_data.vdp_video_surface_destroy(
1907        surface
1908    );
1909
1910    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
1911        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
1912    }
1913
1914    return ret;
1915}
1916
1917static VdpStatus _vdp_cap_video_surface_get_parameters(
1918    VdpVideoSurface surface,
1919    /* output parameters follow */
1920    VdpChromaType * chroma_type,
1921    uint32_t *      width,
1922    uint32_t *      height
1923)
1924{
1925    VdpStatus ret;
1926
1927    fputs("vdp_video_surface_get_parameters(", _vdp_cap_data.fp);
1928    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
1929        fprintf(
1930            _vdp_cap_data.fp,
1931            "%u, %s, %s, %s",
1932            surface,
1933            chroma_type ? "-" : "NULL",
1934            width ? "-" : "NULL",
1935            height ? "-" : "NULL"
1936        );
1937    }
1938    fputs(")\n", _vdp_cap_data.fp);
1939
1940    ret = _vdp_cap_data.vdp_video_surface_get_parameters(
1941        surface,
1942        chroma_type,
1943        width,
1944        height
1945    );
1946
1947    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
1948        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
1949        if (ret == VDP_STATUS_OK) {
1950            if (chroma_type) {
1951                fprintf(_vdp_cap_data.fp, ", %u", *chroma_type);
1952            }
1953            else {
1954                fputs(", ???", _vdp_cap_data.fp);
1955            }
1956            if (width) {
1957                fprintf(_vdp_cap_data.fp, ", %u", *width);
1958            }
1959            else {
1960                fputs(", ???", _vdp_cap_data.fp);
1961            }
1962            if (height) {
1963                fprintf(_vdp_cap_data.fp, ", %u", *height);
1964            }
1965            else {
1966                fputs(", ???", _vdp_cap_data.fp);
1967            }
1968        }
1969        fputs("\n", _vdp_cap_data.fp);
1970    }
1971
1972    return ret;
1973}
1974
1975static VdpStatus _vdp_cap_video_surface_get_bits_y_cb_cr(
1976    VdpVideoSurface  surface,
1977    VdpYCbCrFormat   destination_ycbcr_format,
1978    void * const *   destination_data,
1979    uint32_t const * destination_pitches
1980)
1981{
1982    VdpStatus ret;
1983
1984    _VdpcapPlane planes[3];
1985    uint32_t    plane_count = _VDP_TRACE_ARSIZE(planes);
1986    bool dump_data = _vdp_cap_init_planes(
1987        surface,
1988        destination_data,
1989        destination_pitches,
1990        0,
1991        &plane_count,
1992        planes,
1993        _vdp_cap_init_planes_adapt_surface_video,
1994        _vdp_cap_init_planes_adapt_format_bits_ycbcr,
1995        destination_ycbcr_format
1996    );
1997    if (!dump_data) {
1998        plane_count = 0;
1999    }
2000
2001    fputs("vdp_video_surface_get_bits_y_cb_cr(", _vdp_cap_data.fp);
2002    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2003        fprintf(
2004            _vdp_cap_data.fp,
2005            "%u, %u, ",
2006            surface,
2007            destination_ycbcr_format
2008        );
2009        _vdp_cap_dump_void_pointer_list(plane_count, destination_data, true);
2010        fputs(", ", _vdp_cap_data.fp);
2011        _vdp_cap_dump_uint32_t_list(plane_count, destination_pitches, true);
2012    }
2013    fputs(")\n", _vdp_cap_data.fp);
2014
2015    ret = _vdp_cap_data.vdp_video_surface_get_bits_y_cb_cr(
2016        surface,
2017        destination_ycbcr_format,
2018        destination_data,
2019        destination_pitches
2020    );
2021
2022    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2023        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
2024    }
2025    if (_vdp_cap_data.level >= LEVEL_DATA) {
2026        fputs("    ... Data: ", _vdp_cap_data.fp);
2027        if (dump_data) {
2028            _vdp_cap_dump_plane_list(plane_count, planes);
2029        }
2030        else {
2031           fputs("???", _vdp_cap_data.fp);
2032        }
2033        fputs("\n", _vdp_cap_data.fp);
2034    }
2035
2036    return ret;
2037}
2038
2039static VdpStatus _vdp_cap_video_surface_put_bits_y_cb_cr(
2040    VdpVideoSurface      surface,
2041    VdpYCbCrFormat       source_ycbcr_format,
2042    void const * const * source_data,
2043    uint32_t const *     source_pitches
2044)
2045{
2046    VdpStatus ret;
2047
2048    _VdpcapPlane planes[3];
2049    uint32_t    plane_count = _VDP_TRACE_ARSIZE(planes);
2050    bool dump_data = _vdp_cap_init_planes(
2051        surface,
2052        source_data,
2053        source_pitches,
2054        0,
2055        &plane_count,
2056        planes,
2057        _vdp_cap_init_planes_adapt_surface_video,
2058        _vdp_cap_init_planes_adapt_format_bits_ycbcr,
2059        source_ycbcr_format
2060    );
2061    if (!dump_data) {
2062        plane_count = 0;
2063    }
2064
2065    fputs("vdp_video_surface_put_bits_y_cb_cr(", _vdp_cap_data.fp);
2066    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2067        fprintf(
2068            _vdp_cap_data.fp,
2069            "%u, %u, ",
2070            surface,
2071            source_ycbcr_format
2072        );
2073        _vdp_cap_dump_void_pointer_list(plane_count, source_data, true);
2074        fputs(", ", _vdp_cap_data.fp);
2075        _vdp_cap_dump_uint32_t_list(plane_count, source_pitches, true);
2076        fputs(", ", _vdp_cap_data.fp);
2077    }
2078    fputs(")\n", _vdp_cap_data.fp);
2079    if (_vdp_cap_data.level >= LEVEL_DATA) {
2080        fputs("    ... Data: ", _vdp_cap_data.fp);
2081        if (dump_data) {
2082            _vdp_cap_dump_plane_list(plane_count, planes);
2083        }
2084        else {
2085           fputs("???", _vdp_cap_data.fp);
2086        }
2087        fputs("\n", _vdp_cap_data.fp);
2088    }
2089
2090    ret = _vdp_cap_data.vdp_video_surface_put_bits_y_cb_cr(
2091        surface,
2092        source_ycbcr_format,
2093        source_data,
2094        source_pitches
2095    );
2096
2097    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2098        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
2099    }
2100
2101    return ret;
2102}
2103
2104static VdpStatus _vdp_cap_output_surface_query_capabilities(
2105    VdpDevice     device,
2106    VdpRGBAFormat surface_rgba_format,
2107    /* output parameters follow */
2108    VdpBool *     is_supported,
2109    uint32_t *    max_width,
2110    uint32_t *    max_height
2111)
2112{
2113    VdpStatus ret;
2114
2115    fputs("vdp_output_surface_query_capabilities(", _vdp_cap_data.fp);
2116    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2117        fprintf(
2118            _vdp_cap_data.fp,
2119            "%u, %u, %s, %s, %s",
2120            device,
2121            surface_rgba_format,
2122            is_supported ? "-" : "NULL",
2123            max_width ? "-" : "NULL",
2124            max_height ? "-" : "NULL"
2125        );
2126    }
2127    fputs(")\n", _vdp_cap_data.fp);
2128
2129    ret = _vdp_cap_data.vdp_output_surface_query_capabilities(
2130        device,
2131        surface_rgba_format,
2132        is_supported,
2133        max_width,
2134        max_height
2135    );
2136
2137    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2138        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
2139        if (ret == VDP_STATUS_OK) {
2140            if (is_supported) {
2141                fprintf(_vdp_cap_data.fp, ", %d", *is_supported);
2142            }
2143            else {
2144                fputs(", ???", _vdp_cap_data.fp);
2145            }
2146            if (max_width) {
2147                fprintf(_vdp_cap_data.fp, ", %u", *max_width);
2148            }
2149            else {
2150                fputs(", ???", _vdp_cap_data.fp);
2151            }
2152            if (max_height) {
2153                fprintf(_vdp_cap_data.fp, ", %u", *max_height);
2154            }
2155            else {
2156                fputs(", ???", _vdp_cap_data.fp);
2157            }
2158        }
2159        fputs("\n", _vdp_cap_data.fp);
2160    }
2161
2162    return ret;
2163}
2164
2165static VdpStatus _vdp_cap_output_surface_query_get_put_bits_native_capabilities(
2166    VdpDevice     device,
2167    VdpRGBAFormat surface_rgba_format,
2168    /* output parameters follow */
2169    VdpBool *     is_supported
2170)
2171{
2172    VdpStatus ret;
2173
2174    fputs("vdp_output_surface_query_get_put_bits_native_capabilities(", _vdp_cap_data.fp);
2175    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2176        fprintf(
2177            _vdp_cap_data.fp,
2178            "%u, %u, %s",
2179            device,
2180            surface_rgba_format,
2181            is_supported ? "-" : "NULL"
2182        );
2183    }
2184    fputs(")\n", _vdp_cap_data.fp);
2185
2186    ret = _vdp_cap_data.vdp_output_surface_query_get_put_bits_native_capabilities(
2187        device,
2188        surface_rgba_format,
2189        is_supported
2190    );
2191
2192    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2193        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
2194        if (ret == VDP_STATUS_OK) {
2195            if (is_supported) {
2196                fprintf(_vdp_cap_data.fp, ", %d", *is_supported);
2197            }
2198            else {
2199                fputs(", ???", _vdp_cap_data.fp);
2200            }
2201        }
2202        fputs("\n", _vdp_cap_data.fp);
2203    }
2204
2205    return ret;
2206}
2207
2208static VdpStatus _vdp_cap_output_surface_query_put_bits_indexed_capabilities(
2209    VdpDevice           device,
2210    VdpRGBAFormat       surface_rgba_format,
2211    VdpIndexedFormat    bits_indexed_format,
2212    VdpColorTableFormat color_table_format,
2213    /* output parameters follow */
2214    VdpBool *           is_supported
2215)
2216{
2217    VdpStatus ret;
2218
2219    fputs("vdp_output_surface_query_put_bits_indexed_capabilities(", _vdp_cap_data.fp);
2220    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2221        fprintf(
2222            _vdp_cap_data.fp,
2223            "%u, %u, %u, %u, %s",
2224            device,
2225            surface_rgba_format,
2226            bits_indexed_format,
2227            color_table_format,
2228            is_supported ? "-" : "NULL"
2229        );
2230    }
2231    fputs(")\n", _vdp_cap_data.fp);
2232
2233    ret = _vdp_cap_data.vdp_output_surface_query_put_bits_indexed_capabilities(
2234        device,
2235        surface_rgba_format,
2236        bits_indexed_format,
2237        color_table_format,
2238        is_supported
2239    );
2240
2241    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2242        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
2243        if (ret == VDP_STATUS_OK) {
2244            if (is_supported) {
2245                fprintf(_vdp_cap_data.fp, ", %d", *is_supported);
2246            }
2247            else {
2248                fputs(", ???", _vdp_cap_data.fp);
2249            }
2250        }
2251        fputs("\n", _vdp_cap_data.fp);
2252    }
2253
2254    return ret;
2255}
2256
2257static VdpStatus _vdp_cap_output_surface_query_put_bits_y_cb_cr_capabilities(
2258    VdpDevice      device,
2259    VdpRGBAFormat  surface_rgba_format,
2260    VdpYCbCrFormat bits_ycbcr_format,
2261    /* output parameters follow */
2262    VdpBool *      is_supported
2263)
2264{
2265    VdpStatus ret;
2266
2267    fputs("vdp_output_surface_query_put_bits_y_cb_cr_capabilities(", _vdp_cap_data.fp);
2268    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2269        fprintf(
2270            _vdp_cap_data.fp,
2271            "%u, %u, %u, %s",
2272            device,
2273            surface_rgba_format,
2274            bits_ycbcr_format,
2275            is_supported ? "-" : "NULL"
2276        );
2277    }
2278    fputs(")\n", _vdp_cap_data.fp);
2279
2280    ret = _vdp_cap_data.vdp_output_surface_query_put_bits_y_cb_cr_capabilities(
2281        device,
2282        surface_rgba_format,
2283        bits_ycbcr_format,
2284        is_supported
2285    );
2286
2287    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2288        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
2289        if (ret == VDP_STATUS_OK) {
2290            if (is_supported) {
2291                fprintf(_vdp_cap_data.fp, ", %d", *is_supported);
2292            }
2293            else {
2294                fputs(", ???", _vdp_cap_data.fp);
2295            }
2296        }
2297        fputs("\n", _vdp_cap_data.fp);
2298    }
2299
2300    return ret;
2301}
2302
2303static VdpStatus _vdp_cap_output_surface_create(
2304    VdpDevice          device,
2305    VdpRGBAFormat      rgba_format,
2306    uint32_t           width,
2307    uint32_t           height,
2308    /* output parameters follow */
2309    VdpOutputSurface * surface
2310)
2311{
2312    VdpStatus ret;
2313
2314    fputs("vdp_output_surface_create(", _vdp_cap_data.fp);
2315    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2316        fprintf(
2317            _vdp_cap_data.fp,
2318            "%u, %u, %u, %u, %s",
2319            device,
2320            rgba_format,
2321            width,
2322            height,
2323            surface ? "-" : "NULL"
2324        );
2325    }
2326    fputs(")\n", _vdp_cap_data.fp);
2327
2328    ret = _vdp_cap_data.vdp_output_surface_create(
2329        device,
2330        rgba_format,
2331        width,
2332        height,
2333        surface
2334    );
2335
2336    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2337        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
2338        if (ret == VDP_STATUS_OK) {
2339            if (surface) {
2340                fprintf(_vdp_cap_data.fp, ", %u", *surface);
2341            }
2342            else {
2343                fputs(", ???", _vdp_cap_data.fp);
2344            }
2345        }
2346        fputs("\n", _vdp_cap_data.fp);
2347    }
2348
2349    return ret;
2350}
2351
2352static VdpStatus _vdp_cap_output_surface_destroy(
2353    VdpOutputSurface surface
2354)
2355{
2356    VdpStatus ret;
2357
2358    fputs("vdp_output_surface_destroy(", _vdp_cap_data.fp);
2359    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2360        fprintf(
2361            _vdp_cap_data.fp,
2362            "%u",
2363            surface
2364        );
2365    }
2366    fputs(")\n", _vdp_cap_data.fp);
2367
2368    ret = _vdp_cap_data.vdp_output_surface_destroy(
2369        surface
2370    );
2371
2372    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2373        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
2374    }
2375
2376    return ret;
2377}
2378
2379static VdpStatus _vdp_cap_output_surface_get_parameters(
2380    VdpOutputSurface surface,
2381    /* output parameters follow */
2382    VdpRGBAFormat *  rgba_format,
2383    uint32_t *       width,
2384    uint32_t *       height
2385)
2386{
2387    VdpStatus ret;
2388
2389    fputs("vdp_output_surface_get_parameters(", _vdp_cap_data.fp);
2390    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2391        fprintf(
2392            _vdp_cap_data.fp,
2393            "%u, %s, %s, %s",
2394            surface,
2395            rgba_format ? "-" : "NULL",
2396            width ? "-" : "NULL",
2397            height ? "-" : "NULL"
2398        );
2399    }
2400    fputs(")\n", _vdp_cap_data.fp);
2401
2402    ret = _vdp_cap_data.vdp_output_surface_get_parameters(
2403        surface,
2404        rgba_format,
2405        width,
2406        height
2407    );
2408
2409    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2410        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
2411        if (ret == VDP_STATUS_OK) {
2412            if (rgba_format) {
2413                fprintf(_vdp_cap_data.fp, ", %u", *rgba_format);
2414            }
2415            else {
2416                fputs(", ???", _vdp_cap_data.fp);
2417            }
2418            if (width) {
2419                fprintf(_vdp_cap_data.fp, ", %u", *width);
2420            }
2421            else {
2422                fputs(", ???", _vdp_cap_data.fp);
2423            }
2424            if (height) {
2425                fprintf(_vdp_cap_data.fp, ", %u", *height);
2426            }
2427            else {
2428                fputs(", ???", _vdp_cap_data.fp);
2429            }
2430        }
2431        fputs("\n", _vdp_cap_data.fp);
2432    }
2433
2434    return ret;
2435}
2436
2437static VdpStatus _vdp_cap_output_surface_get_bits_native(
2438    VdpOutputSurface  surface,
2439    VdpRect const *   source_rect,
2440    void * const *    destination_data,
2441    uint32_t const *  destination_pitches
2442)
2443{
2444    VdpStatus ret;
2445
2446    _VdpcapPlane planes[1];
2447    uint32_t    plane_count = _VDP_TRACE_ARSIZE(planes);
2448    bool dump_data = _vdp_cap_init_planes(
2449        surface,
2450        destination_data,
2451        destination_pitches,
2452        source_rect,
2453        &plane_count,
2454        planes,
2455        _vdp_cap_init_planes_adapt_surface_output,
2456        _vdp_cap_init_planes_adapt_format_surface_rgba,
2457        0
2458    );
2459    if (!dump_data) {
2460        plane_count = 0;
2461    }
2462
2463    fputs("vdp_output_surface_get_bits_native(", _vdp_cap_data.fp);
2464    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2465        fprintf(
2466            _vdp_cap_data.fp,
2467            "%u, ",
2468            surface
2469        );
2470        _vdp_cap_dump_rect(source_rect);
2471        fputs(", ", _vdp_cap_data.fp);
2472        _vdp_cap_dump_void_pointer_list(plane_count, destination_data, true);
2473        fputs(", ", _vdp_cap_data.fp);
2474        _vdp_cap_dump_uint32_t_list(plane_count, destination_pitches, true);
2475    }
2476    fputs(")\n", _vdp_cap_data.fp);
2477
2478    ret = _vdp_cap_data.vdp_output_surface_get_bits_native(
2479        surface,
2480        source_rect,
2481        destination_data,
2482        destination_pitches
2483    );
2484
2485    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2486        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
2487    }
2488    if (_vdp_cap_data.level >= LEVEL_DATA) {
2489        fputs("    ... Data: ", _vdp_cap_data.fp);
2490        if (dump_data) {
2491            _vdp_cap_dump_plane_list(plane_count, planes);
2492        }
2493        else {
2494           fputs("???", _vdp_cap_data.fp);
2495        }
2496        fputs("\n", _vdp_cap_data.fp);
2497    }
2498
2499    return ret;
2500}
2501
2502static VdpStatus _vdp_cap_output_surface_put_bits_native(
2503    VdpOutputSurface     surface,
2504    void const * const * source_data,
2505    uint32_t const *     source_pitches,
2506    VdpRect const *      destination_rect
2507)
2508{
2509    VdpStatus ret;
2510
2511    _VdpcapPlane planes[1];
2512    uint32_t    plane_count = _VDP_TRACE_ARSIZE(planes);
2513    bool dump_data = _vdp_cap_init_planes(
2514        surface,
2515        source_data,
2516        source_pitches,
2517        destination_rect,
2518        &plane_count,
2519        planes,
2520        _vdp_cap_init_planes_adapt_surface_output,
2521        _vdp_cap_init_planes_adapt_format_surface_rgba,
2522        0
2523    );
2524    if (!dump_data) {
2525        plane_count = 0;
2526    }
2527
2528    fputs("vdp_output_surface_put_bits_native(", _vdp_cap_data.fp);
2529    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2530        fprintf(
2531            _vdp_cap_data.fp,
2532            "%u, ",
2533            surface
2534        );
2535        _vdp_cap_dump_void_pointer_list(plane_count, source_data, true);
2536        fputs(", ", _vdp_cap_data.fp);
2537        _vdp_cap_dump_uint32_t_list(plane_count, source_pitches, true);
2538        fputs(", ", _vdp_cap_data.fp);
2539        _vdp_cap_dump_rect(destination_rect);
2540    }
2541    fputs(")\n", _vdp_cap_data.fp);
2542    if (_vdp_cap_data.level >= LEVEL_DATA) {
2543        fputs("    ... Data: ", _vdp_cap_data.fp);
2544        if (dump_data) {
2545            _vdp_cap_dump_plane_list(plane_count, planes);
2546        }
2547        else {
2548           fputs("???", _vdp_cap_data.fp);
2549        }
2550        fputs("\n", _vdp_cap_data.fp);
2551    }
2552
2553    ret = _vdp_cap_data.vdp_output_surface_put_bits_native(
2554        surface,
2555        source_data,
2556        source_pitches,
2557        destination_rect
2558    );
2559
2560    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2561        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
2562    }
2563
2564    return ret;
2565}
2566
2567static VdpStatus _vdp_cap_output_surface_put_bits_indexed(
2568    VdpOutputSurface     surface,
2569    VdpIndexedFormat     source_indexed_format,
2570    void const * const * source_data,
2571    uint32_t const *     source_pitches,
2572    VdpRect const *      destination_rect,
2573    VdpColorTableFormat  color_table_format,
2574    void const *         color_table
2575)
2576{
2577    VdpStatus ret;
2578
2579    _VdpcapPlane planes[1];
2580    uint32_t    plane_count = _VDP_TRACE_ARSIZE(planes);
2581    bool dump_data = _vdp_cap_init_planes(
2582        surface,
2583        source_data,
2584        source_pitches,
2585        destination_rect,
2586        &plane_count,
2587        planes,
2588        _vdp_cap_init_planes_adapt_surface_output,
2589        _vdp_cap_init_planes_adapt_format_bits_indexed,
2590        source_indexed_format
2591    );
2592    if (!dump_data) {
2593        plane_count = 0;
2594    }
2595
2596    fputs("vdp_output_surface_put_bits_indexed(", _vdp_cap_data.fp);
2597    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2598        fprintf(
2599            _vdp_cap_data.fp,
2600            "%u, %u, ",
2601            surface,
2602            source_indexed_format
2603        );
2604        _vdp_cap_dump_void_pointer_list(plane_count, source_data, true);
2605        fputs(", ", _vdp_cap_data.fp);
2606        _vdp_cap_dump_uint32_t_list(plane_count, source_pitches, true);
2607        fputs(", ", _vdp_cap_data.fp);
2608        _vdp_cap_dump_rect(destination_rect);
2609        fprintf(
2610            _vdp_cap_data.fp,
2611            ", %u, ",
2612            color_table_format
2613        );
2614        _vdp_cap_dump_color_table(
2615            source_indexed_format,
2616            color_table_format,
2617            color_table
2618        );
2619    }
2620    fputs(")\n", _vdp_cap_data.fp);
2621    if (_vdp_cap_data.level >= LEVEL_DATA) {
2622        fputs("    ... Data: ", _vdp_cap_data.fp);
2623        if (dump_data) {
2624            _vdp_cap_dump_plane_list(plane_count, planes);
2625        }
2626        else {
2627           fputs("???", _vdp_cap_data.fp);
2628        }
2629        fputs("\n", _vdp_cap_data.fp);
2630    }
2631
2632    ret = _vdp_cap_data.vdp_output_surface_put_bits_indexed(
2633        surface,
2634        source_indexed_format,
2635        source_data,
2636        source_pitches,
2637        destination_rect,
2638        color_table_format,
2639        color_table
2640    );
2641
2642    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2643        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
2644    }
2645
2646    return ret;
2647}
2648
2649static VdpStatus _vdp_cap_output_surface_put_bits_y_cb_cr(
2650    VdpOutputSurface     surface,
2651    VdpYCbCrFormat       source_ycbcr_format,
2652    void const * const * source_data,
2653    uint32_t const *     source_pitches,
2654    VdpRect const *      destination_rect,
2655    VdpCSCMatrix const * csc_matrix
2656)
2657{
2658    VdpStatus ret;
2659
2660    _VdpcapPlane planes[1];
2661    uint32_t    plane_count = _VDP_TRACE_ARSIZE(planes);
2662    bool dump_data = _vdp_cap_init_planes(
2663        surface,
2664        source_data,
2665        source_pitches,
2666        destination_rect,
2667        &plane_count,
2668        planes,
2669        _vdp_cap_init_planes_adapt_surface_output,
2670        _vdp_cap_init_planes_adapt_format_bits_ycbcr,
2671        source_ycbcr_format
2672    );
2673    if (!dump_data) {
2674        plane_count = 0;
2675    }
2676
2677    fputs("vdp_output_surface_put_bits_y_cb_cr(", _vdp_cap_data.fp);
2678    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2679        fprintf(
2680            _vdp_cap_data.fp,
2681            "%u, %u, ",
2682            surface,
2683            source_ycbcr_format
2684        );
2685        _vdp_cap_dump_void_pointer_list(plane_count, source_data, true);
2686        fputs(", ", _vdp_cap_data.fp);
2687        _vdp_cap_dump_uint32_t_list(plane_count, source_pitches, true);
2688        fputs(", ", _vdp_cap_data.fp);
2689        _vdp_cap_dump_rect(destination_rect);
2690        fputs(", ", _vdp_cap_data.fp);
2691        _vdp_cap_dump_csc_matrix(csc_matrix);
2692    }
2693    fputs(")\n", _vdp_cap_data.fp);
2694    if (_vdp_cap_data.level >= LEVEL_DATA) {
2695        fputs("    ... Data: ", _vdp_cap_data.fp);
2696        if (dump_data) {
2697            _vdp_cap_dump_plane_list(plane_count, planes);
2698        }
2699        else {
2700           fputs("???", _vdp_cap_data.fp);
2701        }
2702        fputs("\n", _vdp_cap_data.fp);
2703    }
2704
2705    ret = _vdp_cap_data.vdp_output_surface_put_bits_y_cb_cr(
2706        surface,
2707        source_ycbcr_format,
2708        source_data,
2709        source_pitches,
2710        destination_rect,
2711        csc_matrix
2712    );
2713
2714    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2715        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
2716    }
2717
2718    return ret;
2719}
2720
2721static VdpStatus _vdp_cap_bitmap_surface_query_capabilities(
2722    VdpDevice     device,
2723    VdpRGBAFormat surface_rgba_format,
2724    /* output parameters follow */
2725    VdpBool *     is_supported,
2726    uint32_t *    max_width,
2727    uint32_t *    max_height
2728)
2729{
2730    VdpStatus ret;
2731
2732    fputs("vdp_bitmap_surface_query_capabilities(", _vdp_cap_data.fp);
2733    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2734        fprintf(
2735            _vdp_cap_data.fp,
2736            "%u, %u, %s, %s, %s",
2737            device,
2738            surface_rgba_format,
2739            is_supported ? "-" : "NULL",
2740            max_width ? "-" : "NULL",
2741            max_height ? "-" : "NULL"
2742        );
2743    }
2744    fputs(")\n", _vdp_cap_data.fp);
2745
2746    ret = _vdp_cap_data.vdp_bitmap_surface_query_capabilities(
2747        device,
2748        surface_rgba_format,
2749        is_supported,
2750        max_width,
2751        max_height
2752    );
2753
2754    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2755        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
2756        if (ret == VDP_STATUS_OK) {
2757            if (is_supported) {
2758                fprintf(_vdp_cap_data.fp, ", %d", *is_supported);
2759            }
2760            else {
2761                fputs(", ???", _vdp_cap_data.fp);
2762            }
2763            if (max_width) {
2764                fprintf(_vdp_cap_data.fp, ", %u", *max_width);
2765            }
2766            else {
2767                fputs(", ???", _vdp_cap_data.fp);
2768            }
2769            if (max_height) {
2770                fprintf(_vdp_cap_data.fp, ", %u", *max_height);
2771            }
2772            else {
2773                fputs(", ???", _vdp_cap_data.fp);
2774            }
2775        }
2776        fputs("\n", _vdp_cap_data.fp);
2777    }
2778
2779    return ret;
2780}
2781
2782static VdpStatus _vdp_cap_bitmap_surface_create(
2783    VdpDevice         device,
2784    VdpRGBAFormat     rgba_format,
2785    uint32_t          width,
2786    uint32_t          height,
2787    VdpBool           frequently_accessed,
2788    /* output parameters follow */
2789    VdpBitmapSurface * surface
2790)
2791{
2792    VdpStatus ret;
2793
2794    fputs("vdp_bitmap_surface_create(", _vdp_cap_data.fp);
2795    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2796        fprintf(
2797            _vdp_cap_data.fp,
2798            "%u, %u, %u, %u, %d, %s",
2799            device,
2800            rgba_format,
2801            width,
2802            height,
2803            frequently_accessed,
2804            surface ? "-" : "NULL"
2805        );
2806    }
2807    fputs(")\n", _vdp_cap_data.fp);
2808
2809    ret = _vdp_cap_data.vdp_bitmap_surface_create(
2810        device,
2811        rgba_format,
2812        width,
2813        height,
2814        frequently_accessed,
2815        surface
2816    );
2817
2818    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2819        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
2820        if (ret == VDP_STATUS_OK) {
2821            if (surface) {
2822                fprintf(_vdp_cap_data.fp, ", %u", *surface);
2823            }
2824            else {
2825                fputs(", ???", _vdp_cap_data.fp);
2826            }
2827        }
2828        fputs("\n", _vdp_cap_data.fp);
2829    }
2830
2831    return ret;
2832}
2833
2834static VdpStatus _vdp_cap_bitmap_surface_destroy(
2835    VdpBitmapSurface surface
2836)
2837{
2838    VdpStatus ret;
2839
2840    fputs("vdp_bitmap_surface_destroy(", _vdp_cap_data.fp);
2841    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2842        fprintf(
2843            _vdp_cap_data.fp,
2844            "%u",
2845            surface
2846        );
2847    }
2848    fputs(")\n", _vdp_cap_data.fp);
2849
2850    ret = _vdp_cap_data.vdp_bitmap_surface_destroy(
2851        surface
2852    );
2853
2854    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2855        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
2856    }
2857
2858    return ret;
2859}
2860
2861static VdpStatus _vdp_cap_bitmap_surface_get_parameters(
2862    VdpBitmapSurface surface,
2863    /* output parameters follow */
2864    VdpRGBAFormat * rgba_format,
2865    uint32_t *      width,
2866    uint32_t *      height,
2867    VdpBool *       frequently_accessed
2868)
2869{
2870    VdpStatus ret;
2871
2872    fputs("vdp_bitmap_surface_get_parameters(", _vdp_cap_data.fp);
2873    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2874        fprintf(
2875            _vdp_cap_data.fp,
2876            "%u, %s, %s, %s, %s",
2877            surface,
2878            rgba_format ? "-" : "NULL",
2879            width ? "-" : "NULL",
2880            height ? "-" : "NULL",
2881            frequently_accessed ? "-" : "NULL"
2882        );
2883    }
2884    fputs(")\n", _vdp_cap_data.fp);
2885
2886    ret = _vdp_cap_data.vdp_bitmap_surface_get_parameters(
2887        surface,
2888        rgba_format,
2889        width,
2890        height,
2891        frequently_accessed
2892    );
2893
2894    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2895        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
2896        if (ret == VDP_STATUS_OK) {
2897            if (rgba_format) {
2898                fprintf(_vdp_cap_data.fp, ", %u", *rgba_format);
2899            }
2900            else {
2901                fputs(", ???", _vdp_cap_data.fp);
2902            }
2903            if (width) {
2904                fprintf(_vdp_cap_data.fp, ", %u", *width);
2905            }
2906            else {
2907                fputs(", ???", _vdp_cap_data.fp);
2908            }
2909            if (height) {
2910                fprintf(_vdp_cap_data.fp, ", %u", *height);
2911            }
2912            else {
2913                fputs(", ???", _vdp_cap_data.fp);
2914            }
2915            if (frequently_accessed) {
2916                fprintf(_vdp_cap_data.fp, ", %d", *frequently_accessed);
2917            }
2918            else {
2919                fputs(", ???", _vdp_cap_data.fp);
2920            }
2921        }
2922        fputs("\n", _vdp_cap_data.fp);
2923    }
2924
2925    return ret;
2926}
2927
2928static VdpStatus _vdp_cap_bitmap_surface_put_bits_native(
2929    VdpBitmapSurface     surface,
2930    void const * const * source_data,
2931    uint32_t const *     source_pitches,
2932    VdpRect const *      destination_rect
2933)
2934{
2935    VdpStatus ret;
2936
2937    _VdpcapPlane planes[1];
2938    uint32_t    plane_count = _VDP_TRACE_ARSIZE(planes);
2939    bool dump_data = _vdp_cap_init_planes(
2940        surface,
2941        source_data,
2942        source_pitches,
2943        destination_rect,
2944        &plane_count,
2945        planes,
2946        _vdp_cap_init_planes_adapt_surface_bitmap,
2947        _vdp_cap_init_planes_adapt_format_surface_rgba,
2948        0
2949    );
2950    if (!dump_data) {
2951        plane_count = 0;
2952    }
2953
2954    fputs("vdp_bitmap_surface_put_bits_native(", _vdp_cap_data.fp);
2955    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2956        fprintf(
2957            _vdp_cap_data.fp,
2958            "%u, ",
2959            surface
2960        );
2961        _vdp_cap_dump_void_pointer_list(plane_count, source_data, true);
2962        fputs(", ", _vdp_cap_data.fp);
2963        _vdp_cap_dump_uint32_t_list(plane_count, source_pitches, true);
2964        fputs(", ", _vdp_cap_data.fp);
2965        _vdp_cap_dump_rect(destination_rect);
2966    }
2967    fputs(")\n", _vdp_cap_data.fp);
2968    if (_vdp_cap_data.level >= LEVEL_DATA) {
2969        fputs("    ... Data: ", _vdp_cap_data.fp);
2970        if (dump_data) {
2971            _vdp_cap_dump_plane_list(plane_count, planes);
2972        }
2973        else {
2974           fputs("???", _vdp_cap_data.fp);
2975        }
2976        fputs("\n", _vdp_cap_data.fp);
2977    }
2978
2979    ret = _vdp_cap_data.vdp_bitmap_surface_put_bits_native(
2980        surface,
2981        source_data,
2982        source_pitches,
2983        destination_rect
2984    );
2985
2986    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
2987        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
2988    }
2989
2990    return ret;
2991}
2992
2993static VdpStatus _vdp_cap_output_surface_render_output_surface(
2994    VdpOutputSurface                         destination_surface,
2995    VdpRect const *                          destination_rect,
2996    VdpOutputSurface                         source_surface,
2997    VdpRect const *                          source_rect,
2998    VdpColor const *                         colors,
2999    VdpOutputSurfaceRenderBlendState const * blend_state,
3000    uint32_t                                 flags
3001)
3002{
3003    VdpStatus ret;
3004
3005    fputs("vdp_output_surface_render_output_surface(", _vdp_cap_data.fp);
3006    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3007        fprintf(
3008            _vdp_cap_data.fp,
3009            "%u, ",
3010            destination_surface
3011        );
3012        _vdp_cap_dump_rect(destination_rect);
3013        fprintf(
3014            _vdp_cap_data.fp,
3015            ", %u, ",
3016            source_surface
3017        );
3018        _vdp_cap_dump_rect(source_rect);
3019        fputs(", ", _vdp_cap_data.fp);
3020        _vdp_cap_dump_color_list((flags & VDP_OUTPUT_SURFACE_RENDER_COLOR_PER_VERTEX) ? 4 : 1, colors);
3021        fputs(", ", _vdp_cap_data.fp);
3022        _vdp_cap_dump_blend_state(blend_state);
3023        fprintf(
3024            _vdp_cap_data.fp,
3025            ", %u",
3026            flags
3027        );
3028    }
3029    fputs(")\n", _vdp_cap_data.fp);
3030
3031    ret = _vdp_cap_data.vdp_output_surface_render_output_surface(
3032        destination_surface,
3033        destination_rect,
3034        source_surface,
3035        source_rect,
3036        colors,
3037        blend_state,
3038        flags
3039    );
3040
3041    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3042        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
3043    }
3044
3045    return ret;
3046}
3047
3048static VdpStatus _vdp_cap_output_surface_render_bitmap_surface(
3049    VdpOutputSurface                         destination_surface,
3050    VdpRect const *                          destination_rect,
3051    VdpBitmapSurface                         source_surface,
3052    VdpRect const *                          source_rect,
3053    VdpColor const *                         colors,
3054    VdpOutputSurfaceRenderBlendState const * blend_state,
3055    uint32_t                                 flags
3056)
3057{
3058    VdpStatus ret;
3059
3060    fputs("vdp_output_surface_render_bitmap_surface(", _vdp_cap_data.fp);
3061    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3062        fprintf(
3063            _vdp_cap_data.fp,
3064            "%u, ",
3065            destination_surface
3066        );
3067        _vdp_cap_dump_rect(destination_rect);
3068        fprintf(
3069            _vdp_cap_data.fp,
3070            ", %u, ",
3071            source_surface
3072        );
3073        _vdp_cap_dump_rect(source_rect);
3074        fputs(", ", _vdp_cap_data.fp);
3075        _vdp_cap_dump_color_list((flags & VDP_OUTPUT_SURFACE_RENDER_COLOR_PER_VERTEX) ? 4 : 1, colors);
3076        fputs(", ", _vdp_cap_data.fp);
3077        _vdp_cap_dump_blend_state(blend_state);
3078        fprintf(
3079            _vdp_cap_data.fp,
3080            ", %u",
3081            flags
3082        );
3083    }
3084    fputs(")\n", _vdp_cap_data.fp);
3085
3086    ret = _vdp_cap_data.vdp_output_surface_render_bitmap_surface(
3087        destination_surface,
3088        destination_rect,
3089        source_surface,
3090        source_rect,
3091        colors,
3092        blend_state,
3093        flags
3094    );
3095
3096    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3097        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
3098    }
3099
3100    return ret;
3101}
3102
3103static VdpStatus _vdp_cap_decoder_query_capabilities(
3104    VdpDevice         device,
3105    VdpDecoderProfile profile,
3106    /* output parameters follow */
3107    VdpBool *         is_supported,
3108    uint32_t *        max_level,
3109    uint32_t *        max_macroblocks,
3110    uint32_t *        max_width,
3111    uint32_t *        max_height
3112)
3113{
3114    VdpStatus ret;
3115
3116    fputs("vdp_decoder_query_capabilities(", _vdp_cap_data.fp);
3117    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3118        fprintf(
3119            _vdp_cap_data.fp,
3120            "%u, %u, %s, %s, %s, %s, %s",
3121            device,
3122            profile,
3123            is_supported ? "-" : "NULL",
3124            max_level ? "-" : "NULL",
3125            max_macroblocks ? "-" : "NULL",
3126            max_width ? "-" : "NULL",
3127            max_height ? "-" : "NULL"
3128        );
3129    }
3130    fputs(")\n", _vdp_cap_data.fp);
3131
3132    ret = _vdp_cap_data.vdp_decoder_query_capabilities(
3133        device,
3134        profile,
3135        is_supported,
3136        max_level,
3137        max_macroblocks,
3138        max_width,
3139        max_height
3140    );
3141
3142    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3143        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
3144        if (ret == VDP_STATUS_OK) {
3145            if (is_supported) {
3146                fprintf(_vdp_cap_data.fp, ", %d", *is_supported);
3147            }
3148            else {
3149                fputs(", ???", _vdp_cap_data.fp);
3150            }
3151            if (max_level) {
3152                fprintf(_vdp_cap_data.fp, ", %u", *max_level);
3153            }
3154            else {
3155                fputs(", ???", _vdp_cap_data.fp);
3156            }
3157            if (max_macroblocks) {
3158                fprintf(_vdp_cap_data.fp, ", %u", *max_macroblocks);
3159            }
3160            else {
3161                fputs(", ???", _vdp_cap_data.fp);
3162            }
3163            if (max_width) {
3164                fprintf(_vdp_cap_data.fp, ", %u", *max_width);
3165            }
3166            else {
3167                fputs(", ???", _vdp_cap_data.fp);
3168            }
3169            if (max_height) {
3170                fprintf(_vdp_cap_data.fp, ", %u", *max_height);
3171            }
3172            else {
3173                fputs(", ???", _vdp_cap_data.fp);
3174            }
3175        }
3176        fputs("\n", _vdp_cap_data.fp);
3177    }
3178
3179    return ret;
3180}
3181
3182static VdpStatus _vdp_cap_decoder_create(
3183    VdpDevice         device,
3184    VdpDecoderProfile profile,
3185    uint32_t          width,
3186    uint32_t          height,
3187    uint32_t          max_references,
3188    /* output parameters follow */
3189    VdpDecoder *      decoder
3190)
3191{
3192    VdpStatus ret;
3193
3194    fputs("vdp_decoder_create(", _vdp_cap_data.fp);
3195    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3196        fprintf(
3197            _vdp_cap_data.fp,
3198            "%u, %u, %u, %u, %u, %s",
3199            device,
3200            profile,
3201            width,
3202            height,
3203            max_references,
3204            decoder ? "-" : "NULL"
3205        );
3206    }
3207    fputs(")\n", _vdp_cap_data.fp);
3208
3209    ret = _vdp_cap_data.vdp_decoder_create(
3210        device,
3211        profile,
3212        width,
3213        height,
3214        max_references,
3215        decoder
3216    );
3217
3218    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3219        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
3220        if (ret == VDP_STATUS_OK) {
3221            if (decoder) {
3222                fprintf(_vdp_cap_data.fp, ", %u", *decoder);
3223            }
3224            else {
3225                fputs(", ???", _vdp_cap_data.fp);
3226            }
3227        }
3228        fputs("\n", _vdp_cap_data.fp);
3229    }
3230
3231    return ret;
3232}
3233
3234static VdpStatus _vdp_cap_decoder_destroy(
3235    VdpDecoder decoder
3236)
3237{
3238    VdpStatus ret;
3239
3240    fputs("vdp_decoder_destroy(", _vdp_cap_data.fp);
3241    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3242        fprintf(
3243            _vdp_cap_data.fp,
3244            "%u",
3245            decoder
3246        );
3247    }
3248    fputs(")\n", _vdp_cap_data.fp);
3249
3250    ret = _vdp_cap_data.vdp_decoder_destroy(
3251        decoder
3252    );
3253
3254    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3255        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
3256    }
3257
3258    return ret;
3259}
3260
3261static VdpStatus _vdp_cap_decoder_get_parameters(
3262    VdpDecoder          decoder,
3263    /* output parameters follow */
3264    VdpDecoderProfile * profile,
3265    uint32_t *          width,
3266    uint32_t *          height
3267)
3268{
3269    VdpStatus ret;
3270
3271    fputs("vdp_decoder_get_parameters(", _vdp_cap_data.fp);
3272    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3273        fprintf(
3274            _vdp_cap_data.fp,
3275            "%u, %s, %s, %s",
3276            decoder,
3277            profile ? "-" : "NULL",
3278            width ? "-" : "NULL",
3279            height ? "-" : "NULL"
3280        );
3281    }
3282    fputs(")\n", _vdp_cap_data.fp);
3283
3284    ret = _vdp_cap_data.vdp_decoder_get_parameters(
3285        decoder,
3286        profile,
3287        width,
3288        height
3289    );
3290
3291    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3292        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
3293        if (ret == VDP_STATUS_OK) {
3294            if (profile) {
3295                fprintf(_vdp_cap_data.fp, ", %u", *profile);
3296            }
3297            else {
3298                fputs(", ???", _vdp_cap_data.fp);
3299            }
3300            if (width) {
3301                fprintf(_vdp_cap_data.fp, ", %u", *width);
3302            }
3303            else {
3304                fputs(", ???", _vdp_cap_data.fp);
3305            }
3306            if (height) {
3307                fprintf(_vdp_cap_data.fp, ", %u", *height);
3308            }
3309            else {
3310                fputs(", ???", _vdp_cap_data.fp);
3311            }
3312        }
3313        fputs("\n", _vdp_cap_data.fp);
3314    }
3315
3316    return ret;
3317}
3318
3319static VdpStatus _vdp_cap_decoder_render(
3320    VdpDecoder                 decoder,
3321    VdpVideoSurface            target,
3322    VdpPictureInfo const *     picture_info,
3323    uint32_t                   bitstream_buffer_count,
3324    VdpBitstreamBuffer const * bitstream_buffers
3325)
3326{
3327    VdpStatus ret;
3328
3329    fputs("vdp_decoder_render(", _vdp_cap_data.fp);
3330    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3331        VdpDecoderProfile profile;
3332        uint32_t          width;
3333        uint32_t          height;
3334
3335        ret = _vdp_cap_data.vdp_decoder_get_parameters(
3336            decoder,
3337            &profile,
3338            &width,
3339            &height
3340        );
3341
3342        fprintf(
3343            _vdp_cap_data.fp,
3344            "%u, %u, ",
3345            decoder,
3346            target
3347        );
3348        _vdp_cap_dump_picture_info(profile, picture_info);
3349        fprintf(
3350            _vdp_cap_data.fp,
3351            ", %u, ",
3352            bitstream_buffer_count
3353        );
3354        _vdp_cap_dump_bitstream_buffer_list(bitstream_buffer_count, bitstream_buffers);
3355    }
3356    fputs(")\n", _vdp_cap_data.fp);
3357
3358    ret = _vdp_cap_data.vdp_decoder_render(
3359        decoder,
3360        target,
3361        picture_info,
3362        bitstream_buffer_count,
3363        bitstream_buffers
3364    );
3365
3366    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3367        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
3368    }
3369
3370    return ret;
3371}
3372
3373
3374static VdpStatus _vdp_cap_video_mixer_query_feature_support(
3375    VdpDevice            device,
3376    VdpVideoMixerFeature feature,
3377    /* output parameters follow */
3378    VdpBool *            is_supported
3379)
3380{
3381    VdpStatus ret;
3382
3383    fputs("vdp_video_mixer_query_feature_support(", _vdp_cap_data.fp);
3384    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3385        fprintf(
3386            _vdp_cap_data.fp,
3387            "%u, %u, %s",
3388            device,
3389            feature,
3390            is_supported ? "-" : "NULL"
3391        );
3392    }
3393    fputs(")\n", _vdp_cap_data.fp);
3394
3395    ret = _vdp_cap_data.vdp_video_mixer_query_feature_support(
3396        device,
3397        feature,
3398        is_supported
3399    );
3400
3401    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3402        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
3403        if (ret == VDP_STATUS_OK) {
3404            if (is_supported) {
3405                fprintf(_vdp_cap_data.fp, ", %d", *is_supported);
3406            }
3407            else {
3408                fputs(", ???", _vdp_cap_data.fp);
3409            }
3410        }
3411        fputs("\n", _vdp_cap_data.fp);
3412    }
3413
3414    return ret;
3415}
3416
3417static VdpStatus _vdp_cap_video_mixer_query_parameter_support(
3418    VdpDevice              device,
3419    VdpVideoMixerParameter parameter,
3420    /* output parameters follow */
3421    VdpBool *              is_supported
3422)
3423{
3424    VdpStatus ret;
3425
3426    fputs("vdp_video_mixer_query_parameter_support(", _vdp_cap_data.fp);
3427    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3428        fprintf(
3429            _vdp_cap_data.fp,
3430            "%u, %u, %s",
3431            device,
3432            parameter,
3433            is_supported ? "-" : "NULL"
3434        );
3435    }
3436    fputs(")\n", _vdp_cap_data.fp);
3437
3438    ret = _vdp_cap_data.vdp_video_mixer_query_parameter_support(
3439        device,
3440        parameter,
3441        is_supported
3442    );
3443
3444    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3445        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
3446        if (ret == VDP_STATUS_OK) {
3447            if (is_supported) {
3448                fprintf(_vdp_cap_data.fp, ", %d", *is_supported);
3449            }
3450            else {
3451                fputs(", ???", _vdp_cap_data.fp);
3452            }
3453        }
3454        fputs("\n", _vdp_cap_data.fp);
3455    }
3456
3457    return ret;
3458}
3459
3460static VdpStatus _vdp_cap_video_mixer_query_attribute_support(
3461    VdpDevice              device,
3462    VdpVideoMixerAttribute attribute,
3463    /* output parameters follow */
3464    VdpBool *              is_supported
3465)
3466{
3467    VdpStatus ret;
3468
3469    fputs("vdp_video_mixer_query_attribute_support(", _vdp_cap_data.fp);
3470    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3471        fprintf(
3472            _vdp_cap_data.fp,
3473            "%u, %u, %s",
3474            device,
3475            attribute,
3476            is_supported ? "-" : "NULL"
3477        );
3478    }
3479    fputs(")\n", _vdp_cap_data.fp);
3480
3481    ret = _vdp_cap_data.vdp_video_mixer_query_attribute_support(
3482        device,
3483        attribute,
3484        is_supported
3485    );
3486
3487    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3488        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
3489        if (ret == VDP_STATUS_OK) {
3490            if (is_supported) {
3491                fprintf(_vdp_cap_data.fp, ", %d", *is_supported);
3492            }
3493            else {
3494                fputs(", ???", _vdp_cap_data.fp);
3495            }
3496        }
3497        fputs("\n", _vdp_cap_data.fp);
3498    }
3499
3500    return ret;
3501}
3502
3503static VdpStatus _vdp_cap_video_mixer_query_parameter_value_range(
3504    VdpDevice              device,
3505    VdpVideoMixerParameter parameter,
3506    /* output parameters follow */
3507    void *                 min_value,
3508    void *                 max_value
3509)
3510{
3511    VdpStatus ret;
3512
3513    fputs("vdp_video_mixer_query_parameter_value_range(", _vdp_cap_data.fp);
3514    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3515        fprintf(
3516            _vdp_cap_data.fp,
3517            "%u, %u, %s, %s",
3518            device,
3519            parameter,
3520            min_value ? "-" : "NULL",
3521            max_value ? "-" : "NULL"
3522        );
3523    }
3524    fputs(")\n", _vdp_cap_data.fp);
3525
3526    ret = _vdp_cap_data.vdp_video_mixer_query_parameter_value_range(
3527        device,
3528        parameter,
3529        min_value,
3530        max_value
3531    );
3532
3533    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3534        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
3535        if (ret == VDP_STATUS_OK) {
3536            fputs(", ", _vdp_cap_data.fp);
3537            _vdp_cap_dump_video_mixer_parameter_value(parameter, min_value);
3538            fputs(", ", _vdp_cap_data.fp);
3539            _vdp_cap_dump_video_mixer_parameter_value(parameter, max_value);
3540        }
3541        fputs("\n", _vdp_cap_data.fp);
3542    }
3543
3544    return ret;
3545}
3546
3547static VdpStatus _vdp_cap_video_mixer_query_attribute_value_range(
3548    VdpDevice              device,
3549    VdpVideoMixerAttribute attribute,
3550    /* output parameters follow */
3551    void *                 min_value,
3552    void *                 max_value
3553)
3554{
3555    VdpStatus ret;
3556
3557    fputs("vdp_video_mixer_query_attribute_value_range(", _vdp_cap_data.fp);
3558    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3559        fprintf(
3560            _vdp_cap_data.fp,
3561            "%u, %u, %s, %s",
3562            device,
3563            attribute,
3564            min_value ? "-" : "NULL",
3565            max_value ? "-" : "NULL"
3566        );
3567    }
3568    fputs(")\n", _vdp_cap_data.fp);
3569
3570    ret = _vdp_cap_data.vdp_video_mixer_query_attribute_value_range(
3571        device,
3572        attribute,
3573        min_value,
3574        max_value
3575    );
3576
3577    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3578        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
3579        if (ret == VDP_STATUS_OK) {
3580            fputs(", ", _vdp_cap_data.fp);
3581            _vdp_cap_dump_video_mixer_attribute_value(attribute, min_value, false);
3582            fputs(", ", _vdp_cap_data.fp);
3583            _vdp_cap_dump_video_mixer_attribute_value(attribute, max_value, false);
3584        }
3585        fputs("\n", _vdp_cap_data.fp);
3586    }
3587
3588    return ret;
3589}
3590
3591static VdpStatus _vdp_cap_video_mixer_create(
3592    VdpDevice                      device,
3593    uint32_t                       feature_count,
3594    VdpVideoMixerFeature const *   features,
3595    uint32_t                       parameter_count,
3596    VdpVideoMixerParameter const * parameters,
3597    void const * const *           parameter_values,
3598    /* output parameters follow */
3599    VdpVideoMixer *                mixer
3600)
3601{
3602    VdpStatus ret;
3603
3604    fputs("vdp_video_mixer_create(", _vdp_cap_data.fp);
3605    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3606        fprintf(_vdp_cap_data.fp, "%u, %u, ", device, feature_count);
3607        _vdp_cap_dump_video_mixer_feature_list(feature_count, features);
3608        fprintf(_vdp_cap_data.fp, ", %u, ", parameter_count);
3609        _vdp_cap_dump_video_mixer_parameter_list(parameter_count, parameters);
3610        fputs(", ", _vdp_cap_data.fp);
3611        _vdp_cap_dump_video_mixer_parameter_value_list(
3612            parameter_count,
3613            parameters,
3614            parameter_values
3615        );
3616        fprintf(_vdp_cap_data.fp, ", %s", mixer ? "-" : "NULL");
3617    }
3618    fputs(")\n", _vdp_cap_data.fp);
3619
3620    ret = _vdp_cap_data.vdp_video_mixer_create(
3621        device,
3622        feature_count,
3623        features,
3624        parameter_count,
3625        parameters,
3626        parameter_values,
3627        mixer
3628    );
3629
3630    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3631        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
3632        if (ret == VDP_STATUS_OK) {
3633            if (mixer) {
3634                fprintf(_vdp_cap_data.fp, ", %u", *mixer);
3635            }
3636            else {
3637                fputs(", ???", _vdp_cap_data.fp);
3638            }
3639        }
3640        fputs("\n", _vdp_cap_data.fp);
3641    }
3642
3643    return ret;
3644}
3645
3646static VdpStatus _vdp_cap_video_mixer_set_feature_enables(
3647    VdpVideoMixer                mixer,
3648    uint32_t                     feature_count,
3649    VdpVideoMixerFeature const * features,
3650    VdpBool const *              feature_enables
3651)
3652{
3653    VdpStatus ret;
3654
3655    fputs("vdp_video_mixer_set_feature_enables(", _vdp_cap_data.fp);
3656    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3657        fprintf(_vdp_cap_data.fp, "%u, %u, ", mixer, feature_count);
3658        _vdp_cap_dump_video_mixer_feature_list(feature_count, features);
3659        fputs(", ", _vdp_cap_data.fp);
3660        _vdp_cap_dump_bool_list(feature_count, feature_enables);
3661    }
3662    fputs(")\n", _vdp_cap_data.fp);
3663
3664    ret = _vdp_cap_data.vdp_video_mixer_set_feature_enables(
3665        mixer,
3666        feature_count,
3667        features,
3668        feature_enables
3669    );
3670
3671    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3672        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
3673    }
3674
3675    return ret;
3676}
3677
3678static VdpStatus _vdp_cap_video_mixer_set_attribute_values(
3679    VdpVideoMixer                  mixer,
3680    uint32_t                       attribute_count,
3681    VdpVideoMixerAttribute const * attributes,
3682    void const * const *           attribute_values
3683)
3684{
3685    VdpStatus ret;
3686
3687    fputs("vdp_video_mixer_set_attribute_values(", _vdp_cap_data.fp);
3688    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3689        fprintf(_vdp_cap_data.fp, "%u, %u, ", mixer, attribute_count);
3690        _vdp_cap_dump_video_mixer_attribute_list(attribute_count, attributes);
3691        fputs(", ", _vdp_cap_data.fp);
3692        _vdp_cap_dump_video_mixer_attribute_value_list(
3693            attribute_count,
3694            attributes,
3695            attribute_values,
3696            false
3697        );
3698    }
3699    fputs(")\n", _vdp_cap_data.fp);
3700
3701    ret = _vdp_cap_data.vdp_video_mixer_set_attribute_values(
3702        mixer,
3703        attribute_count,
3704        attributes,
3705        attribute_values
3706    );
3707
3708    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3709        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
3710    }
3711
3712    return ret;
3713}
3714
3715static VdpStatus _vdp_cap_video_mixer_get_feature_support(
3716    VdpVideoMixer                mixer,
3717    uint32_t                     feature_count,
3718    VdpVideoMixerFeature const * features,
3719    /* output parameters follow */
3720    VdpBool *                    feature_supports
3721)
3722{
3723    VdpStatus ret;
3724
3725    fputs("vdp_video_mixer_get_feature_support(", _vdp_cap_data.fp);
3726    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3727        fprintf(_vdp_cap_data.fp, "%u, %u, ", mixer, feature_count);
3728        _vdp_cap_dump_video_mixer_feature_list(feature_count, features);
3729        fputs(feature_supports ? "-" : "NULL", _vdp_cap_data.fp);
3730    }
3731    fputs(")\n", _vdp_cap_data.fp);
3732
3733    ret = _vdp_cap_data.vdp_video_mixer_get_feature_support(
3734        mixer,
3735        feature_count,
3736        features,
3737        feature_supports
3738    );
3739
3740    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3741        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
3742        if (ret == VDP_STATUS_OK) {
3743            fputs(", ", _vdp_cap_data.fp);
3744            _vdp_cap_dump_bool_list(feature_count, feature_supports);
3745        }
3746        fputs("\n", _vdp_cap_data.fp);
3747    }
3748
3749    return ret;
3750}
3751
3752static VdpStatus _vdp_cap_video_mixer_get_feature_enables(
3753    VdpVideoMixer                mixer,
3754    uint32_t                     feature_count,
3755    VdpVideoMixerFeature const * features,
3756    /* output parameters follow */
3757    VdpBool *                    feature_enables
3758)
3759{
3760    VdpStatus ret;
3761
3762    fputs("vdp_video_mixer_get_feature_enables(", _vdp_cap_data.fp);
3763    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3764        fprintf(_vdp_cap_data.fp, "%u, %u, ", mixer, feature_count);
3765        _vdp_cap_dump_video_mixer_feature_list(feature_count, features);
3766        fprintf(_vdp_cap_data.fp, ", %s", feature_enables ? "-" : "NULL");
3767    }
3768    fputs(")\n", _vdp_cap_data.fp);
3769
3770    ret = _vdp_cap_data.vdp_video_mixer_get_feature_enables(
3771        mixer,
3772        feature_count,
3773        features,
3774        feature_enables
3775    );
3776
3777    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3778        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
3779        if (ret == VDP_STATUS_OK) {
3780            fputs(", ", _vdp_cap_data.fp);
3781            _vdp_cap_dump_bool_list(feature_count, feature_enables);
3782        }
3783        fputs("\n", _vdp_cap_data.fp);
3784    }
3785
3786    return ret;
3787}
3788
3789static VdpStatus _vdp_cap_video_mixer_get_parameter_values(
3790    VdpVideoMixer                  mixer,
3791    uint32_t                       parameter_count,
3792    VdpVideoMixerParameter const * parameters,
3793    /* output parameters follow */
3794    void * const *                 parameter_values
3795)
3796{
3797    VdpStatus ret;
3798
3799    fputs("vdp_video_mixer_get_parameter_values(", _vdp_cap_data.fp);
3800    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3801        fprintf(_vdp_cap_data.fp, "%u, %u, ", mixer, parameter_count);
3802        _vdp_cap_dump_video_mixer_parameter_list(parameter_count, parameters);
3803        fprintf(_vdp_cap_data.fp, ", %s", parameter_values ? "-" : "NULL");
3804    }
3805    fputs(")\n", _vdp_cap_data.fp);
3806
3807    ret = _vdp_cap_data.vdp_video_mixer_get_parameter_values(
3808        mixer,
3809        parameter_count,
3810        parameters,
3811        parameter_values
3812    );
3813
3814    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3815        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
3816        if (ret == VDP_STATUS_OK) {
3817            fputs(", ", _vdp_cap_data.fp);
3818            _vdp_cap_dump_video_mixer_parameter_value_list(
3819                parameter_count,
3820                parameters,
3821                parameter_values
3822            );
3823        }
3824        fputs("\n", _vdp_cap_data.fp);
3825    }
3826
3827    return ret;
3828}
3829
3830static VdpStatus _vdp_cap_video_mixer_get_attribute_values(
3831    VdpVideoMixer                  mixer,
3832    uint32_t                       attribute_count,
3833    VdpVideoMixerAttribute const * attributes,
3834    /* output parameters follow */
3835    void * const *                 attribute_values
3836)
3837{
3838    VdpStatus ret;
3839
3840    fputs("vdp_video_mixer_get_attribute_values(", _vdp_cap_data.fp);
3841    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3842        fprintf(_vdp_cap_data.fp, "%u, %u, ", mixer, attribute_count);
3843        _vdp_cap_dump_video_mixer_attribute_list(attribute_count, attributes);
3844        fprintf(_vdp_cap_data.fp, ", %s", attribute_values ? "-" : "NULL");
3845    }
3846    fputs(")\n", _vdp_cap_data.fp);
3847
3848    ret = _vdp_cap_data.vdp_video_mixer_get_attribute_values(
3849        mixer,
3850        attribute_count,
3851        attributes,
3852        attribute_values
3853    );
3854
3855    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3856        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
3857        if (ret == VDP_STATUS_OK) {
3858            fputs(", ", _vdp_cap_data.fp);
3859            _vdp_cap_dump_video_mixer_attribute_value_list(
3860                attribute_count,
3861                attributes,
3862                attribute_values,
3863                true
3864            );
3865        }
3866        fputs("\n", _vdp_cap_data.fp);
3867    }
3868
3869    return ret;
3870}
3871
3872static VdpStatus _vdp_cap_video_mixer_destroy(
3873    VdpVideoMixer mixer
3874)
3875{
3876    VdpStatus ret;
3877
3878    fputs("vdp_video_mixer_destroy(", _vdp_cap_data.fp);
3879    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3880        fprintf(
3881            _vdp_cap_data.fp,
3882            "%u",
3883            mixer
3884        );
3885    }
3886    fputs(")\n", _vdp_cap_data.fp);
3887
3888    ret = _vdp_cap_data.vdp_video_mixer_destroy(
3889        mixer
3890    );
3891
3892    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3893        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
3894    }
3895
3896    return ret;
3897}
3898
3899static VdpStatus _vdp_cap_video_mixer_render(
3900    VdpVideoMixer                 mixer,
3901    VdpOutputSurface              background_surface,
3902    VdpRect const *               background_source_rect,
3903    VdpVideoMixerPictureStructure current_picture_structure,
3904    uint32_t                      video_surface_past_count,
3905    VdpVideoSurface const *       video_surface_past,
3906    VdpVideoSurface               video_surface_current,
3907    uint32_t                      video_surface_future_count,
3908    VdpVideoSurface const *       video_surface_future,
3909    VdpRect const *               video_source_rect,
3910    VdpOutputSurface              destination_surface,
3911    VdpRect const *               destination_rect,
3912    VdpRect const *               destination_video_rect,
3913    uint32_t                      layer_count,
3914    VdpLayer const *              layers
3915)
3916{
3917    VdpStatus ret;
3918
3919    fputs("vdp_video_mixer_render(", _vdp_cap_data.fp);
3920    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3921        fprintf(
3922            _vdp_cap_data.fp,
3923            "%u, %u, ",
3924            mixer,
3925            background_surface
3926        );
3927        _vdp_cap_dump_rect(background_source_rect);
3928        fprintf(
3929            _vdp_cap_data.fp,
3930            ", %d, %u, ",
3931            current_picture_structure,
3932            video_surface_past_count
3933        );
3934        _vdp_cap_dump_uint32_t_list(video_surface_past_count, video_surface_past, false);
3935        fprintf(
3936            _vdp_cap_data.fp,
3937            ", %u, %u, ",
3938            video_surface_current,
3939            video_surface_future_count
3940        );
3941        _vdp_cap_dump_uint32_t_list(video_surface_future_count, video_surface_future, false);
3942        fputs(", ", _vdp_cap_data.fp);
3943        _vdp_cap_dump_rect(video_source_rect);
3944        fprintf(
3945            _vdp_cap_data.fp,
3946            ", %u, ",
3947            destination_surface
3948        );
3949        _vdp_cap_dump_rect(destination_rect);
3950        fputs(", ", _vdp_cap_data.fp);
3951        _vdp_cap_dump_rect(destination_video_rect);
3952        fprintf(
3953            _vdp_cap_data.fp,
3954            ", %u, ",
3955            layer_count
3956        );
3957        _vdp_cap_dump_layers_list(layer_count, layers);
3958    }
3959    fputs(")\n", _vdp_cap_data.fp);
3960
3961    ret = _vdp_cap_data.vdp_video_mixer_render(
3962        mixer,
3963        background_surface,
3964        background_source_rect,
3965        current_picture_structure,
3966        video_surface_past_count,
3967        video_surface_past,
3968        video_surface_current,
3969        video_surface_future_count,
3970        video_surface_future,
3971        video_source_rect,
3972        destination_surface,
3973        destination_rect,
3974        destination_video_rect,
3975        layer_count,
3976        layers
3977    );
3978
3979    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3980        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
3981    }
3982
3983    return ret;
3984}
3985
3986static VdpStatus _vdp_cap_presentation_queue_target_destroy(
3987    VdpPresentationQueueTarget presentation_queue_target
3988)
3989{
3990    VdpStatus ret;
3991
3992    fputs("vdp_presentation_queue_target_destroy(", _vdp_cap_data.fp);
3993    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
3994        fprintf(
3995            _vdp_cap_data.fp,
3996            "%u",
3997            presentation_queue_target
3998        );
3999    }
4000    fputs(")\n", _vdp_cap_data.fp);
4001
4002    ret = _vdp_cap_data.vdp_presentation_queue_target_destroy(
4003        presentation_queue_target
4004    );
4005
4006    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4007        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
4008    }
4009
4010    return ret;
4011}
4012
4013static VdpStatus _vdp_cap_presentation_queue_create(
4014    VdpDevice                  device,
4015    VdpPresentationQueueTarget presentation_queue_target,
4016    /* output parameters follow */
4017    VdpPresentationQueue *     presentation_queue
4018)
4019{
4020    VdpStatus ret;
4021
4022    fputs("vdp_presentation_queue_create(", _vdp_cap_data.fp);
4023    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4024        fprintf(
4025            _vdp_cap_data.fp,
4026            "%u, %u, %s",
4027            device,
4028            presentation_queue_target,
4029            presentation_queue ? "-" : "NULL"
4030        );
4031    }
4032    fputs(")\n", _vdp_cap_data.fp);
4033
4034    ret = _vdp_cap_data.vdp_presentation_queue_create(
4035        device,
4036        presentation_queue_target,
4037        presentation_queue
4038    );
4039
4040    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4041        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
4042        if (ret == VDP_STATUS_OK) {
4043            if (presentation_queue) {
4044                fprintf(_vdp_cap_data.fp, ", %u", *presentation_queue);
4045            }
4046            else {
4047                fputs(", ???", _vdp_cap_data.fp);
4048            }
4049        }
4050        fputs("\n", _vdp_cap_data.fp);
4051    }
4052
4053    return ret;
4054}
4055
4056static VdpStatus _vdp_cap_presentation_queue_destroy(
4057    VdpPresentationQueue presentation_queue
4058)
4059{
4060    VdpStatus ret;
4061
4062    fputs("vdp_presentation_queue_destroy(", _vdp_cap_data.fp);
4063    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4064        fprintf(
4065            _vdp_cap_data.fp,
4066            "%u",
4067            presentation_queue
4068        );
4069    }
4070    fputs(")\n", _vdp_cap_data.fp);
4071
4072    ret = _vdp_cap_data.vdp_presentation_queue_destroy(
4073        presentation_queue
4074    );
4075
4076    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4077        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
4078    }
4079
4080    return ret;
4081}
4082
4083static VdpStatus _vdp_cap_presentation_queue_set_background_color(
4084    VdpPresentationQueue presentation_queue,
4085    VdpColor * const     background_color
4086)
4087{
4088    VdpStatus ret;
4089
4090    fputs("vdp_presentation_queue_set_background_color(", _vdp_cap_data.fp);
4091    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4092        fprintf(
4093            _vdp_cap_data.fp,
4094            "%u, ",
4095            presentation_queue
4096        );
4097        _vdp_cap_dump_color(background_color);
4098    }
4099    fputs(")\n", _vdp_cap_data.fp);
4100
4101    ret = _vdp_cap_data.vdp_presentation_queue_set_background_color(
4102        presentation_queue,
4103        background_color
4104    );
4105
4106    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4107        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
4108    }
4109
4110    return ret;
4111}
4112
4113static VdpStatus _vdp_cap_presentation_queue_get_background_color(
4114    VdpPresentationQueue presentation_queue,
4115    VdpColor *           background_color
4116)
4117{
4118    VdpStatus ret;
4119
4120    fputs("vdp_presentation_queue_get_background_color(", _vdp_cap_data.fp);
4121    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4122        fprintf(
4123            _vdp_cap_data.fp,
4124            "%u, %s",
4125            presentation_queue,
4126            background_color ? "-" : "NULL"
4127        );
4128    }
4129    fputs(")\n", _vdp_cap_data.fp);
4130
4131    ret = _vdp_cap_data.vdp_presentation_queue_get_background_color(
4132        presentation_queue,
4133        background_color
4134    );
4135
4136    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4137        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
4138        if (ret == VDP_STATUS_OK) {
4139            fputs(", ", _vdp_cap_data.fp);
4140            _vdp_cap_dump_color(background_color);
4141        }
4142        fputs("\n", _vdp_cap_data.fp);
4143    }
4144
4145    return ret;
4146}
4147
4148static VdpStatus _vdp_cap_presentation_queue_get_time(
4149    VdpPresentationQueue presentation_queue,
4150    /* output parameters follow */
4151    VdpTime *            current_time
4152)
4153{
4154    VdpStatus ret;
4155
4156    fputs("vdp_presentation_queue_get_time(", _vdp_cap_data.fp);
4157    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4158        fprintf(
4159            _vdp_cap_data.fp,
4160            "%u, %s",
4161            presentation_queue,
4162            current_time ? "-" : "NULL"
4163        );
4164    }
4165    fputs(")\n", _vdp_cap_data.fp);
4166
4167    ret = _vdp_cap_data.vdp_presentation_queue_get_time(
4168        presentation_queue,
4169        current_time
4170    );
4171
4172    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4173        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
4174        if (ret == VDP_STATUS_OK) {
4175            if (current_time) {
4176                fprintf(_vdp_cap_data.fp, ", %" PRIu64, *current_time);
4177            }
4178            else {
4179                fputs(", ???", _vdp_cap_data.fp);
4180            }
4181        }
4182        fputs("\n", _vdp_cap_data.fp);
4183    }
4184
4185    return ret;
4186}
4187
4188static VdpStatus _vdp_cap_presentation_queue_display(
4189    VdpPresentationQueue presentation_queue,
4190    VdpOutputSurface     surface,
4191    uint32_t             clip_width,
4192    uint32_t             clip_height,
4193    VdpTime              earliest_presentation_time
4194)
4195{
4196    VdpStatus ret;
4197
4198    fputs("vdp_presentation_queue_display(", _vdp_cap_data.fp);
4199    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4200        fprintf(
4201            _vdp_cap_data.fp,
4202            "%u, %u, %u, %u, %" PRIu64,
4203            presentation_queue,
4204            surface,
4205            clip_width,
4206            clip_height,
4207            earliest_presentation_time
4208        );
4209    }
4210    fputs(")\n", _vdp_cap_data.fp);
4211
4212    ret = _vdp_cap_data.vdp_presentation_queue_display(
4213        presentation_queue,
4214        surface,
4215        clip_width,
4216        clip_height,
4217        earliest_presentation_time
4218    );
4219
4220    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4221        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
4222    }
4223
4224    return ret;
4225}
4226
4227static VdpStatus _vdp_cap_presentation_queue_block_until_surface_idle(
4228    VdpPresentationQueue presentation_queue,
4229    VdpOutputSurface     surface,
4230    /* output parameters follow */
4231    VdpTime *            first_presentation_time
4232)
4233{
4234    VdpStatus ret;
4235
4236    fputs("vdp_presentation_queue_block_until_surface_idle(", _vdp_cap_data.fp);
4237    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4238        fprintf(
4239            _vdp_cap_data.fp,
4240            "%u, %u, %s",
4241            presentation_queue,
4242            surface,
4243            first_presentation_time ? "-" : "NULL"
4244        );
4245    }
4246    fputs(")\n", _vdp_cap_data.fp);
4247
4248    ret = _vdp_cap_data.vdp_presentation_queue_block_until_surface_idle(
4249        presentation_queue,
4250        surface,
4251        first_presentation_time
4252    );
4253
4254    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4255        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
4256        if (ret == VDP_STATUS_OK) {
4257            if (first_presentation_time) {
4258                fprintf(_vdp_cap_data.fp, ", %" PRIu64, *first_presentation_time);
4259            }
4260            else {
4261                fputs(", ???", _vdp_cap_data.fp);
4262            }
4263        }
4264        fputs("\n", _vdp_cap_data.fp);
4265    }
4266
4267    return ret;
4268}
4269
4270static VdpStatus _vdp_cap_presentation_queue_query_surface_status(
4271    VdpPresentationQueue         presentation_queue,
4272    VdpOutputSurface             surface,
4273    /* output parameters follow */
4274    VdpPresentationQueueStatus * status,
4275    VdpTime *                    first_presentation_time
4276)
4277{
4278    VdpStatus ret;
4279
4280    fputs("vdp_presentation_queue_query_surface_status(", _vdp_cap_data.fp);
4281    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4282        fprintf(
4283            _vdp_cap_data.fp,
4284            "%u, %u, %s, %s",
4285            presentation_queue,
4286            surface,
4287            status ? "-" : "NULL",
4288            first_presentation_time ? "-" : "NULL"
4289        );
4290    }
4291    fputs(")\n", _vdp_cap_data.fp);
4292
4293    ret = _vdp_cap_data.vdp_presentation_queue_query_surface_status(
4294        presentation_queue,
4295        surface,
4296        status,
4297        first_presentation_time
4298    );
4299
4300    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4301        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
4302        if (ret == VDP_STATUS_OK) {
4303            if (status) {
4304                fprintf(_vdp_cap_data.fp, ", %d", *status);
4305            }
4306            else {
4307                fputs(", ???", _vdp_cap_data.fp);
4308            }
4309            if (first_presentation_time) {
4310                fprintf(_vdp_cap_data.fp, ", %" PRIu64, *first_presentation_time);
4311            }
4312            else {
4313                fputs(", ???", _vdp_cap_data.fp);
4314            }
4315        }
4316        fputs("\n", _vdp_cap_data.fp);
4317    }
4318
4319    return ret;
4320}
4321
4322static VdpStatus _vdp_cap_preemption_callback_register(
4323    VdpDevice             device,
4324    VdpPreemptionCallback callback,
4325    void *                context
4326)
4327{
4328    VdpStatus ret;
4329
4330    fputs("vdp_preemption_callback_register(", _vdp_cap_data.fp);
4331    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4332        fprintf(
4333            _vdp_cap_data.fp,
4334            "%u, %p, %p",
4335            device,
4336            callback,
4337            context
4338        );
4339    }
4340    fputs(")\n", _vdp_cap_data.fp);
4341
4342    ret = _vdp_cap_data.vdp_preemption_callback_register(
4343        device,
4344        callback,
4345        context
4346    );
4347
4348    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4349        fprintf(_vdp_cap_data.fp, "    -> %d\n", ret);
4350    }
4351
4352    return ret;
4353}
4354
4355static VdpStatus _vdp_cap_presentation_queue_target_create_x11(
4356    VdpDevice                    device,
4357    Drawable                     drawable,
4358    /* output parameters follow */
4359    VdpPresentationQueueTarget * target
4360)
4361{
4362    VdpStatus ret;
4363
4364    fprintf(_vdp_cap_data.fp, "vdp_presentation_queue_target_create_x11(");
4365    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4366        fprintf(
4367            _vdp_cap_data.fp,
4368            "%u, %lu, %s",
4369            device,
4370            drawable,
4371            target ? "-" : "NULL"
4372        );
4373    }
4374    fputs(")\n", _vdp_cap_data.fp);
4375
4376    ret = _vdp_cap_data.vdp_presentation_queue_target_create_x11(
4377        device,
4378        drawable,
4379        target
4380    );
4381
4382    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4383        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
4384        if (ret == VDP_STATUS_OK) {
4385            if (target) {
4386                fprintf(_vdp_cap_data.fp, ", %u", *target);
4387            }
4388            else {
4389                fputs(", ???", _vdp_cap_data.fp);
4390            }
4391        }
4392        fputs("\n", _vdp_cap_data.fp);
4393    }
4394
4395    return ret;
4396}
4397
4398static VdpStatus _vdp_cap_get_proc_address(
4399    VdpDevice device,
4400    VdpFuncId function_id,
4401    /* output parameters follow */
4402    void * *  function_pointer
4403)
4404{
4405    VdpStatus ret;
4406
4407    fputs("vdp_get_proc_address(", _vdp_cap_data.fp);
4408    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4409        fprintf(
4410            _vdp_cap_data.fp,
4411            "%u, %u, %s",
4412            device,
4413            function_id,
4414            function_pointer ? "-" : "NULL"
4415        );
4416    }
4417    fputs(")\n", _vdp_cap_data.fp);
4418
4419    if (device != _vdp_cap_data.vdp_device) {
4420        _VDP_TRACE_ERROR_BREAKPOINT();
4421        ret =  VDP_STATUS_ERROR;
4422    }
4423    else if (!function_pointer) {
4424        _VDP_TRACE_ERROR_BREAKPOINT();
4425        ret =  VDP_STATUS_ERROR;
4426    }
4427    else {
4428        ret = VDP_STATUS_OK;
4429        *function_pointer = 0;
4430
4431        switch (function_id) {
4432        case VDP_FUNC_ID_GET_ERROR_STRING:
4433            if (_vdp_cap_data.vdp_get_error_string) {
4434                *function_pointer = (void *)&_vdp_cap_get_error_string;
4435            }
4436            break;
4437        case VDP_FUNC_ID_GET_PROC_ADDRESS:
4438            if (_vdp_cap_data.vdp_get_proc_address) {
4439                *function_pointer = (void *)&_vdp_cap_get_proc_address;
4440            }
4441            break;
4442        case VDP_FUNC_ID_GET_API_VERSION:
4443            if (_vdp_cap_data.vdp_get_api_version) {
4444                *function_pointer = (void *)&_vdp_cap_get_api_version;
4445            }
4446            break;
4447        case VDP_FUNC_ID_GET_INFORMATION_STRING:
4448            if (_vdp_cap_data.vdp_get_information_string) {
4449                *function_pointer = (void *)&_vdp_cap_get_information_string;
4450            }
4451            break;
4452        case VDP_FUNC_ID_DEVICE_DESTROY:
4453            if (_vdp_cap_data.vdp_device_destroy) {
4454                *function_pointer = (void *)&_vdp_cap_device_destroy;
4455            }
4456            break;
4457        case VDP_FUNC_ID_GENERATE_CSC_MATRIX:
4458            if (_vdp_cap_data.vdp_generate_csc_matrix) {
4459                *function_pointer = (void *)&_vdp_cap_generate_csc_matrix;
4460            }
4461            break;
4462        case VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES:
4463            if (_vdp_cap_data.vdp_video_surface_query_capabilities) {
4464                *function_pointer = (void *)&_vdp_cap_video_surface_query_capabilities;
4465            }
4466            break;
4467        case VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES:
4468            if (_vdp_cap_data.vdp_video_surface_query_get_put_bits_y_cb_cr_capabilities) {
4469                *function_pointer = (void *)&_vdp_cap_video_surface_query_get_put_bits_y_cb_cr_capabilities;
4470            }
4471            break;
4472        case VDP_FUNC_ID_VIDEO_SURFACE_CREATE:
4473            if (_vdp_cap_data.vdp_video_surface_create) {
4474                *function_pointer = (void *)&_vdp_cap_video_surface_create;
4475            }
4476            break;
4477        case VDP_FUNC_ID_VIDEO_SURFACE_DESTROY:
4478            if (_vdp_cap_data.vdp_video_surface_destroy) {
4479                *function_pointer = (void *)&_vdp_cap_video_surface_destroy;
4480            }
4481            break;
4482        case VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS:
4483            if (_vdp_cap_data.vdp_video_surface_get_parameters) {
4484                *function_pointer = (void *)&_vdp_cap_video_surface_get_parameters;
4485            }
4486            break;
4487        case VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR:
4488            if (_vdp_cap_data.vdp_video_surface_get_bits_y_cb_cr) {
4489                *function_pointer = (void *)&_vdp_cap_video_surface_get_bits_y_cb_cr;
4490            }
4491            break;
4492        case VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR:
4493            if (_vdp_cap_data.vdp_video_surface_put_bits_y_cb_cr) {
4494                *function_pointer = (void *)&_vdp_cap_video_surface_put_bits_y_cb_cr;
4495            }
4496            break;
4497        case VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_CAPABILITIES:
4498            if (_vdp_cap_data.vdp_output_surface_query_capabilities) {
4499                *function_pointer = (void *)&_vdp_cap_output_surface_query_capabilities;
4500            }
4501            break;
4502        case VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_GET_PUT_BITS_NATIVE_CAPABILITIES:
4503            if (_vdp_cap_data.vdp_output_surface_query_get_put_bits_native_capabilities) {
4504                *function_pointer = (void *)&_vdp_cap_output_surface_query_get_put_bits_native_capabilities;
4505            }
4506            break;
4507        case VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_PUT_BITS_INDEXED_CAPABILITIES:
4508            if (_vdp_cap_data.vdp_output_surface_query_put_bits_indexed_capabilities) {
4509                *function_pointer = (void *)&_vdp_cap_output_surface_query_put_bits_indexed_capabilities;
4510            }
4511            break;
4512        case VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_PUT_BITS_Y_CB_CR_CAPABILITIES:
4513            if (_vdp_cap_data.vdp_output_surface_query_put_bits_y_cb_cr_capabilities) {
4514                *function_pointer = (void *)&_vdp_cap_output_surface_query_put_bits_y_cb_cr_capabilities;
4515            }
4516            break;
4517        case VDP_FUNC_ID_OUTPUT_SURFACE_CREATE:
4518            if (_vdp_cap_data.vdp_output_surface_create) {
4519                *function_pointer = (void *)&_vdp_cap_output_surface_create;
4520            }
4521            break;
4522        case VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY:
4523            if (_vdp_cap_data.vdp_output_surface_destroy) {
4524                *function_pointer = (void *)&_vdp_cap_output_surface_destroy;
4525            }
4526            break;
4527        case VDP_FUNC_ID_OUTPUT_SURFACE_GET_PARAMETERS:
4528            if (_vdp_cap_data.vdp_output_surface_get_parameters) {
4529                *function_pointer = (void *)&_vdp_cap_output_surface_get_parameters;
4530            }
4531            break;
4532        case VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE:
4533            if (_vdp_cap_data.vdp_output_surface_get_bits_native) {
4534                *function_pointer = (void *)&_vdp_cap_output_surface_get_bits_native;
4535            }
4536            break;
4537        case VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE:
4538            if (_vdp_cap_data.vdp_output_surface_put_bits_native) {
4539                *function_pointer = (void *)&_vdp_cap_output_surface_put_bits_native;
4540            }
4541            break;
4542        case VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_INDEXED:
4543            if (_vdp_cap_data.vdp_output_surface_put_bits_indexed) {
4544                *function_pointer = (void *)&_vdp_cap_output_surface_put_bits_indexed;
4545            }
4546            break;
4547        case VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_Y_CB_CR:
4548            if (_vdp_cap_data.vdp_output_surface_put_bits_y_cb_cr) {
4549                *function_pointer = (void *)&_vdp_cap_output_surface_put_bits_y_cb_cr;
4550            }
4551            break;
4552        case VDP_FUNC_ID_BITMAP_SURFACE_QUERY_CAPABILITIES:
4553            if (_vdp_cap_data.vdp_bitmap_surface_query_capabilities) {
4554                *function_pointer = (void *)&_vdp_cap_bitmap_surface_query_capabilities;
4555            }
4556            break;
4557        case VDP_FUNC_ID_BITMAP_SURFACE_CREATE:
4558            if (_vdp_cap_data.vdp_bitmap_surface_create) {
4559                *function_pointer = (void *)&_vdp_cap_bitmap_surface_create;
4560            }
4561            break;
4562        case VDP_FUNC_ID_BITMAP_SURFACE_DESTROY:
4563            if (_vdp_cap_data.vdp_bitmap_surface_destroy) {
4564                *function_pointer = (void *)&_vdp_cap_bitmap_surface_destroy;
4565            }
4566            break;
4567        case VDP_FUNC_ID_BITMAP_SURFACE_GET_PARAMETERS:
4568            if (_vdp_cap_data.vdp_bitmap_surface_get_parameters) {
4569                *function_pointer = (void *)&_vdp_cap_bitmap_surface_get_parameters;
4570            }
4571            break;
4572        case VDP_FUNC_ID_BITMAP_SURFACE_PUT_BITS_NATIVE:
4573            if (_vdp_cap_data.vdp_bitmap_surface_put_bits_native) {
4574                *function_pointer = (void *)&_vdp_cap_bitmap_surface_put_bits_native;
4575            }
4576            break;
4577        case VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE:
4578            if (_vdp_cap_data.vdp_output_surface_render_output_surface) {
4579                *function_pointer = (void *)&_vdp_cap_output_surface_render_output_surface;
4580            }
4581            break;
4582        case VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_BITMAP_SURFACE:
4583            if (_vdp_cap_data.vdp_output_surface_render_bitmap_surface) {
4584                *function_pointer = (void *)&_vdp_cap_output_surface_render_bitmap_surface;
4585            }
4586            break;
4587        case VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES:
4588            if (_vdp_cap_data.vdp_decoder_query_capabilities) {
4589                *function_pointer = (void *)&_vdp_cap_decoder_query_capabilities;
4590            }
4591            break;
4592        case VDP_FUNC_ID_DECODER_CREATE:
4593            if (_vdp_cap_data.vdp_decoder_create) {
4594                *function_pointer = (void *)&_vdp_cap_decoder_create;
4595            }
4596            break;
4597        case VDP_FUNC_ID_DECODER_DESTROY:
4598            if (_vdp_cap_data.vdp_decoder_destroy) {
4599                *function_pointer = (void *)&_vdp_cap_decoder_destroy;
4600            }
4601            break;
4602        case VDP_FUNC_ID_DECODER_GET_PARAMETERS:
4603            if (_vdp_cap_data.vdp_decoder_get_parameters) {
4604                *function_pointer = (void *)&_vdp_cap_decoder_get_parameters;
4605            }
4606            break;
4607        case VDP_FUNC_ID_DECODER_RENDER:
4608            if (_vdp_cap_data.vdp_decoder_render) {
4609                *function_pointer = (void *)&_vdp_cap_decoder_render;
4610            }
4611            break;
4612        case VDP_FUNC_ID_VIDEO_MIXER_QUERY_FEATURE_SUPPORT:
4613            if (_vdp_cap_data.vdp_video_mixer_query_feature_support) {
4614                *function_pointer = (void *)&_vdp_cap_video_mixer_query_feature_support;
4615            }
4616            break;
4617        case VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_SUPPORT:
4618            if (_vdp_cap_data.vdp_video_mixer_query_parameter_support) {
4619                *function_pointer = (void *)&_vdp_cap_video_mixer_query_parameter_support;
4620            }
4621            break;
4622        case VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_SUPPORT:
4623            if (_vdp_cap_data.vdp_video_mixer_query_attribute_support) {
4624                *function_pointer = (void *)&_vdp_cap_video_mixer_query_attribute_support;
4625            }
4626            break;
4627        case VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_VALUE_RANGE:
4628            if (_vdp_cap_data.vdp_video_mixer_query_parameter_value_range) {
4629                *function_pointer = (void *)&_vdp_cap_video_mixer_query_parameter_value_range;
4630            }
4631            break;
4632        case VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_VALUE_RANGE:
4633            if (_vdp_cap_data.vdp_video_mixer_query_attribute_value_range) {
4634                *function_pointer = (void *)&_vdp_cap_video_mixer_query_attribute_value_range;
4635            }
4636            break;
4637        case VDP_FUNC_ID_VIDEO_MIXER_CREATE:
4638            if (_vdp_cap_data.vdp_video_mixer_create) {
4639                *function_pointer = (void *)&_vdp_cap_video_mixer_create;
4640            }
4641            break;
4642        case VDP_FUNC_ID_VIDEO_MIXER_SET_FEATURE_ENABLES:
4643            if (_vdp_cap_data.vdp_video_mixer_set_feature_enables) {
4644                *function_pointer = (void *)&_vdp_cap_video_mixer_set_feature_enables;
4645            }
4646            break;
4647        case VDP_FUNC_ID_VIDEO_MIXER_SET_ATTRIBUTE_VALUES:
4648            if (_vdp_cap_data.vdp_video_mixer_set_attribute_values) {
4649                *function_pointer = (void *)&_vdp_cap_video_mixer_set_attribute_values;
4650            }
4651            break;
4652        case VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_SUPPORT:
4653            if (_vdp_cap_data.vdp_video_mixer_get_feature_support) {
4654                *function_pointer = (void *)&_vdp_cap_video_mixer_get_feature_support;
4655            }
4656            break;
4657        case VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_ENABLES:
4658            if (_vdp_cap_data.vdp_video_mixer_get_feature_enables) {
4659                *function_pointer = (void *)&_vdp_cap_video_mixer_get_feature_enables;
4660            }
4661            break;
4662        case VDP_FUNC_ID_VIDEO_MIXER_GET_PARAMETER_VALUES:
4663            if (_vdp_cap_data.vdp_video_mixer_get_parameter_values) {
4664                *function_pointer = (void *)&_vdp_cap_video_mixer_get_parameter_values;
4665            }
4666            break;
4667        case VDP_FUNC_ID_VIDEO_MIXER_GET_ATTRIBUTE_VALUES:
4668            if (_vdp_cap_data.vdp_video_mixer_get_attribute_values) {
4669                *function_pointer = (void *)&_vdp_cap_video_mixer_get_attribute_values;
4670            }
4671            break;
4672        case VDP_FUNC_ID_VIDEO_MIXER_DESTROY:
4673            if (_vdp_cap_data.vdp_video_mixer_destroy) {
4674                *function_pointer = (void *)&_vdp_cap_video_mixer_destroy;
4675            }
4676            break;
4677        case VDP_FUNC_ID_VIDEO_MIXER_RENDER:
4678            if (_vdp_cap_data.vdp_video_mixer_render) {
4679                *function_pointer = (void *)&_vdp_cap_video_mixer_render;
4680            }
4681            break;
4682        case VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_DESTROY:
4683            if (_vdp_cap_data.vdp_presentation_queue_target_destroy) {
4684                *function_pointer = (void *)&_vdp_cap_presentation_queue_target_destroy;
4685            }
4686            break;
4687        case VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE:
4688            if (_vdp_cap_data.vdp_presentation_queue_create) {
4689                *function_pointer = (void *)&_vdp_cap_presentation_queue_create;
4690            }
4691            break;
4692        case VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY:
4693            if (_vdp_cap_data.vdp_presentation_queue_destroy) {
4694                *function_pointer = (void *)&_vdp_cap_presentation_queue_destroy;
4695            }
4696            break;
4697        case VDP_FUNC_ID_PRESENTATION_QUEUE_SET_BACKGROUND_COLOR:
4698            if (_vdp_cap_data.vdp_presentation_queue_set_background_color) {
4699                *function_pointer = (void *)&_vdp_cap_presentation_queue_set_background_color;
4700            }
4701            break;
4702        case VDP_FUNC_ID_PRESENTATION_QUEUE_GET_BACKGROUND_COLOR:
4703            if (_vdp_cap_data.vdp_presentation_queue_get_background_color) {
4704                *function_pointer = (void *)&_vdp_cap_presentation_queue_get_background_color;
4705            }
4706            break;
4707        case VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME:
4708            if (_vdp_cap_data.vdp_presentation_queue_get_time) {
4709                *function_pointer = (void *)&_vdp_cap_presentation_queue_get_time;
4710            }
4711            break;
4712        case VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY:
4713            if (_vdp_cap_data.vdp_presentation_queue_display) {
4714                *function_pointer = (void *)&_vdp_cap_presentation_queue_display;
4715            }
4716            break;
4717        case VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE:
4718            if (_vdp_cap_data.vdp_presentation_queue_block_until_surface_idle) {
4719                *function_pointer = (void *)&_vdp_cap_presentation_queue_block_until_surface_idle;
4720            }
4721            break;
4722        case VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS:
4723            if (_vdp_cap_data.vdp_presentation_queue_query_surface_status) {
4724                *function_pointer = (void *)&_vdp_cap_presentation_queue_query_surface_status;
4725            }
4726            break;
4727        case VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER:
4728            if (_vdp_cap_data.vdp_preemption_callback_register) {
4729                *function_pointer = (void *)&_vdp_cap_preemption_callback_register;
4730            }
4731            break;
4732        case VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11:
4733            if (_vdp_cap_data.vdp_presentation_queue_target_create_x11) {
4734                *function_pointer = (void *)&_vdp_cap_presentation_queue_target_create_x11;
4735            }
4736            break;
4737        default:
4738            fprintf(
4739                _vdp_cap_data.fp,
4740                "VDPAU capture: Not able to proxy function %d",
4741                function_id
4742            );
4743            ret = _vdp_cap_data.vdp_get_proc_address(device, function_id, function_pointer);
4744            break;
4745        }
4746
4747        if ((ret == VDP_STATUS_OK) && !*function_pointer) {
4748            ret = VDP_STATUS_INVALID_FUNC_ID;
4749        }
4750    }
4751
4752    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4753        fprintf(_vdp_cap_data.fp, "    -> %d", ret);
4754        if (ret == VDP_STATUS_OK) {
4755            fprintf(
4756                _vdp_cap_data.fp,
4757                ", %p",
4758                *function_pointer
4759            );
4760        }
4761        fputs("\n", _vdp_cap_data.fp);
4762    }
4763
4764    return ret;
4765}
4766
4767extern "C" void vdp_trace_set_backend_handle(
4768    void * driver_dll_handle
4769)
4770{
4771    _vdp_cap_data.dll = driver_dll_handle;
4772}
4773
4774extern "C" VdpDeviceCreateX11 vdp_trace_device_create_x11;
4775
4776VdpStatus vdp_trace_device_create_x11(
4777    Display *             display,
4778    int                   screen,
4779    /* output parameters follow */
4780    VdpDevice *           device,
4781    VdpGetProcAddress * * get_proc_address
4782)
4783{
4784    if (!device || !get_proc_address) {
4785        _VDP_TRACE_ERROR_BREAKPOINT();
4786        return VDP_STATUS_INVALID_POINTER;
4787    }
4788
4789    // For now, the capture library only allows a single VdpDevice
4790    // This could probably be fixed by dynamically associating most of
4791    // _vdp_cap_data with a VdpDevice handle.
4792    if (_vdp_cap_data.fp) {
4793        fprintf(_vdp_cap_data.fp,
4794            "VDPAU trace: Multiple devices created; "
4795            "will return get_proc_address results from the latest only\n"
4796        );
4797    }
4798    else {
4799        _vdp_cap_data.level = 0;
4800        char const * vdpau_trace = secure_getenv("VDPAU_TRACE");
4801        if (vdpau_trace) {
4802            _vdp_cap_data.level = atoi(vdpau_trace);
4803        }
4804
4805        _vdp_cap_data.fp = 0;
4806        char const * vdpau_trace_file = secure_getenv("VDPAU_TRACE_FILE");
4807        if (vdpau_trace_file && strlen(vdpau_trace_file)) {
4808            if (vdpau_trace_file[0] == '&') {
4809                int fd = atoi(&vdpau_trace_file[1]);
4810                _vdp_cap_data.fp = fdopen(fd, "wt");
4811            }
4812            else {
4813                _vdp_cap_data.fp = fopen(vdpau_trace_file, "wt");
4814            }
4815            if (!_vdp_cap_data.fp) {
4816                fprintf(
4817                    stderr,
4818                    "VDPAU capture: ERROR: Can't open '%s' for writing, defaulting to stderr\n",
4819                    vdpau_trace_file
4820                );
4821            }
4822        }
4823        if (!_vdp_cap_data.fp) {
4824            _vdp_cap_data.fp = stderr;
4825        }
4826        fprintf(_vdp_cap_data.fp, "VDPAU capture: Enabled\n");
4827    }
4828
4829    fprintf(_vdp_cap_data.fp, "vdp_imp_device_create_x11(");
4830    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4831        fprintf(
4832            _vdp_cap_data.fp,
4833            "%p, %d, -, -",
4834            display,
4835            screen
4836        );
4837    }
4838    fputs(")\n", _vdp_cap_data.fp);
4839
4840    VdpStatus vdp_st = VDP_STATUS_ERROR;
4841
4842    VdpDeviceCreateX11 * vdp_imp_device_create_x11;
4843    vdp_imp_device_create_x11 = (VdpDeviceCreateX11*)dlsym(
4844        _vdp_cap_data.dll,
4845         "vdp_imp_device_create_x11"
4846    );
4847    if (!vdp_imp_device_create_x11) {
4848        _VDP_TRACE_ERROR_BREAKPOINT();
4849        vdp_st = VDP_STATUS_NO_IMPLEMENTATION;
4850        goto done;
4851    }
4852
4853    vdp_st = vdp_imp_device_create_x11(
4854        display,
4855        screen,
4856        &_vdp_cap_data.vdp_device,
4857        &_vdp_cap_data.vdp_get_proc_address
4858    );
4859    if (vdp_st != VDP_STATUS_OK) {
4860        _VDP_TRACE_ERROR_BREAKPOINT();
4861        goto done;
4862    }
4863
4864    *device = _vdp_cap_data.vdp_device;
4865    *get_proc_address = _vdp_cap_get_proc_address;
4866
4867#define GET_POINTER(_id_, _var_) \
4868    vdp_st = _vdp_cap_data.vdp_get_proc_address( \
4869        _vdp_cap_data.vdp_device, \
4870        (_id_), \
4871        (void * *)&_vdp_cap_data._var_ \
4872    ); \
4873    if (vdp_st != VDP_STATUS_OK) { \
4874        _vdp_cap_data._var_ = 0; \
4875    }
4876
4877    GET_POINTER(VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER,                          vdp_preemption_callback_register);
4878    GET_POINTER(VDP_FUNC_ID_GET_ERROR_STRING,                                      vdp_get_error_string);
4879    GET_POINTER(VDP_FUNC_ID_GET_API_VERSION,                                       vdp_get_api_version);
4880    GET_POINTER(VDP_FUNC_ID_GET_INFORMATION_STRING,                                vdp_get_information_string);
4881    GET_POINTER(VDP_FUNC_ID_DEVICE_DESTROY,                                        vdp_device_destroy);
4882    GET_POINTER(VDP_FUNC_ID_GENERATE_CSC_MATRIX,                                   vdp_generate_csc_matrix);
4883    GET_POINTER(VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES,                      vdp_video_surface_query_capabilities);
4884    GET_POINTER(VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES, vdp_video_surface_query_get_put_bits_y_cb_cr_capabilities);
4885    GET_POINTER(VDP_FUNC_ID_VIDEO_SURFACE_CREATE,                                  vdp_video_surface_create);
4886    GET_POINTER(VDP_FUNC_ID_VIDEO_SURFACE_DESTROY,                                 vdp_video_surface_destroy);
4887    GET_POINTER(VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS,                          vdp_video_surface_get_parameters);
4888    GET_POINTER(VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR,                        vdp_video_surface_get_bits_y_cb_cr);
4889    GET_POINTER(VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR,                        vdp_video_surface_put_bits_y_cb_cr);
4890    GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_CAPABILITIES,                     vdp_output_surface_query_capabilities);
4891    GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_GET_PUT_BITS_NATIVE_CAPABILITIES, vdp_output_surface_query_get_put_bits_native_capabilities);
4892    GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_PUT_BITS_INDEXED_CAPABILITIES,    vdp_output_surface_query_put_bits_indexed_capabilities);
4893    GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_PUT_BITS_Y_CB_CR_CAPABILITIES,    vdp_output_surface_query_put_bits_y_cb_cr_capabilities);
4894    GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_CREATE,                                 vdp_output_surface_create);
4895    GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY,                                vdp_output_surface_destroy);
4896    GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_GET_PARAMETERS,                         vdp_output_surface_get_parameters);
4897    GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE,                        vdp_output_surface_get_bits_native);
4898    GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE,                        vdp_output_surface_put_bits_native);
4899    GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_INDEXED,                       vdp_output_surface_put_bits_indexed);
4900    GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_Y_CB_CR,                       vdp_output_surface_put_bits_y_cb_cr);
4901    GET_POINTER(VDP_FUNC_ID_BITMAP_SURFACE_QUERY_CAPABILITIES,                     vdp_bitmap_surface_query_capabilities);
4902    GET_POINTER(VDP_FUNC_ID_BITMAP_SURFACE_CREATE,                                 vdp_bitmap_surface_create);
4903    GET_POINTER(VDP_FUNC_ID_BITMAP_SURFACE_DESTROY,                                vdp_bitmap_surface_destroy);
4904    GET_POINTER(VDP_FUNC_ID_BITMAP_SURFACE_GET_PARAMETERS,                         vdp_bitmap_surface_get_parameters);
4905    GET_POINTER(VDP_FUNC_ID_BITMAP_SURFACE_PUT_BITS_NATIVE,                        vdp_bitmap_surface_put_bits_native);
4906    GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE,                  vdp_output_surface_render_output_surface);
4907    GET_POINTER(VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_BITMAP_SURFACE,                  vdp_output_surface_render_bitmap_surface);
4908    GET_POINTER(VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES,                            vdp_decoder_query_capabilities);
4909    GET_POINTER(VDP_FUNC_ID_DECODER_CREATE,                                        vdp_decoder_create);
4910    GET_POINTER(VDP_FUNC_ID_DECODER_DESTROY,                                       vdp_decoder_destroy);
4911    GET_POINTER(VDP_FUNC_ID_DECODER_GET_PARAMETERS,                                vdp_decoder_get_parameters);
4912    GET_POINTER(VDP_FUNC_ID_DECODER_RENDER,                                        vdp_decoder_render);
4913    GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_QUERY_FEATURE_SUPPORT,                     vdp_video_mixer_query_feature_support);
4914    GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_SUPPORT,                   vdp_video_mixer_query_parameter_support);
4915    GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_SUPPORT,                   vdp_video_mixer_query_attribute_support);
4916    GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_VALUE_RANGE,               vdp_video_mixer_query_parameter_value_range);
4917    GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_VALUE_RANGE,               vdp_video_mixer_query_attribute_value_range);
4918    GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_CREATE,                                    vdp_video_mixer_create);
4919    GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_SET_FEATURE_ENABLES,                       vdp_video_mixer_set_feature_enables);
4920    GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_SET_ATTRIBUTE_VALUES,                      vdp_video_mixer_set_attribute_values);
4921    GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_SUPPORT,                       vdp_video_mixer_get_feature_support);
4922    GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_ENABLES,                       vdp_video_mixer_get_feature_enables);
4923    GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_GET_PARAMETER_VALUES,                      vdp_video_mixer_get_parameter_values);
4924    GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_GET_ATTRIBUTE_VALUES,                      vdp_video_mixer_get_attribute_values);
4925    GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_DESTROY,                                   vdp_video_mixer_destroy);
4926    GET_POINTER(VDP_FUNC_ID_VIDEO_MIXER_RENDER,                                    vdp_video_mixer_render);
4927    GET_POINTER(VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_DESTROY,                     vdp_presentation_queue_target_destroy);
4928    GET_POINTER(VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE,                             vdp_presentation_queue_create);
4929    GET_POINTER(VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY,                            vdp_presentation_queue_destroy);
4930    GET_POINTER(VDP_FUNC_ID_PRESENTATION_QUEUE_SET_BACKGROUND_COLOR,               vdp_presentation_queue_set_background_color);
4931    GET_POINTER(VDP_FUNC_ID_PRESENTATION_QUEUE_GET_BACKGROUND_COLOR,               vdp_presentation_queue_get_background_color);
4932    GET_POINTER(VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME,                           vdp_presentation_queue_get_time);
4933    GET_POINTER(VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY,                            vdp_presentation_queue_display);
4934    GET_POINTER(VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE,           vdp_presentation_queue_block_until_surface_idle);
4935    GET_POINTER(VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS,               vdp_presentation_queue_query_surface_status);
4936    GET_POINTER(VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER,                          vdp_preemption_callback_register);
4937    GET_POINTER(VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11,                  vdp_presentation_queue_target_create_x11);
4938
4939    vdp_st = VDP_STATUS_OK;
4940
4941done:
4942    if (_vdp_cap_data.level >= LEVEL_PARAMS) {
4943        fprintf(_vdp_cap_data.fp, "    -> %d", vdp_st);
4944        if (vdp_st == VDP_STATUS_OK) {
4945            fprintf(
4946                _vdp_cap_data.fp,
4947                ", %x, %p",
4948                _vdp_cap_data.vdp_device,
4949                _vdp_cap_data.vdp_get_proc_address
4950            );
4951        }
4952        fputs("\n", _vdp_cap_data.fp);
4953    }
4954
4955    return vdp_st;
4956}
4957
4958