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