output.c revision 736dda82ca5477b8976e2c6b810a71efe2337267
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->pipe; 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_reset_dirty_area(&vlsurface->dirty_area); 117 118 return VDP_STATUS_OK; 119} 120 121/** 122 * Destroy a VdpOutputSurface. 123 */ 124VdpStatus 125vlVdpOutputSurfaceDestroy(VdpOutputSurface surface) 126{ 127 vlVdpOutputSurface *vlsurface; 128 129 vlsurface = vlGetDataHTAB(surface); 130 if (!vlsurface) 131 return VDP_STATUS_INVALID_HANDLE; 132 133 pipe_surface_reference(&vlsurface->surface, NULL); 134 pipe_sampler_view_reference(&vlsurface->sampler_view, NULL); 135 136 vlRemoveDataHTAB(surface); 137 FREE(vlsurface); 138 139 return VDP_STATUS_OK; 140} 141 142/** 143 * Retrieve the parameters used to create a VdpOutputSurface. 144 */ 145VdpStatus 146vlVdpOutputSurfaceGetParameters(VdpOutputSurface surface, 147 VdpRGBAFormat *rgba_format, 148 uint32_t *width, uint32_t *height) 149{ 150 vlVdpOutputSurface *vlsurface; 151 152 vlsurface = vlGetDataHTAB(surface); 153 if (!vlsurface) 154 return VDP_STATUS_INVALID_HANDLE; 155 156 *rgba_format = PipeToFormatRGBA(vlsurface->sampler_view->texture->format); 157 *width = vlsurface->sampler_view->texture->width0; 158 *height = vlsurface->sampler_view->texture->height0; 159 160 return VDP_STATUS_OK; 161} 162 163/** 164 * Copy image data from a VdpOutputSurface to application memory in the 165 * surface's native format. 166 */ 167VdpStatus 168vlVdpOutputSurfaceGetBitsNative(VdpOutputSurface surface, 169 VdpRect const *source_rect, 170 void *const *destination_data, 171 uint32_t const *destination_pitches) 172{ 173 return VDP_STATUS_NO_IMPLEMENTATION; 174} 175 176/** 177 * Copy image data from application memory in the surface's native format to 178 * a VdpOutputSurface. 179 */ 180VdpStatus 181vlVdpOutputSurfacePutBitsNative(VdpOutputSurface surface, 182 void const *const *source_data, 183 uint32_t const *source_pitches, 184 VdpRect const *destination_rect) 185{ 186 return VDP_STATUS_NO_IMPLEMENTATION; 187} 188 189/** 190 * Copy image data from application memory in a specific indexed format to 191 * a VdpOutputSurface. 192 */ 193VdpStatus 194vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface, 195 VdpIndexedFormat source_indexed_format, 196 void const *const *source_data, 197 uint32_t const *source_pitch, 198 VdpRect const *destination_rect, 199 VdpColorTableFormat color_table_format, 200 void const *color_table) 201{ 202 vlVdpOutputSurface *vlsurface; 203 struct pipe_context *context; 204 struct vl_compositor *compositor; 205 206 enum pipe_format index_format; 207 enum pipe_format colortbl_format; 208 209 struct pipe_resource *res, res_tmpl; 210 struct pipe_sampler_view sv_tmpl; 211 struct pipe_sampler_view *sv_idx = NULL, *sv_tbl = NULL; 212 213 struct pipe_box box; 214 struct pipe_video_rect dst_rect; 215 216 vlsurface = vlGetDataHTAB(surface); 217 if (!vlsurface) 218 return VDP_STATUS_INVALID_HANDLE; 219 220 context = vlsurface->device->context->pipe; 221 compositor = &vlsurface->device->compositor; 222 223 index_format = FormatIndexedToPipe(source_indexed_format); 224 if (index_format == PIPE_FORMAT_NONE) 225 return VDP_STATUS_INVALID_INDEXED_FORMAT; 226 227 if (!source_data || !source_pitch) 228 return VDP_STATUS_INVALID_POINTER; 229 230 colortbl_format = FormatColorTableToPipe(color_table_format); 231 if (colortbl_format == PIPE_FORMAT_NONE) 232 return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT; 233 234 if (!color_table) 235 return VDP_STATUS_INVALID_POINTER; 236 237 memset(&res_tmpl, 0, sizeof(res_tmpl)); 238 res_tmpl.target = PIPE_TEXTURE_2D; 239 res_tmpl.format = index_format; 240 241 if (destination_rect) { 242 res_tmpl.width0 = abs(destination_rect->x0-destination_rect->x1); 243 res_tmpl.height0 = abs(destination_rect->y0-destination_rect->y1); 244 } else { 245 res_tmpl.width0 = vlsurface->surface->texture->width0; 246 res_tmpl.height0 = vlsurface->surface->texture->height0; 247 } 248 res_tmpl.depth0 = 1; 249 res_tmpl.array_size = 1; 250 res_tmpl.usage = PIPE_USAGE_STAGING; 251 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; 252 253 res = context->screen->resource_create(context->screen, &res_tmpl); 254 if (!res) 255 goto error_resource; 256 257 box.x = box.y = box.z = 0; 258 box.width = res->width0; 259 box.height = res->height0; 260 box.depth = res->depth0; 261 262 context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box, 263 source_data[0], source_pitch[0], 264 source_pitch[0] * res->height0); 265 266 memset(&sv_tmpl, 0, sizeof(sv_tmpl)); 267 u_sampler_view_default_template(&sv_tmpl, res, res->format); 268 269 sv_idx = context->create_sampler_view(context, res, &sv_tmpl); 270 pipe_resource_reference(&res, NULL); 271 272 if (!sv_idx) 273 goto error_resource; 274 275 memset(&res_tmpl, 0, sizeof(res_tmpl)); 276 res_tmpl.target = PIPE_TEXTURE_1D; 277 res_tmpl.format = colortbl_format; 278 res_tmpl.width0 = 1 << util_format_get_component_bits( 279 index_format, UTIL_FORMAT_COLORSPACE_RGB, 0); 280 res_tmpl.height0 = 1; 281 res_tmpl.depth0 = 1; 282 res_tmpl.array_size = 1; 283 res_tmpl.usage = PIPE_USAGE_STAGING; 284 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; 285 286 res = context->screen->resource_create(context->screen, &res_tmpl); 287 if (!res) 288 goto error_resource; 289 290 box.x = box.y = box.z = 0; 291 box.width = res->width0; 292 box.height = res->height0; 293 box.depth = res->depth0; 294 295 context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box, color_table, 296 util_format_get_stride(colortbl_format, res->width0), 0); 297 298 memset(&sv_tmpl, 0, sizeof(sv_tmpl)); 299 u_sampler_view_default_template(&sv_tmpl, res, res->format); 300 301 sv_tbl = context->create_sampler_view(context, res, &sv_tmpl); 302 pipe_resource_reference(&res, NULL); 303 304 if (!sv_tbl) 305 goto error_resource; 306 307 vl_compositor_clear_layers(compositor); 308 vl_compositor_set_palette_layer(compositor, 0, sv_idx, sv_tbl, NULL, NULL, false); 309 vl_compositor_render(compositor, vlsurface->surface, 310 RectToPipe(destination_rect, &dst_rect), NULL, NULL); 311 312 pipe_sampler_view_reference(&sv_idx, NULL); 313 pipe_sampler_view_reference(&sv_tbl, NULL); 314 315 return VDP_STATUS_OK; 316 317error_resource: 318 pipe_sampler_view_reference(&sv_idx, NULL); 319 pipe_sampler_view_reference(&sv_tbl, NULL); 320 return VDP_STATUS_RESOURCES; 321} 322 323/** 324 * Copy image data from application memory in a specific YCbCr format to 325 * a VdpOutputSurface. 326 */ 327VdpStatus 328vlVdpOutputSurfacePutBitsYCbCr(VdpOutputSurface surface, 329 VdpYCbCrFormat source_ycbcr_format, 330 void const *const *source_data, 331 uint32_t const *source_pitches, 332 VdpRect const *destination_rect, 333 VdpCSCMatrix const *csc_matrix) 334{ 335 return VDP_STATUS_NO_IMPLEMENTATION; 336} 337 338static unsigned 339BlendFactorToPipe(VdpOutputSurfaceRenderBlendFactor factor) 340{ 341 switch (factor) { 342 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO: 343 return PIPE_BLENDFACTOR_ZERO; 344 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE: 345 return PIPE_BLENDFACTOR_ONE; 346 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_COLOR: 347 return PIPE_BLENDFACTOR_SRC_COLOR; 348 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: 349 return PIPE_BLENDFACTOR_INV_SRC_COLOR; 350 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA: 351 return PIPE_BLENDFACTOR_SRC_ALPHA; 352 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: 353 return PIPE_BLENDFACTOR_INV_SRC_ALPHA; 354 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_ALPHA: 355 return PIPE_BLENDFACTOR_DST_ALPHA; 356 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: 357 return PIPE_BLENDFACTOR_INV_DST_ALPHA; 358 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_COLOR: 359 return PIPE_BLENDFACTOR_DST_COLOR; 360 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_COLOR: 361 return PIPE_BLENDFACTOR_INV_DST_COLOR; 362 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA_SATURATE: 363 return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE; 364 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_COLOR: 365 return PIPE_BLENDFACTOR_CONST_COLOR; 366 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR: 367 return PIPE_BLENDFACTOR_INV_CONST_COLOR; 368 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_ALPHA: 369 return PIPE_BLENDFACTOR_CONST_ALPHA; 370 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA: 371 return PIPE_BLENDFACTOR_INV_CONST_ALPHA; 372 default: 373 assert(0); 374 return PIPE_BLENDFACTOR_ONE; 375 } 376} 377 378static unsigned 379BlendEquationToPipe(VdpOutputSurfaceRenderBlendEquation equation) 380{ 381 switch (equation) { 382 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_SUBTRACT: 383 return PIPE_BLEND_SUBTRACT; 384 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_REVERSE_SUBTRACT: 385 return PIPE_BLEND_REVERSE_SUBTRACT; 386 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD: 387 return PIPE_BLEND_ADD; 388 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MIN: 389 return PIPE_BLEND_MIN; 390 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MAX: 391 return PIPE_BLEND_MAX; 392 default: 393 assert(0); 394 return PIPE_BLEND_ADD; 395 } 396} 397 398static void * 399BlenderToPipe(struct pipe_context *context, 400 VdpOutputSurfaceRenderBlendState const *blend_state) 401{ 402 struct pipe_blend_state blend; 403 404 memset(&blend, 0, sizeof blend); 405 blend.independent_blend_enable = 0; 406 407 if (blend_state) { 408 blend.rt[0].blend_enable = 1; 409 blend.rt[0].rgb_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_color); 410 blend.rt[0].rgb_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_color); 411 blend.rt[0].alpha_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_alpha); 412 blend.rt[0].alpha_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_alpha); 413 blend.rt[0].rgb_func = BlendEquationToPipe(blend_state->blend_equation_color); 414 blend.rt[0].alpha_func = BlendEquationToPipe(blend_state->blend_equation_alpha); 415 } else { 416 blend.rt[0].blend_enable = 0; 417 } 418 419 blend.logicop_enable = 0; 420 blend.logicop_func = PIPE_LOGICOP_CLEAR; 421 blend.rt[0].colormask = PIPE_MASK_RGBA; 422 blend.dither = 0; 423 424 return context->create_blend_state(context, &blend); 425} 426 427/** 428 * Composite a sub-rectangle of a VdpOutputSurface into a sub-rectangle of 429 * another VdpOutputSurface; Output Surface object VdpOutputSurface. 430 */ 431VdpStatus 432vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface, 433 VdpRect const *destination_rect, 434 VdpOutputSurface source_surface, 435 VdpRect const *source_rect, 436 VdpColor const *colors, 437 VdpOutputSurfaceRenderBlendState const *blend_state, 438 uint32_t flags) 439{ 440 vlVdpOutputSurface *dst_vlsurface; 441 vlVdpOutputSurface *src_vlsurface; 442 443 struct pipe_context *context; 444 struct vl_compositor *compositor; 445 446 struct pipe_video_rect src_rect; 447 struct pipe_video_rect dst_rect; 448 449 void *blend; 450 451 dst_vlsurface = vlGetDataHTAB(destination_surface); 452 if (!dst_vlsurface) 453 return VDP_STATUS_INVALID_HANDLE; 454 455 src_vlsurface = vlGetDataHTAB(source_surface); 456 if (!src_vlsurface) 457 return VDP_STATUS_INVALID_HANDLE; 458 459 if (dst_vlsurface->device != src_vlsurface->device) 460 return VDP_STATUS_HANDLE_DEVICE_MISMATCH; 461 462 context = dst_vlsurface->device->context->pipe; 463 compositor = &dst_vlsurface->device->compositor; 464 465 blend = BlenderToPipe(context, blend_state); 466 467 vl_compositor_clear_layers(compositor); 468 vl_compositor_set_layer_blend(compositor, 0, blend, false); 469 vl_compositor_set_rgba_layer(compositor, 0, src_vlsurface->sampler_view, 470 RectToPipe(source_rect, &src_rect), NULL); 471 vl_compositor_render(compositor, dst_vlsurface->surface, 472 RectToPipe(destination_rect, &dst_rect), NULL, false); 473 474 context->delete_blend_state(context, blend); 475 476 return VDP_STATUS_OK; 477} 478 479/** 480 * Composite a sub-rectangle of a VdpBitmapSurface into a sub-rectangle of 481 * a VdpOutputSurface; Output Surface object VdpOutputSurface. 482 */ 483VdpStatus 484vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface, 485 VdpRect const *destination_rect, 486 VdpBitmapSurface source_surface, 487 VdpRect const *source_rect, 488 VdpColor const *colors, 489 VdpOutputSurfaceRenderBlendState const *blend_state, 490 uint32_t flags) 491{ 492 return VDP_STATUS_NO_IMPLEMENTATION; 493} 494