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 */
39VdpStatus
40vlVdpGetApiVersion(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 */
53VdpStatus
54vlVdpGetInformationString(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 */
66VdpStatus
67vlVdpVideoSurfaceQueryCapabilities(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 */
102VdpStatus
103vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities(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 */
172VdpStatus
173vlVdpDecoderQueryCapabilities(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 */
227VdpStatus
228vlVdpOutputSurfaceQueryCapabilities(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 */
279VdpStatus
280vlVdpOutputSurfaceQueryGetPutBitsNativeCapabilities(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 */
317VdpStatus
318vlVdpOutputSurfaceQueryPutBitsIndexedCapabilities(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 */
378VdpStatus
379vlVdpOutputSurfaceQueryPutBitsYCbCrCapabilities(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 */
427VdpStatus
428vlVdpBitmapSurfaceQueryCapabilities(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 */
478VdpStatus
479vlVdpVideoMixerQueryFeatureSupport(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 */
503VdpStatus
504vlVdpVideoMixerQueryParameterSupport(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 */
527VdpStatus
528vlVdpVideoMixerQueryParameterValueRange(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 */
572VdpStatus
573vlVdpVideoMixerQueryAttributeSupport(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 */
598VdpStatus
599vlVdpVideoMixerQueryAttributeValueRange(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