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