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