17ec681f3Smrg/**************************************************************************
27ec681f3Smrg *
37ec681f3Smrg * Copyright 2010 Younes Manton.
47ec681f3Smrg * All Rights Reserved.
57ec681f3Smrg *
67ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
77ec681f3Smrg * copy of this software and associated documentation files (the
87ec681f3Smrg * "Software"), to deal in the Software without restriction, including
97ec681f3Smrg * without limitation the rights to use, copy, modify, merge, publish,
107ec681f3Smrg * distribute, sub license, and/or sell copies of the Software, and to
117ec681f3Smrg * permit persons to whom the Software is furnished to do so, subject to
127ec681f3Smrg * the following conditions:
137ec681f3Smrg *
147ec681f3Smrg * The above copyright notice and this permission notice (including the
157ec681f3Smrg * next paragraph) shall be included in all copies or substantial portions
167ec681f3Smrg * of the Software.
177ec681f3Smrg *
187ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
197ec681f3Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
207ec681f3Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
217ec681f3Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
227ec681f3Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
237ec681f3Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
247ec681f3Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
257ec681f3Smrg *
267ec681f3Smrg **************************************************************************/
277ec681f3Smrg
287ec681f3Smrg#include <assert.h>
297ec681f3Smrg#include <math.h>
307ec681f3Smrg
317ec681f3Smrg#include "vdpau_private.h"
327ec681f3Smrg#include "pipe/p_screen.h"
337ec681f3Smrg#include "pipe/p_defines.h"
347ec681f3Smrg#include "util/u_debug.h"
357ec681f3Smrg
367ec681f3Smrg/**
377ec681f3Smrg * Retrieve the VDPAU version implemented by the backend.
387ec681f3Smrg */
397ec681f3SmrgVdpStatus
407ec681f3SmrgvlVdpGetApiVersion(uint32_t *api_version)
417ec681f3Smrg{
427ec681f3Smrg   if (!api_version)
437ec681f3Smrg      return VDP_STATUS_INVALID_POINTER;
447ec681f3Smrg
457ec681f3Smrg   *api_version = 1;
467ec681f3Smrg   return VDP_STATUS_OK;
477ec681f3Smrg}
487ec681f3Smrg
497ec681f3Smrg/**
507ec681f3Smrg * Retrieve an implementation-specific string description of the implementation.
517ec681f3Smrg * This typically includes detailed version information.
527ec681f3Smrg */
537ec681f3SmrgVdpStatus
547ec681f3SmrgvlVdpGetInformationString(char const **information_string)
557ec681f3Smrg{
567ec681f3Smrg   if (!information_string)
577ec681f3Smrg      return VDP_STATUS_INVALID_POINTER;
587ec681f3Smrg
597ec681f3Smrg   *information_string = INFORMATION_STRING;
607ec681f3Smrg   return VDP_STATUS_OK;
617ec681f3Smrg}
627ec681f3Smrg
637ec681f3Smrg/**
647ec681f3Smrg * Query the implementation's VdpVideoSurface capabilities.
657ec681f3Smrg */
667ec681f3SmrgVdpStatus
677ec681f3SmrgvlVdpVideoSurfaceQueryCapabilities(VdpDevice device, VdpChromaType surface_chroma_type,
687ec681f3Smrg                                   VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height)
697ec681f3Smrg{
707ec681f3Smrg   vlVdpDevice *dev;
717ec681f3Smrg   struct pipe_screen *pscreen;
727ec681f3Smrg   uint32_t max_2d_texture_size;
737ec681f3Smrg
747ec681f3Smrg   if (!(is_supported && max_width && max_height))
757ec681f3Smrg      return VDP_STATUS_INVALID_POINTER;
767ec681f3Smrg
777ec681f3Smrg   dev = vlGetDataHTAB(device);
787ec681f3Smrg   if (!dev)
797ec681f3Smrg      return VDP_STATUS_INVALID_HANDLE;
807ec681f3Smrg
817ec681f3Smrg   pscreen = dev->vscreen->pscreen;
827ec681f3Smrg   if (!pscreen)
837ec681f3Smrg      return VDP_STATUS_RESOURCES;
847ec681f3Smrg
857ec681f3Smrg   mtx_lock(&dev->mutex);
867ec681f3Smrg
877ec681f3Smrg   /* XXX: Current limits */
887ec681f3Smrg   *is_supported = true;
897ec681f3Smrg   max_2d_texture_size = pscreen->get_param(pscreen, PIPE_CAP_MAX_TEXTURE_2D_SIZE);
907ec681f3Smrg   mtx_unlock(&dev->mutex);
917ec681f3Smrg   if (!max_2d_texture_size)
927ec681f3Smrg      return VDP_STATUS_RESOURCES;
937ec681f3Smrg
947ec681f3Smrg   *max_width = *max_height = max_2d_texture_size;
957ec681f3Smrg
967ec681f3Smrg   return VDP_STATUS_OK;
977ec681f3Smrg}
987ec681f3Smrg
997ec681f3Smrg/**
1007ec681f3Smrg * Query the implementation's VdpVideoSurface GetBits/PutBits capabilities.
1017ec681f3Smrg */
1027ec681f3SmrgVdpStatus
1037ec681f3SmrgvlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities(VdpDevice device, VdpChromaType surface_chroma_type,
1047ec681f3Smrg                                                  VdpYCbCrFormat bits_ycbcr_format,
1057ec681f3Smrg                                                  VdpBool *is_supported)
1067ec681f3Smrg{
1077ec681f3Smrg   vlVdpDevice *dev;
1087ec681f3Smrg   struct pipe_screen *pscreen;
1097ec681f3Smrg
1107ec681f3Smrg   if (!is_supported)
1117ec681f3Smrg      return VDP_STATUS_INVALID_POINTER;
1127ec681f3Smrg
1137ec681f3Smrg   dev = vlGetDataHTAB(device);
1147ec681f3Smrg   if (!dev)
1157ec681f3Smrg      return VDP_STATUS_INVALID_HANDLE;
1167ec681f3Smrg
1177ec681f3Smrg   pscreen = dev->vscreen->pscreen;
1187ec681f3Smrg   if (!pscreen)
1197ec681f3Smrg      return VDP_STATUS_RESOURCES;
1207ec681f3Smrg
1217ec681f3Smrg   mtx_lock(&dev->mutex);
1227ec681f3Smrg
1237ec681f3Smrg   switch(bits_ycbcr_format) {
1247ec681f3Smrg   case VDP_YCBCR_FORMAT_NV12:
1257ec681f3Smrg      *is_supported = surface_chroma_type == VDP_CHROMA_TYPE_420;
1267ec681f3Smrg      break;
1277ec681f3Smrg
1287ec681f3Smrg   case VDP_YCBCR_FORMAT_YV12:
1297ec681f3Smrg      *is_supported = surface_chroma_type == VDP_CHROMA_TYPE_420;
1307ec681f3Smrg
1317ec681f3Smrg      /* We can convert YV12 to NV12 on the fly! */
1327ec681f3Smrg      if (*is_supported &&
1337ec681f3Smrg          pscreen->is_video_format_supported(pscreen,
1347ec681f3Smrg                                             PIPE_FORMAT_NV12,
1357ec681f3Smrg                                             PIPE_VIDEO_PROFILE_UNKNOWN,
1367ec681f3Smrg                                             PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) {
1377ec681f3Smrg         mtx_unlock(&dev->mutex);
1387ec681f3Smrg         return VDP_STATUS_OK;
1397ec681f3Smrg      }
1407ec681f3Smrg      break;
1417ec681f3Smrg
1427ec681f3Smrg   case VDP_YCBCR_FORMAT_UYVY:
1437ec681f3Smrg   case VDP_YCBCR_FORMAT_YUYV:
1447ec681f3Smrg      *is_supported = surface_chroma_type == VDP_CHROMA_TYPE_422;
1457ec681f3Smrg      break;
1467ec681f3Smrg
1477ec681f3Smrg   case VDP_YCBCR_FORMAT_Y8U8V8A8:
1487ec681f3Smrg   case VDP_YCBCR_FORMAT_V8U8Y8A8:
1497ec681f3Smrg      *is_supported = surface_chroma_type == VDP_CHROMA_TYPE_444;
1507ec681f3Smrg      break;
1517ec681f3Smrg
1527ec681f3Smrg   default:
1537ec681f3Smrg      *is_supported = false;
1547ec681f3Smrg      break;
1557ec681f3Smrg   }
1567ec681f3Smrg
1577ec681f3Smrg   if (*is_supported &&
1587ec681f3Smrg       !pscreen->is_video_format_supported(pscreen,
1597ec681f3Smrg                                           FormatYCBCRToPipe(bits_ycbcr_format),
1607ec681f3Smrg                                           PIPE_VIDEO_PROFILE_UNKNOWN,
1617ec681f3Smrg                                           PIPE_VIDEO_ENTRYPOINT_BITSTREAM)) {
1627ec681f3Smrg      *is_supported = false;
1637ec681f3Smrg   }
1647ec681f3Smrg   mtx_unlock(&dev->mutex);
1657ec681f3Smrg
1667ec681f3Smrg   return VDP_STATUS_OK;
1677ec681f3Smrg}
1687ec681f3Smrg
1697ec681f3Smrg/**
1707ec681f3Smrg * Query the implementation's VdpDecoder capabilities.
1717ec681f3Smrg */
1727ec681f3SmrgVdpStatus
1737ec681f3SmrgvlVdpDecoderQueryCapabilities(VdpDevice device, VdpDecoderProfile profile,
1747ec681f3Smrg                              VdpBool *is_supported, uint32_t *max_level, uint32_t *max_macroblocks,
1757ec681f3Smrg                              uint32_t *max_width, uint32_t *max_height)
1767ec681f3Smrg{
1777ec681f3Smrg   vlVdpDevice *dev;
1787ec681f3Smrg   struct pipe_screen *pscreen;
1797ec681f3Smrg   enum pipe_video_profile p_profile;
1807ec681f3Smrg
1817ec681f3Smrg   if (!(is_supported && max_level && max_macroblocks && max_width && max_height))
1827ec681f3Smrg      return VDP_STATUS_INVALID_POINTER;
1837ec681f3Smrg
1847ec681f3Smrg   dev = vlGetDataHTAB(device);
1857ec681f3Smrg   if (!dev)
1867ec681f3Smrg      return VDP_STATUS_INVALID_HANDLE;
1877ec681f3Smrg
1887ec681f3Smrg   pscreen = dev->vscreen->pscreen;
1897ec681f3Smrg   if (!pscreen)
1907ec681f3Smrg      return VDP_STATUS_RESOURCES;
1917ec681f3Smrg
1927ec681f3Smrg   p_profile = ProfileToPipe(profile);
1937ec681f3Smrg   if (p_profile == PIPE_VIDEO_PROFILE_UNKNOWN)	{
1947ec681f3Smrg      *is_supported = false;
1957ec681f3Smrg      return VDP_STATUS_OK;
1967ec681f3Smrg   }
1977ec681f3Smrg
1987ec681f3Smrg   mtx_lock(&dev->mutex);
1997ec681f3Smrg   *is_supported = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
2007ec681f3Smrg                                            PIPE_VIDEO_CAP_SUPPORTED);
2017ec681f3Smrg   if (*is_supported) {
2027ec681f3Smrg      *max_width = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
2037ec681f3Smrg                                            PIPE_VIDEO_CAP_MAX_WIDTH);
2047ec681f3Smrg      *max_height = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
2057ec681f3Smrg                                             PIPE_VIDEO_CAP_MAX_HEIGHT);
2067ec681f3Smrg      *max_level = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
2077ec681f3Smrg                                            PIPE_VIDEO_CAP_MAX_LEVEL);
2087ec681f3Smrg      *max_macroblocks = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
2097ec681f3Smrg                                            PIPE_VIDEO_CAP_MAX_MACROBLOCKS);
2107ec681f3Smrg      if (*max_macroblocks == 0) {
2117ec681f3Smrg         *max_macroblocks = (*max_width/16)*(*max_height/16);
2127ec681f3Smrg      }
2137ec681f3Smrg   } else {
2147ec681f3Smrg      *max_width = 0;
2157ec681f3Smrg      *max_height = 0;
2167ec681f3Smrg      *max_level = 0;
2177ec681f3Smrg      *max_macroblocks = 0;
2187ec681f3Smrg   }
2197ec681f3Smrg   mtx_unlock(&dev->mutex);
2207ec681f3Smrg
2217ec681f3Smrg   return VDP_STATUS_OK;
2227ec681f3Smrg}
2237ec681f3Smrg
2247ec681f3Smrg/**
2257ec681f3Smrg * Query the implementation's VdpOutputSurface capabilities.
2267ec681f3Smrg */
2277ec681f3SmrgVdpStatus
2287ec681f3SmrgvlVdpOutputSurfaceQueryCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format,
2297ec681f3Smrg                                    VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height)
2307ec681f3Smrg{
2317ec681f3Smrg   vlVdpDevice *dev;
2327ec681f3Smrg   struct pipe_screen *pscreen;
2337ec681f3Smrg   enum pipe_format format;
2347ec681f3Smrg
2357ec681f3Smrg   dev = vlGetDataHTAB(device);
2367ec681f3Smrg   if (!dev)
2377ec681f3Smrg      return VDP_STATUS_INVALID_HANDLE;
2387ec681f3Smrg
2397ec681f3Smrg   pscreen = dev->vscreen->pscreen;
2407ec681f3Smrg   if (!pscreen)
2417ec681f3Smrg      return VDP_STATUS_RESOURCES;
2427ec681f3Smrg
2437ec681f3Smrg   format = VdpFormatRGBAToPipe(surface_rgba_format);
2447ec681f3Smrg   if (format == PIPE_FORMAT_NONE || format == PIPE_FORMAT_A8_UNORM)
2457ec681f3Smrg      return VDP_STATUS_INVALID_RGBA_FORMAT;
2467ec681f3Smrg
2477ec681f3Smrg   if (!(is_supported && max_width && max_height))
2487ec681f3Smrg      return VDP_STATUS_INVALID_POINTER;
2497ec681f3Smrg
2507ec681f3Smrg   mtx_lock(&dev->mutex);
2517ec681f3Smrg   *is_supported = pscreen->is_format_supported
2527ec681f3Smrg   (
2537ec681f3Smrg      pscreen, format, PIPE_TEXTURE_2D, 1, 1,
2547ec681f3Smrg      PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET
2557ec681f3Smrg   );
2567ec681f3Smrg   if (*is_supported) {
2577ec681f3Smrg      uint32_t max_2d_texture_size = pscreen->get_param(
2587ec681f3Smrg         pscreen, PIPE_CAP_MAX_TEXTURE_2D_SIZE);
2597ec681f3Smrg
2607ec681f3Smrg      if (!max_2d_texture_size) {
2617ec681f3Smrg         mtx_unlock(&dev->mutex);
2627ec681f3Smrg         return VDP_STATUS_ERROR;
2637ec681f3Smrg      }
2647ec681f3Smrg
2657ec681f3Smrg      *max_width = *max_height = max_2d_texture_size;
2667ec681f3Smrg   } else {
2677ec681f3Smrg      *max_width = 0;
2687ec681f3Smrg      *max_height = 0;
2697ec681f3Smrg   }
2707ec681f3Smrg   mtx_unlock(&dev->mutex);
2717ec681f3Smrg
2727ec681f3Smrg   return VDP_STATUS_OK;
2737ec681f3Smrg}
2747ec681f3Smrg
2757ec681f3Smrg/**
2767ec681f3Smrg * Query the implementation's capability to perform a PutBits operation using
2777ec681f3Smrg * application data matching the surface's format.
2787ec681f3Smrg */
2797ec681f3SmrgVdpStatus
2807ec681f3SmrgvlVdpOutputSurfaceQueryGetPutBitsNativeCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format,
2817ec681f3Smrg                                                    VdpBool *is_supported)
2827ec681f3Smrg{
2837ec681f3Smrg   vlVdpDevice *dev;
2847ec681f3Smrg   struct pipe_screen *pscreen;
2857ec681f3Smrg   enum pipe_format format;
2867ec681f3Smrg
2877ec681f3Smrg   dev = vlGetDataHTAB(device);
2887ec681f3Smrg   if (!dev)
2897ec681f3Smrg      return VDP_STATUS_INVALID_HANDLE;
2907ec681f3Smrg
2917ec681f3Smrg   pscreen = dev->vscreen->pscreen;
2927ec681f3Smrg   if (!pscreen)
2937ec681f3Smrg      return VDP_STATUS_ERROR;
2947ec681f3Smrg
2957ec681f3Smrg   format = VdpFormatRGBAToPipe(surface_rgba_format);
2967ec681f3Smrg   if (format == PIPE_FORMAT_NONE || format == PIPE_FORMAT_A8_UNORM)
2977ec681f3Smrg      return VDP_STATUS_INVALID_RGBA_FORMAT;
2987ec681f3Smrg
2997ec681f3Smrg   if (!is_supported)
3007ec681f3Smrg      return VDP_STATUS_INVALID_POINTER;
3017ec681f3Smrg
3027ec681f3Smrg   mtx_lock(&dev->mutex);
3037ec681f3Smrg   *is_supported = pscreen->is_format_supported
3047ec681f3Smrg   (
3057ec681f3Smrg      pscreen, format, PIPE_TEXTURE_2D, 1, 1,
3067ec681f3Smrg      PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET
3077ec681f3Smrg   );
3087ec681f3Smrg   mtx_unlock(&dev->mutex);
3097ec681f3Smrg
3107ec681f3Smrg   return VDP_STATUS_OK;
3117ec681f3Smrg}
3127ec681f3Smrg
3137ec681f3Smrg/**
3147ec681f3Smrg * Query the implementation's capability to perform a PutBits operation using
3157ec681f3Smrg * application data in a specific indexed format.
3167ec681f3Smrg */
3177ec681f3SmrgVdpStatus
3187ec681f3SmrgvlVdpOutputSurfaceQueryPutBitsIndexedCapabilities(VdpDevice device,
3197ec681f3Smrg                                                  VdpRGBAFormat surface_rgba_format,
3207ec681f3Smrg                                                  VdpIndexedFormat bits_indexed_format,
3217ec681f3Smrg                                                  VdpColorTableFormat color_table_format,
3227ec681f3Smrg                                                  VdpBool *is_supported)
3237ec681f3Smrg{
3247ec681f3Smrg   vlVdpDevice *dev;
3257ec681f3Smrg   struct pipe_screen *pscreen;
3267ec681f3Smrg   enum pipe_format rgba_format, index_format, colortbl_format;
3277ec681f3Smrg
3287ec681f3Smrg   dev = vlGetDataHTAB(device);
3297ec681f3Smrg   if (!dev)
3307ec681f3Smrg      return VDP_STATUS_INVALID_HANDLE;
3317ec681f3Smrg
3327ec681f3Smrg   pscreen = dev->vscreen->pscreen;
3337ec681f3Smrg   if (!pscreen)
3347ec681f3Smrg      return VDP_STATUS_ERROR;
3357ec681f3Smrg
3367ec681f3Smrg   rgba_format = VdpFormatRGBAToPipe(surface_rgba_format);
3377ec681f3Smrg   if (rgba_format == PIPE_FORMAT_NONE || rgba_format == PIPE_FORMAT_A8_UNORM)
3387ec681f3Smrg      return VDP_STATUS_INVALID_RGBA_FORMAT;
3397ec681f3Smrg
3407ec681f3Smrg   index_format = FormatIndexedToPipe(bits_indexed_format);
3417ec681f3Smrg   if (index_format == PIPE_FORMAT_NONE)
3427ec681f3Smrg       return VDP_STATUS_INVALID_INDEXED_FORMAT;
3437ec681f3Smrg
3447ec681f3Smrg   colortbl_format = FormatColorTableToPipe(color_table_format);
3457ec681f3Smrg   if (colortbl_format == PIPE_FORMAT_NONE)
3467ec681f3Smrg       return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT;
3477ec681f3Smrg
3487ec681f3Smrg   if (!is_supported)
3497ec681f3Smrg      return VDP_STATUS_INVALID_POINTER;
3507ec681f3Smrg
3517ec681f3Smrg   mtx_lock(&dev->mutex);
3527ec681f3Smrg   *is_supported = pscreen->is_format_supported
3537ec681f3Smrg   (
3547ec681f3Smrg      pscreen, rgba_format, PIPE_TEXTURE_2D, 1, 1,
3557ec681f3Smrg      PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET
3567ec681f3Smrg   );
3577ec681f3Smrg
3587ec681f3Smrg   *is_supported &= pscreen->is_format_supported
3597ec681f3Smrg   (
3607ec681f3Smrg      pscreen, index_format, PIPE_TEXTURE_2D, 1, 1,
3617ec681f3Smrg      PIPE_BIND_SAMPLER_VIEW
3627ec681f3Smrg   );
3637ec681f3Smrg
3647ec681f3Smrg   *is_supported &= pscreen->is_format_supported
3657ec681f3Smrg   (
3667ec681f3Smrg      pscreen, colortbl_format, PIPE_TEXTURE_1D, 1, 1,
3677ec681f3Smrg      PIPE_BIND_SAMPLER_VIEW
3687ec681f3Smrg   );
3697ec681f3Smrg   mtx_unlock(&dev->mutex);
3707ec681f3Smrg
3717ec681f3Smrg   return VDP_STATUS_OK;
3727ec681f3Smrg}
3737ec681f3Smrg
3747ec681f3Smrg/**
3757ec681f3Smrg * Query the implementation's capability to perform a PutBits operation using
3767ec681f3Smrg * application data in a specific YCbCr/YUB format.
3777ec681f3Smrg */
3787ec681f3SmrgVdpStatus
3797ec681f3SmrgvlVdpOutputSurfaceQueryPutBitsYCbCrCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format,
3807ec681f3Smrg                                                VdpYCbCrFormat bits_ycbcr_format,
3817ec681f3Smrg                                                VdpBool *is_supported)
3827ec681f3Smrg{
3837ec681f3Smrg   vlVdpDevice *dev;
3847ec681f3Smrg   struct pipe_screen *pscreen;
3857ec681f3Smrg   enum pipe_format rgba_format, ycbcr_format;
3867ec681f3Smrg
3877ec681f3Smrg   dev = vlGetDataHTAB(device);
3887ec681f3Smrg   if (!dev)
3897ec681f3Smrg      return VDP_STATUS_INVALID_HANDLE;
3907ec681f3Smrg
3917ec681f3Smrg   pscreen = dev->vscreen->pscreen;
3927ec681f3Smrg   if (!pscreen)
3937ec681f3Smrg      return VDP_STATUS_ERROR;
3947ec681f3Smrg
3957ec681f3Smrg   rgba_format = VdpFormatRGBAToPipe(surface_rgba_format);
3967ec681f3Smrg   if (rgba_format == PIPE_FORMAT_NONE || rgba_format == PIPE_FORMAT_A8_UNORM)
3977ec681f3Smrg      return VDP_STATUS_INVALID_RGBA_FORMAT;
3987ec681f3Smrg
3997ec681f3Smrg   ycbcr_format = FormatYCBCRToPipe(bits_ycbcr_format);
4007ec681f3Smrg   if (ycbcr_format == PIPE_FORMAT_NONE)
4017ec681f3Smrg       return VDP_STATUS_INVALID_INDEXED_FORMAT;
4027ec681f3Smrg
4037ec681f3Smrg   if (!is_supported)
4047ec681f3Smrg      return VDP_STATUS_INVALID_POINTER;
4057ec681f3Smrg
4067ec681f3Smrg   mtx_lock(&dev->mutex);
4077ec681f3Smrg   *is_supported = pscreen->is_format_supported
4087ec681f3Smrg   (
4097ec681f3Smrg      pscreen, rgba_format, PIPE_TEXTURE_2D, 1, 1,
4107ec681f3Smrg      PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET
4117ec681f3Smrg   );
4127ec681f3Smrg
4137ec681f3Smrg   *is_supported &= pscreen->is_video_format_supported
4147ec681f3Smrg   (
4157ec681f3Smrg      pscreen, ycbcr_format,
4167ec681f3Smrg      PIPE_VIDEO_PROFILE_UNKNOWN,
4177ec681f3Smrg      PIPE_VIDEO_ENTRYPOINT_BITSTREAM
4187ec681f3Smrg   );
4197ec681f3Smrg   mtx_unlock(&dev->mutex);
4207ec681f3Smrg
4217ec681f3Smrg   return VDP_STATUS_OK;
4227ec681f3Smrg}
4237ec681f3Smrg
4247ec681f3Smrg/**
4257ec681f3Smrg * Query the implementation's VdpBitmapSurface capabilities.
4267ec681f3Smrg */
4277ec681f3SmrgVdpStatus
4287ec681f3SmrgvlVdpBitmapSurfaceQueryCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format,
4297ec681f3Smrg                                    VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height)
4307ec681f3Smrg{
4317ec681f3Smrg   vlVdpDevice *dev;
4327ec681f3Smrg   struct pipe_screen *pscreen;
4337ec681f3Smrg   enum pipe_format format;
4347ec681f3Smrg
4357ec681f3Smrg   dev = vlGetDataHTAB(device);
4367ec681f3Smrg   if (!dev)
4377ec681f3Smrg      return VDP_STATUS_INVALID_HANDLE;
4387ec681f3Smrg
4397ec681f3Smrg   pscreen = dev->vscreen->pscreen;
4407ec681f3Smrg   if (!pscreen)
4417ec681f3Smrg      return VDP_STATUS_RESOURCES;
4427ec681f3Smrg
4437ec681f3Smrg   format = VdpFormatRGBAToPipe(surface_rgba_format);
4447ec681f3Smrg   if (format == PIPE_FORMAT_NONE)
4457ec681f3Smrg      return VDP_STATUS_INVALID_RGBA_FORMAT;
4467ec681f3Smrg
4477ec681f3Smrg   if (!(is_supported && max_width && max_height))
4487ec681f3Smrg      return VDP_STATUS_INVALID_POINTER;
4497ec681f3Smrg
4507ec681f3Smrg   mtx_lock(&dev->mutex);
4517ec681f3Smrg   *is_supported = pscreen->is_format_supported
4527ec681f3Smrg   (
4537ec681f3Smrg      pscreen, format, PIPE_TEXTURE_2D, 1, 1,
4547ec681f3Smrg      PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET
4557ec681f3Smrg   );
4567ec681f3Smrg   if (*is_supported) {
4577ec681f3Smrg      uint32_t max_2d_texture_size = pscreen->get_param(
4587ec681f3Smrg         pscreen, PIPE_CAP_MAX_TEXTURE_2D_SIZE);
4597ec681f3Smrg
4607ec681f3Smrg      if (!max_2d_texture_size) {
4617ec681f3Smrg         mtx_unlock(&dev->mutex);
4627ec681f3Smrg         return VDP_STATUS_ERROR;
4637ec681f3Smrg      }
4647ec681f3Smrg
4657ec681f3Smrg      *max_width = *max_height = max_2d_texture_size;
4667ec681f3Smrg   } else {
4677ec681f3Smrg      *max_width = 0;
4687ec681f3Smrg      *max_height = 0;
4697ec681f3Smrg   }
4707ec681f3Smrg   mtx_unlock(&dev->mutex);
4717ec681f3Smrg
4727ec681f3Smrg   return VDP_STATUS_OK;
4737ec681f3Smrg}
4747ec681f3Smrg
4757ec681f3Smrg/**
4767ec681f3Smrg * Query the implementation's support for a specific feature.
4777ec681f3Smrg */
4787ec681f3SmrgVdpStatus
4797ec681f3SmrgvlVdpVideoMixerQueryFeatureSupport(VdpDevice device, VdpVideoMixerFeature feature,
4807ec681f3Smrg                                   VdpBool *is_supported)
4817ec681f3Smrg{
4827ec681f3Smrg   if (!is_supported)
4837ec681f3Smrg      return VDP_STATUS_INVALID_POINTER;
4847ec681f3Smrg
4857ec681f3Smrg   switch (feature) {
4867ec681f3Smrg   case VDP_VIDEO_MIXER_FEATURE_SHARPNESS:
4877ec681f3Smrg   case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION:
4887ec681f3Smrg   case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL:
4897ec681f3Smrg   case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY:
4907ec681f3Smrg   case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1:
4917ec681f3Smrg      *is_supported = VDP_TRUE;
4927ec681f3Smrg      break;
4937ec681f3Smrg   default:
4947ec681f3Smrg      *is_supported = VDP_FALSE;
4957ec681f3Smrg      break;
4967ec681f3Smrg   }
4977ec681f3Smrg   return VDP_STATUS_OK;
4987ec681f3Smrg}
4997ec681f3Smrg
5007ec681f3Smrg/**
5017ec681f3Smrg * Query the implementation's support for a specific parameter.
5027ec681f3Smrg */
5037ec681f3SmrgVdpStatus
5047ec681f3SmrgvlVdpVideoMixerQueryParameterSupport(VdpDevice device, VdpVideoMixerParameter parameter,
5057ec681f3Smrg                                     VdpBool *is_supported)
5067ec681f3Smrg{
5077ec681f3Smrg   if (!is_supported)
5087ec681f3Smrg      return VDP_STATUS_INVALID_POINTER;
5097ec681f3Smrg
5107ec681f3Smrg   switch (parameter) {
5117ec681f3Smrg   case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH:
5127ec681f3Smrg   case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT:
5137ec681f3Smrg   case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE:
5147ec681f3Smrg   case VDP_VIDEO_MIXER_PARAMETER_LAYERS:
5157ec681f3Smrg      *is_supported = VDP_TRUE;
5167ec681f3Smrg      break;
5177ec681f3Smrg   default:
5187ec681f3Smrg      *is_supported = VDP_FALSE;
5197ec681f3Smrg      break;
5207ec681f3Smrg   }
5217ec681f3Smrg   return VDP_STATUS_OK;
5227ec681f3Smrg}
5237ec681f3Smrg
5247ec681f3Smrg/**
5257ec681f3Smrg * Query the implementation's supported for a specific parameter.
5267ec681f3Smrg */
5277ec681f3SmrgVdpStatus
5287ec681f3SmrgvlVdpVideoMixerQueryParameterValueRange(VdpDevice device, VdpVideoMixerParameter parameter,
5297ec681f3Smrg                                        void *min_value, void *max_value)
5307ec681f3Smrg{
5317ec681f3Smrg   vlVdpDevice *dev = vlGetDataHTAB(device);
5327ec681f3Smrg   struct pipe_screen *screen;
5337ec681f3Smrg
5347ec681f3Smrg   if (!dev)
5357ec681f3Smrg      return VDP_STATUS_INVALID_HANDLE;
5367ec681f3Smrg   if (!(min_value && max_value))
5377ec681f3Smrg      return VDP_STATUS_INVALID_POINTER;
5387ec681f3Smrg
5397ec681f3Smrg   mtx_lock(&dev->mutex);
5407ec681f3Smrg   screen = dev->vscreen->pscreen;
5417ec681f3Smrg   switch (parameter) {
5427ec681f3Smrg   case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH:
5437ec681f3Smrg      *(uint32_t*)min_value = 48;
5447ec681f3Smrg      *(uint32_t*)max_value = screen->get_video_param(screen, PIPE_VIDEO_PROFILE_UNKNOWN,
5457ec681f3Smrg                                                      PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
5467ec681f3Smrg                                                      PIPE_VIDEO_CAP_MAX_WIDTH);
5477ec681f3Smrg      break;
5487ec681f3Smrg   case VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT:
5497ec681f3Smrg      *(uint32_t*)min_value = 48;
5507ec681f3Smrg      *(uint32_t*)max_value = screen->get_video_param(screen, PIPE_VIDEO_PROFILE_UNKNOWN,
5517ec681f3Smrg                                                      PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
5527ec681f3Smrg                                                      PIPE_VIDEO_CAP_MAX_HEIGHT);
5537ec681f3Smrg      break;
5547ec681f3Smrg
5557ec681f3Smrg   case VDP_VIDEO_MIXER_PARAMETER_LAYERS:
5567ec681f3Smrg      *(uint32_t*)min_value = 0;
5577ec681f3Smrg      *(uint32_t*)max_value = 4;
5587ec681f3Smrg      break;
5597ec681f3Smrg
5607ec681f3Smrg   case VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE:
5617ec681f3Smrg   default:
5627ec681f3Smrg      mtx_unlock(&dev->mutex);
5637ec681f3Smrg      return VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER;
5647ec681f3Smrg   }
5657ec681f3Smrg   mtx_unlock(&dev->mutex);
5667ec681f3Smrg   return VDP_STATUS_OK;
5677ec681f3Smrg}
5687ec681f3Smrg
5697ec681f3Smrg/**
5707ec681f3Smrg * Query the implementation's support for a specific attribute.
5717ec681f3Smrg */
5727ec681f3SmrgVdpStatus
5737ec681f3SmrgvlVdpVideoMixerQueryAttributeSupport(VdpDevice device, VdpVideoMixerAttribute attribute,
5747ec681f3Smrg                                     VdpBool *is_supported)
5757ec681f3Smrg{
5767ec681f3Smrg   if (!is_supported)
5777ec681f3Smrg      return VDP_STATUS_INVALID_POINTER;
5787ec681f3Smrg
5797ec681f3Smrg   switch (attribute) {
5807ec681f3Smrg   case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR:
5817ec681f3Smrg   case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX:
5827ec681f3Smrg   case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL:
5837ec681f3Smrg   case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL:
5847ec681f3Smrg   case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA:
5857ec681f3Smrg   case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA:
5867ec681f3Smrg   case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE:
5877ec681f3Smrg      *is_supported = VDP_TRUE;
5887ec681f3Smrg      break;
5897ec681f3Smrg   default:
5907ec681f3Smrg      *is_supported = VDP_FALSE;
5917ec681f3Smrg   }
5927ec681f3Smrg   return VDP_STATUS_OK;
5937ec681f3Smrg}
5947ec681f3Smrg
5957ec681f3Smrg/**
5967ec681f3Smrg * Query the implementation's supported for a specific attribute.
5977ec681f3Smrg */
5987ec681f3SmrgVdpStatus
5997ec681f3SmrgvlVdpVideoMixerQueryAttributeValueRange(VdpDevice device, VdpVideoMixerAttribute attribute,
6007ec681f3Smrg                                        void *min_value, void *max_value)
6017ec681f3Smrg{
6027ec681f3Smrg   if (!(min_value && max_value))
6037ec681f3Smrg      return VDP_STATUS_INVALID_POINTER;
6047ec681f3Smrg
6057ec681f3Smrg   switch (attribute) {
6067ec681f3Smrg   case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL:
6077ec681f3Smrg   case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA:
6087ec681f3Smrg   case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA:
6097ec681f3Smrg      *(float*)min_value = 0.0f;
6107ec681f3Smrg      *(float*)max_value = 1.0f;
6117ec681f3Smrg      break;
6127ec681f3Smrg   case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL:
6137ec681f3Smrg      *(float*)min_value = -1.0f;
6147ec681f3Smrg      *(float*)max_value = 1.0f;
6157ec681f3Smrg      break;
6167ec681f3Smrg   case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE:
6177ec681f3Smrg      *(uint8_t*)min_value = 0;
6187ec681f3Smrg      *(uint8_t*)max_value = 1;
6197ec681f3Smrg      break;
6207ec681f3Smrg   case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR:
6217ec681f3Smrg   case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX:
6227ec681f3Smrg   default:
6237ec681f3Smrg      return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE;
6247ec681f3Smrg   }
6257ec681f3Smrg   return VDP_STATUS_OK;
6267ec681f3Smrg}
627