output.c revision 05579339c0da442669ea75749651e8cf4f9ec39b
1/************************************************************************** 2 * 3 * Copyright 2010 Thomas Balling Sørensen. 4 * Copyright 2011 Christian König. 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 */ 43VdpStatus 44vlVdpOutputSurfaceCreate(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 */ 132VdpStatus 133vlVdpOutputSurfaceDestroy(VdpOutputSurface surface) 134{ 135 vlVdpOutputSurface *vlsurface; 136 137 vlsurface = vlGetDataHTAB(surface); 138 if (!vlsurface) 139 return VDP_STATUS_INVALID_HANDLE; 140 141 pipe_mutex_lock(vlsurface->device->mutex); 142 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL); 143 144 pipe_surface_reference(&vlsurface->surface, NULL); 145 pipe_sampler_view_reference(&vlsurface->sampler_view, NULL); 146 vl_compositor_cleanup_state(&vlsurface->cstate); 147 pipe_mutex_unlock(vlsurface->device->mutex); 148 149 vlRemoveDataHTAB(surface); 150 FREE(vlsurface); 151 152 return VDP_STATUS_OK; 153} 154 155/** 156 * Retrieve the parameters used to create a VdpOutputSurface. 157 */ 158VdpStatus 159vlVdpOutputSurfaceGetParameters(VdpOutputSurface surface, 160 VdpRGBAFormat *rgba_format, 161 uint32_t *width, uint32_t *height) 162{ 163 vlVdpOutputSurface *vlsurface; 164 165 vlsurface = vlGetDataHTAB(surface); 166 if (!vlsurface) 167 return VDP_STATUS_INVALID_HANDLE; 168 169 *rgba_format = PipeToFormatRGBA(vlsurface->sampler_view->texture->format); 170 *width = vlsurface->sampler_view->texture->width0; 171 *height = vlsurface->sampler_view->texture->height0; 172 173 return VDP_STATUS_OK; 174} 175 176/** 177 * Copy image data from a VdpOutputSurface to application memory in the 178 * surface's native format. 179 */ 180VdpStatus 181vlVdpOutputSurfaceGetBitsNative(VdpOutputSurface surface, 182 VdpRect const *source_rect, 183 void *const *destination_data, 184 uint32_t const *destination_pitches) 185{ 186 vlVdpOutputSurface *vlsurface; 187 struct pipe_context *pipe; 188 struct pipe_resource *res; 189 struct pipe_box box; 190 struct pipe_transfer *transfer; 191 uint8_t *map; 192 193 vlsurface = vlGetDataHTAB(surface); 194 if (!vlsurface) 195 return VDP_STATUS_INVALID_HANDLE; 196 197 pipe = vlsurface->device->context; 198 if (!pipe) 199 return VDP_STATUS_INVALID_HANDLE; 200 201 pipe_mutex_lock(vlsurface->device->mutex); 202 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL); 203 204 res = vlsurface->sampler_view->texture; 205 box = RectToPipeBox(source_rect, res); 206 transfer = pipe->get_transfer(pipe, res, 0, PIPE_TRANSFER_READ, &box); 207 if (transfer == NULL) { 208 pipe_mutex_unlock(vlsurface->device->mutex); 209 return VDP_STATUS_RESOURCES; 210 } 211 212 map = pipe_transfer_map(pipe, transfer); 213 if (map == NULL) { 214 pipe_transfer_destroy(pipe, transfer); 215 pipe_mutex_unlock(vlsurface->device->mutex); 216 return VDP_STATUS_RESOURCES; 217 } 218 219 util_copy_rect(*destination_data, res->format, *destination_pitches, 0, 0, 220 box.width, box.height, map, transfer->stride, 0, 0); 221 222 pipe_transfer_unmap(pipe, transfer); 223 pipe_transfer_destroy(pipe, transfer); 224 pipe_mutex_unlock(vlsurface->device->mutex); 225 226 return VDP_STATUS_OK; 227} 228 229/** 230 * Copy image data from application memory in the surface's native format to 231 * a VdpOutputSurface. 232 */ 233VdpStatus 234vlVdpOutputSurfacePutBitsNative(VdpOutputSurface surface, 235 void const *const *source_data, 236 uint32_t const *source_pitches, 237 VdpRect const *destination_rect) 238{ 239 vlVdpOutputSurface *vlsurface; 240 struct pipe_box dst_box; 241 struct pipe_context *pipe; 242 243 vlsurface = vlGetDataHTAB(surface); 244 if (!vlsurface) 245 return VDP_STATUS_INVALID_HANDLE; 246 247 pipe = vlsurface->device->context; 248 if (!pipe) 249 return VDP_STATUS_INVALID_HANDLE; 250 251 pipe_mutex_lock(vlsurface->device->mutex); 252 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL); 253 254 dst_box = RectToPipeBox(destination_rect, vlsurface->sampler_view->texture); 255 pipe->transfer_inline_write(pipe, vlsurface->sampler_view->texture, 0, 256 PIPE_TRANSFER_WRITE, &dst_box, *source_data, 257 *source_pitches, 0); 258 pipe_mutex_unlock(vlsurface->device->mutex); 259 260 return VDP_STATUS_OK; 261} 262 263/** 264 * Copy image data from application memory in a specific indexed format to 265 * a VdpOutputSurface. 266 */ 267VdpStatus 268vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface, 269 VdpIndexedFormat source_indexed_format, 270 void const *const *source_data, 271 uint32_t const *source_pitch, 272 VdpRect const *destination_rect, 273 VdpColorTableFormat color_table_format, 274 void const *color_table) 275{ 276 vlVdpOutputSurface *vlsurface; 277 struct pipe_context *context; 278 struct vl_compositor *compositor; 279 struct vl_compositor_state *cstate; 280 281 enum pipe_format index_format; 282 enum pipe_format colortbl_format; 283 284 struct pipe_resource *res, res_tmpl; 285 struct pipe_sampler_view sv_tmpl; 286 struct pipe_sampler_view *sv_idx = NULL, *sv_tbl = NULL; 287 288 struct pipe_box box; 289 struct u_rect dst_rect; 290 291 vlsurface = vlGetDataHTAB(surface); 292 if (!vlsurface) 293 return VDP_STATUS_INVALID_HANDLE; 294 295 context = vlsurface->device->context; 296 compositor = &vlsurface->device->compositor; 297 cstate = &vlsurface->cstate; 298 299 index_format = FormatIndexedToPipe(source_indexed_format); 300 if (index_format == PIPE_FORMAT_NONE) 301 return VDP_STATUS_INVALID_INDEXED_FORMAT; 302 303 if (!source_data || !source_pitch) 304 return VDP_STATUS_INVALID_POINTER; 305 306 colortbl_format = FormatColorTableToPipe(color_table_format); 307 if (colortbl_format == PIPE_FORMAT_NONE) 308 return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT; 309 310 if (!color_table) 311 return VDP_STATUS_INVALID_POINTER; 312 313 memset(&res_tmpl, 0, sizeof(res_tmpl)); 314 res_tmpl.target = PIPE_TEXTURE_2D; 315 res_tmpl.format = index_format; 316 317 if (destination_rect) { 318 res_tmpl.width0 = abs(destination_rect->x0-destination_rect->x1); 319 res_tmpl.height0 = abs(destination_rect->y0-destination_rect->y1); 320 } else { 321 res_tmpl.width0 = vlsurface->surface->texture->width0; 322 res_tmpl.height0 = vlsurface->surface->texture->height0; 323 } 324 res_tmpl.depth0 = 1; 325 res_tmpl.array_size = 1; 326 res_tmpl.usage = PIPE_USAGE_STAGING; 327 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; 328 329 pipe_mutex_lock(vlsurface->device->mutex); 330 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL); 331 332 res = context->screen->resource_create(context->screen, &res_tmpl); 333 if (!res) 334 goto error_resource; 335 336 box.x = box.y = box.z = 0; 337 box.width = res->width0; 338 box.height = res->height0; 339 box.depth = res->depth0; 340 341 context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box, 342 source_data[0], source_pitch[0], 343 source_pitch[0] * res->height0); 344 345 memset(&sv_tmpl, 0, sizeof(sv_tmpl)); 346 u_sampler_view_default_template(&sv_tmpl, res, res->format); 347 348 sv_idx = context->create_sampler_view(context, res, &sv_tmpl); 349 pipe_resource_reference(&res, NULL); 350 351 if (!sv_idx) 352 goto error_resource; 353 354 memset(&res_tmpl, 0, sizeof(res_tmpl)); 355 res_tmpl.target = PIPE_TEXTURE_1D; 356 res_tmpl.format = colortbl_format; 357 res_tmpl.width0 = 1 << util_format_get_component_bits( 358 index_format, UTIL_FORMAT_COLORSPACE_RGB, 0); 359 res_tmpl.height0 = 1; 360 res_tmpl.depth0 = 1; 361 res_tmpl.array_size = 1; 362 res_tmpl.usage = PIPE_USAGE_STAGING; 363 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; 364 365 res = context->screen->resource_create(context->screen, &res_tmpl); 366 if (!res) 367 goto error_resource; 368 369 box.x = box.y = box.z = 0; 370 box.width = res->width0; 371 box.height = res->height0; 372 box.depth = res->depth0; 373 374 context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box, color_table, 375 util_format_get_stride(colortbl_format, res->width0), 0); 376 377 memset(&sv_tmpl, 0, sizeof(sv_tmpl)); 378 u_sampler_view_default_template(&sv_tmpl, res, res->format); 379 380 sv_tbl = context->create_sampler_view(context, res, &sv_tmpl); 381 pipe_resource_reference(&res, NULL); 382 383 if (!sv_tbl) 384 goto error_resource; 385 386 vl_compositor_clear_layers(cstate); 387 vl_compositor_set_palette_layer(cstate, compositor, 0, sv_idx, sv_tbl, NULL, NULL, false); 388 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); 389 vl_compositor_render(cstate, compositor, vlsurface->surface, NULL); 390 391 pipe_sampler_view_reference(&sv_idx, NULL); 392 pipe_sampler_view_reference(&sv_tbl, NULL); 393 pipe_mutex_unlock(vlsurface->device->mutex); 394 395 return VDP_STATUS_OK; 396 397error_resource: 398 pipe_sampler_view_reference(&sv_idx, NULL); 399 pipe_sampler_view_reference(&sv_tbl, NULL); 400 pipe_mutex_unlock(vlsurface->device->mutex); 401 return VDP_STATUS_RESOURCES; 402} 403 404/** 405 * Copy image data from application memory in a specific YCbCr format to 406 * a VdpOutputSurface. 407 */ 408VdpStatus 409vlVdpOutputSurfacePutBitsYCbCr(VdpOutputSurface surface, 410 VdpYCbCrFormat source_ycbcr_format, 411 void const *const *source_data, 412 uint32_t const *source_pitches, 413 VdpRect const *destination_rect, 414 VdpCSCMatrix const *csc_matrix) 415{ 416 vlVdpOutputSurface *vlsurface; 417 struct vl_compositor *compositor; 418 struct vl_compositor_state *cstate; 419 420 struct pipe_context *pipe; 421 enum pipe_format format; 422 struct pipe_video_buffer vtmpl, *vbuffer; 423 struct u_rect dst_rect; 424 struct pipe_sampler_view **sampler_views; 425 426 unsigned i; 427 428 vlsurface = vlGetDataHTAB(surface); 429 if (!vlsurface) 430 return VDP_STATUS_INVALID_HANDLE; 431 432 433 pipe = vlsurface->device->context; 434 compositor = &vlsurface->device->compositor; 435 cstate = &vlsurface->cstate; 436 437 format = FormatYCBCRToPipe(source_ycbcr_format); 438 if (format == PIPE_FORMAT_NONE) 439 return VDP_STATUS_INVALID_Y_CB_CR_FORMAT; 440 441 if (!source_data || !source_pitches) 442 return VDP_STATUS_INVALID_POINTER; 443 444 pipe_mutex_lock(vlsurface->device->mutex); 445 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL); 446 memset(&vtmpl, 0, sizeof(vtmpl)); 447 vtmpl.buffer_format = format; 448 vtmpl.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; 449 450 if (destination_rect) { 451 vtmpl.width = abs(destination_rect->x0-destination_rect->x1); 452 vtmpl.height = abs(destination_rect->y0-destination_rect->y1); 453 } else { 454 vtmpl.width = vlsurface->surface->texture->width0; 455 vtmpl.height = vlsurface->surface->texture->height0; 456 } 457 458 vbuffer = pipe->create_video_buffer(pipe, &vtmpl); 459 if (!vbuffer) { 460 pipe_mutex_unlock(vlsurface->device->mutex); 461 return VDP_STATUS_RESOURCES; 462 } 463 464 sampler_views = vbuffer->get_sampler_view_planes(vbuffer); 465 if (!sampler_views) { 466 vbuffer->destroy(vbuffer); 467 pipe_mutex_unlock(vlsurface->device->mutex); 468 return VDP_STATUS_RESOURCES; 469 } 470 471 for (i = 0; i < 3; ++i) { 472 struct pipe_sampler_view *sv = sampler_views[i]; 473 if (!sv) continue; 474 475 struct pipe_box dst_box = { 476 0, 0, 0, 477 sv->texture->width0, sv->texture->height0, 1 478 }; 479 480 pipe->transfer_inline_write(pipe, sv->texture, 0, PIPE_TRANSFER_WRITE, &dst_box, 481 source_data[i], source_pitches[i], 0); 482 } 483 484 if (!csc_matrix) { 485 vl_csc_matrix csc; 486 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, 1, &csc); 487 vl_compositor_set_csc_matrix(cstate, (const vl_csc_matrix*)&csc); 488 } else { 489 vl_compositor_set_csc_matrix(cstate, csc_matrix); 490 } 491 492 vl_compositor_clear_layers(cstate); 493 vl_compositor_set_buffer_layer(cstate, compositor, 0, vbuffer, NULL, NULL, VL_COMPOSITOR_WEAVE); 494 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); 495 vl_compositor_render(cstate, compositor, vlsurface->surface, NULL); 496 497 vbuffer->destroy(vbuffer); 498 pipe_mutex_unlock(vlsurface->device->mutex); 499 500 return VDP_STATUS_OK; 501} 502 503static unsigned 504BlendFactorToPipe(VdpOutputSurfaceRenderBlendFactor factor) 505{ 506 switch (factor) { 507 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO: 508 return PIPE_BLENDFACTOR_ZERO; 509 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE: 510 return PIPE_BLENDFACTOR_ONE; 511 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_COLOR: 512 return PIPE_BLENDFACTOR_SRC_COLOR; 513 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: 514 return PIPE_BLENDFACTOR_INV_SRC_COLOR; 515 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA: 516 return PIPE_BLENDFACTOR_SRC_ALPHA; 517 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: 518 return PIPE_BLENDFACTOR_INV_SRC_ALPHA; 519 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_ALPHA: 520 return PIPE_BLENDFACTOR_DST_ALPHA; 521 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: 522 return PIPE_BLENDFACTOR_INV_DST_ALPHA; 523 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_COLOR: 524 return PIPE_BLENDFACTOR_DST_COLOR; 525 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_COLOR: 526 return PIPE_BLENDFACTOR_INV_DST_COLOR; 527 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA_SATURATE: 528 return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE; 529 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_COLOR: 530 return PIPE_BLENDFACTOR_CONST_COLOR; 531 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR: 532 return PIPE_BLENDFACTOR_INV_CONST_COLOR; 533 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_ALPHA: 534 return PIPE_BLENDFACTOR_CONST_ALPHA; 535 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA: 536 return PIPE_BLENDFACTOR_INV_CONST_ALPHA; 537 default: 538 assert(0); 539 return PIPE_BLENDFACTOR_ONE; 540 } 541} 542 543static unsigned 544BlendEquationToPipe(VdpOutputSurfaceRenderBlendEquation equation) 545{ 546 switch (equation) { 547 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_SUBTRACT: 548 return PIPE_BLEND_SUBTRACT; 549 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_REVERSE_SUBTRACT: 550 return PIPE_BLEND_REVERSE_SUBTRACT; 551 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD: 552 return PIPE_BLEND_ADD; 553 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MIN: 554 return PIPE_BLEND_MIN; 555 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MAX: 556 return PIPE_BLEND_MAX; 557 default: 558 assert(0); 559 return PIPE_BLEND_ADD; 560 } 561} 562 563static void * 564BlenderToPipe(struct pipe_context *context, 565 VdpOutputSurfaceRenderBlendState const *blend_state) 566{ 567 struct pipe_blend_state blend; 568 569 memset(&blend, 0, sizeof blend); 570 blend.independent_blend_enable = 0; 571 572 if (blend_state) { 573 blend.rt[0].blend_enable = 1; 574 blend.rt[0].rgb_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_color); 575 blend.rt[0].rgb_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_color); 576 blend.rt[0].alpha_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_alpha); 577 blend.rt[0].alpha_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_alpha); 578 blend.rt[0].rgb_func = BlendEquationToPipe(blend_state->blend_equation_color); 579 blend.rt[0].alpha_func = BlendEquationToPipe(blend_state->blend_equation_alpha); 580 } else { 581 blend.rt[0].blend_enable = 0; 582 } 583 584 blend.logicop_enable = 0; 585 blend.logicop_func = PIPE_LOGICOP_CLEAR; 586 blend.rt[0].colormask = PIPE_MASK_RGBA; 587 blend.dither = 0; 588 589 return context->create_blend_state(context, &blend); 590} 591 592static struct vertex4f * 593ColorsToPipe(VdpColor const *colors, uint32_t flags, struct vertex4f result[4]) 594{ 595 unsigned i; 596 struct vertex4f *dst = result; 597 598 if (!colors) 599 return NULL; 600 601 for (i = 0; i < 4; ++i) { 602 dst->x = colors->red; 603 dst->y = colors->green; 604 dst->z = colors->blue; 605 dst->w = colors->alpha; 606 607 ++dst; 608 if (flags & VDP_OUTPUT_SURFACE_RENDER_COLOR_PER_VERTEX) 609 ++colors; 610 } 611 return result; 612} 613 614/** 615 * Composite a sub-rectangle of a VdpOutputSurface into a sub-rectangle of 616 * another VdpOutputSurface; Output Surface object VdpOutputSurface. 617 */ 618VdpStatus 619vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface, 620 VdpRect const *destination_rect, 621 VdpOutputSurface source_surface, 622 VdpRect const *source_rect, 623 VdpColor const *colors, 624 VdpOutputSurfaceRenderBlendState const *blend_state, 625 uint32_t flags) 626{ 627 vlVdpOutputSurface *dst_vlsurface; 628 vlVdpOutputSurface *src_vlsurface; 629 630 struct pipe_context *context; 631 struct vl_compositor *compositor; 632 struct vl_compositor_state *cstate; 633 634 struct u_rect src_rect, dst_rect; 635 636 struct vertex4f vlcolors[4]; 637 void *blend; 638 639 dst_vlsurface = vlGetDataHTAB(destination_surface); 640 if (!dst_vlsurface) 641 return VDP_STATUS_INVALID_HANDLE; 642 643 src_vlsurface = vlGetDataHTAB(source_surface); 644 if (!src_vlsurface) 645 return VDP_STATUS_INVALID_HANDLE; 646 647 if (dst_vlsurface->device != src_vlsurface->device) 648 return VDP_STATUS_HANDLE_DEVICE_MISMATCH; 649 650 pipe_mutex_lock(dst_vlsurface->device->mutex); 651 vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL); 652 653 context = dst_vlsurface->device->context; 654 compositor = &dst_vlsurface->device->compositor; 655 cstate = &dst_vlsurface->cstate; 656 657 blend = BlenderToPipe(context, blend_state); 658 659 vl_compositor_clear_layers(cstate); 660 vl_compositor_set_layer_blend(cstate, 0, blend, false); 661 vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view, 662 RectToPipe(source_rect, &src_rect), NULL, 663 ColorsToPipe(colors, flags, vlcolors)); 664 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); 665 vl_compositor_render(cstate, compositor, dst_vlsurface->surface, NULL); 666 667 context->delete_blend_state(context, blend); 668 pipe_mutex_unlock(dst_vlsurface->device->mutex); 669 670 return VDP_STATUS_OK; 671} 672 673/** 674 * Composite a sub-rectangle of a VdpBitmapSurface into a sub-rectangle of 675 * a VdpOutputSurface; Output Surface object VdpOutputSurface. 676 */ 677VdpStatus 678vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface, 679 VdpRect const *destination_rect, 680 VdpBitmapSurface source_surface, 681 VdpRect const *source_rect, 682 VdpColor const *colors, 683 VdpOutputSurfaceRenderBlendState const *blend_state, 684 uint32_t flags) 685{ 686 vlVdpOutputSurface *dst_vlsurface; 687 vlVdpBitmapSurface *src_vlsurface; 688 689 struct pipe_context *context; 690 struct vl_compositor *compositor; 691 struct vl_compositor_state *cstate; 692 693 struct u_rect src_rect, dst_rect; 694 695 struct vertex4f vlcolors[4]; 696 void *blend; 697 698 dst_vlsurface = vlGetDataHTAB(destination_surface); 699 if (!dst_vlsurface) 700 return VDP_STATUS_INVALID_HANDLE; 701 702 src_vlsurface = vlGetDataHTAB(source_surface); 703 if (!src_vlsurface) 704 return VDP_STATUS_INVALID_HANDLE; 705 706 if (dst_vlsurface->device != src_vlsurface->device) 707 return VDP_STATUS_HANDLE_DEVICE_MISMATCH; 708 709 context = dst_vlsurface->device->context; 710 compositor = &dst_vlsurface->device->compositor; 711 cstate = &dst_vlsurface->cstate; 712 713 pipe_mutex_lock(dst_vlsurface->device->mutex); 714 vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL); 715 716 blend = BlenderToPipe(context, blend_state); 717 718 vl_compositor_clear_layers(cstate); 719 vl_compositor_set_layer_blend(cstate, 0, blend, false); 720 vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view, 721 RectToPipe(source_rect, &src_rect), NULL, 722 ColorsToPipe(colors, flags, vlcolors)); 723 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); 724 vl_compositor_render(cstate, compositor, dst_vlsurface->surface, NULL); 725 726 context->delete_blend_state(context, blend); 727 pipe_mutex_unlock(dst_vlsurface->device->mutex); 728 729 return VDP_STATUS_OK; 730} 731