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 VMWARE 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/format/u_format.h" 35#include "util/u_surface.h" 36 37#include "vl/vl_csc.h" 38 39#include "frontend/drm_driver.h" 40 41#include "vdpau_private.h" 42 43/** 44 * Create a VdpOutputSurface. 45 */ 46VdpStatus 47vlVdpOutputSurfaceCreate(VdpDevice device, 48 VdpRGBAFormat rgba_format, 49 uint32_t width, uint32_t height, 50 VdpOutputSurface *surface) 51{ 52 struct pipe_context *pipe; 53 struct pipe_resource res_tmpl, *res; 54 struct pipe_sampler_view sv_templ; 55 struct pipe_surface surf_templ; 56 57 vlVdpOutputSurface *vlsurface = NULL; 58 59 if (!(width && height)) 60 return VDP_STATUS_INVALID_SIZE; 61 62 vlVdpDevice *dev = vlGetDataHTAB(device); 63 if (!dev) 64 return VDP_STATUS_INVALID_HANDLE; 65 66 pipe = dev->context; 67 if (!pipe) 68 return VDP_STATUS_INVALID_HANDLE; 69 70 vlsurface = CALLOC(1, sizeof(vlVdpOutputSurface)); 71 if (!vlsurface) 72 return VDP_STATUS_RESOURCES; 73 74 DeviceReference(&vlsurface->device, dev); 75 76 memset(&res_tmpl, 0, sizeof(res_tmpl)); 77 78 /* 79 * The output won't look correctly when this buffer is send to X, 80 * if the VDPAU RGB component order doesn't match the X11 one so 81 * we only allow the X11 format 82 */ 83 vlsurface->send_to_X = dev->vscreen->color_depth == 24 && 84 rgba_format == VDP_RGBA_FORMAT_B8G8R8A8; 85 86 res_tmpl.target = PIPE_TEXTURE_2D; 87 res_tmpl.format = VdpFormatRGBAToPipe(rgba_format); 88 res_tmpl.width0 = width; 89 res_tmpl.height0 = height; 90 res_tmpl.depth0 = 1; 91 res_tmpl.array_size = 1; 92 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET | 93 PIPE_BIND_SHARED | PIPE_BIND_SCANOUT; 94 res_tmpl.usage = PIPE_USAGE_DEFAULT; 95 96 mtx_lock(&dev->mutex); 97 98 if (!CheckSurfaceParams(pipe->screen, &res_tmpl)) 99 goto err_unlock; 100 101 res = pipe->screen->resource_create(pipe->screen, &res_tmpl); 102 if (!res) 103 goto err_unlock; 104 105 vlVdpDefaultSamplerViewTemplate(&sv_templ, res); 106 vlsurface->sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ); 107 if (!vlsurface->sampler_view) 108 goto err_resource; 109 110 memset(&surf_templ, 0, sizeof(surf_templ)); 111 surf_templ.format = res->format; 112 vlsurface->surface = pipe->create_surface(pipe, res, &surf_templ); 113 if (!vlsurface->surface) 114 goto err_resource; 115 116 *surface = vlAddDataHTAB(vlsurface); 117 if (*surface == 0) 118 goto err_resource; 119 120 pipe_resource_reference(&res, NULL); 121 122 if (!vl_compositor_init_state(&vlsurface->cstate, pipe)) 123 goto err_resource; 124 125 vl_compositor_reset_dirty_area(&vlsurface->dirty_area); 126 mtx_unlock(&dev->mutex); 127 128 return VDP_STATUS_OK; 129 130err_resource: 131 pipe_sampler_view_reference(&vlsurface->sampler_view, NULL); 132 pipe_surface_reference(&vlsurface->surface, NULL); 133 pipe_resource_reference(&res, NULL); 134err_unlock: 135 mtx_unlock(&dev->mutex); 136 DeviceReference(&vlsurface->device, NULL); 137 FREE(vlsurface); 138 return VDP_STATUS_ERROR; 139} 140 141/** 142 * Destroy a VdpOutputSurface. 143 */ 144VdpStatus 145vlVdpOutputSurfaceDestroy(VdpOutputSurface surface) 146{ 147 vlVdpOutputSurface *vlsurface; 148 struct pipe_context *pipe; 149 150 vlsurface = vlGetDataHTAB(surface); 151 if (!vlsurface) 152 return VDP_STATUS_INVALID_HANDLE; 153 154 pipe = vlsurface->device->context; 155 156 mtx_lock(&vlsurface->device->mutex); 157 158 pipe_surface_reference(&vlsurface->surface, NULL); 159 pipe_sampler_view_reference(&vlsurface->sampler_view, NULL); 160 pipe->screen->fence_reference(pipe->screen, &vlsurface->fence, NULL); 161 vl_compositor_cleanup_state(&vlsurface->cstate); 162 mtx_unlock(&vlsurface->device->mutex); 163 164 vlRemoveDataHTAB(surface); 165 DeviceReference(&vlsurface->device, NULL); 166 FREE(vlsurface); 167 168 return VDP_STATUS_OK; 169} 170 171/** 172 * Retrieve the parameters used to create a VdpOutputSurface. 173 */ 174VdpStatus 175vlVdpOutputSurfaceGetParameters(VdpOutputSurface surface, 176 VdpRGBAFormat *rgba_format, 177 uint32_t *width, uint32_t *height) 178{ 179 vlVdpOutputSurface *vlsurface; 180 181 vlsurface = vlGetDataHTAB(surface); 182 if (!vlsurface) 183 return VDP_STATUS_INVALID_HANDLE; 184 185 *rgba_format = PipeToFormatRGBA(vlsurface->sampler_view->texture->format); 186 *width = vlsurface->sampler_view->texture->width0; 187 *height = vlsurface->sampler_view->texture->height0; 188 189 return VDP_STATUS_OK; 190} 191 192/** 193 * Copy image data from a VdpOutputSurface to application memory in the 194 * surface's native format. 195 */ 196VdpStatus 197vlVdpOutputSurfaceGetBitsNative(VdpOutputSurface surface, 198 VdpRect const *source_rect, 199 void *const *destination_data, 200 uint32_t const *destination_pitches) 201{ 202 vlVdpOutputSurface *vlsurface; 203 struct pipe_context *pipe; 204 struct pipe_resource *res; 205 struct pipe_box box; 206 struct pipe_transfer *transfer; 207 uint8_t *map; 208 209 vlsurface = vlGetDataHTAB(surface); 210 if (!vlsurface) 211 return VDP_STATUS_INVALID_HANDLE; 212 213 pipe = vlsurface->device->context; 214 if (!pipe) 215 return VDP_STATUS_INVALID_HANDLE; 216 217 if (!destination_data || !destination_pitches) 218 return VDP_STATUS_INVALID_POINTER; 219 220 mtx_lock(&vlsurface->device->mutex); 221 222 res = vlsurface->sampler_view->texture; 223 box = RectToPipeBox(source_rect, res); 224 map = pipe->texture_map(pipe, res, 0, PIPE_MAP_READ, &box, &transfer); 225 if (!map) { 226 mtx_unlock(&vlsurface->device->mutex); 227 return VDP_STATUS_RESOURCES; 228 } 229 230 util_copy_rect(*destination_data, res->format, *destination_pitches, 0, 0, 231 box.width, box.height, map, transfer->stride, 0, 0); 232 233 pipe_texture_unmap(pipe, transfer); 234 mtx_unlock(&vlsurface->device->mutex); 235 236 return VDP_STATUS_OK; 237} 238 239/** 240 * Copy image data from application memory in the surface's native format to 241 * a VdpOutputSurface. 242 */ 243VdpStatus 244vlVdpOutputSurfacePutBitsNative(VdpOutputSurface surface, 245 void const *const *source_data, 246 uint32_t const *source_pitches, 247 VdpRect const *destination_rect) 248{ 249 vlVdpOutputSurface *vlsurface; 250 struct pipe_box dst_box; 251 struct pipe_context *pipe; 252 253 vlsurface = vlGetDataHTAB(surface); 254 if (!vlsurface) 255 return VDP_STATUS_INVALID_HANDLE; 256 257 pipe = vlsurface->device->context; 258 if (!pipe) 259 return VDP_STATUS_INVALID_HANDLE; 260 261 if (!source_data || !source_pitches) 262 return VDP_STATUS_INVALID_POINTER; 263 264 mtx_lock(&vlsurface->device->mutex); 265 266 dst_box = RectToPipeBox(destination_rect, vlsurface->sampler_view->texture); 267 268 /* Check for a no-op. (application bug?) */ 269 if (!dst_box.width || !dst_box.height) { 270 mtx_unlock(&vlsurface->device->mutex); 271 return VDP_STATUS_OK; 272 } 273 274 pipe->texture_subdata(pipe, vlsurface->sampler_view->texture, 0, 275 PIPE_MAP_WRITE, &dst_box, *source_data, 276 *source_pitches, 0); 277 mtx_unlock(&vlsurface->device->mutex); 278 279 return VDP_STATUS_OK; 280} 281 282/** 283 * Copy image data from application memory in a specific indexed format to 284 * a VdpOutputSurface. 285 */ 286VdpStatus 287vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface, 288 VdpIndexedFormat source_indexed_format, 289 void const *const *source_data, 290 uint32_t const *source_pitch, 291 VdpRect const *destination_rect, 292 VdpColorTableFormat color_table_format, 293 void const *color_table) 294{ 295 vlVdpOutputSurface *vlsurface; 296 struct pipe_context *context; 297 struct vl_compositor *compositor; 298 struct vl_compositor_state *cstate; 299 300 enum pipe_format index_format; 301 enum pipe_format colortbl_format; 302 303 struct pipe_resource *res, res_tmpl; 304 struct pipe_sampler_view sv_tmpl; 305 struct pipe_sampler_view *sv_idx = NULL, *sv_tbl = NULL; 306 307 struct pipe_box box; 308 struct u_rect dst_rect; 309 310 vlsurface = vlGetDataHTAB(surface); 311 if (!vlsurface) 312 return VDP_STATUS_INVALID_HANDLE; 313 314 context = vlsurface->device->context; 315 compositor = &vlsurface->device->compositor; 316 cstate = &vlsurface->cstate; 317 318 index_format = FormatIndexedToPipe(source_indexed_format); 319 if (index_format == PIPE_FORMAT_NONE) 320 return VDP_STATUS_INVALID_INDEXED_FORMAT; 321 322 if (!source_data || !source_pitch) 323 return VDP_STATUS_INVALID_POINTER; 324 325 colortbl_format = FormatColorTableToPipe(color_table_format); 326 if (colortbl_format == PIPE_FORMAT_NONE) 327 return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT; 328 329 if (!color_table) 330 return VDP_STATUS_INVALID_POINTER; 331 332 memset(&res_tmpl, 0, sizeof(res_tmpl)); 333 res_tmpl.target = PIPE_TEXTURE_2D; 334 res_tmpl.format = index_format; 335 336 if (destination_rect) { 337 if (destination_rect->x1 > destination_rect->x0 && 338 destination_rect->y1 > destination_rect->y0) { 339 res_tmpl.width0 = destination_rect->x1 - destination_rect->x0; 340 res_tmpl.height0 = destination_rect->y1 - destination_rect->y0; 341 } 342 } else { 343 res_tmpl.width0 = vlsurface->surface->texture->width0; 344 res_tmpl.height0 = vlsurface->surface->texture->height0; 345 } 346 res_tmpl.depth0 = 1; 347 res_tmpl.array_size = 1; 348 res_tmpl.usage = PIPE_USAGE_STAGING; 349 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; 350 351 mtx_lock(&vlsurface->device->mutex); 352 353 if (!CheckSurfaceParams(context->screen, &res_tmpl)) 354 goto error_resource; 355 356 res = context->screen->resource_create(context->screen, &res_tmpl); 357 if (!res) 358 goto error_resource; 359 360 box.x = box.y = box.z = 0; 361 box.width = res->width0; 362 box.height = res->height0; 363 box.depth = res->depth0; 364 365 context->texture_subdata(context, res, 0, PIPE_MAP_WRITE, &box, 366 source_data[0], source_pitch[0], 367 source_pitch[0] * res->height0); 368 369 memset(&sv_tmpl, 0, sizeof(sv_tmpl)); 370 u_sampler_view_default_template(&sv_tmpl, res, res->format); 371 372 sv_idx = context->create_sampler_view(context, res, &sv_tmpl); 373 pipe_resource_reference(&res, NULL); 374 375 if (!sv_idx) 376 goto error_resource; 377 378 memset(&res_tmpl, 0, sizeof(res_tmpl)); 379 res_tmpl.target = PIPE_TEXTURE_1D; 380 res_tmpl.format = colortbl_format; 381 res_tmpl.width0 = 1 << util_format_get_component_bits( 382 index_format, UTIL_FORMAT_COLORSPACE_RGB, 0); 383 res_tmpl.height0 = 1; 384 res_tmpl.depth0 = 1; 385 res_tmpl.array_size = 1; 386 res_tmpl.usage = PIPE_USAGE_STAGING; 387 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; 388 389 res = context->screen->resource_create(context->screen, &res_tmpl); 390 if (!res) 391 goto error_resource; 392 393 box.x = box.y = box.z = 0; 394 box.width = res->width0; 395 box.height = res->height0; 396 box.depth = res->depth0; 397 398 context->texture_subdata(context, res, 0, PIPE_MAP_WRITE, &box, color_table, 399 util_format_get_stride(colortbl_format, res->width0), 0); 400 401 memset(&sv_tmpl, 0, sizeof(sv_tmpl)); 402 u_sampler_view_default_template(&sv_tmpl, res, res->format); 403 404 sv_tbl = context->create_sampler_view(context, res, &sv_tmpl); 405 pipe_resource_reference(&res, NULL); 406 407 if (!sv_tbl) 408 goto error_resource; 409 410 vl_compositor_clear_layers(cstate); 411 vl_compositor_set_palette_layer(cstate, compositor, 0, sv_idx, sv_tbl, NULL, NULL, false); 412 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); 413 vl_compositor_render(cstate, compositor, vlsurface->surface, &vlsurface->dirty_area, false); 414 415 pipe_sampler_view_reference(&sv_idx, NULL); 416 pipe_sampler_view_reference(&sv_tbl, NULL); 417 mtx_unlock(&vlsurface->device->mutex); 418 419 return VDP_STATUS_OK; 420 421error_resource: 422 pipe_sampler_view_reference(&sv_idx, NULL); 423 pipe_sampler_view_reference(&sv_tbl, NULL); 424 mtx_unlock(&vlsurface->device->mutex); 425 return VDP_STATUS_RESOURCES; 426} 427 428/** 429 * Copy image data from application memory in a specific YCbCr format to 430 * a VdpOutputSurface. 431 */ 432VdpStatus 433vlVdpOutputSurfacePutBitsYCbCr(VdpOutputSurface surface, 434 VdpYCbCrFormat source_ycbcr_format, 435 void const *const *source_data, 436 uint32_t const *source_pitches, 437 VdpRect const *destination_rect, 438 VdpCSCMatrix const *csc_matrix) 439{ 440 vlVdpOutputSurface *vlsurface; 441 struct vl_compositor *compositor; 442 struct vl_compositor_state *cstate; 443 444 struct pipe_context *pipe; 445 enum pipe_format format; 446 struct pipe_video_buffer vtmpl, *vbuffer; 447 struct u_rect dst_rect; 448 struct pipe_sampler_view **sampler_views; 449 450 unsigned i; 451 452 vlsurface = vlGetDataHTAB(surface); 453 if (!vlsurface) 454 return VDP_STATUS_INVALID_HANDLE; 455 456 457 pipe = vlsurface->device->context; 458 compositor = &vlsurface->device->compositor; 459 cstate = &vlsurface->cstate; 460 461 format = FormatYCBCRToPipe(source_ycbcr_format); 462 if (format == PIPE_FORMAT_NONE) 463 return VDP_STATUS_INVALID_Y_CB_CR_FORMAT; 464 465 if (!source_data || !source_pitches) 466 return VDP_STATUS_INVALID_POINTER; 467 468 mtx_lock(&vlsurface->device->mutex); 469 memset(&vtmpl, 0, sizeof(vtmpl)); 470 vtmpl.buffer_format = format; 471 472 if (destination_rect) { 473 if (destination_rect->x1 > destination_rect->x0 && 474 destination_rect->y1 > destination_rect->y0) { 475 vtmpl.width = destination_rect->x1 - destination_rect->x0; 476 vtmpl.height = destination_rect->y1 - destination_rect->y0; 477 } 478 } else { 479 vtmpl.width = vlsurface->surface->texture->width0; 480 vtmpl.height = vlsurface->surface->texture->height0; 481 } 482 483 vbuffer = pipe->create_video_buffer(pipe, &vtmpl); 484 if (!vbuffer) { 485 mtx_unlock(&vlsurface->device->mutex); 486 return VDP_STATUS_RESOURCES; 487 } 488 489 sampler_views = vbuffer->get_sampler_view_planes(vbuffer); 490 if (!sampler_views) { 491 vbuffer->destroy(vbuffer); 492 mtx_unlock(&vlsurface->device->mutex); 493 return VDP_STATUS_RESOURCES; 494 } 495 496 for (i = 0; i < 3; ++i) { 497 struct pipe_sampler_view *sv = sampler_views[i]; 498 if (!sv) continue; 499 500 struct pipe_box dst_box = { 501 0, 0, 0, 502 sv->texture->width0, sv->texture->height0, 1 503 }; 504 505 pipe->texture_subdata(pipe, sv->texture, 0, PIPE_MAP_WRITE, &dst_box, 506 source_data[i], source_pitches[i], 0); 507 } 508 509 if (!csc_matrix) { 510 vl_csc_matrix csc; 511 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, 1, &csc); 512 if (!vl_compositor_set_csc_matrix(cstate, (const vl_csc_matrix*)&csc, 1.0f, 0.0f)) 513 goto err_csc_matrix; 514 } else { 515 if (!vl_compositor_set_csc_matrix(cstate, csc_matrix, 1.0f, 0.0f)) 516 goto err_csc_matrix; 517 } 518 519 vl_compositor_clear_layers(cstate); 520 vl_compositor_set_buffer_layer(cstate, compositor, 0, vbuffer, NULL, NULL, VL_COMPOSITOR_WEAVE); 521 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); 522 vl_compositor_render(cstate, compositor, vlsurface->surface, &vlsurface->dirty_area, false); 523 524 vbuffer->destroy(vbuffer); 525 mtx_unlock(&vlsurface->device->mutex); 526 527 return VDP_STATUS_OK; 528err_csc_matrix: 529 vbuffer->destroy(vbuffer); 530 mtx_unlock(&vlsurface->device->mutex); 531 return VDP_STATUS_ERROR; 532} 533 534static unsigned 535BlendFactorToPipe(VdpOutputSurfaceRenderBlendFactor factor) 536{ 537 switch (factor) { 538 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO: 539 return PIPE_BLENDFACTOR_ZERO; 540 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE: 541 return PIPE_BLENDFACTOR_ONE; 542 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_COLOR: 543 return PIPE_BLENDFACTOR_SRC_COLOR; 544 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: 545 return PIPE_BLENDFACTOR_INV_SRC_COLOR; 546 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA: 547 return PIPE_BLENDFACTOR_SRC_ALPHA; 548 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: 549 return PIPE_BLENDFACTOR_INV_SRC_ALPHA; 550 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_ALPHA: 551 return PIPE_BLENDFACTOR_DST_ALPHA; 552 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: 553 return PIPE_BLENDFACTOR_INV_DST_ALPHA; 554 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_COLOR: 555 return PIPE_BLENDFACTOR_DST_COLOR; 556 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_COLOR: 557 return PIPE_BLENDFACTOR_INV_DST_COLOR; 558 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA_SATURATE: 559 return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE; 560 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_COLOR: 561 return PIPE_BLENDFACTOR_CONST_COLOR; 562 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR: 563 return PIPE_BLENDFACTOR_INV_CONST_COLOR; 564 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_ALPHA: 565 return PIPE_BLENDFACTOR_CONST_ALPHA; 566 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA: 567 return PIPE_BLENDFACTOR_INV_CONST_ALPHA; 568 default: 569 assert(0); 570 return PIPE_BLENDFACTOR_ONE; 571 } 572} 573 574static unsigned 575BlendEquationToPipe(VdpOutputSurfaceRenderBlendEquation equation) 576{ 577 switch (equation) { 578 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_SUBTRACT: 579 return PIPE_BLEND_SUBTRACT; 580 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_REVERSE_SUBTRACT: 581 return PIPE_BLEND_REVERSE_SUBTRACT; 582 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD: 583 return PIPE_BLEND_ADD; 584 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MIN: 585 return PIPE_BLEND_MIN; 586 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MAX: 587 return PIPE_BLEND_MAX; 588 default: 589 assert(0); 590 return PIPE_BLEND_ADD; 591 } 592} 593 594static void * 595BlenderToPipe(struct pipe_context *context, 596 VdpOutputSurfaceRenderBlendState const *blend_state) 597{ 598 struct pipe_blend_state blend; 599 600 memset(&blend, 0, sizeof blend); 601 blend.independent_blend_enable = 0; 602 603 if (blend_state) { 604 blend.rt[0].blend_enable = 1; 605 blend.rt[0].rgb_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_color); 606 blend.rt[0].rgb_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_color); 607 blend.rt[0].alpha_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_alpha); 608 blend.rt[0].alpha_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_alpha); 609 blend.rt[0].rgb_func = BlendEquationToPipe(blend_state->blend_equation_color); 610 blend.rt[0].alpha_func = BlendEquationToPipe(blend_state->blend_equation_alpha); 611 } else { 612 blend.rt[0].blend_enable = 0; 613 } 614 615 blend.logicop_enable = 0; 616 blend.logicop_func = PIPE_LOGICOP_CLEAR; 617 blend.rt[0].colormask = PIPE_MASK_RGBA; 618 blend.dither = 0; 619 620 return context->create_blend_state(context, &blend); 621} 622 623static struct vertex4f * 624ColorsToPipe(VdpColor const *colors, uint32_t flags, struct vertex4f result[4]) 625{ 626 unsigned i; 627 struct vertex4f *dst = result; 628 629 if (!colors) 630 return NULL; 631 632 for (i = 0; i < 4; ++i) { 633 dst->x = colors->red; 634 dst->y = colors->green; 635 dst->z = colors->blue; 636 dst->w = colors->alpha; 637 638 ++dst; 639 if (flags & VDP_OUTPUT_SURFACE_RENDER_COLOR_PER_VERTEX) 640 ++colors; 641 } 642 return result; 643} 644 645/** 646 * Composite a sub-rectangle of a VdpOutputSurface into a sub-rectangle of 647 * another VdpOutputSurface; Output Surface object VdpOutputSurface. 648 */ 649VdpStatus 650vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface, 651 VdpRect const *destination_rect, 652 VdpOutputSurface source_surface, 653 VdpRect const *source_rect, 654 VdpColor const *colors, 655 VdpOutputSurfaceRenderBlendState const *blend_state, 656 uint32_t flags) 657{ 658 vlVdpOutputSurface *dst_vlsurface; 659 660 struct pipe_context *context; 661 struct pipe_sampler_view *src_sv; 662 struct vl_compositor *compositor; 663 struct vl_compositor_state *cstate; 664 665 struct u_rect src_rect, dst_rect; 666 667 struct vertex4f vlcolors[4]; 668 void *blend; 669 670 dst_vlsurface = vlGetDataHTAB(destination_surface); 671 if (!dst_vlsurface) 672 return VDP_STATUS_INVALID_HANDLE; 673 674 if (source_surface == VDP_INVALID_HANDLE) { 675 src_sv = dst_vlsurface->device->dummy_sv; 676 677 } else { 678 vlVdpOutputSurface *src_vlsurface = vlGetDataHTAB(source_surface); 679 if (!src_vlsurface) 680 return VDP_STATUS_INVALID_HANDLE; 681 682 if (dst_vlsurface->device != src_vlsurface->device) 683 return VDP_STATUS_HANDLE_DEVICE_MISMATCH; 684 685 src_sv = src_vlsurface->sampler_view; 686 } 687 688 mtx_lock(&dst_vlsurface->device->mutex); 689 690 context = dst_vlsurface->device->context; 691 compositor = &dst_vlsurface->device->compositor; 692 cstate = &dst_vlsurface->cstate; 693 694 blend = BlenderToPipe(context, blend_state); 695 696 vl_compositor_clear_layers(cstate); 697 vl_compositor_set_layer_blend(cstate, 0, blend, false); 698 vl_compositor_set_rgba_layer(cstate, compositor, 0, src_sv, 699 RectToPipe(source_rect, &src_rect), NULL, 700 ColorsToPipe(colors, flags, vlcolors)); 701 STATIC_ASSERT(VL_COMPOSITOR_ROTATE_0 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_0); 702 STATIC_ASSERT(VL_COMPOSITOR_ROTATE_90 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_90); 703 STATIC_ASSERT(VL_COMPOSITOR_ROTATE_180 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_180); 704 STATIC_ASSERT(VL_COMPOSITOR_ROTATE_270 == VDP_OUTPUT_SURFACE_RENDER_ROTATE_270); 705 vl_compositor_set_layer_rotation(cstate, 0, flags & 3); 706 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); 707 vl_compositor_render(cstate, compositor, dst_vlsurface->surface, &dst_vlsurface->dirty_area, false); 708 709 context->delete_blend_state(context, blend); 710 mtx_unlock(&dst_vlsurface->device->mutex); 711 712 return VDP_STATUS_OK; 713} 714 715/** 716 * Composite a sub-rectangle of a VdpBitmapSurface into a sub-rectangle of 717 * a VdpOutputSurface; Output Surface object VdpOutputSurface. 718 */ 719VdpStatus 720vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface, 721 VdpRect const *destination_rect, 722 VdpBitmapSurface source_surface, 723 VdpRect const *source_rect, 724 VdpColor const *colors, 725 VdpOutputSurfaceRenderBlendState const *blend_state, 726 uint32_t flags) 727{ 728 vlVdpOutputSurface *dst_vlsurface; 729 730 struct pipe_context *context; 731 struct pipe_sampler_view *src_sv; 732 struct vl_compositor *compositor; 733 struct vl_compositor_state *cstate; 734 735 struct u_rect src_rect, dst_rect; 736 737 struct vertex4f vlcolors[4]; 738 void *blend; 739 740 dst_vlsurface = vlGetDataHTAB(destination_surface); 741 if (!dst_vlsurface) 742 return VDP_STATUS_INVALID_HANDLE; 743 744 if (source_surface == VDP_INVALID_HANDLE) { 745 src_sv = dst_vlsurface->device->dummy_sv; 746 747 } else { 748 vlVdpBitmapSurface *src_vlsurface = vlGetDataHTAB(source_surface); 749 if (!src_vlsurface) 750 return VDP_STATUS_INVALID_HANDLE; 751 752 if (dst_vlsurface->device != src_vlsurface->device) 753 return VDP_STATUS_HANDLE_DEVICE_MISMATCH; 754 755 src_sv = src_vlsurface->sampler_view; 756 } 757 758 context = dst_vlsurface->device->context; 759 compositor = &dst_vlsurface->device->compositor; 760 cstate = &dst_vlsurface->cstate; 761 762 mtx_lock(&dst_vlsurface->device->mutex); 763 764 blend = BlenderToPipe(context, blend_state); 765 766 vl_compositor_clear_layers(cstate); 767 vl_compositor_set_layer_blend(cstate, 0, blend, false); 768 vl_compositor_set_rgba_layer(cstate, compositor, 0, src_sv, 769 RectToPipe(source_rect, &src_rect), NULL, 770 ColorsToPipe(colors, flags, vlcolors)); 771 vl_compositor_set_layer_rotation(cstate, 0, flags & 3); 772 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); 773 vl_compositor_render(cstate, compositor, dst_vlsurface->surface, &dst_vlsurface->dirty_area, false); 774 775 context->delete_blend_state(context, blend); 776 mtx_unlock(&dst_vlsurface->device->mutex); 777 778 return VDP_STATUS_OK; 779} 780 781struct pipe_resource *vlVdpOutputSurfaceGallium(VdpOutputSurface surface) 782{ 783 vlVdpOutputSurface *vlsurface; 784 785 vlsurface = vlGetDataHTAB(surface); 786 if (!vlsurface || !vlsurface->surface) 787 return NULL; 788 789 mtx_lock(&vlsurface->device->mutex); 790 vlsurface->device->context->flush(vlsurface->device->context, NULL, 0); 791 mtx_unlock(&vlsurface->device->mutex); 792 793 return vlsurface->surface->texture; 794} 795 796VdpStatus vlVdpOutputSurfaceDMABuf(VdpOutputSurface surface, 797 struct VdpSurfaceDMABufDesc *result) 798{ 799 vlVdpOutputSurface *vlsurface; 800 struct pipe_screen *pscreen; 801 struct winsys_handle whandle; 802 803 memset(result, 0, sizeof(*result)); 804 result->handle = -1; 805 806 vlsurface = vlGetDataHTAB(surface); 807 if (!vlsurface || !vlsurface->surface) 808 return VDP_STATUS_INVALID_HANDLE; 809 810 mtx_lock(&vlsurface->device->mutex); 811 vlsurface->device->context->flush(vlsurface->device->context, NULL, 0); 812 813 memset(&whandle, 0, sizeof(struct winsys_handle)); 814 whandle.type = WINSYS_HANDLE_TYPE_FD; 815 816 pscreen = vlsurface->surface->texture->screen; 817 if (!pscreen->resource_get_handle(pscreen, vlsurface->device->context, 818 vlsurface->surface->texture, &whandle, 819 PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE)) { 820 mtx_unlock(&vlsurface->device->mutex); 821 return VDP_STATUS_NO_IMPLEMENTATION; 822 } 823 824 mtx_unlock(&vlsurface->device->mutex); 825 826 result->handle = whandle.handle; 827 result->width = vlsurface->surface->width; 828 result->height = vlsurface->surface->height; 829 result->offset = whandle.offset; 830 result->stride = whandle.stride; 831 result->format = PipeToFormatRGBA(vlsurface->surface->format); 832 833 return VDP_STATUS_OK; 834} 835