surface.c revision 7ec681f3
1/************************************************************************** 2 * 3 * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. 4 * Copyright 2014 Advanced Micro Devices, Inc. 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 THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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 "pipe/p_screen.h" 30#include "pipe/p_video_codec.h" 31 32#include "frontend/drm_driver.h" 33 34#include "util/u_memory.h" 35#include "util/u_handle_table.h" 36#include "util/u_rect.h" 37#include "util/u_sampler.h" 38#include "util/u_surface.h" 39#include "util/u_video.h" 40 41#include "vl/vl_compositor.h" 42#include "vl/vl_video_buffer.h" 43#include "vl/vl_winsys.h" 44 45#include "va_private.h" 46 47#include <va/va_drmcommon.h> 48#include "drm-uapi/drm_fourcc.h" 49 50static const enum pipe_format vpp_surface_formats[] = { 51 PIPE_FORMAT_B8G8R8A8_UNORM, PIPE_FORMAT_R8G8B8A8_UNORM, 52 PIPE_FORMAT_B8G8R8X8_UNORM, PIPE_FORMAT_R8G8B8X8_UNORM 53}; 54 55VAStatus 56vlVaCreateSurfaces(VADriverContextP ctx, int width, int height, int format, 57 int num_surfaces, VASurfaceID *surfaces) 58{ 59 return vlVaCreateSurfaces2(ctx, format, width, height, surfaces, num_surfaces, 60 NULL, 0); 61} 62 63VAStatus 64vlVaDestroySurfaces(VADriverContextP ctx, VASurfaceID *surface_list, int num_surfaces) 65{ 66 vlVaDriver *drv; 67 int i; 68 69 if (!ctx) 70 return VA_STATUS_ERROR_INVALID_CONTEXT; 71 72 drv = VL_VA_DRIVER(ctx); 73 mtx_lock(&drv->mutex); 74 for (i = 0; i < num_surfaces; ++i) { 75 vlVaSurface *surf = handle_table_get(drv->htab, surface_list[i]); 76 if (!surf) { 77 mtx_unlock(&drv->mutex); 78 return VA_STATUS_ERROR_INVALID_SURFACE; 79 } 80 if (surf->buffer) 81 surf->buffer->destroy(surf->buffer); 82 util_dynarray_fini(&surf->subpics); 83 FREE(surf); 84 handle_table_remove(drv->htab, surface_list[i]); 85 } 86 mtx_unlock(&drv->mutex); 87 88 return VA_STATUS_SUCCESS; 89} 90 91VAStatus 92vlVaSyncSurface(VADriverContextP ctx, VASurfaceID render_target) 93{ 94 vlVaDriver *drv; 95 vlVaContext *context; 96 vlVaSurface *surf; 97 98 if (!ctx) 99 return VA_STATUS_ERROR_INVALID_CONTEXT; 100 101 drv = VL_VA_DRIVER(ctx); 102 if (!drv) 103 return VA_STATUS_ERROR_INVALID_CONTEXT; 104 105 mtx_lock(&drv->mutex); 106 surf = handle_table_get(drv->htab, render_target); 107 108 if (!surf || !surf->buffer) { 109 mtx_unlock(&drv->mutex); 110 return VA_STATUS_ERROR_INVALID_SURFACE; 111 } 112 113 if (!surf->feedback) { 114 // No outstanding operation: nothing to do. 115 mtx_unlock(&drv->mutex); 116 return VA_STATUS_SUCCESS; 117 } 118 119 context = handle_table_get(drv->htab, surf->ctx); 120 if (!context) { 121 mtx_unlock(&drv->mutex); 122 return VA_STATUS_ERROR_INVALID_CONTEXT; 123 } 124 125 if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { 126 if (u_reduce_video_profile(context->templat.profile) == PIPE_VIDEO_FORMAT_MPEG4_AVC) { 127 int frame_diff; 128 if (context->desc.h264enc.frame_num_cnt >= surf->frame_num_cnt) 129 frame_diff = context->desc.h264enc.frame_num_cnt - surf->frame_num_cnt; 130 else 131 frame_diff = 0xFFFFFFFF - surf->frame_num_cnt + 1 + context->desc.h264enc.frame_num_cnt; 132 if ((frame_diff == 0) && 133 (surf->force_flushed == false) && 134 (context->desc.h264enc.frame_num_cnt % 2 != 0)) { 135 context->decoder->flush(context->decoder); 136 context->first_single_submitted = true; 137 } 138 } 139 context->decoder->get_feedback(context->decoder, surf->feedback, &(surf->coded_buf->coded_size)); 140 surf->feedback = NULL; 141 } 142 mtx_unlock(&drv->mutex); 143 return VA_STATUS_SUCCESS; 144} 145 146VAStatus 147vlVaQuerySurfaceStatus(VADriverContextP ctx, VASurfaceID render_target, VASurfaceStatus *status) 148{ 149 vlVaDriver *drv; 150 vlVaSurface *surf; 151 vlVaContext *context; 152 153 if (!ctx) 154 return VA_STATUS_ERROR_INVALID_CONTEXT; 155 156 drv = VL_VA_DRIVER(ctx); 157 if (!drv) 158 return VA_STATUS_ERROR_INVALID_CONTEXT; 159 160 mtx_lock(&drv->mutex); 161 162 surf = handle_table_get(drv->htab, render_target); 163 if (!surf || !surf->buffer) { 164 mtx_unlock(&drv->mutex); 165 return VA_STATUS_ERROR_INVALID_SURFACE; 166 } 167 168 context = handle_table_get(drv->htab, surf->ctx); 169 if (!context) { 170 mtx_unlock(&drv->mutex); 171 return VA_STATUS_ERROR_INVALID_CONTEXT; 172 } 173 174 if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { 175 if(surf->feedback == NULL) 176 *status=VASurfaceReady; 177 else 178 *status=VASurfaceRendering; 179 } 180 181 mtx_unlock(&drv->mutex); 182 183 return VA_STATUS_SUCCESS; 184} 185 186VAStatus 187vlVaQuerySurfaceError(VADriverContextP ctx, VASurfaceID render_target, VAStatus error_status, void **error_info) 188{ 189 if (!ctx) 190 return VA_STATUS_ERROR_INVALID_CONTEXT; 191 192 return VA_STATUS_ERROR_UNIMPLEMENTED; 193} 194 195static void 196upload_sampler(struct pipe_context *pipe, struct pipe_sampler_view *dst, 197 const struct pipe_box *dst_box, const void *src, unsigned src_stride, 198 unsigned src_x, unsigned src_y) 199{ 200 struct pipe_transfer *transfer; 201 void *map; 202 203 map = pipe->texture_map(pipe, dst->texture, 0, PIPE_MAP_WRITE, 204 dst_box, &transfer); 205 if (!map) 206 return; 207 208 util_copy_rect(map, dst->texture->format, transfer->stride, 0, 0, 209 dst_box->width, dst_box->height, 210 src, src_stride, src_x, src_y); 211 212 pipe->texture_unmap(pipe, transfer); 213} 214 215static VAStatus 216vlVaPutSubpictures(vlVaSurface *surf, vlVaDriver *drv, 217 struct pipe_surface *surf_draw, struct u_rect *dirty_area, 218 struct u_rect *src_rect, struct u_rect *dst_rect) 219{ 220 vlVaSubpicture *sub; 221 int i; 222 223 if (!(surf->subpics.data || surf->subpics.size)) 224 return VA_STATUS_SUCCESS; 225 226 for (i = 0; i < surf->subpics.size/sizeof(vlVaSubpicture *); i++) { 227 struct pipe_blend_state blend; 228 void *blend_state; 229 vlVaBuffer *buf; 230 struct pipe_box box; 231 struct u_rect *s, *d, sr, dr, c; 232 int sw, sh, dw, dh; 233 234 sub = ((vlVaSubpicture **)surf->subpics.data)[i]; 235 if (!sub) 236 continue; 237 238 buf = handle_table_get(drv->htab, sub->image->buf); 239 if (!buf) 240 return VA_STATUS_ERROR_INVALID_IMAGE; 241 242 box.x = 0; 243 box.y = 0; 244 box.z = 0; 245 box.width = sub->dst_rect.x1 - sub->dst_rect.x0; 246 box.height = sub->dst_rect.y1 - sub->dst_rect.y0; 247 box.depth = 1; 248 249 s = &sub->src_rect; 250 d = &sub->dst_rect; 251 sw = s->x1 - s->x0; 252 sh = s->y1 - s->y0; 253 dw = d->x1 - d->x0; 254 dh = d->y1 - d->y0; 255 c.x0 = MAX2(d->x0, s->x0); 256 c.y0 = MAX2(d->y0, s->y0); 257 c.x1 = MIN2(d->x0 + dw, src_rect->x1); 258 c.y1 = MIN2(d->y0 + dh, src_rect->y1); 259 sr.x0 = s->x0 + (c.x0 - d->x0)*(sw/(float)dw); 260 sr.y0 = s->y0 + (c.y0 - d->y0)*(sh/(float)dh); 261 sr.x1 = s->x0 + (c.x1 - d->x0)*(sw/(float)dw); 262 sr.y1 = s->y0 + (c.y1 - d->y0)*(sh/(float)dh); 263 264 s = src_rect; 265 d = dst_rect; 266 sw = s->x1 - s->x0; 267 sh = s->y1 - s->y0; 268 dw = d->x1 - d->x0; 269 dh = d->y1 - d->y0; 270 dr.x0 = d->x0 + c.x0*(dw/(float)sw); 271 dr.y0 = d->y0 + c.y0*(dh/(float)sh); 272 dr.x1 = d->x0 + c.x1*(dw/(float)sw); 273 dr.y1 = d->y0 + c.y1*(dh/(float)sh); 274 275 memset(&blend, 0, sizeof(blend)); 276 blend.independent_blend_enable = 0; 277 blend.rt[0].blend_enable = 1; 278 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; 279 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; 280 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO; 281 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 282 blend.rt[0].rgb_func = PIPE_BLEND_ADD; 283 blend.rt[0].alpha_func = PIPE_BLEND_ADD; 284 blend.rt[0].colormask = PIPE_MASK_RGBA; 285 blend.logicop_enable = 0; 286 blend.logicop_func = PIPE_LOGICOP_CLEAR; 287 blend.dither = 0; 288 blend_state = drv->pipe->create_blend_state(drv->pipe, &blend); 289 290 vl_compositor_clear_layers(&drv->cstate); 291 vl_compositor_set_layer_blend(&drv->cstate, 0, blend_state, false); 292 upload_sampler(drv->pipe, sub->sampler, &box, buf->data, 293 sub->image->pitches[0], 0, 0); 294 vl_compositor_set_rgba_layer(&drv->cstate, &drv->compositor, 0, sub->sampler, 295 &sr, NULL, NULL); 296 vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dr); 297 vl_compositor_render(&drv->cstate, &drv->compositor, surf_draw, dirty_area, false); 298 drv->pipe->delete_blend_state(drv->pipe, blend_state); 299 } 300 301 return VA_STATUS_SUCCESS; 302} 303 304VAStatus 305vlVaPutSurface(VADriverContextP ctx, VASurfaceID surface_id, void* draw, short srcx, short srcy, 306 unsigned short srcw, unsigned short srch, short destx, short desty, 307 unsigned short destw, unsigned short desth, VARectangle *cliprects, 308 unsigned int number_cliprects, unsigned int flags) 309{ 310 vlVaDriver *drv; 311 vlVaSurface *surf; 312 struct pipe_screen *screen; 313 struct pipe_resource *tex; 314 struct pipe_surface surf_templ, *surf_draw; 315 struct vl_screen *vscreen; 316 struct u_rect src_rect, *dirty_area; 317 struct u_rect dst_rect = {destx, destx + destw, desty, desty + desth}; 318 enum pipe_format format; 319 VAStatus status; 320 321 if (!ctx) 322 return VA_STATUS_ERROR_INVALID_CONTEXT; 323 324 drv = VL_VA_DRIVER(ctx); 325 mtx_lock(&drv->mutex); 326 surf = handle_table_get(drv->htab, surface_id); 327 if (!surf) { 328 mtx_unlock(&drv->mutex); 329 return VA_STATUS_ERROR_INVALID_SURFACE; 330 } 331 332 screen = drv->pipe->screen; 333 vscreen = drv->vscreen; 334 335 tex = vscreen->texture_from_drawable(vscreen, draw); 336 if (!tex) { 337 mtx_unlock(&drv->mutex); 338 return VA_STATUS_ERROR_INVALID_DISPLAY; 339 } 340 341 dirty_area = vscreen->get_dirty_area(vscreen); 342 343 memset(&surf_templ, 0, sizeof(surf_templ)); 344 surf_templ.format = tex->format; 345 surf_draw = drv->pipe->create_surface(drv->pipe, tex, &surf_templ); 346 if (!surf_draw) { 347 pipe_resource_reference(&tex, NULL); 348 mtx_unlock(&drv->mutex); 349 return VA_STATUS_ERROR_INVALID_DISPLAY; 350 } 351 352 src_rect.x0 = srcx; 353 src_rect.y0 = srcy; 354 src_rect.x1 = srcw + srcx; 355 src_rect.y1 = srch + srcy; 356 357 format = surf->buffer->buffer_format; 358 359 vl_compositor_clear_layers(&drv->cstate); 360 361 if (format == PIPE_FORMAT_B8G8R8A8_UNORM || format == PIPE_FORMAT_B8G8R8X8_UNORM || 362 format == PIPE_FORMAT_R8G8B8A8_UNORM || format == PIPE_FORMAT_R8G8B8X8_UNORM) { 363 struct pipe_sampler_view **views; 364 365 views = surf->buffer->get_sampler_view_planes(surf->buffer); 366 vl_compositor_set_rgba_layer(&drv->cstate, &drv->compositor, 0, views[0], &src_rect, NULL, NULL); 367 } else 368 vl_compositor_set_buffer_layer(&drv->cstate, &drv->compositor, 0, surf->buffer, &src_rect, NULL, VL_COMPOSITOR_WEAVE); 369 370 vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dst_rect); 371 vl_compositor_render(&drv->cstate, &drv->compositor, surf_draw, dirty_area, true); 372 373 status = vlVaPutSubpictures(surf, drv, surf_draw, dirty_area, &src_rect, &dst_rect); 374 if (status) { 375 mtx_unlock(&drv->mutex); 376 return status; 377 } 378 379 /* flush before calling flush_frontbuffer so that rendering is flushed 380 * to back buffer so the texture can be copied in flush_frontbuffer 381 */ 382 drv->pipe->flush(drv->pipe, NULL, 0); 383 384 screen->flush_frontbuffer(screen, drv->pipe, tex, 0, 0, 385 vscreen->get_private(vscreen), NULL); 386 387 388 pipe_resource_reference(&tex, NULL); 389 pipe_surface_reference(&surf_draw, NULL); 390 mtx_unlock(&drv->mutex); 391 392 return VA_STATUS_SUCCESS; 393} 394 395VAStatus 396vlVaLockSurface(VADriverContextP ctx, VASurfaceID surface, unsigned int *fourcc, 397 unsigned int *luma_stride, unsigned int *chroma_u_stride, unsigned int *chroma_v_stride, 398 unsigned int *luma_offset, unsigned int *chroma_u_offset, unsigned int *chroma_v_offset, 399 unsigned int *buffer_name, void **buffer) 400{ 401 if (!ctx) 402 return VA_STATUS_ERROR_INVALID_CONTEXT; 403 404 return VA_STATUS_ERROR_UNIMPLEMENTED; 405} 406 407VAStatus 408vlVaUnlockSurface(VADriverContextP ctx, VASurfaceID surface) 409{ 410 if (!ctx) 411 return VA_STATUS_ERROR_INVALID_CONTEXT; 412 413 return VA_STATUS_ERROR_UNIMPLEMENTED; 414} 415 416VAStatus 417vlVaQuerySurfaceAttributes(VADriverContextP ctx, VAConfigID config_id, 418 VASurfaceAttrib *attrib_list, unsigned int *num_attribs) 419{ 420 vlVaDriver *drv; 421 vlVaConfig *config; 422 VASurfaceAttrib *attribs; 423 struct pipe_screen *pscreen; 424 int i, j; 425 426 STATIC_ASSERT(ARRAY_SIZE(vpp_surface_formats) <= VL_VA_MAX_IMAGE_FORMATS); 427 428 if (config_id == VA_INVALID_ID) 429 return VA_STATUS_ERROR_INVALID_CONFIG; 430 431 if (!attrib_list && !num_attribs) 432 return VA_STATUS_ERROR_INVALID_PARAMETER; 433 434 if (!attrib_list) { 435 *num_attribs = VL_VA_MAX_IMAGE_FORMATS + VASurfaceAttribCount; 436 return VA_STATUS_SUCCESS; 437 } 438 439 if (!ctx) 440 return VA_STATUS_ERROR_INVALID_CONTEXT; 441 442 drv = VL_VA_DRIVER(ctx); 443 444 if (!drv) 445 return VA_STATUS_ERROR_INVALID_CONTEXT; 446 447 mtx_lock(&drv->mutex); 448 config = handle_table_get(drv->htab, config_id); 449 mtx_unlock(&drv->mutex); 450 451 if (!config) 452 return VA_STATUS_ERROR_INVALID_CONFIG; 453 454 pscreen = VL_VA_PSCREEN(ctx); 455 456 if (!pscreen) 457 return VA_STATUS_ERROR_INVALID_CONTEXT; 458 459 attribs = CALLOC(VL_VA_MAX_IMAGE_FORMATS + VASurfaceAttribCount, 460 sizeof(VASurfaceAttrib)); 461 462 if (!attribs) 463 return VA_STATUS_ERROR_ALLOCATION_FAILED; 464 465 i = 0; 466 467 /* vlVaCreateConfig returns PIPE_VIDEO_PROFILE_UNKNOWN 468 * only for VAEntrypointVideoProc. */ 469 if (config->profile == PIPE_VIDEO_PROFILE_UNKNOWN) { 470 if (config->rt_format & VA_RT_FORMAT_RGB32) { 471 for (j = 0; j < ARRAY_SIZE(vpp_surface_formats); ++j) { 472 attribs[i].type = VASurfaceAttribPixelFormat; 473 attribs[i].value.type = VAGenericValueTypeInteger; 474 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; 475 attribs[i].value.value.i = PipeFormatToVaFourcc(vpp_surface_formats[j]); 476 i++; 477 } 478 } 479 } 480 if (config->rt_format & VA_RT_FORMAT_YUV420) { 481 attribs[i].type = VASurfaceAttribPixelFormat; 482 attribs[i].value.type = VAGenericValueTypeInteger; 483 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; 484 attribs[i].value.value.i = VA_FOURCC_NV12; 485 i++; 486 } 487 if (config->rt_format & VA_RT_FORMAT_YUV420_10 || 488 (config->rt_format & VA_RT_FORMAT_YUV420 && 489 config->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE)) { 490 attribs[i].type = VASurfaceAttribPixelFormat; 491 attribs[i].value.type = VAGenericValueTypeInteger; 492 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; 493 attribs[i].value.value.i = VA_FOURCC_P010; 494 i++; 495 attribs[i].type = VASurfaceAttribPixelFormat; 496 attribs[i].value.type = VAGenericValueTypeInteger; 497 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; 498 attribs[i].value.value.i = VA_FOURCC_P016; 499 i++; 500 } 501 502 attribs[i].type = VASurfaceAttribMemoryType; 503 attribs[i].value.type = VAGenericValueTypeInteger; 504 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; 505 attribs[i].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA | 506 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME | 507 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2; 508 i++; 509 510 attribs[i].type = VASurfaceAttribExternalBufferDescriptor; 511 attribs[i].value.type = VAGenericValueTypePointer; 512 attribs[i].flags = VA_SURFACE_ATTRIB_SETTABLE; 513 attribs[i].value.value.p = NULL; /* ignore */ 514 i++; 515 516#ifdef HAVE_VA_SURFACE_ATTRIB_DRM_FORMAT_MODIFIERS 517 if (drv->pipe->create_video_buffer_with_modifiers) { 518 attribs[i].type = VASurfaceAttribDRMFormatModifiers; 519 attribs[i].value.type = VAGenericValueTypePointer; 520 attribs[i].flags = VA_SURFACE_ATTRIB_SETTABLE; 521 attribs[i].value.value.p = NULL; /* ignore */ 522 i++; 523 } 524#endif 525 526 if (config->entrypoint != PIPE_VIDEO_ENTRYPOINT_UNKNOWN) { 527 attribs[i].type = VASurfaceAttribMaxWidth; 528 attribs[i].value.type = VAGenericValueTypeInteger; 529 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE; 530 attribs[i].value.value.i = 531 pscreen->get_video_param(pscreen, 532 config->profile, config->entrypoint, 533 PIPE_VIDEO_CAP_MAX_WIDTH); 534 i++; 535 536 attribs[i].type = VASurfaceAttribMaxHeight; 537 attribs[i].value.type = VAGenericValueTypeInteger; 538 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE; 539 attribs[i].value.value.i = 540 pscreen->get_video_param(pscreen, 541 config->profile, config->entrypoint, 542 PIPE_VIDEO_CAP_MAX_HEIGHT); 543 i++; 544 } else { 545 attribs[i].type = VASurfaceAttribMaxWidth; 546 attribs[i].value.type = VAGenericValueTypeInteger; 547 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE; 548 attribs[i].value.value.i = vl_video_buffer_max_size(pscreen); 549 i++; 550 551 attribs[i].type = VASurfaceAttribMaxHeight; 552 attribs[i].value.type = VAGenericValueTypeInteger; 553 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE; 554 attribs[i].value.value.i = vl_video_buffer_max_size(pscreen); 555 i++; 556 } 557 558 if (i > *num_attribs) { 559 *num_attribs = i; 560 FREE(attribs); 561 return VA_STATUS_ERROR_MAX_NUM_EXCEEDED; 562 } 563 564 *num_attribs = i; 565 memcpy(attrib_list, attribs, i * sizeof(VASurfaceAttrib)); 566 FREE(attribs); 567 568 return VA_STATUS_SUCCESS; 569} 570 571static VAStatus 572surface_from_external_memory(VADriverContextP ctx, vlVaSurface *surface, 573 VASurfaceAttribExternalBuffers *memory_attribute, 574 unsigned index, struct pipe_video_buffer *templat) 575{ 576 vlVaDriver *drv; 577 struct pipe_screen *pscreen; 578 struct pipe_resource res_templ; 579 struct winsys_handle whandle; 580 struct pipe_resource *resources[VL_NUM_COMPONENTS]; 581 enum pipe_format resource_formats[VL_NUM_COMPONENTS]; 582 VAStatus result; 583 int i; 584 585 pscreen = VL_VA_PSCREEN(ctx); 586 drv = VL_VA_DRIVER(ctx); 587 588 if (!memory_attribute || !memory_attribute->buffers || 589 index > memory_attribute->num_buffers) 590 return VA_STATUS_ERROR_INVALID_PARAMETER; 591 592 if (surface->templat.width != memory_attribute->width || 593 surface->templat.height != memory_attribute->height || 594 memory_attribute->num_planes < 1) 595 return VA_STATUS_ERROR_INVALID_PARAMETER; 596 597 if (memory_attribute->num_planes > VL_NUM_COMPONENTS) 598 return VA_STATUS_ERROR_INVALID_PARAMETER; 599 600 vl_get_video_buffer_formats(pscreen, templat->buffer_format, resource_formats); 601 602 memset(&res_templ, 0, sizeof(res_templ)); 603 res_templ.target = PIPE_TEXTURE_2D; 604 res_templ.last_level = 0; 605 res_templ.depth0 = 1; 606 res_templ.array_size = 1; 607 res_templ.bind = PIPE_BIND_SAMPLER_VIEW; 608 res_templ.usage = PIPE_USAGE_DEFAULT; 609 610 memset(&whandle, 0, sizeof(struct winsys_handle)); 611 whandle.type = WINSYS_HANDLE_TYPE_FD; 612 whandle.handle = memory_attribute->buffers[index]; 613 whandle.modifier = DRM_FORMAT_MOD_INVALID; 614 whandle.format = templat->buffer_format; 615 616 // Create a resource for each plane. 617 memset(resources, 0, sizeof resources); 618 for (i = 0; i < memory_attribute->num_planes; i++) { 619 unsigned num_planes = util_format_get_num_planes(templat->buffer_format); 620 621 res_templ.format = resource_formats[i]; 622 if (res_templ.format == PIPE_FORMAT_NONE) { 623 if (i < num_planes) { 624 result = VA_STATUS_ERROR_INVALID_PARAMETER; 625 goto fail; 626 } else { 627 continue; 628 } 629 } 630 631 res_templ.width0 = util_format_get_plane_width(templat->buffer_format, i, 632 memory_attribute->width); 633 res_templ.height0 = util_format_get_plane_height(templat->buffer_format, i, 634 memory_attribute->height); 635 636 whandle.stride = memory_attribute->pitches[i]; 637 whandle.offset = memory_attribute->offsets[i]; 638 resources[i] = pscreen->resource_from_handle(pscreen, &res_templ, &whandle, 639 PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE); 640 if (!resources[i]) { 641 result = VA_STATUS_ERROR_ALLOCATION_FAILED; 642 goto fail; 643 } 644 } 645 646 surface->buffer = vl_video_buffer_create_ex2(drv->pipe, templat, resources); 647 if (!surface->buffer) { 648 result = VA_STATUS_ERROR_ALLOCATION_FAILED; 649 goto fail; 650 } 651 return VA_STATUS_SUCCESS; 652 653fail: 654 for (i = 0; i < VL_NUM_COMPONENTS; i++) 655 pipe_resource_reference(&resources[i], NULL); 656 return result; 657} 658 659static VAStatus 660surface_from_prime_2(VADriverContextP ctx, vlVaSurface *surface, 661 VADRMPRIMESurfaceDescriptor *desc, 662 struct pipe_video_buffer *templat) 663{ 664 vlVaDriver *drv; 665 struct pipe_screen *pscreen; 666 struct pipe_resource res_templ; 667 struct winsys_handle whandle; 668 struct pipe_resource *resources[VL_NUM_COMPONENTS]; 669 enum pipe_format resource_formats[VL_NUM_COMPONENTS]; 670 unsigned num_format_planes, expected_planes, input_planes, plane; 671 VAStatus result; 672 673 num_format_planes = util_format_get_num_planes(templat->buffer_format); 674 pscreen = VL_VA_PSCREEN(ctx); 675 drv = VL_VA_DRIVER(ctx); 676 677 if (!desc || desc->num_layers >= 4 ||desc->num_objects == 0) 678 return VA_STATUS_ERROR_INVALID_PARAMETER; 679 680 if (surface->templat.width != desc->width || 681 surface->templat.height != desc->height || 682 desc->num_layers < 1) 683 return VA_STATUS_ERROR_INVALID_PARAMETER; 684 685 if (desc->num_layers != num_format_planes) 686 return VA_STATUS_ERROR_INVALID_PARAMETER; 687 688 input_planes = 0; 689 for (unsigned i = 0; i < desc->num_layers; ++i) { 690 if (desc->layers[i].num_planes == 0 || desc->layers[i].num_planes > 4) 691 return VA_STATUS_ERROR_INVALID_PARAMETER; 692 693 for (unsigned j = 0; j < desc->layers[i].num_planes; ++j) 694 if (desc->layers[i].object_index[j] >= desc->num_objects) 695 return VA_STATUS_ERROR_INVALID_PARAMETER; 696 697 input_planes += desc->layers[i].num_planes; 698 } 699 700 expected_planes = num_format_planes; 701 if (desc->objects[0].drm_format_modifier != DRM_FORMAT_MOD_INVALID && 702 pscreen->is_dmabuf_modifier_supported && 703 pscreen->is_dmabuf_modifier_supported(pscreen, desc->objects[0].drm_format_modifier, 704 templat->buffer_format, NULL) && 705 pscreen->get_dmabuf_modifier_planes) 706 expected_planes = pscreen->get_dmabuf_modifier_planes(pscreen, desc->objects[0].drm_format_modifier, 707 templat->buffer_format); 708 709 if (input_planes != expected_planes) 710 return VA_STATUS_ERROR_INVALID_PARAMETER; 711 712 vl_get_video_buffer_formats(pscreen, templat->buffer_format, resource_formats); 713 714 memset(&res_templ, 0, sizeof(res_templ)); 715 res_templ.target = PIPE_TEXTURE_2D; 716 res_templ.last_level = 0; 717 res_templ.depth0 = 1; 718 res_templ.array_size = 1; 719 res_templ.width0 = desc->width; 720 res_templ.height0 = desc->height; 721 res_templ.bind = PIPE_BIND_SAMPLER_VIEW; 722 res_templ.usage = PIPE_USAGE_DEFAULT; 723 res_templ.format = templat->buffer_format; 724 725 memset(&whandle, 0, sizeof(struct winsys_handle)); 726 whandle.type = WINSYS_HANDLE_TYPE_FD; 727 whandle.format = templat->buffer_format; 728 whandle.modifier = desc->objects[0].drm_format_modifier; 729 730 // Create a resource for each plane. 731 memset(resources, 0, sizeof resources); 732 733 /* This does a backwards walk to set the next pointers. It interleaves so 734 * that the main planes always come first and then the first compression metadata 735 * plane of each main plane etc. */ 736 plane = input_planes - 1; 737 for (int layer_plane = 3; layer_plane >= 0; --layer_plane) { 738 for (int layer = desc->num_layers - 1; layer >= 0; --layer) { 739 if (layer_plane >= desc->layers[layer].num_planes) 740 continue; 741 742 if (plane < num_format_planes) 743 res_templ.format = resource_formats[plane]; 744 745 whandle.stride = desc->layers[layer].pitch[layer_plane]; 746 whandle.offset = desc->layers[layer].offset[layer_plane]; 747 whandle.handle = desc->objects[desc->layers[layer].object_index[layer_plane]].fd; 748 whandle.plane = plane; 749 750 resources[plane] = pscreen->resource_from_handle(pscreen, &res_templ, &whandle, 751 PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE); 752 if (!resources[plane]) { 753 result = VA_STATUS_ERROR_ALLOCATION_FAILED; 754 goto fail; 755 } 756 757 /* After the resource gets created the resource now owns the next reference. */ 758 res_templ.next = NULL; 759 760 if (plane) 761 pipe_resource_reference(&res_templ.next, resources[plane]); 762 --plane; 763 } 764 } 765 766 surface->buffer = vl_video_buffer_create_ex2(drv->pipe, templat, resources); 767 if (!surface->buffer) { 768 result = VA_STATUS_ERROR_ALLOCATION_FAILED; 769 goto fail; 770 } 771 return VA_STATUS_SUCCESS; 772 773fail: 774 pipe_resource_reference(&res_templ.next, NULL); 775 for (int i = 0; i < VL_NUM_COMPONENTS; i++) 776 pipe_resource_reference(&resources[i], NULL); 777 return result; 778} 779 780VAStatus 781vlVaHandleSurfaceAllocate(vlVaDriver *drv, vlVaSurface *surface, 782 struct pipe_video_buffer *templat, 783 const uint64_t *modifiers, 784 unsigned int modifiers_count) 785{ 786 struct pipe_surface **surfaces; 787 unsigned i; 788 789 if (modifiers_count > 0) { 790 if (!drv->pipe->create_video_buffer_with_modifiers) 791 return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED; 792 surface->buffer = 793 drv->pipe->create_video_buffer_with_modifiers(drv->pipe, templat, 794 modifiers, 795 modifiers_count); 796 } else { 797 surface->buffer = drv->pipe->create_video_buffer(drv->pipe, templat); 798 } 799 if (!surface->buffer) 800 return VA_STATUS_ERROR_ALLOCATION_FAILED; 801 802 surfaces = surface->buffer->get_surfaces(surface->buffer); 803 for (i = 0; i < VL_MAX_SURFACES; ++i) { 804 union pipe_color_union c = {}; 805 806 if (!surfaces[i]) 807 continue; 808 809 if (i > !!surface->buffer->interlaced) 810 c.f[0] = c.f[1] = c.f[2] = c.f[3] = 0.5f; 811 812 drv->pipe->clear_render_target(drv->pipe, surfaces[i], &c, 0, 0, 813 surfaces[i]->width, surfaces[i]->height, 814 false); 815 } 816 drv->pipe->flush(drv->pipe, NULL, 0); 817 818 return VA_STATUS_SUCCESS; 819} 820 821VAStatus 822vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format, 823 unsigned int width, unsigned int height, 824 VASurfaceID *surfaces, unsigned int num_surfaces, 825 VASurfaceAttrib *attrib_list, unsigned int num_attribs) 826{ 827 vlVaDriver *drv; 828 VASurfaceAttribExternalBuffers *memory_attribute; 829 VADRMPRIMESurfaceDescriptor *prime_desc; 830#ifdef HAVE_VA_SURFACE_ATTRIB_DRM_FORMAT_MODIFIERS 831 const VADRMFormatModifierList *modifier_list; 832#endif 833 struct pipe_video_buffer templat; 834 struct pipe_screen *pscreen; 835 int i; 836 int memory_type; 837 int expected_fourcc; 838 VAStatus vaStatus; 839 vlVaSurface *surf; 840 bool protected; 841 const uint64_t *modifiers; 842 unsigned int modifiers_count; 843 844 if (!ctx) 845 return VA_STATUS_ERROR_INVALID_CONTEXT; 846 847 if (!(width && height)) 848 return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; 849 850 drv = VL_VA_DRIVER(ctx); 851 852 if (!drv) 853 return VA_STATUS_ERROR_INVALID_CONTEXT; 854 855 pscreen = VL_VA_PSCREEN(ctx); 856 857 if (!pscreen) 858 return VA_STATUS_ERROR_INVALID_CONTEXT; 859 860 /* Default. */ 861 memory_attribute = NULL; 862 prime_desc = NULL; 863 memory_type = VA_SURFACE_ATTRIB_MEM_TYPE_VA; 864 expected_fourcc = 0; 865 modifiers = NULL; 866 modifiers_count = 0; 867 868 for (i = 0; i < num_attribs && attrib_list; i++) { 869 if (!(attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) 870 continue; 871 872 switch (attrib_list[i].type) { 873 case VASurfaceAttribPixelFormat: 874 if (attrib_list[i].value.type != VAGenericValueTypeInteger) 875 return VA_STATUS_ERROR_INVALID_PARAMETER; 876 expected_fourcc = attrib_list[i].value.value.i; 877 break; 878 case VASurfaceAttribMemoryType: 879 if (attrib_list[i].value.type != VAGenericValueTypeInteger) 880 return VA_STATUS_ERROR_INVALID_PARAMETER; 881 882 switch (attrib_list[i].value.value.i) { 883 case VA_SURFACE_ATTRIB_MEM_TYPE_VA: 884 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: 885 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2: 886 memory_type = attrib_list[i].value.value.i; 887 break; 888 default: 889 return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; 890 } 891 break; 892 case VASurfaceAttribExternalBufferDescriptor: 893 if (attrib_list[i].value.type != VAGenericValueTypePointer) 894 return VA_STATUS_ERROR_INVALID_PARAMETER; 895 if (memory_type == VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2) 896 prime_desc = (VADRMPRIMESurfaceDescriptor *)attrib_list[i].value.value.p; 897 else 898 memory_attribute = (VASurfaceAttribExternalBuffers *)attrib_list[i].value.value.p; 899 break; 900#ifdef HAVE_VA_SURFACE_ATTRIB_DRM_FORMAT_MODIFIERS 901 case VASurfaceAttribDRMFormatModifiers: 902 if (attrib_list[i].value.type != VAGenericValueTypePointer) 903 return VA_STATUS_ERROR_INVALID_PARAMETER; 904 modifier_list = attrib_list[i].value.value.p; 905 modifiers = modifier_list->modifiers; 906 modifiers_count = modifier_list->num_modifiers; 907 break; 908#endif 909 case VASurfaceAttribUsageHint: 910 if (attrib_list[i].value.type != VAGenericValueTypeInteger) 911 return VA_STATUS_ERROR_INVALID_PARAMETER; 912 break; 913 default: 914 return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED; 915 } 916 } 917 918 protected = format & VA_RT_FORMAT_PROTECTED; 919 format &= ~VA_RT_FORMAT_PROTECTED; 920 921 if (VA_RT_FORMAT_YUV420 != format && 922 VA_RT_FORMAT_YUV422 != format && 923 VA_RT_FORMAT_YUV444 != format && 924 VA_RT_FORMAT_YUV420_10BPP != format && 925 VA_RT_FORMAT_RGB32 != format) { 926 return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; 927 } 928 929 switch (memory_type) { 930 case VA_SURFACE_ATTRIB_MEM_TYPE_VA: 931 break; 932 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: 933 if (!memory_attribute) 934 return VA_STATUS_ERROR_INVALID_PARAMETER; 935 if (modifiers) 936 return VA_STATUS_ERROR_INVALID_PARAMETER; 937 938 expected_fourcc = memory_attribute->pixel_format; 939 break; 940 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2: 941 if (!prime_desc) 942 return VA_STATUS_ERROR_INVALID_PARAMETER; 943 944 expected_fourcc = prime_desc->fourcc; 945 break; 946 default: 947 assert(0); 948 } 949 950 memset(&templat, 0, sizeof(templat)); 951 952 templat.buffer_format = pscreen->get_video_param( 953 pscreen, 954 PIPE_VIDEO_PROFILE_UNKNOWN, 955 PIPE_VIDEO_ENTRYPOINT_BITSTREAM, 956 PIPE_VIDEO_CAP_PREFERED_FORMAT 957 ); 958 959 if (modifiers) 960 templat.interlaced = false; 961 else 962 templat.interlaced = 963 pscreen->get_video_param(pscreen, PIPE_VIDEO_PROFILE_UNKNOWN, 964 PIPE_VIDEO_ENTRYPOINT_BITSTREAM, 965 PIPE_VIDEO_CAP_PREFERS_INTERLACED); 966 967 if (expected_fourcc) { 968 enum pipe_format expected_format = VaFourccToPipeFormat(expected_fourcc); 969 970 if (expected_format != templat.buffer_format || memory_attribute) 971 templat.interlaced = 0; 972 973 templat.buffer_format = expected_format; 974 } 975 976 templat.width = width; 977 templat.height = height; 978 if (protected) 979 templat.bind |= PIPE_BIND_PROTECTED; 980 981 memset(surfaces, VA_INVALID_ID, num_surfaces * sizeof(VASurfaceID)); 982 983 mtx_lock(&drv->mutex); 984 for (i = 0; i < num_surfaces; i++) { 985 surf = CALLOC(1, sizeof(vlVaSurface)); 986 if (!surf) { 987 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 988 goto no_res; 989 } 990 991 surf->templat = templat; 992 993 switch (memory_type) { 994 case VA_SURFACE_ATTRIB_MEM_TYPE_VA: 995 /* The application will clear the TILING flag when the surface is 996 * intended to be exported as dmabuf. Adding shared flag because not 997 * null memory_attribute means VASurfaceAttribExternalBuffers is used. 998 */ 999 if (memory_attribute && 1000 !(memory_attribute->flags & VA_SURFACE_EXTBUF_DESC_ENABLE_TILING)) 1001 templat.bind = PIPE_BIND_LINEAR | PIPE_BIND_SHARED; 1002 1003 vaStatus = vlVaHandleSurfaceAllocate(drv, surf, &templat, modifiers, 1004 modifiers_count); 1005 if (vaStatus != VA_STATUS_SUCCESS) 1006 goto free_surf; 1007 break; 1008 1009 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: 1010 vaStatus = surface_from_external_memory(ctx, surf, memory_attribute, i, &templat); 1011 if (vaStatus != VA_STATUS_SUCCESS) 1012 goto free_surf; 1013 break; 1014 1015 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2: 1016 vaStatus = surface_from_prime_2(ctx, surf, prime_desc, &templat); 1017 if (vaStatus != VA_STATUS_SUCCESS) 1018 goto free_surf; 1019 break; 1020 default: 1021 assert(0); 1022 } 1023 1024 util_dynarray_init(&surf->subpics, NULL); 1025 surfaces[i] = handle_table_add(drv->htab, surf); 1026 if (!surfaces[i]) { 1027 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 1028 goto destroy_surf; 1029 } 1030 } 1031 mtx_unlock(&drv->mutex); 1032 1033 return VA_STATUS_SUCCESS; 1034 1035destroy_surf: 1036 surf->buffer->destroy(surf->buffer); 1037 1038free_surf: 1039 FREE(surf); 1040 1041no_res: 1042 mtx_unlock(&drv->mutex); 1043 if (i) 1044 vlVaDestroySurfaces(ctx, surfaces, i); 1045 1046 return vaStatus; 1047} 1048 1049VAStatus 1050vlVaQueryVideoProcFilters(VADriverContextP ctx, VAContextID context, 1051 VAProcFilterType *filters, unsigned int *num_filters) 1052{ 1053 unsigned int num = 0; 1054 1055 if (!ctx) 1056 return VA_STATUS_ERROR_INVALID_CONTEXT; 1057 1058 if (!num_filters || !filters) 1059 return VA_STATUS_ERROR_INVALID_PARAMETER; 1060 1061 filters[num++] = VAProcFilterDeinterlacing; 1062 1063 *num_filters = num; 1064 1065 return VA_STATUS_SUCCESS; 1066} 1067 1068VAStatus 1069vlVaQueryVideoProcFilterCaps(VADriverContextP ctx, VAContextID context, 1070 VAProcFilterType type, void *filter_caps, 1071 unsigned int *num_filter_caps) 1072{ 1073 unsigned int i; 1074 1075 if (!ctx) 1076 return VA_STATUS_ERROR_INVALID_CONTEXT; 1077 1078 if (!filter_caps || !num_filter_caps) 1079 return VA_STATUS_ERROR_INVALID_PARAMETER; 1080 1081 i = 0; 1082 1083 switch (type) { 1084 case VAProcFilterNone: 1085 break; 1086 case VAProcFilterDeinterlacing: { 1087 VAProcFilterCapDeinterlacing *deint = filter_caps; 1088 1089 if (*num_filter_caps < 3) { 1090 *num_filter_caps = 3; 1091 return VA_STATUS_ERROR_MAX_NUM_EXCEEDED; 1092 } 1093 1094 deint[i++].type = VAProcDeinterlacingBob; 1095 deint[i++].type = VAProcDeinterlacingWeave; 1096 deint[i++].type = VAProcDeinterlacingMotionAdaptive; 1097 break; 1098 } 1099 1100 case VAProcFilterNoiseReduction: 1101 case VAProcFilterSharpening: 1102 case VAProcFilterColorBalance: 1103 case VAProcFilterSkinToneEnhancement: 1104 return VA_STATUS_ERROR_UNIMPLEMENTED; 1105 default: 1106 assert(0); 1107 } 1108 1109 *num_filter_caps = i; 1110 1111 return VA_STATUS_SUCCESS; 1112} 1113 1114static VAProcColorStandardType vpp_input_color_standards[] = { 1115 VAProcColorStandardBT601 1116}; 1117 1118static VAProcColorStandardType vpp_output_color_standards[] = { 1119 VAProcColorStandardBT601 1120}; 1121 1122VAStatus 1123vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx, VAContextID context, 1124 VABufferID *filters, unsigned int num_filters, 1125 VAProcPipelineCaps *pipeline_cap) 1126{ 1127 unsigned int i = 0; 1128 1129 if (!ctx) 1130 return VA_STATUS_ERROR_INVALID_CONTEXT; 1131 1132 if (!pipeline_cap) 1133 return VA_STATUS_ERROR_INVALID_PARAMETER; 1134 1135 if (num_filters && !filters) 1136 return VA_STATUS_ERROR_INVALID_PARAMETER; 1137 1138 pipeline_cap->pipeline_flags = 0; 1139 pipeline_cap->filter_flags = 0; 1140 pipeline_cap->num_forward_references = 0; 1141 pipeline_cap->num_backward_references = 0; 1142 pipeline_cap->num_input_color_standards = ARRAY_SIZE(vpp_input_color_standards); 1143 pipeline_cap->input_color_standards = vpp_input_color_standards; 1144 pipeline_cap->num_output_color_standards = ARRAY_SIZE(vpp_output_color_standards); 1145 pipeline_cap->output_color_standards = vpp_output_color_standards; 1146 1147 for (i = 0; i < num_filters; i++) { 1148 vlVaBuffer *buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, filters[i]); 1149 VAProcFilterParameterBufferBase *filter; 1150 1151 if (!buf || buf->type != VAProcFilterParameterBufferType) 1152 return VA_STATUS_ERROR_INVALID_BUFFER; 1153 1154 filter = buf->data; 1155 switch (filter->type) { 1156 case VAProcFilterDeinterlacing: { 1157 VAProcFilterParameterBufferDeinterlacing *deint = buf->data; 1158 if (deint->algorithm == VAProcDeinterlacingMotionAdaptive) { 1159 pipeline_cap->num_forward_references = 2; 1160 pipeline_cap->num_backward_references = 1; 1161 } 1162 break; 1163 } 1164 default: 1165 return VA_STATUS_ERROR_UNIMPLEMENTED; 1166 } 1167 } 1168 1169 return VA_STATUS_SUCCESS; 1170} 1171 1172static uint32_t pipe_format_to_drm_format(enum pipe_format format) 1173{ 1174 switch (format) { 1175 case PIPE_FORMAT_R8_UNORM: 1176 return DRM_FORMAT_R8; 1177 case PIPE_FORMAT_R8G8_UNORM: 1178 return DRM_FORMAT_GR88; 1179 case PIPE_FORMAT_R16_UNORM: 1180 return DRM_FORMAT_R16; 1181 case PIPE_FORMAT_R16G16_UNORM: 1182 return DRM_FORMAT_GR1616; 1183 case PIPE_FORMAT_B8G8R8A8_UNORM: 1184 return DRM_FORMAT_ARGB8888; 1185 case PIPE_FORMAT_R8G8B8A8_UNORM: 1186 return DRM_FORMAT_ABGR8888; 1187 case PIPE_FORMAT_B8G8R8X8_UNORM: 1188 return DRM_FORMAT_XRGB8888; 1189 case PIPE_FORMAT_R8G8B8X8_UNORM: 1190 return DRM_FORMAT_XBGR8888; 1191 case PIPE_FORMAT_NV12: 1192 return DRM_FORMAT_NV12; 1193 case PIPE_FORMAT_P010: 1194 return DRM_FORMAT_P010; 1195 default: 1196 return DRM_FORMAT_INVALID; 1197 } 1198} 1199 1200#if VA_CHECK_VERSION(1, 1, 0) 1201VAStatus 1202vlVaExportSurfaceHandle(VADriverContextP ctx, 1203 VASurfaceID surface_id, 1204 uint32_t mem_type, 1205 uint32_t flags, 1206 void *descriptor) 1207{ 1208 vlVaDriver *drv; 1209 vlVaSurface *surf; 1210 struct pipe_surface **surfaces; 1211 struct pipe_screen *screen; 1212 VAStatus ret; 1213 unsigned int usage; 1214 int i, p; 1215 1216 VADRMPRIMESurfaceDescriptor *desc = descriptor; 1217 1218 if (mem_type != VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2) 1219 return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; 1220 1221 drv = VL_VA_DRIVER(ctx); 1222 screen = VL_VA_PSCREEN(ctx); 1223 mtx_lock(&drv->mutex); 1224 1225 surf = handle_table_get(drv->htab, surface_id); 1226 if (!surf || !surf->buffer) { 1227 mtx_unlock(&drv->mutex); 1228 return VA_STATUS_ERROR_INVALID_SURFACE; 1229 } 1230 1231 if (surf->buffer->interlaced) { 1232 struct pipe_video_buffer *interlaced = surf->buffer; 1233 struct u_rect src_rect, dst_rect; 1234 1235 surf->templat.interlaced = false; 1236 1237 ret = vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0); 1238 if (ret != VA_STATUS_SUCCESS) { 1239 mtx_unlock(&drv->mutex); 1240 return VA_STATUS_ERROR_ALLOCATION_FAILED; 1241 } 1242 1243 src_rect.x0 = dst_rect.x0 = 0; 1244 src_rect.y0 = dst_rect.y0 = 0; 1245 src_rect.x1 = dst_rect.x1 = surf->templat.width; 1246 src_rect.y1 = dst_rect.y1 = surf->templat.height; 1247 1248 vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor, 1249 interlaced, surf->buffer, 1250 &src_rect, &dst_rect, 1251 VL_COMPOSITOR_WEAVE); 1252 1253 interlaced->destroy(interlaced); 1254 } 1255 1256 surfaces = surf->buffer->get_surfaces(surf->buffer); 1257 1258 usage = 0; 1259 if (flags & VA_EXPORT_SURFACE_WRITE_ONLY) 1260 usage |= PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE; 1261 1262 desc->fourcc = PipeFormatToVaFourcc(surf->buffer->buffer_format); 1263 desc->width = surf->buffer->width; 1264 desc->height = surf->buffer->height; 1265 1266 for (p = 0; p < VL_MAX_SURFACES; p++) { 1267 struct winsys_handle whandle; 1268 struct pipe_resource *resource; 1269 uint32_t drm_format; 1270 1271 if (!surfaces[p]) 1272 break; 1273 1274 resource = surfaces[p]->texture; 1275 1276 drm_format = pipe_format_to_drm_format(resource->format); 1277 if (drm_format == DRM_FORMAT_INVALID) { 1278 ret = VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; 1279 goto fail; 1280 } 1281 1282 memset(&whandle, 0, sizeof(whandle)); 1283 whandle.type = WINSYS_HANDLE_TYPE_FD; 1284 1285 if (!screen->resource_get_handle(screen, drv->pipe, resource, 1286 &whandle, usage)) { 1287 ret = VA_STATUS_ERROR_INVALID_SURFACE; 1288 goto fail; 1289 } 1290 1291 desc->objects[p].fd = (int)whandle.handle; 1292 desc->objects[p].size = 0; 1293 desc->objects[p].drm_format_modifier = whandle.modifier; 1294 1295 if (flags & VA_EXPORT_SURFACE_COMPOSED_LAYERS) { 1296 desc->layers[0].object_index[p] = p; 1297 desc->layers[0].offset[p] = whandle.offset; 1298 desc->layers[0].pitch[p] = whandle.stride; 1299 } else { 1300 desc->layers[p].drm_format = drm_format; 1301 desc->layers[p].num_planes = 1; 1302 desc->layers[p].object_index[0] = p; 1303 desc->layers[p].offset[0] = whandle.offset; 1304 desc->layers[p].pitch[0] = whandle.stride; 1305 } 1306 } 1307 1308 desc->num_objects = p; 1309 1310 if (flags & VA_EXPORT_SURFACE_COMPOSED_LAYERS) { 1311 uint32_t drm_format = pipe_format_to_drm_format(surf->buffer->buffer_format); 1312 if (drm_format == DRM_FORMAT_INVALID) { 1313 ret = VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; 1314 goto fail; 1315 } 1316 1317 desc->num_layers = 1; 1318 desc->layers[0].drm_format = drm_format; 1319 desc->layers[0].num_planes = p; 1320 } else { 1321 desc->num_layers = p; 1322 } 1323 1324 mtx_unlock(&drv->mutex); 1325 1326 return VA_STATUS_SUCCESS; 1327 1328fail: 1329 for (i = 0; i < p; i++) 1330 close(desc->objects[i].fd); 1331 1332 mtx_unlock(&drv->mutex); 1333 1334 return ret; 1335} 1336#endif 1337