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 */
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_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 */
103VdpStatus
104vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities(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 */
154VdpStatus
155vlVdpDecoderQueryCapabilities(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 */
201VdpStatus
202vlVdpOutputSurfaceQueryCapabilities(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 */
253VdpStatus
254vlVdpOutputSurfaceQueryGetPutBitsNativeCapabilities(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 */
291VdpStatus
292vlVdpOutputSurfaceQueryPutBitsIndexedCapabilities(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 */
352VdpStatus
353vlVdpOutputSurfaceQueryPutBitsYCbCrCapabilities(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 */
400VdpStatus
401vlVdpBitmapSurfaceQueryCapabilities(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 */
451VdpStatus
452vlVdpVideoMixerQueryFeatureSupport(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 */
473VdpStatus
474vlVdpVideoMixerQueryParameterSupport(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 */
497VdpStatus
498vlVdpVideoMixerQueryParameterValueRange(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 */
539VdpStatus
540vlVdpVideoMixerQueryAttributeSupport(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 */
565VdpStatus
566vlVdpVideoMixerQueryAttributeValueRange(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