output.c revision abf31e3822665b6bdf5ac78b757a21522c9448b1
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 "vdpau_private.h" 37 38/** 39 * Create a VdpOutputSurface. 40 */ 41VdpStatus 42vlVdpOutputSurfaceCreate(VdpDevice device, 43 VdpRGBAFormat rgba_format, 44 uint32_t width, uint32_t height, 45 VdpOutputSurface *surface) 46{ 47 struct pipe_context *pipe; 48 struct pipe_resource res_tmpl, *res; 49 struct pipe_sampler_view sv_templ; 50 struct pipe_surface surf_templ; 51 52 vlVdpOutputSurface *vlsurface = NULL; 53 54 if (!(width && height)) 55 return VDP_STATUS_INVALID_SIZE; 56 57 vlVdpDevice *dev = vlGetDataHTAB(device); 58 if (!dev) 59 return VDP_STATUS_INVALID_HANDLE; 60 61 pipe = dev->context; 62 if (!pipe) 63 return VDP_STATUS_INVALID_HANDLE; 64 65 vlsurface = CALLOC(1, sizeof(vlVdpOutputSurface)); 66 if (!vlsurface) 67 return VDP_STATUS_RESOURCES; 68 69 vlsurface->device = dev; 70 71 memset(&res_tmpl, 0, sizeof(res_tmpl)); 72 73 res_tmpl.target = PIPE_TEXTURE_2D; 74 res_tmpl.format = FormatRGBAToPipe(rgba_format); 75 res_tmpl.width0 = width; 76 res_tmpl.height0 = height; 77 res_tmpl.depth0 = 1; 78 res_tmpl.array_size = 1; 79 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; 80 res_tmpl.usage = PIPE_USAGE_STATIC; 81 82 res = pipe->screen->resource_create(pipe->screen, &res_tmpl); 83 if (!res) { 84 FREE(dev); 85 return VDP_STATUS_ERROR; 86 } 87 88 memset(&sv_templ, 0, sizeof(sv_templ)); 89 u_sampler_view_default_template(&sv_templ, res, res->format); 90 vlsurface->sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ); 91 if (!vlsurface->sampler_view) { 92 pipe_resource_reference(&res, NULL); 93 FREE(dev); 94 return VDP_STATUS_ERROR; 95 } 96 97 memset(&surf_templ, 0, sizeof(surf_templ)); 98 surf_templ.format = res->format; 99 surf_templ.usage = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; 100 vlsurface->surface = pipe->create_surface(pipe, res, &surf_templ); 101 if (!vlsurface->surface) { 102 pipe_resource_reference(&res, NULL); 103 FREE(dev); 104 return VDP_STATUS_ERROR; 105 } 106 107 *surface = vlAddDataHTAB(vlsurface); 108 if (*surface == 0) { 109 pipe_resource_reference(&res, NULL); 110 FREE(dev); 111 return VDP_STATUS_ERROR; 112 } 113 114 pipe_resource_reference(&res, NULL); 115 116 vl_compositor_init_state(&vlsurface->cstate, pipe); 117 vl_compositor_reset_dirty_area(&vlsurface->dirty_area); 118 119 return VDP_STATUS_OK; 120} 121 122/** 123 * Destroy a VdpOutputSurface. 124 */ 125VdpStatus 126vlVdpOutputSurfaceDestroy(VdpOutputSurface surface) 127{ 128 vlVdpOutputSurface *vlsurface; 129 130 vlsurface = vlGetDataHTAB(surface); 131 if (!vlsurface) 132 return VDP_STATUS_INVALID_HANDLE; 133 134 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL); 135 136 pipe_surface_reference(&vlsurface->surface, NULL); 137 pipe_sampler_view_reference(&vlsurface->sampler_view, NULL); 138 vl_compositor_cleanup_state(&vlsurface->cstate); 139 140 vlRemoveDataHTAB(surface); 141 FREE(vlsurface); 142 143 return VDP_STATUS_OK; 144} 145 146/** 147 * Retrieve the parameters used to create a VdpOutputSurface. 148 */ 149VdpStatus 150vlVdpOutputSurfaceGetParameters(VdpOutputSurface surface, 151 VdpRGBAFormat *rgba_format, 152 uint32_t *width, uint32_t *height) 153{ 154 vlVdpOutputSurface *vlsurface; 155 156 vlsurface = vlGetDataHTAB(surface); 157 if (!vlsurface) 158 return VDP_STATUS_INVALID_HANDLE; 159 160 *rgba_format = PipeToFormatRGBA(vlsurface->sampler_view->texture->format); 161 *width = vlsurface->sampler_view->texture->width0; 162 *height = vlsurface->sampler_view->texture->height0; 163 164 return VDP_STATUS_OK; 165} 166 167/** 168 * Copy image data from a VdpOutputSurface to application memory in the 169 * surface's native format. 170 */ 171VdpStatus 172vlVdpOutputSurfaceGetBitsNative(VdpOutputSurface surface, 173 VdpRect const *source_rect, 174 void *const *destination_data, 175 uint32_t const *destination_pitches) 176{ 177 return VDP_STATUS_NO_IMPLEMENTATION; 178} 179 180/** 181 * Copy image data from application memory in the surface's native format to 182 * a VdpOutputSurface. 183 */ 184VdpStatus 185vlVdpOutputSurfacePutBitsNative(VdpOutputSurface surface, 186 void const *const *source_data, 187 uint32_t const *source_pitches, 188 VdpRect const *destination_rect) 189{ 190 return VDP_STATUS_NO_IMPLEMENTATION; 191} 192 193/** 194 * Copy image data from application memory in a specific indexed format to 195 * a VdpOutputSurface. 196 */ 197VdpStatus 198vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface, 199 VdpIndexedFormat source_indexed_format, 200 void const *const *source_data, 201 uint32_t const *source_pitch, 202 VdpRect const *destination_rect, 203 VdpColorTableFormat color_table_format, 204 void const *color_table) 205{ 206 vlVdpOutputSurface *vlsurface; 207 struct pipe_context *context; 208 struct vl_compositor *compositor; 209 struct vl_compositor_state *cstate; 210 211 enum pipe_format index_format; 212 enum pipe_format colortbl_format; 213 214 struct pipe_resource *res, res_tmpl; 215 struct pipe_sampler_view sv_tmpl; 216 struct pipe_sampler_view *sv_idx = NULL, *sv_tbl = NULL; 217 218 struct pipe_box box; 219 struct u_rect dst_rect; 220 221 vlsurface = vlGetDataHTAB(surface); 222 if (!vlsurface) 223 return VDP_STATUS_INVALID_HANDLE; 224 225 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL); 226 227 context = vlsurface->device->context; 228 compositor = &vlsurface->device->compositor; 229 cstate = &vlsurface->cstate; 230 231 index_format = FormatIndexedToPipe(source_indexed_format); 232 if (index_format == PIPE_FORMAT_NONE) 233 return VDP_STATUS_INVALID_INDEXED_FORMAT; 234 235 if (!source_data || !source_pitch) 236 return VDP_STATUS_INVALID_POINTER; 237 238 colortbl_format = FormatColorTableToPipe(color_table_format); 239 if (colortbl_format == PIPE_FORMAT_NONE) 240 return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT; 241 242 if (!color_table) 243 return VDP_STATUS_INVALID_POINTER; 244 245 memset(&res_tmpl, 0, sizeof(res_tmpl)); 246 res_tmpl.target = PIPE_TEXTURE_2D; 247 res_tmpl.format = index_format; 248 249 if (destination_rect) { 250 res_tmpl.width0 = abs(destination_rect->x0-destination_rect->x1); 251 res_tmpl.height0 = abs(destination_rect->y0-destination_rect->y1); 252 } else { 253 res_tmpl.width0 = vlsurface->surface->texture->width0; 254 res_tmpl.height0 = vlsurface->surface->texture->height0; 255 } 256 res_tmpl.depth0 = 1; 257 res_tmpl.array_size = 1; 258 res_tmpl.usage = PIPE_USAGE_STAGING; 259 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; 260 261 res = context->screen->resource_create(context->screen, &res_tmpl); 262 if (!res) 263 goto error_resource; 264 265 box.x = box.y = box.z = 0; 266 box.width = res->width0; 267 box.height = res->height0; 268 box.depth = res->depth0; 269 270 context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box, 271 source_data[0], source_pitch[0], 272 source_pitch[0] * res->height0); 273 274 memset(&sv_tmpl, 0, sizeof(sv_tmpl)); 275 u_sampler_view_default_template(&sv_tmpl, res, res->format); 276 277 sv_idx = context->create_sampler_view(context, res, &sv_tmpl); 278 pipe_resource_reference(&res, NULL); 279 280 if (!sv_idx) 281 goto error_resource; 282 283 memset(&res_tmpl, 0, sizeof(res_tmpl)); 284 res_tmpl.target = PIPE_TEXTURE_1D; 285 res_tmpl.format = colortbl_format; 286 res_tmpl.width0 = 1 << util_format_get_component_bits( 287 index_format, UTIL_FORMAT_COLORSPACE_RGB, 0); 288 res_tmpl.height0 = 1; 289 res_tmpl.depth0 = 1; 290 res_tmpl.array_size = 1; 291 res_tmpl.usage = PIPE_USAGE_STAGING; 292 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; 293 294 res = context->screen->resource_create(context->screen, &res_tmpl); 295 if (!res) 296 goto error_resource; 297 298 box.x = box.y = box.z = 0; 299 box.width = res->width0; 300 box.height = res->height0; 301 box.depth = res->depth0; 302 303 context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box, color_table, 304 util_format_get_stride(colortbl_format, res->width0), 0); 305 306 memset(&sv_tmpl, 0, sizeof(sv_tmpl)); 307 u_sampler_view_default_template(&sv_tmpl, res, res->format); 308 309 sv_tbl = context->create_sampler_view(context, res, &sv_tmpl); 310 pipe_resource_reference(&res, NULL); 311 312 if (!sv_tbl) 313 goto error_resource; 314 315 vl_compositor_clear_layers(cstate); 316 vl_compositor_set_palette_layer(cstate, compositor, 0, sv_idx, sv_tbl, NULL, NULL, false); 317 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); 318 vl_compositor_render(cstate, compositor, vlsurface->surface, NULL); 319 320 pipe_sampler_view_reference(&sv_idx, NULL); 321 pipe_sampler_view_reference(&sv_tbl, NULL); 322 323 return VDP_STATUS_OK; 324 325error_resource: 326 pipe_sampler_view_reference(&sv_idx, NULL); 327 pipe_sampler_view_reference(&sv_tbl, NULL); 328 return VDP_STATUS_RESOURCES; 329} 330 331/** 332 * Copy image data from application memory in a specific YCbCr format to 333 * a VdpOutputSurface. 334 */ 335VdpStatus 336vlVdpOutputSurfacePutBitsYCbCr(VdpOutputSurface surface, 337 VdpYCbCrFormat source_ycbcr_format, 338 void const *const *source_data, 339 uint32_t const *source_pitches, 340 VdpRect const *destination_rect, 341 VdpCSCMatrix const *csc_matrix) 342{ 343 return VDP_STATUS_NO_IMPLEMENTATION; 344} 345 346static unsigned 347BlendFactorToPipe(VdpOutputSurfaceRenderBlendFactor factor) 348{ 349 switch (factor) { 350 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO: 351 return PIPE_BLENDFACTOR_ZERO; 352 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE: 353 return PIPE_BLENDFACTOR_ONE; 354 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_COLOR: 355 return PIPE_BLENDFACTOR_SRC_COLOR; 356 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: 357 return PIPE_BLENDFACTOR_INV_SRC_COLOR; 358 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA: 359 return PIPE_BLENDFACTOR_SRC_ALPHA; 360 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: 361 return PIPE_BLENDFACTOR_INV_SRC_ALPHA; 362 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_ALPHA: 363 return PIPE_BLENDFACTOR_DST_ALPHA; 364 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: 365 return PIPE_BLENDFACTOR_INV_DST_ALPHA; 366 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_COLOR: 367 return PIPE_BLENDFACTOR_DST_COLOR; 368 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_COLOR: 369 return PIPE_BLENDFACTOR_INV_DST_COLOR; 370 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA_SATURATE: 371 return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE; 372 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_COLOR: 373 return PIPE_BLENDFACTOR_CONST_COLOR; 374 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR: 375 return PIPE_BLENDFACTOR_INV_CONST_COLOR; 376 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_ALPHA: 377 return PIPE_BLENDFACTOR_CONST_ALPHA; 378 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA: 379 return PIPE_BLENDFACTOR_INV_CONST_ALPHA; 380 default: 381 assert(0); 382 return PIPE_BLENDFACTOR_ONE; 383 } 384} 385 386static unsigned 387BlendEquationToPipe(VdpOutputSurfaceRenderBlendEquation equation) 388{ 389 switch (equation) { 390 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_SUBTRACT: 391 return PIPE_BLEND_SUBTRACT; 392 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_REVERSE_SUBTRACT: 393 return PIPE_BLEND_REVERSE_SUBTRACT; 394 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD: 395 return PIPE_BLEND_ADD; 396 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MIN: 397 return PIPE_BLEND_MIN; 398 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MAX: 399 return PIPE_BLEND_MAX; 400 default: 401 assert(0); 402 return PIPE_BLEND_ADD; 403 } 404} 405 406static void * 407BlenderToPipe(struct pipe_context *context, 408 VdpOutputSurfaceRenderBlendState const *blend_state) 409{ 410 struct pipe_blend_state blend; 411 412 memset(&blend, 0, sizeof blend); 413 blend.independent_blend_enable = 0; 414 415 if (blend_state) { 416 blend.rt[0].blend_enable = 1; 417 blend.rt[0].rgb_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_color); 418 blend.rt[0].rgb_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_color); 419 blend.rt[0].alpha_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_alpha); 420 blend.rt[0].alpha_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_alpha); 421 blend.rt[0].rgb_func = BlendEquationToPipe(blend_state->blend_equation_color); 422 blend.rt[0].alpha_func = BlendEquationToPipe(blend_state->blend_equation_alpha); 423 } else { 424 blend.rt[0].blend_enable = 0; 425 } 426 427 blend.logicop_enable = 0; 428 blend.logicop_func = PIPE_LOGICOP_CLEAR; 429 blend.rt[0].colormask = PIPE_MASK_RGBA; 430 blend.dither = 0; 431 432 return context->create_blend_state(context, &blend); 433} 434 435/** 436 * Composite a sub-rectangle of a VdpOutputSurface into a sub-rectangle of 437 * another VdpOutputSurface; Output Surface object VdpOutputSurface. 438 */ 439VdpStatus 440vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface, 441 VdpRect const *destination_rect, 442 VdpOutputSurface source_surface, 443 VdpRect const *source_rect, 444 VdpColor const *colors, 445 VdpOutputSurfaceRenderBlendState const *blend_state, 446 uint32_t flags) 447{ 448 vlVdpOutputSurface *dst_vlsurface; 449 vlVdpOutputSurface *src_vlsurface; 450 451 struct pipe_context *context; 452 struct vl_compositor *compositor; 453 struct vl_compositor_state *cstate; 454 455 struct u_rect src_rect, dst_rect; 456 457 void *blend; 458 459 dst_vlsurface = vlGetDataHTAB(destination_surface); 460 if (!dst_vlsurface) 461 return VDP_STATUS_INVALID_HANDLE; 462 463 src_vlsurface = vlGetDataHTAB(source_surface); 464 if (!src_vlsurface) 465 return VDP_STATUS_INVALID_HANDLE; 466 467 if (dst_vlsurface->device != src_vlsurface->device) 468 return VDP_STATUS_HANDLE_DEVICE_MISMATCH; 469 470 vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL); 471 472 context = dst_vlsurface->device->context; 473 compositor = &dst_vlsurface->device->compositor; 474 cstate = &dst_vlsurface->cstate; 475 476 blend = BlenderToPipe(context, blend_state); 477 478 vl_compositor_clear_layers(cstate); 479 vl_compositor_set_layer_blend(cstate, 0, blend, false); 480 vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view, 481 RectToPipe(source_rect, &src_rect), NULL, NULL); 482 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); 483 vl_compositor_render(cstate, compositor, dst_vlsurface->surface, NULL); 484 485 context->delete_blend_state(context, blend); 486 487 return VDP_STATUS_OK; 488} 489 490/** 491 * Composite a sub-rectangle of a VdpBitmapSurface into a sub-rectangle of 492 * a VdpOutputSurface; Output Surface object VdpOutputSurface. 493 */ 494VdpStatus 495vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface, 496 VdpRect const *destination_rect, 497 VdpBitmapSurface source_surface, 498 VdpRect const *source_rect, 499 VdpColor const *colors, 500 VdpOutputSurfaceRenderBlendState const *blend_state, 501 uint32_t flags) 502{ 503 vlVdpOutputSurface *dst_vlsurface; 504 vlVdpBitmapSurface *src_vlsurface; 505 506 struct pipe_context *context; 507 struct vl_compositor *compositor; 508 struct vl_compositor_state *cstate; 509 510 struct u_rect src_rect, dst_rect; 511 512 void *blend; 513 514 dst_vlsurface = vlGetDataHTAB(destination_surface); 515 if (!dst_vlsurface) 516 return VDP_STATUS_INVALID_HANDLE; 517 518 src_vlsurface = vlGetDataHTAB(source_surface); 519 if (!src_vlsurface) 520 return VDP_STATUS_INVALID_HANDLE; 521 522 if (dst_vlsurface->device != src_vlsurface->device) 523 return VDP_STATUS_HANDLE_DEVICE_MISMATCH; 524 525 vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL); 526 527 context = dst_vlsurface->device->context; 528 compositor = &dst_vlsurface->device->compositor; 529 cstate = &dst_vlsurface->cstate; 530 531 blend = BlenderToPipe(context, blend_state); 532 533 vl_compositor_clear_layers(cstate); 534 vl_compositor_set_layer_blend(cstate, 0, blend, false); 535 vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view, 536 RectToPipe(source_rect, &src_rect), NULL, NULL); 537 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect)); 538 vl_compositor_render(cstate, compositor, dst_vlsurface->surface, NULL); 539 540 context->delete_blend_state(context, blend); 541 542 return VDP_STATUS_OK; 543} 544