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