1 /************************************************************************** 2 * 3 * Copyright 2010 Thomas Balling Srensen. 4 * Copyright 2011 Christian Knig. 5 * All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sub license, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial portions 17 * of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 **************************************************************************/ 28 29 #include <vdpau/vdpau.h> 30 31 #include "util/u_debug.h" 32 #include "util/u_memory.h" 33 #include "util/u_sampler.h" 34 #include "util/u_format.h" 35 36 #include "vl/vl_csc.h" 37 38 #include "vdpau_private.h" 39 40 /** 41 * Create a VdpOutputSurface. 42 */ 43 VdpStatus 44 vlVdpOutputSurfaceCreate(VdpDevice device, 45 VdpRGBAFormat rgba_format, 46 uint32_t width, uint32_t height, 47 VdpOutputSurface *surface) 48 { 49 struct pipe_context *pipe; 50 struct pipe_resource res_tmpl, *res; 51 struct pipe_sampler_view sv_templ; 52 struct pipe_surface surf_templ; 53 54 vlVdpOutputSurface *vlsurface = NULL; 55 56 if (!(width && height)) 57 return VDP_STATUS_INVALID_SIZE; 58 59 vlVdpDevice *dev = vlGetDataHTAB(device); 60 if (!dev) 61 return VDP_STATUS_INVALID_HANDLE; 62 63 pipe = dev->context; 64 if (!pipe) 65 return VDP_STATUS_INVALID_HANDLE; 66 67 vlsurface = CALLOC(1, sizeof(vlVdpOutputSurface)); 68 if (!vlsurface) 69 return VDP_STATUS_RESOURCES; 70 71 vlsurface->device = dev; 72 73 memset(&res_tmpl, 0, sizeof(res_tmpl)); 74 75 res_tmpl.target = PIPE_TEXTURE_2D; 76 res_tmpl.format = FormatRGBAToPipe(rgba_format); 77 res_tmpl.width0 = width; 78 res_tmpl.height0 = height; 79 res_tmpl.depth0 = 1; 80 res_tmpl.array_size = 1; 81 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; 82 res_tmpl.usage = PIPE_USAGE_STATIC; 83 84 pipe_mutex_lock(dev->mutex); 85 res = pipe->screen->resource_create(pipe->screen, &res_tmpl); 86 if (!res) { 87 pipe_mutex_unlock(dev->mutex); 88 FREE(dev); 89 return VDP_STATUS_ERROR; 90 } 91 92 vlVdpDefaultSamplerViewTemplate(&sv_templ, res); 93 vlsurface->sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ); 94 if (!vlsurface->sampler_view) { 95 pipe_resource_reference(&res, NULL); 96 pipe_mutex_unlock(dev->mutex); 97 FREE(dev); 98 return VDP_STATUS_ERROR; 99 } 100 101 memset(&surf_templ, 0, sizeof(surf_templ)); 102 surf_templ.format = res->format; 103 surf_templ.usage = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; 104 vlsurface->surface = pipe->create_surface(pipe, res, &surf_templ); 105 if (!vlsurface->surface) { 106 pipe_resource_reference(&res, NULL); 107 pipe_mutex_unlock(dev->mutex); 108 FREE(dev); 109 return VDP_STATUS_ERROR; 110 } 111 112 *surface = vlAddDataHTAB(vlsurface); 113 if (*surface == 0) { 114 pipe_resource_reference(&res, NULL); 115 pipe_mutex_unlock(dev->mutex); 116 FREE(dev); 117 return VDP_STATUS_ERROR; 118 } 119 120 pipe_resource_reference(&res, NULL); 121 122 vl_compositor_init_state(&vlsurface->cstate, pipe); 123 vl_compositor_reset_dirty_area(&vlsurface->dirty_area); 124 pipe_mutex_unlock(dev->mutex); 125 126 return VDP_STATUS_OK; 127 } 128 129 /** 130 * Destroy a VdpOutputSurface. 131 */ 132 VdpStatus 133 vlVdpOutputSurfaceDestroy(VdpOutputSurface surface) 134 { 135 vlVdpOutputSurface *vlsurface; 136 struct pipe_context *pipe; 137 138 vlsurface = vlGetDataHTAB(surface); 139 if (!vlsurface) 140 return VDP_STATUS_INVALID_HANDLE; 141 142 pipe = vlsurface->device->context; 143 144 pipe_mutex_lock(vlsurface->device->mutex); 145 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL); 146 147 pipe_surface_reference(&vlsurface->surface, NULL); 148 pipe_sampler_view_reference(&vlsurface->sampler_view, NULL); 149 pipe->screen->fence_reference(pipe->screen, &vlsurface->fence, NULL); 150 vl_compositor_cleanup_state(&vlsurface->cstate); 151 pipe_mutex_unlock(vlsurface->device->mutex); 152 153 vlRemoveDataHTAB(surface); 154 FREE(vlsurface); 155 156 return VDP_STATUS_OK; 157 } 158 159 /** 160 * Retrieve the parameters used to create a VdpOutputSurface. 161 */ 162 VdpStatus 163 vlVdpOutputSurfaceGetParameters(VdpOutputSurface surface, 164 VdpRGBAFormat *rgba_format, 165 uint32_t *width, uint32_t *height) 166 { 167 vlVdpOutputSurface *vlsurface; 168 169 vlsurface = vlGetDataHTAB(surface); 170 if (!vlsurface) 171 return VDP_STATUS_INVALID_HANDLE; 172 173 *rgba_format = PipeToFormatRGBA(vlsurface->sampler_view->texture->format); 174 *width = vlsurface->sampler_view->texture->width0; 175 *height = vlsurface->sampler_view->texture->height0; 176 177 return VDP_STATUS_OK; 178 } 179 180 /** 181 * Copy image data from a VdpOutputSurface to application memory in the 182 * surface's native format. 183 */ 184 VdpStatus 185 vlVdpOutputSurfaceGetBitsNative(VdpOutputSurface surface, 186 VdpRect const *source_rect, 187 void *const *destination_data, 188 uint32_t const *destination_pitches) 189 { 190 vlVdpOutputSurface *vlsurface; 191 struct pipe_context *pipe; 192 struct pipe_resource *res; 193 struct pipe_box box; 194 struct pipe_transfer *transfer; 195 uint8_t *map; 196 197 vlsurface = vlGetDataHTAB(surface); 198 if (!vlsurface) 199 return VDP_STATUS_INVALID_HANDLE; 200 201 pipe = vlsurface->device->context; 202 if (!pipe) 203 return VDP_STATUS_INVALID_HANDLE; 204 205 pipe_mutex_lock(vlsurface->device->mutex); 206 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL); 207 208 res = vlsurface->sampler_view->texture; 209 box = RectToPipeBox(source_rect, res); 210 transfer = pipe->get_transfer(pipe, res, 0, PIPE_TRANSFER_READ, &box); 211 if (transfer == NULL) { 212 pipe_mutex_unlock(vlsurface->device->mutex); 213 return VDP_STATUS_RESOURCES; 214 } 215 216 map = pipe_transfer_map(pipe, transfer); 217 if (map == NULL) { 218 pipe_transfer_destroy(pipe, transfer); 219 pipe_mutex_unlock(vlsurface->device->mutex); 220 return VDP_STATUS_RESOURCES; 221 } 222 223 util_copy_rect(*destination_data, res->format, *destination_pitches, 0, 0, 224 box.width, box.height, map, transfer->stride, 0, 0); 225 226 pipe_transfer_unmap(pipe, transfer); 227 pipe_transfer_destroy(pipe, transfer); 228 pipe_mutex_unlock(vlsurface->device->mutex); 229 230 return VDP_STATUS_OK; 231 } 232 233 /** 234 * Copy image data from application memory in the surface's native format to 235 * a VdpOutputSurface. 236 */ 237 VdpStatus 238 vlVdpOutputSurfacePutBitsNative(VdpOutputSurface surface, 239 void const *const *source_data, 240 uint32_t const *source_pitches, 241 VdpRect const *destination_rect) 242 { 243 vlVdpOutputSurface *vlsurface; 244 struct pipe_box dst_box; 245 struct pipe_context *pipe; 246 247 vlsurface = vlGetDataHTAB(surface); 248 if (!vlsurface) 249 return VDP_STATUS_INVALID_HANDLE; 250 251 pipe = vlsurface->device->context; 252 if (!pipe) 253 return VDP_STATUS_INVALID_HANDLE; 254 255 pipe_mutex_lock(vlsurface->device->mutex); 256 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL); 257 258 dst_box = RectToPipeBox(destination_rect, vlsurface->sampler_view->texture); 259 pipe->transfer_inline_write(pipe, vlsurface->sampler_view->texture, 0, 260 PIPE_TRANSFER_WRITE, &dst_box, *source_data, 261 *source_pitches, 0); 262 pipe_mutex_unlock(vlsurface->device->mutex); 263 264 return VDP_STATUS_OK; 265 } 266 267 /** 268 * Copy image data from application memory in a specific indexed format to 269 * a VdpOutputSurface. 270 */ 271 VdpStatus 272 vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface, 273 VdpIndexedFormat source_indexed_format, 274 void const *const *source_data, 275 uint32_t const *source_pitch, 276 VdpRect const *destination_rect, 277 VdpColorTableFormat color_table_format, 278 void const *color_table) 279 { 280 vlVdpOutputSurface *vlsurface; 281 struct pipe_context *context; 282 struct vl_compositor *compositor; 283 struct vl_compositor_state *cstate; 284 285 enum pipe_format index_format; 286 enum pipe_format colortbl_format; 287 288 struct pipe_resource *res, res_tmpl; 289 struct pipe_sampler_view sv_tmpl; 290 struct pipe_sampler_view *sv_idx = NULL, *sv_tbl = NULL; 291 292 struct pipe_box box; 293 struct u_rect dst_rect; 294 295 vlsurface = vlGetDataHTAB(surface); 296 if (!vlsurface) 297 return VDP_STATUS_INVALID_HANDLE; 298 299 context = vlsurface->device->context; 300 compositor = &vlsurface->device->compositor; 301 cstate = &vlsurface->cstate; 302 303 index_format = FormatIndexedToPipe(source_indexed_format); 304 if (index_format == PIPE_FORMAT_NONE) 305 return VDP_STATUS_INVALID_INDEXED_FORMAT; 306 307 if (!source_data || !source_pitch) 308 return VDP_STATUS_INVALID_POINTER; 309 310 colortbl_format = FormatColorTableToPipe(color_table_format); 311 if (colortbl_format == PIPE_FORMAT_NONE) 312 return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT; 313 314 if (!color_table) 315 return VDP_STATUS_INVALID_POINTER; 316 317 memset(&res_tmpl, 0, sizeof(res_tmpl)); 318 res_tmpl.target = PIPE_TEXTURE_2D; 319 res_tmpl.format = index_format; 320 321 if (destination_rect) { 322 res_tmpl.width0 = abs(destination_rect->x0-destination_rect->x1); 323 res_tmpl.height0 = abs(destination_rect->y0-destination_rect->y1); 324 } else { 325 res_tmpl.width0 = vlsurface->surface->texture->width0; 326 res_tmpl.height0 = vlsurface->surface->texture->height0; 327 } 328 res_tmpl.depth0 = 1; 329 res_tmpl.array_size = 1; 330 res_tmpl.usage = PIPE_USAGE_STAGING; 331 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; 332 333 pipe_mutex_lock(vlsurface->device->mutex); 334 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL); 335 336 res = context->screen->resource_create(context->screen, &res_tmpl); 337 if (!res) 338 goto error_resource; 339 340 box.x = box.y = box.z = 0; 341 box.width = res->width0; 342 box.height = res->height0; 343 box.depth = res->depth0; 344 345 context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box, 346 source_data[0], source_pitch[0], 347 source_pitch[0] * res->height0); 348 349 memset(&sv_tmpl, 0, sizeof(sv_tmpl)); 350 u_sampler_view_default_template(&sv_tmpl, res, res->format); 351 352 sv_idx = context->create_sampler_view(context, res, &sv_tmpl); 353 pipe_resource_reference(&res, NULL); 354 355 if (!sv_idx) 356 goto error_resource; 357 358 memset(&res_tmpl, 0, sizeof(res_tmpl)); 359 res_tmpl.target = PIPE_TEXTURE_1D; 360 res_tmpl.format = colortbl_format; 361 res_tmpl.width0 = 1 << util_format_get_component_bits( 362 index_format, UTIL_FORMAT_COLORSPACE_RGB, 0); 363 res_tmpl.height0 = 1; 364 res_tmpl.depth0 = 1; 365 res_tmpl.array_size = 1; 366 res_tmpl.usage = PIPE_USAGE_STAGING; 367 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; 368 369 res = context->screen->resource_create(context->screen, &res_tmpl); 370 if (!res) 371 goto error_resource; 372 373 box.x = box.y = box.z = 0; 374 box.width = res->width0; 375 box.height = res->height0; 376 box.depth = res->depth0; 377 378 context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box, color_table, 379 util_format_get_stride(colortbl_format, res->width0), 0); 380 381 memset(&sv_tmpl, 0, sizeof(sv_tmpl)); 382 u_sampler_view_default_template(&sv_tmpl, res, res->format); 383 384 sv_tbl = context->create_sampler_view(context, res, &sv_tmpl); 385 pipe_resource_reference(&res, NULL); 386 387 if (!sv_tbl) 388 goto error_resource; 389 390 vl_compositor_clear_layers(cstate); 391 vl_compositor_set_palette_layer(cstate, compositor, 0, sv_idx, sv_tbl, NULL, NULL, false); 392 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); 393 vl_compositor_render(cstate, compositor, vlsurface->surface, NULL); 394 395 pipe_sampler_view_reference(&sv_idx, NULL); 396 pipe_sampler_view_reference(&sv_tbl, NULL); 397 pipe_mutex_unlock(vlsurface->device->mutex); 398 399 return VDP_STATUS_OK; 400 401 error_resource: 402 pipe_sampler_view_reference(&sv_idx, NULL); 403 pipe_sampler_view_reference(&sv_tbl, NULL); 404 pipe_mutex_unlock(vlsurface->device->mutex); 405 return VDP_STATUS_RESOURCES; 406 } 407 408 /** 409 * Copy image data from application memory in a specific YCbCr format to 410 * a VdpOutputSurface. 411 */ 412 VdpStatus 413 vlVdpOutputSurfacePutBitsYCbCr(VdpOutputSurface surface, 414 VdpYCbCrFormat source_ycbcr_format, 415 void const *const *source_data, 416 uint32_t const *source_pitches, 417 VdpRect const *destination_rect, 418 VdpCSCMatrix const *csc_matrix) 419 { 420 vlVdpOutputSurface *vlsurface; 421 struct vl_compositor *compositor; 422 struct vl_compositor_state *cstate; 423 424 struct pipe_context *pipe; 425 enum pipe_format format; 426 struct pipe_video_buffer vtmpl, *vbuffer; 427 struct u_rect dst_rect; 428 struct pipe_sampler_view **sampler_views; 429 430 unsigned i; 431 432 vlsurface = vlGetDataHTAB(surface); 433 if (!vlsurface) 434 return VDP_STATUS_INVALID_HANDLE; 435 436 437 pipe = vlsurface->device->context; 438 compositor = &vlsurface->device->compositor; 439 cstate = &vlsurface->cstate; 440 441 format = FormatYCBCRToPipe(source_ycbcr_format); 442 if (format == PIPE_FORMAT_NONE) 443 return VDP_STATUS_INVALID_Y_CB_CR_FORMAT; 444 445 if (!source_data || !source_pitches) 446 return VDP_STATUS_INVALID_POINTER; 447 448 pipe_mutex_lock(vlsurface->device->mutex); 449 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL); 450 memset(&vtmpl, 0, sizeof(vtmpl)); 451 vtmpl.buffer_format = format; 452 vtmpl.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; 453 454 if (destination_rect) { 455 vtmpl.width = abs(destination_rect->x0-destination_rect->x1); 456 vtmpl.height = abs(destination_rect->y0-destination_rect->y1); 457 } else { 458 vtmpl.width = vlsurface->surface->texture->width0; 459 vtmpl.height = vlsurface->surface->texture->height0; 460 } 461 462 vbuffer = pipe->create_video_buffer(pipe, &vtmpl); 463 if (!vbuffer) { 464 pipe_mutex_unlock(vlsurface->device->mutex); 465 return VDP_STATUS_RESOURCES; 466 } 467 468 sampler_views = vbuffer->get_sampler_view_planes(vbuffer); 469 if (!sampler_views) { 470 vbuffer->destroy(vbuffer); 471 pipe_mutex_unlock(vlsurface->device->mutex); 472 return VDP_STATUS_RESOURCES; 473 } 474 475 for (i = 0; i < 3; ++i) { 476 struct pipe_sampler_view *sv = sampler_views[i]; 477 if (!sv) continue; 478 479 struct pipe_box dst_box = { 480 0, 0, 0, 481 sv->texture->width0, sv->texture->height0, 1 482 }; 483 484 pipe->transfer_inline_write(pipe, sv->texture, 0, PIPE_TRANSFER_WRITE, &dst_box, 485 source_data[i], source_pitches[i], 0); 486 } 487 488 if (!csc_matrix) { 489 vl_csc_matrix csc; 490 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, 1, &csc); 491 vl_compositor_set_csc_matrix(cstate, (const vl_csc_matrix*)&csc); 492 } else { 493 vl_compositor_set_csc_matrix(cstate, csc_matrix); 494 } 495 496 vl_compositor_clear_layers(cstate); 497 vl_compositor_set_buffer_layer(cstate, compositor, 0, vbuffer, NULL, NULL, VL_COMPOSITOR_WEAVE); 498 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); 499 vl_compositor_render(cstate, compositor, vlsurface->surface, NULL); 500 501 vbuffer->destroy(vbuffer); 502 pipe_mutex_unlock(vlsurface->device->mutex); 503 504 return VDP_STATUS_OK; 505 } 506 507 static unsigned 508 BlendFactorToPipe(VdpOutputSurfaceRenderBlendFactor factor) 509 { 510 switch (factor) { 511 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO: 512 return PIPE_BLENDFACTOR_ZERO; 513 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE: 514 return PIPE_BLENDFACTOR_ONE; 515 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_COLOR: 516 return PIPE_BLENDFACTOR_SRC_COLOR; 517 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: 518 return PIPE_BLENDFACTOR_INV_SRC_COLOR; 519 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA: 520 return PIPE_BLENDFACTOR_SRC_ALPHA; 521 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: 522 return PIPE_BLENDFACTOR_INV_SRC_ALPHA; 523 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_ALPHA: 524 return PIPE_BLENDFACTOR_DST_ALPHA; 525 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: 526 return PIPE_BLENDFACTOR_INV_DST_ALPHA; 527 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_COLOR: 528 return PIPE_BLENDFACTOR_DST_COLOR; 529 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_COLOR: 530 return PIPE_BLENDFACTOR_INV_DST_COLOR; 531 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA_SATURATE: 532 return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE; 533 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_COLOR: 534 return PIPE_BLENDFACTOR_CONST_COLOR; 535 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR: 536 return PIPE_BLENDFACTOR_INV_CONST_COLOR; 537 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_ALPHA: 538 return PIPE_BLENDFACTOR_CONST_ALPHA; 539 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA: 540 return PIPE_BLENDFACTOR_INV_CONST_ALPHA; 541 default: 542 assert(0); 543 return PIPE_BLENDFACTOR_ONE; 544 } 545 } 546 547 static unsigned 548 BlendEquationToPipe(VdpOutputSurfaceRenderBlendEquation equation) 549 { 550 switch (equation) { 551 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_SUBTRACT: 552 return PIPE_BLEND_SUBTRACT; 553 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_REVERSE_SUBTRACT: 554 return PIPE_BLEND_REVERSE_SUBTRACT; 555 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD: 556 return PIPE_BLEND_ADD; 557 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MIN: 558 return PIPE_BLEND_MIN; 559 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MAX: 560 return PIPE_BLEND_MAX; 561 default: 562 assert(0); 563 return PIPE_BLEND_ADD; 564 } 565 } 566 567 static void * 568 BlenderToPipe(struct pipe_context *context, 569 VdpOutputSurfaceRenderBlendState const *blend_state) 570 { 571 struct pipe_blend_state blend; 572 573 memset(&blend, 0, sizeof blend); 574 blend.independent_blend_enable = 0; 575 576 if (blend_state) { 577 blend.rt[0].blend_enable = 1; 578 blend.rt[0].rgb_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_color); 579 blend.rt[0].rgb_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_color); 580 blend.rt[0].alpha_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_alpha); 581 blend.rt[0].alpha_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_alpha); 582 blend.rt[0].rgb_func = BlendEquationToPipe(blend_state->blend_equation_color); 583 blend.rt[0].alpha_func = BlendEquationToPipe(blend_state->blend_equation_alpha); 584 } else { 585 blend.rt[0].blend_enable = 0; 586 } 587 588 blend.logicop_enable = 0; 589 blend.logicop_func = PIPE_LOGICOP_CLEAR; 590 blend.rt[0].colormask = PIPE_MASK_RGBA; 591 blend.dither = 0; 592 593 return context->create_blend_state(context, &blend); 594 } 595 596 static struct vertex4f * 597 ColorsToPipe(VdpColor const *colors, uint32_t flags, struct vertex4f result[4]) 598 { 599 unsigned i; 600 struct vertex4f *dst = result; 601 602 if (!colors) 603 return NULL; 604 605 for (i = 0; i < 4; ++i) { 606 dst->x = colors->red; 607 dst->y = colors->green; 608 dst->z = colors->blue; 609 dst->w = colors->alpha; 610 611 ++dst; 612 if (flags & VDP_OUTPUT_SURFACE_RENDER_COLOR_PER_VERTEX) 613 ++colors; 614 } 615 return result; 616 } 617 618 /** 619 * Composite a sub-rectangle of a VdpOutputSurface into a sub-rectangle of 620 * another VdpOutputSurface; Output Surface object VdpOutputSurface. 621 */ 622 VdpStatus 623 vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface, 624 VdpRect const *destination_rect, 625 VdpOutputSurface source_surface, 626 VdpRect const *source_rect, 627 VdpColor const *colors, 628 VdpOutputSurfaceRenderBlendState const *blend_state, 629 uint32_t flags) 630 { 631 vlVdpOutputSurface *dst_vlsurface; 632 vlVdpOutputSurface *src_vlsurface; 633 634 struct pipe_context *context; 635 struct vl_compositor *compositor; 636 struct vl_compositor_state *cstate; 637 638 struct u_rect src_rect, dst_rect; 639 640 struct vertex4f vlcolors[4]; 641 void *blend; 642 643 dst_vlsurface = vlGetDataHTAB(destination_surface); 644 if (!dst_vlsurface) 645 return VDP_STATUS_INVALID_HANDLE; 646 647 src_vlsurface = vlGetDataHTAB(source_surface); 648 if (!src_vlsurface) 649 return VDP_STATUS_INVALID_HANDLE; 650 651 if (dst_vlsurface->device != src_vlsurface->device) 652 return VDP_STATUS_HANDLE_DEVICE_MISMATCH; 653 654 pipe_mutex_lock(dst_vlsurface->device->mutex); 655 vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL); 656 657 context = dst_vlsurface->device->context; 658 compositor = &dst_vlsurface->device->compositor; 659 cstate = &dst_vlsurface->cstate; 660 661 blend = BlenderToPipe(context, blend_state); 662 663 vl_compositor_clear_layers(cstate); 664 vl_compositor_set_layer_blend(cstate, 0, blend, false); 665 vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view, 666 RectToPipe(source_rect, &src_rect), NULL, 667 ColorsToPipe(colors, flags, vlcolors)); 668 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); 669 vl_compositor_render(cstate, compositor, dst_vlsurface->surface, NULL); 670 671 context->delete_blend_state(context, blend); 672 pipe_mutex_unlock(dst_vlsurface->device->mutex); 673 674 return VDP_STATUS_OK; 675 } 676 677 /** 678 * Composite a sub-rectangle of a VdpBitmapSurface into a sub-rectangle of 679 * a VdpOutputSurface; Output Surface object VdpOutputSurface. 680 */ 681 VdpStatus 682 vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface, 683 VdpRect const *destination_rect, 684 VdpBitmapSurface source_surface, 685 VdpRect const *source_rect, 686 VdpColor const *colors, 687 VdpOutputSurfaceRenderBlendState const *blend_state, 688 uint32_t flags) 689 { 690 vlVdpOutputSurface *dst_vlsurface; 691 vlVdpBitmapSurface *src_vlsurface; 692 693 struct pipe_context *context; 694 struct vl_compositor *compositor; 695 struct vl_compositor_state *cstate; 696 697 struct u_rect src_rect, dst_rect; 698 699 struct vertex4f vlcolors[4]; 700 void *blend; 701 702 dst_vlsurface = vlGetDataHTAB(destination_surface); 703 if (!dst_vlsurface) 704 return VDP_STATUS_INVALID_HANDLE; 705 706 src_vlsurface = vlGetDataHTAB(source_surface); 707 if (!src_vlsurface) 708 return VDP_STATUS_INVALID_HANDLE; 709 710 if (dst_vlsurface->device != src_vlsurface->device) 711 return VDP_STATUS_HANDLE_DEVICE_MISMATCH; 712 713 context = dst_vlsurface->device->context; 714 compositor = &dst_vlsurface->device->compositor; 715 cstate = &dst_vlsurface->cstate; 716 717 pipe_mutex_lock(dst_vlsurface->device->mutex); 718 vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL); 719 720 blend = BlenderToPipe(context, blend_state); 721 722 vl_compositor_clear_layers(cstate); 723 vl_compositor_set_layer_blend(cstate, 0, blend, false); 724 vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view, 725 RectToPipe(source_rect, &src_rect), NULL, 726 ColorsToPipe(colors, flags, vlcolors)); 727 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); 728 vl_compositor_render(cstate, compositor, dst_vlsurface->surface, NULL); 729 730 context->delete_blend_state(context, blend); 731 pipe_mutex_unlock(dst_vlsurface->device->mutex); 732 733 return VDP_STATUS_OK; 734 } 735