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