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