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 TUNGSTEN GRAPHICS 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_level;
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    pipe_mutex_lock(dev->mutex);
86 
87    /* XXX: Current limits */
88    *is_supported = true;
89    max_2d_texture_level = pscreen->get_param(pscreen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS);
90    pipe_mutex_unlock(dev->mutex);
91    if (!max_2d_texture_level)
92       return VDP_STATUS_RESOURCES;
93 
94    /* I am not quite sure if it is max_2d_texture_level-1 or just max_2d_texture_level */
95    *max_width = *max_height = pow(2,max_2d_texture_level-1);
96 
97    return VDP_STATUS_OK;
98 }
99 
100 /**
101  * Query the implementation's VdpVideoSurface GetBits/PutBits capabilities.
102  */
103 VdpStatus
vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities(VdpDevice device,VdpChromaType surface_chroma_type,VdpYCbCrFormat bits_ycbcr_format,VdpBool * is_supported)104 vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities(VdpDevice device, VdpChromaType surface_chroma_type,
105                                                   VdpYCbCrFormat bits_ycbcr_format,
106                                                   VdpBool *is_supported)
107 {
108    vlVdpDevice *dev;
109    struct pipe_screen *pscreen;
110 
111    if (!is_supported)
112       return VDP_STATUS_INVALID_POINTER;
113 
114    dev = vlGetDataHTAB(device);
115    if (!dev)
116       return VDP_STATUS_INVALID_HANDLE;
117 
118    pscreen = dev->vscreen->pscreen;
119    if (!pscreen)
120       return VDP_STATUS_RESOURCES;
121 
122    pipe_mutex_lock(dev->mutex);
123 
124    switch(bits_ycbcr_format) {
125    case VDP_YCBCR_FORMAT_UYVY:
126    case VDP_YCBCR_FORMAT_YUYV:
127       *is_supported = surface_chroma_type == VDP_CHROMA_TYPE_422;
128       break;
129 
130    case VDP_YCBCR_FORMAT_Y8U8V8A8:
131    case VDP_YCBCR_FORMAT_V8U8Y8A8:
132       *is_supported = surface_chroma_type == VDP_CHROMA_TYPE_444;
133       break;
134 
135    default:
136       *is_supported = true;
137       break;
138    }
139 
140    *is_supported &= pscreen->is_video_format_supported
141    (
142       pscreen,
143       FormatYCBCRToPipe(bits_ycbcr_format),
144       PIPE_VIDEO_PROFILE_UNKNOWN
145    );
146    pipe_mutex_unlock(dev->mutex);
147 
148    return VDP_STATUS_OK;
149 }
150 
151 /**
152  * Query the implementation's VdpDecoder capabilities.
153  */
154 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)155 vlVdpDecoderQueryCapabilities(VdpDevice device, VdpDecoderProfile profile,
156                               VdpBool *is_supported, uint32_t *max_level, uint32_t *max_macroblocks,
157                               uint32_t *max_width, uint32_t *max_height)
158 {
159    vlVdpDevice *dev;
160    struct pipe_screen *pscreen;
161    enum pipe_video_profile p_profile;
162 
163    if (!(is_supported && max_level && max_macroblocks && max_width && max_height))
164       return VDP_STATUS_INVALID_POINTER;
165 
166    dev = vlGetDataHTAB(device);
167    if (!dev)
168       return VDP_STATUS_INVALID_HANDLE;
169 
170    pscreen = dev->vscreen->pscreen;
171    if (!pscreen)
172       return VDP_STATUS_RESOURCES;
173 
174    p_profile = ProfileToPipe(profile);
175    if (p_profile == PIPE_VIDEO_PROFILE_UNKNOWN)	{
176       *is_supported = false;
177       return VDP_STATUS_OK;
178    }
179 
180    pipe_mutex_lock(dev->mutex);
181    *is_supported = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_CAP_SUPPORTED);
182    if (*is_supported) {
183       *max_width = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_CAP_MAX_WIDTH);
184       *max_height = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_CAP_MAX_HEIGHT);
185       *max_level = 16;
186       *max_macroblocks = (*max_width/16)*(*max_height/16);
187    } else {
188       *max_width = 0;
189       *max_height = 0;
190       *max_level = 0;
191       *max_macroblocks = 0;
192    }
193    pipe_mutex_unlock(dev->mutex);
194 
195    return VDP_STATUS_OK;
196 }
197 
198 /**
199  * Query the implementation's VdpOutputSurface capabilities.
200  */
201 VdpStatus
vlVdpOutputSurfaceQueryCapabilities(VdpDevice device,VdpRGBAFormat surface_rgba_format,VdpBool * is_supported,uint32_t * max_width,uint32_t * max_height)202 vlVdpOutputSurfaceQueryCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format,
203                                     VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height)
204 {
205    vlVdpDevice *dev;
206    struct pipe_screen *pscreen;
207    enum pipe_format format;
208 
209    dev = vlGetDataHTAB(device);
210    if (!dev)
211       return VDP_STATUS_INVALID_HANDLE;
212 
213    pscreen = dev->vscreen->pscreen;
214    if (!pscreen)
215       return VDP_STATUS_RESOURCES;
216 
217    format = FormatRGBAToPipe(surface_rgba_format);
218    if (format == PIPE_FORMAT_NONE || format == PIPE_FORMAT_A8_UNORM)
219       return VDP_STATUS_INVALID_RGBA_FORMAT;
220 
221    if (!(is_supported && max_width && max_height))
222       return VDP_STATUS_INVALID_POINTER;
223 
224    pipe_mutex_lock(dev->mutex);
225    *is_supported = pscreen->is_format_supported
226    (
227       pscreen, format, PIPE_TEXTURE_3D, 1,
228       PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET
229    );
230    if (*is_supported) {
231       uint32_t max_2d_texture_level = pscreen->get_param(
232          pscreen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS);
233 
234       if (!max_2d_texture_level) {
235          pipe_mutex_unlock(dev->mutex);
236          return VDP_STATUS_ERROR;
237       }
238 
239       *max_width = *max_height = pow(2, max_2d_texture_level - 1);
240    } else {
241       *max_width = 0;
242       *max_height = 0;
243    }
244    pipe_mutex_unlock(dev->mutex);
245 
246    return VDP_STATUS_OK;
247 }
248 
249 /**
250  * Query the implementation's capability to perform a PutBits operation using
251  * application data matching the surface's format.
252  */
253 VdpStatus
vlVdpOutputSurfaceQueryGetPutBitsNativeCapabilities(VdpDevice device,VdpRGBAFormat surface_rgba_format,VdpBool * is_supported)254 vlVdpOutputSurfaceQueryGetPutBitsNativeCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format,
255                                                     VdpBool *is_supported)
256 {
257    vlVdpDevice *dev;
258    struct pipe_screen *pscreen;
259    enum pipe_format format;
260 
261    dev = vlGetDataHTAB(device);
262    if (!dev)
263       return VDP_STATUS_INVALID_HANDLE;
264 
265    pscreen = dev->vscreen->pscreen;
266    if (!pscreen)
267       return VDP_STATUS_ERROR;
268 
269    format = FormatRGBAToPipe(surface_rgba_format);
270    if (format == PIPE_FORMAT_NONE || format == PIPE_FORMAT_A8_UNORM)
271       return VDP_STATUS_INVALID_RGBA_FORMAT;
272 
273    if (!is_supported)
274       return VDP_STATUS_INVALID_POINTER;
275 
276    pipe_mutex_lock(dev->mutex);
277    *is_supported = pscreen->is_format_supported
278    (
279       pscreen, format, PIPE_TEXTURE_2D, 1,
280       PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET
281    );
282    pipe_mutex_unlock(dev->mutex);
283 
284    return VDP_STATUS_OK;
285 }
286 
287 /**
288  * Query the implementation's capability to perform a PutBits operation using
289  * application data in a specific indexed format.
290  */
291 VdpStatus
vlVdpOutputSurfaceQueryPutBitsIndexedCapabilities(VdpDevice device,VdpRGBAFormat surface_rgba_format,VdpIndexedFormat bits_indexed_format,VdpColorTableFormat color_table_format,VdpBool * is_supported)292 vlVdpOutputSurfaceQueryPutBitsIndexedCapabilities(VdpDevice device,
293                                                   VdpRGBAFormat surface_rgba_format,
294                                                   VdpIndexedFormat bits_indexed_format,
295                                                   VdpColorTableFormat color_table_format,
296                                                   VdpBool *is_supported)
297 {
298    vlVdpDevice *dev;
299    struct pipe_screen *pscreen;
300    enum pipe_format rgba_format, index_format, colortbl_format;
301 
302    dev = vlGetDataHTAB(device);
303    if (!dev)
304       return VDP_STATUS_INVALID_HANDLE;
305 
306    pscreen = dev->vscreen->pscreen;
307    if (!pscreen)
308       return VDP_STATUS_ERROR;
309 
310    rgba_format = FormatRGBAToPipe(surface_rgba_format);
311    if (rgba_format == PIPE_FORMAT_NONE || rgba_format == PIPE_FORMAT_A8_UNORM)
312       return VDP_STATUS_INVALID_RGBA_FORMAT;
313 
314    index_format = FormatIndexedToPipe(bits_indexed_format);
315    if (index_format == PIPE_FORMAT_NONE)
316        return VDP_STATUS_INVALID_INDEXED_FORMAT;
317 
318    colortbl_format = FormatColorTableToPipe(color_table_format);
319    if (colortbl_format == PIPE_FORMAT_NONE)
320        return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT;
321 
322    if (!is_supported)
323       return VDP_STATUS_INVALID_POINTER;
324 
325    pipe_mutex_lock(dev->mutex);
326    *is_supported = pscreen->is_format_supported
327    (
328       pscreen, rgba_format, PIPE_TEXTURE_2D, 1,
329       PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET
330    );
331 
332    *is_supported &= pscreen->is_format_supported
333    (
334       pscreen, index_format, PIPE_TEXTURE_2D, 1,
335       PIPE_BIND_SAMPLER_VIEW
336    );
337 
338    *is_supported &= pscreen->is_format_supported
339    (
340       pscreen, colortbl_format, PIPE_TEXTURE_1D, 1,
341       PIPE_BIND_SAMPLER_VIEW
342    );
343    pipe_mutex_unlock(dev->mutex);
344 
345    return VDP_STATUS_OK;
346 }
347 
348 /**
349  * Query the implementation's capability to perform a PutBits operation using
350  * application data in a specific YCbCr/YUB format.
351  */
352 VdpStatus
vlVdpOutputSurfaceQueryPutBitsYCbCrCapabilities(VdpDevice device,VdpRGBAFormat surface_rgba_format,VdpYCbCrFormat bits_ycbcr_format,VdpBool * is_supported)353 vlVdpOutputSurfaceQueryPutBitsYCbCrCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format,
354                                                 VdpYCbCrFormat bits_ycbcr_format,
355                                                 VdpBool *is_supported)
356 {
357    vlVdpDevice *dev;
358    struct pipe_screen *pscreen;
359    enum pipe_format rgba_format, ycbcr_format;
360 
361    dev = vlGetDataHTAB(device);
362    if (!dev)
363       return VDP_STATUS_INVALID_HANDLE;
364 
365    pscreen = dev->vscreen->pscreen;
366    if (!pscreen)
367       return VDP_STATUS_ERROR;
368 
369    rgba_format = FormatRGBAToPipe(surface_rgba_format);
370    if (rgba_format == PIPE_FORMAT_NONE || rgba_format == PIPE_FORMAT_A8_UNORM)
371       return VDP_STATUS_INVALID_RGBA_FORMAT;
372 
373    ycbcr_format = FormatYCBCRToPipe(bits_ycbcr_format);
374    if (ycbcr_format == PIPE_FORMAT_NONE)
375        return VDP_STATUS_INVALID_INDEXED_FORMAT;
376 
377    if (!is_supported)
378       return VDP_STATUS_INVALID_POINTER;
379 
380    pipe_mutex_lock(dev->mutex);
381    *is_supported = pscreen->is_format_supported
382    (
383       pscreen, rgba_format, PIPE_TEXTURE_2D, 1,
384       PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET
385    );
386 
387    *is_supported &= pscreen->is_video_format_supported
388    (
389       pscreen, ycbcr_format,
390       PIPE_VIDEO_PROFILE_UNKNOWN
391    );
392    pipe_mutex_unlock(dev->mutex);
393 
394    return VDP_STATUS_OK;
395 }
396 
397 /**
398  * Query the implementation's VdpBitmapSurface capabilities.
399  */
400 VdpStatus
vlVdpBitmapSurfaceQueryCapabilities(VdpDevice device,VdpRGBAFormat surface_rgba_format,VdpBool * is_supported,uint32_t * max_width,uint32_t * max_height)401 vlVdpBitmapSurfaceQueryCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format,
402                                     VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height)
403 {
404    vlVdpDevice *dev;
405    struct pipe_screen *pscreen;
406    enum pipe_format format;
407 
408    dev = vlGetDataHTAB(device);
409    if (!dev)
410       return VDP_STATUS_INVALID_HANDLE;
411 
412    pscreen = dev->vscreen->pscreen;
413    if (!pscreen)
414       return VDP_STATUS_RESOURCES;
415 
416    format = FormatRGBAToPipe(surface_rgba_format);
417    if (format == PIPE_FORMAT_NONE)
418       return VDP_STATUS_INVALID_RGBA_FORMAT;
419 
420    if (!(is_supported && max_width && max_height))
421       return VDP_STATUS_INVALID_POINTER;
422 
423    pipe_mutex_lock(dev->mutex);
424    *is_supported = pscreen->is_format_supported
425    (
426       pscreen, format, PIPE_TEXTURE_3D, 1,
427       PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET
428    );
429    if (*is_supported) {
430       uint32_t max_2d_texture_level = pscreen->get_param(
431          pscreen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS);
432 
433       if (!max_2d_texture_level) {
434          pipe_mutex_unlock(dev->mutex);
435          return VDP_STATUS_ERROR;
436       }
437 
438       *max_width = *max_height = pow(2, max_2d_texture_level - 1);
439    } else {
440       *max_width = 0;
441       *max_height = 0;
442    }
443    pipe_mutex_unlock(dev->mutex);
444 
445    return VDP_STATUS_OK;
446 }
447 
448 /**
449  * Query the implementation's support for a specific feature.
450  */
451 VdpStatus
vlVdpVideoMixerQueryFeatureSupport(VdpDevice device,VdpVideoMixerFeature feature,VdpBool * is_supported)452 vlVdpVideoMixerQueryFeatureSupport(VdpDevice device, VdpVideoMixerFeature feature,
453                                    VdpBool *is_supported)
454 {
455    if (!is_supported)
456       return VDP_STATUS_INVALID_POINTER;
457 
458    switch (feature) {
459    case VDP_VIDEO_MIXER_FEATURE_SHARPNESS:
460    case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION:
461       *is_supported = VDP_TRUE;
462       break;
463    default:
464       *is_supported = VDP_FALSE;
465       break;
466    }
467    return VDP_STATUS_OK;
468 }
469 
470 /**
471  * Query the implementation's support for a specific parameter.
472  */
473 VdpStatus
vlVdpVideoMixerQueryParameterSupport(VdpDevice device,VdpVideoMixerParameter parameter,VdpBool * is_supported)474 vlVdpVideoMixerQueryParameterSupport(VdpDevice device, VdpVideoMixerParameter parameter,
475                                      VdpBool *is_supported)
476 {
477    if (!is_supported)
478       return VDP_STATUS_INVALID_POINTER;
479 
480    switch (parameter) {
481    case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH:
482    case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT:
483    case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE:
484    case VDP_VIDEO_MIXER_PARAMETER_LAYERS:
485       *is_supported = VDP_TRUE;
486       break;
487    default:
488       *is_supported = VDP_FALSE;
489       break;
490    }
491    return VDP_STATUS_OK;
492 }
493 
494 /**
495  * Query the implementation's supported for a specific parameter.
496  */
497 VdpStatus
vlVdpVideoMixerQueryParameterValueRange(VdpDevice device,VdpVideoMixerParameter parameter,void * min_value,void * max_value)498 vlVdpVideoMixerQueryParameterValueRange(VdpDevice device, VdpVideoMixerParameter parameter,
499                                         void *min_value, void *max_value)
500 {
501    vlVdpDevice *dev = vlGetDataHTAB(device);
502    struct pipe_screen *screen;
503    enum pipe_video_profile prof = PIPE_VIDEO_PROFILE_UNKNOWN;
504 
505    if (!dev)
506       return VDP_STATUS_INVALID_HANDLE;
507    if (!(min_value && max_value))
508       return VDP_STATUS_INVALID_POINTER;
509 
510    pipe_mutex_lock(dev->mutex);
511    screen = dev->vscreen->pscreen;
512    switch (parameter) {
513    case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH:
514       *(uint32_t*)min_value = 48;
515       *(uint32_t*)max_value = screen->get_video_param(screen, prof, PIPE_VIDEO_CAP_MAX_WIDTH);
516       break;
517    case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT:
518       *(uint32_t*)min_value = 48;
519       *(uint32_t*)max_value = screen->get_video_param(screen, prof, PIPE_VIDEO_CAP_MAX_HEIGHT);
520       break;
521 
522    case VDP_VIDEO_MIXER_PARAMETER_LAYERS:
523       *(uint32_t*)min_value = 0;
524       *(uint32_t*)max_value = 4;
525       break;
526 
527    case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE:
528    default:
529       pipe_mutex_unlock(dev->mutex);
530       return VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER;
531    }
532    pipe_mutex_unlock(dev->mutex);
533    return VDP_STATUS_OK;
534 }
535 
536 /**
537  * Query the implementation's support for a specific attribute.
538  */
539 VdpStatus
vlVdpVideoMixerQueryAttributeSupport(VdpDevice device,VdpVideoMixerAttribute attribute,VdpBool * is_supported)540 vlVdpVideoMixerQueryAttributeSupport(VdpDevice device, VdpVideoMixerAttribute attribute,
541                                      VdpBool *is_supported)
542 {
543    if (!is_supported)
544       return VDP_STATUS_INVALID_POINTER;
545 
546    switch (attribute) {
547    case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR:
548    case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX:
549    case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL:
550    case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL:
551    case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA:
552    case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA:
553    case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE:
554       *is_supported = VDP_TRUE;
555       break;
556    default:
557       *is_supported = VDP_FALSE;
558    }
559    return VDP_STATUS_OK;
560 }
561 
562 /**
563  * Query the implementation's supported for a specific attribute.
564  */
565 VdpStatus
vlVdpVideoMixerQueryAttributeValueRange(VdpDevice device,VdpVideoMixerAttribute attribute,void * min_value,void * max_value)566 vlVdpVideoMixerQueryAttributeValueRange(VdpDevice device, VdpVideoMixerAttribute attribute,
567                                         void *min_value, void *max_value)
568 {
569    if (!(min_value && max_value))
570       return VDP_STATUS_INVALID_POINTER;
571 
572    switch (attribute) {
573    case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL:
574    case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA:
575    case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA:
576       *(float*)min_value = 0.f;
577       *(float*)max_value = 1.f;
578       break;
579    case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL:
580       *(float*)min_value = -1.f;
581       *(float*)max_value = 1.f;
582       break;
583    case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE:
584       *(uint8_t*)min_value = 0;
585       *(uint8_t*)max_value = 1;
586       break;
587    case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR:
588    case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX:
589    default:
590       return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE;
591    }
592    return VDP_STATUS_OK;
593 }
594