1 /**************************************************************************
2  *
3  * Copyright 2010 Younes Manton.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 
28 #include <assert.h>
29 #include <math.h>
30 
31 #include "vdpau_private.h"
32 #include "pipe/p_screen.h"
33 #include "pipe/p_defines.h"
34 #include "util/u_debug.h"
35 
36 /**
37  * Retrieve the VDPAU version implemented by the backend.
38  */
39 VdpStatus
vlVdpGetApiVersion(uint32_t * api_version)40 vlVdpGetApiVersion(uint32_t *api_version)
41 {
42    if (!api_version)
43       return VDP_STATUS_INVALID_POINTER;
44 
45    *api_version = 1;
46    return VDP_STATUS_OK;
47 }
48 
49 /**
50  * Retrieve an implementation-specific string description of the implementation.
51  * This typically includes detailed version information.
52  */
53 VdpStatus
vlVdpGetInformationString(char const ** information_string)54 vlVdpGetInformationString(char const **information_string)
55 {
56    if (!information_string)
57       return VDP_STATUS_INVALID_POINTER;
58 
59    *information_string = INFORMATION_STRING;
60    return VDP_STATUS_OK;
61 }
62 
63 /**
64  * Query the implementation's VdpVideoSurface capabilities.
65  */
66 VdpStatus
vlVdpVideoSurfaceQueryCapabilities(VdpDevice device,VdpChromaType surface_chroma_type,VdpBool * is_supported,uint32_t * max_width,uint32_t * max_height)67 vlVdpVideoSurfaceQueryCapabilities(VdpDevice device, VdpChromaType surface_chroma_type,
68                                    VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height)
69 {
70    vlVdpDevice *dev;
71    struct pipe_screen *pscreen;
72    uint32_t max_2d_texture_size;
73 
74    if (!(is_supported && max_width && max_height))
75       return VDP_STATUS_INVALID_POINTER;
76 
77    dev = vlGetDataHTAB(device);
78    if (!dev)
79       return VDP_STATUS_INVALID_HANDLE;
80 
81    pscreen = dev->vscreen->pscreen;
82    if (!pscreen)
83       return VDP_STATUS_RESOURCES;
84 
85    mtx_lock(&dev->mutex);
86 
87    /* XXX: Current limits */
88    *is_supported = true;
89    max_2d_texture_size = pscreen->get_param(pscreen, PIPE_CAP_MAX_TEXTURE_2D_SIZE);
90    mtx_unlock(&dev->mutex);
91    if (!max_2d_texture_size)
92       return VDP_STATUS_RESOURCES;
93 
94    *max_width = *max_height = max_2d_texture_size;
95 
96    return VDP_STATUS_OK;
97 }
98 
99 /**
100  * Query the implementation's VdpVideoSurface GetBits/PutBits capabilities.
101  */
102 VdpStatus
vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities(VdpDevice device,VdpChromaType surface_chroma_type,VdpYCbCrFormat bits_ycbcr_format,VdpBool * is_supported)103 vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities(VdpDevice device, VdpChromaType surface_chroma_type,
104                                                   VdpYCbCrFormat bits_ycbcr_format,
105                                                   VdpBool *is_supported)
106 {
107    vlVdpDevice *dev;
108    struct pipe_screen *pscreen;
109 
110    if (!is_supported)
111       return VDP_STATUS_INVALID_POINTER;
112 
113    dev = vlGetDataHTAB(device);
114    if (!dev)
115       return VDP_STATUS_INVALID_HANDLE;
116 
117    pscreen = dev->vscreen->pscreen;
118    if (!pscreen)
119       return VDP_STATUS_RESOURCES;
120 
121    mtx_lock(&dev->mutex);
122 
123    switch(bits_ycbcr_format) {
124    case VDP_YCBCR_FORMAT_NV12:
125       *is_supported = surface_chroma_type == VDP_CHROMA_TYPE_420;
126       break;
127 
128    case VDP_YCBCR_FORMAT_YV12:
129       *is_supported = surface_chroma_type == VDP_CHROMA_TYPE_420;
130 
131       /* We can convert YV12 to NV12 on the fly! */
132       if (*is_supported &&
133           pscreen->is_video_format_supported(pscreen,
134                                              PIPE_FORMAT_NV12,
135                                              PIPE_VIDEO_PROFILE_UNKNOWN,
136                                              PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) {
137          mtx_unlock(&dev->mutex);
138          return VDP_STATUS_OK;
139       }
140       break;
141 
142    case VDP_YCBCR_FORMAT_UYVY:
143    case VDP_YCBCR_FORMAT_YUYV:
144       *is_supported = surface_chroma_type == VDP_CHROMA_TYPE_422;
145       break;
146 
147    case VDP_YCBCR_FORMAT_Y8U8V8A8:
148    case VDP_YCBCR_FORMAT_V8U8Y8A8:
149       *is_supported = surface_chroma_type == VDP_CHROMA_TYPE_444;
150       break;
151 
152    default:
153       *is_supported = false;
154       break;
155    }
156 
157    if (*is_supported &&
158        !pscreen->is_video_format_supported(pscreen,
159                                            FormatYCBCRToPipe(bits_ycbcr_format),
160                                            PIPE_VIDEO_PROFILE_UNKNOWN,
161                                            PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) {
162       *is_supported = false;
163    }
164    mtx_unlock(&dev->mutex);
165 
166    return VDP_STATUS_OK;
167 }
168 
169 /**
170  * Query the implementation's VdpDecoder capabilities.
171  */
172 VdpStatus
vlVdpDecoderQueryCapabilities(VdpDevice device,VdpDecoderProfile profile,VdpBool * is_supported,uint32_t * max_level,uint32_t * max_macroblocks,uint32_t * max_width,uint32_t * max_height)173 vlVdpDecoderQueryCapabilities(VdpDevice device, VdpDecoderProfile profile,
174                               VdpBool *is_supported, uint32_t *max_level, uint32_t *max_macroblocks,
175                               uint32_t *max_width, uint32_t *max_height)
176 {
177    vlVdpDevice *dev;
178    struct pipe_screen *pscreen;
179    enum pipe_video_profile p_profile;
180 
181    if (!(is_supported && max_level && max_macroblocks && max_width && max_height))
182       return VDP_STATUS_INVALID_POINTER;
183 
184    dev = vlGetDataHTAB(device);
185    if (!dev)
186       return VDP_STATUS_INVALID_HANDLE;
187 
188    pscreen = dev->vscreen->pscreen;
189    if (!pscreen)
190       return VDP_STATUS_RESOURCES;
191 
192    p_profile = ProfileToPipe(profile);
193    if (p_profile == PIPE_VIDEO_PROFILE_UNKNOWN)	{
194       *is_supported = false;
195       return VDP_STATUS_OK;
196    }
197 
198    mtx_lock(&dev->mutex);
199    *is_supported = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
200                                             PIPE_VIDEO_CAP_SUPPORTED);
201    if (*is_supported) {
202       *max_width = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
203                                             PIPE_VIDEO_CAP_MAX_WIDTH);
204       *max_height = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
205                                              PIPE_VIDEO_CAP_MAX_HEIGHT);
206       *max_level = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
207                                             PIPE_VIDEO_CAP_MAX_LEVEL);
208       *max_macroblocks = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
209                                             PIPE_VIDEO_CAP_MAX_MACROBLOCKS);
210       if (*max_macroblocks == 0) {
211          *max_macroblocks = (*max_width/16)*(*max_height/16);
212       }
213    } else {
214       *max_width = 0;
215       *max_height = 0;
216       *max_level = 0;
217       *max_macroblocks = 0;
218    }
219    mtx_unlock(&dev->mutex);
220 
221    return VDP_STATUS_OK;
222 }
223 
224 /**
225  * Query the implementation's VdpOutputSurface capabilities.
226  */
227 VdpStatus
vlVdpOutputSurfaceQueryCapabilities(VdpDevice device,VdpRGBAFormat surface_rgba_format,VdpBool * is_supported,uint32_t * max_width,uint32_t * max_height)228 vlVdpOutputSurfaceQueryCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format,
229                                     VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height)
230 {
231    vlVdpDevice *dev;
232    struct pipe_screen *pscreen;
233    enum pipe_format format;
234 
235    dev = vlGetDataHTAB(device);
236    if (!dev)
237       return VDP_STATUS_INVALID_HANDLE;
238 
239    pscreen = dev->vscreen->pscreen;
240    if (!pscreen)
241       return VDP_STATUS_RESOURCES;
242 
243    format = VdpFormatRGBAToPipe(surface_rgba_format);
244    if (format == PIPE_FORMAT_NONE || format == PIPE_FORMAT_A8_UNORM)
245       return VDP_STATUS_INVALID_RGBA_FORMAT;
246 
247    if (!(is_supported && max_width && max_height))
248       return VDP_STATUS_INVALID_POINTER;
249 
250    mtx_lock(&dev->mutex);
251    *is_supported = pscreen->is_format_supported
252    (
253       pscreen, format, PIPE_TEXTURE_2D, 1, 1,
254       PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET
255    );
256    if (*is_supported) {
257       uint32_t max_2d_texture_size = pscreen->get_param(
258          pscreen, PIPE_CAP_MAX_TEXTURE_2D_SIZE);
259 
260       if (!max_2d_texture_size) {
261          mtx_unlock(&dev->mutex);
262          return VDP_STATUS_ERROR;
263       }
264 
265       *max_width = *max_height = max_2d_texture_size;
266    } else {
267       *max_width = 0;
268       *max_height = 0;
269    }
270    mtx_unlock(&dev->mutex);
271 
272    return VDP_STATUS_OK;
273 }
274 
275 /**
276  * Query the implementation's capability to perform a PutBits operation using
277  * application data matching the surface's format.
278  */
279 VdpStatus
vlVdpOutputSurfaceQueryGetPutBitsNativeCapabilities(VdpDevice device,VdpRGBAFormat surface_rgba_format,VdpBool * is_supported)280 vlVdpOutputSurfaceQueryGetPutBitsNativeCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format,
281                                                     VdpBool *is_supported)
282 {
283    vlVdpDevice *dev;
284    struct pipe_screen *pscreen;
285    enum pipe_format format;
286 
287    dev = vlGetDataHTAB(device);
288    if (!dev)
289       return VDP_STATUS_INVALID_HANDLE;
290 
291    pscreen = dev->vscreen->pscreen;
292    if (!pscreen)
293       return VDP_STATUS_ERROR;
294 
295    format = VdpFormatRGBAToPipe(surface_rgba_format);
296    if (format == PIPE_FORMAT_NONE || format == PIPE_FORMAT_A8_UNORM)
297       return VDP_STATUS_INVALID_RGBA_FORMAT;
298 
299    if (!is_supported)
300       return VDP_STATUS_INVALID_POINTER;
301 
302    mtx_lock(&dev->mutex);
303    *is_supported = pscreen->is_format_supported
304    (
305       pscreen, format, PIPE_TEXTURE_2D, 1, 1,
306       PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET
307    );
308    mtx_unlock(&dev->mutex);
309 
310    return VDP_STATUS_OK;
311 }
312 
313 /**
314  * Query the implementation's capability to perform a PutBits operation using
315  * application data in a specific indexed format.
316  */
317 VdpStatus
vlVdpOutputSurfaceQueryPutBitsIndexedCapabilities(VdpDevice device,VdpRGBAFormat surface_rgba_format,VdpIndexedFormat bits_indexed_format,VdpColorTableFormat color_table_format,VdpBool * is_supported)318 vlVdpOutputSurfaceQueryPutBitsIndexedCapabilities(VdpDevice device,
319                                                   VdpRGBAFormat surface_rgba_format,
320                                                   VdpIndexedFormat bits_indexed_format,
321                                                   VdpColorTableFormat color_table_format,
322                                                   VdpBool *is_supported)
323 {
324    vlVdpDevice *dev;
325    struct pipe_screen *pscreen;
326    enum pipe_format rgba_format, index_format, colortbl_format;
327 
328    dev = vlGetDataHTAB(device);
329    if (!dev)
330       return VDP_STATUS_INVALID_HANDLE;
331 
332    pscreen = dev->vscreen->pscreen;
333    if (!pscreen)
334       return VDP_STATUS_ERROR;
335 
336    rgba_format = VdpFormatRGBAToPipe(surface_rgba_format);
337    if (rgba_format == PIPE_FORMAT_NONE || rgba_format == PIPE_FORMAT_A8_UNORM)
338       return VDP_STATUS_INVALID_RGBA_FORMAT;
339 
340    index_format = FormatIndexedToPipe(bits_indexed_format);
341    if (index_format == PIPE_FORMAT_NONE)
342        return VDP_STATUS_INVALID_INDEXED_FORMAT;
343 
344    colortbl_format = FormatColorTableToPipe(color_table_format);
345    if (colortbl_format == PIPE_FORMAT_NONE)
346        return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT;
347 
348    if (!is_supported)
349       return VDP_STATUS_INVALID_POINTER;
350 
351    mtx_lock(&dev->mutex);
352    *is_supported = pscreen->is_format_supported
353    (
354       pscreen, rgba_format, PIPE_TEXTURE_2D, 1, 1,
355       PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET
356    );
357 
358    *is_supported &= pscreen->is_format_supported
359    (
360       pscreen, index_format, PIPE_TEXTURE_2D, 1, 1,
361       PIPE_BIND_SAMPLER_VIEW
362    );
363 
364    *is_supported &= pscreen->is_format_supported
365    (
366       pscreen, colortbl_format, PIPE_TEXTURE_1D, 1, 1,
367       PIPE_BIND_SAMPLER_VIEW
368    );
369    mtx_unlock(&dev->mutex);
370 
371    return VDP_STATUS_OK;
372 }
373 
374 /**
375  * Query the implementation's capability to perform a PutBits operation using
376  * application data in a specific YCbCr/YUB format.
377  */
378 VdpStatus
vlVdpOutputSurfaceQueryPutBitsYCbCrCapabilities(VdpDevice device,VdpRGBAFormat surface_rgba_format,VdpYCbCrFormat bits_ycbcr_format,VdpBool * is_supported)379 vlVdpOutputSurfaceQueryPutBitsYCbCrCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format,
380                                                 VdpYCbCrFormat bits_ycbcr_format,
381                                                 VdpBool *is_supported)
382 {
383    vlVdpDevice *dev;
384    struct pipe_screen *pscreen;
385    enum pipe_format rgba_format, ycbcr_format;
386 
387    dev = vlGetDataHTAB(device);
388    if (!dev)
389       return VDP_STATUS_INVALID_HANDLE;
390 
391    pscreen = dev->vscreen->pscreen;
392    if (!pscreen)
393       return VDP_STATUS_ERROR;
394 
395    rgba_format = VdpFormatRGBAToPipe(surface_rgba_format);
396    if (rgba_format == PIPE_FORMAT_NONE || rgba_format == PIPE_FORMAT_A8_UNORM)
397       return VDP_STATUS_INVALID_RGBA_FORMAT;
398 
399    ycbcr_format = FormatYCBCRToPipe(bits_ycbcr_format);
400    if (ycbcr_format == PIPE_FORMAT_NONE)
401        return VDP_STATUS_INVALID_INDEXED_FORMAT;
402 
403    if (!is_supported)
404       return VDP_STATUS_INVALID_POINTER;
405 
406    mtx_lock(&dev->mutex);
407    *is_supported = pscreen->is_format_supported
408    (
409       pscreen, rgba_format, PIPE_TEXTURE_2D, 1, 1,
410       PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET
411    );
412 
413    *is_supported &= pscreen->is_video_format_supported
414    (
415       pscreen, ycbcr_format,
416       PIPE_VIDEO_PROFILE_UNKNOWN,
417       PIPE_VIDEO_ENTRYPOINT_BITSTREAM
418    );
419    mtx_unlock(&dev->mutex);
420 
421    return VDP_STATUS_OK;
422 }
423 
424 /**
425  * Query the implementation's VdpBitmapSurface capabilities.
426  */
427 VdpStatus
vlVdpBitmapSurfaceQueryCapabilities(VdpDevice device,VdpRGBAFormat surface_rgba_format,VdpBool * is_supported,uint32_t * max_width,uint32_t * max_height)428 vlVdpBitmapSurfaceQueryCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format,
429                                     VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height)
430 {
431    vlVdpDevice *dev;
432    struct pipe_screen *pscreen;
433    enum pipe_format format;
434 
435    dev = vlGetDataHTAB(device);
436    if (!dev)
437       return VDP_STATUS_INVALID_HANDLE;
438 
439    pscreen = dev->vscreen->pscreen;
440    if (!pscreen)
441       return VDP_STATUS_RESOURCES;
442 
443    format = VdpFormatRGBAToPipe(surface_rgba_format);
444    if (format == PIPE_FORMAT_NONE)
445       return VDP_STATUS_INVALID_RGBA_FORMAT;
446 
447    if (!(is_supported && max_width && max_height))
448       return VDP_STATUS_INVALID_POINTER;
449 
450    mtx_lock(&dev->mutex);
451    *is_supported = pscreen->is_format_supported
452    (
453       pscreen, format, PIPE_TEXTURE_2D, 1, 1,
454       PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET
455    );
456    if (*is_supported) {
457       uint32_t max_2d_texture_size = pscreen->get_param(
458          pscreen, PIPE_CAP_MAX_TEXTURE_2D_SIZE);
459 
460       if (!max_2d_texture_size) {
461          mtx_unlock(&dev->mutex);
462          return VDP_STATUS_ERROR;
463       }
464 
465       *max_width = *max_height = max_2d_texture_size;
466    } else {
467       *max_width = 0;
468       *max_height = 0;
469    }
470    mtx_unlock(&dev->mutex);
471 
472    return VDP_STATUS_OK;
473 }
474 
475 /**
476  * Query the implementation's support for a specific feature.
477  */
478 VdpStatus
vlVdpVideoMixerQueryFeatureSupport(VdpDevice device,VdpVideoMixerFeature feature,VdpBool * is_supported)479 vlVdpVideoMixerQueryFeatureSupport(VdpDevice device, VdpVideoMixerFeature feature,
480                                    VdpBool *is_supported)
481 {
482    if (!is_supported)
483       return VDP_STATUS_INVALID_POINTER;
484 
485    switch (feature) {
486    case VDP_VIDEO_MIXER_FEATURE_SHARPNESS:
487    case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION:
488    case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL:
489    case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY:
490    case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1:
491       *is_supported = VDP_TRUE;
492       break;
493    default:
494       *is_supported = VDP_FALSE;
495       break;
496    }
497    return VDP_STATUS_OK;
498 }
499 
500 /**
501  * Query the implementation's support for a specific parameter.
502  */
503 VdpStatus
vlVdpVideoMixerQueryParameterSupport(VdpDevice device,VdpVideoMixerParameter parameter,VdpBool * is_supported)504 vlVdpVideoMixerQueryParameterSupport(VdpDevice device, VdpVideoMixerParameter parameter,
505                                      VdpBool *is_supported)
506 {
507    if (!is_supported)
508       return VDP_STATUS_INVALID_POINTER;
509 
510    switch (parameter) {
511    case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH:
512    case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT:
513    case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE:
514    case VDP_VIDEO_MIXER_PARAMETER_LAYERS:
515       *is_supported = VDP_TRUE;
516       break;
517    default:
518       *is_supported = VDP_FALSE;
519       break;
520    }
521    return VDP_STATUS_OK;
522 }
523 
524 /**
525  * Query the implementation's supported for a specific parameter.
526  */
527 VdpStatus
vlVdpVideoMixerQueryParameterValueRange(VdpDevice device,VdpVideoMixerParameter parameter,void * min_value,void * max_value)528 vlVdpVideoMixerQueryParameterValueRange(VdpDevice device, VdpVideoMixerParameter parameter,
529                                         void *min_value, void *max_value)
530 {
531    vlVdpDevice *dev = vlGetDataHTAB(device);
532    struct pipe_screen *screen;
533 
534    if (!dev)
535       return VDP_STATUS_INVALID_HANDLE;
536    if (!(min_value && max_value))
537       return VDP_STATUS_INVALID_POINTER;
538 
539    mtx_lock(&dev->mutex);
540    screen = dev->vscreen->pscreen;
541    switch (parameter) {
542    case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH:
543       *(uint32_t*)min_value = 48;
544       *(uint32_t*)max_value = screen->get_video_param(screen, PIPE_VIDEO_PROFILE_UNKNOWN,
545                                                       PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
546                                                       PIPE_VIDEO_CAP_MAX_WIDTH);
547       break;
548    case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT:
549       *(uint32_t*)min_value = 48;
550       *(uint32_t*)max_value = screen->get_video_param(screen, PIPE_VIDEO_PROFILE_UNKNOWN,
551                                                       PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
552                                                       PIPE_VIDEO_CAP_MAX_HEIGHT);
553       break;
554 
555    case VDP_VIDEO_MIXER_PARAMETER_LAYERS:
556       *(uint32_t*)min_value = 0;
557       *(uint32_t*)max_value = 4;
558       break;
559 
560    case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE:
561    default:
562       mtx_unlock(&dev->mutex);
563       return VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER;
564    }
565    mtx_unlock(&dev->mutex);
566    return VDP_STATUS_OK;
567 }
568 
569 /**
570  * Query the implementation's support for a specific attribute.
571  */
572 VdpStatus
vlVdpVideoMixerQueryAttributeSupport(VdpDevice device,VdpVideoMixerAttribute attribute,VdpBool * is_supported)573 vlVdpVideoMixerQueryAttributeSupport(VdpDevice device, VdpVideoMixerAttribute attribute,
574                                      VdpBool *is_supported)
575 {
576    if (!is_supported)
577       return VDP_STATUS_INVALID_POINTER;
578 
579    switch (attribute) {
580    case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR:
581    case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX:
582    case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL:
583    case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL:
584    case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA:
585    case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA:
586    case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE:
587       *is_supported = VDP_TRUE;
588       break;
589    default:
590       *is_supported = VDP_FALSE;
591    }
592    return VDP_STATUS_OK;
593 }
594 
595 /**
596  * Query the implementation's supported for a specific attribute.
597  */
598 VdpStatus
vlVdpVideoMixerQueryAttributeValueRange(VdpDevice device,VdpVideoMixerAttribute attribute,void * min_value,void * max_value)599 vlVdpVideoMixerQueryAttributeValueRange(VdpDevice device, VdpVideoMixerAttribute attribute,
600                                         void *min_value, void *max_value)
601 {
602    if (!(min_value && max_value))
603       return VDP_STATUS_INVALID_POINTER;
604 
605    switch (attribute) {
606    case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL:
607    case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA:
608    case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA:
609       *(float*)min_value = 0.0f;
610       *(float*)max_value = 1.0f;
611       break;
612    case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL:
613       *(float*)min_value = -1.0f;
614       *(float*)max_value = 1.0f;
615       break;
616    case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE:
617       *(uint8_t*)min_value = 0;
618       *(uint8_t*)max_value = 1;
619       break;
620    case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR:
621    case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX:
622    default:
623       return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE;
624    }
625    return VDP_STATUS_OK;
626 }
627