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