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