Home | History | Annotate | Download | only in vdpau
      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
     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
     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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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