1 /************************************************************************** 2 * 3 * Copyright 2010 Thomas Balling Srensen & 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 "state_tracker/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 40 #include "vl/vl_compositor.h" 41 #include "vl/vl_video_buffer.h" 42 #include "vl/vl_winsys.h" 43 44 #include "va_private.h" 45 46 DEBUG_GET_ONCE_BOOL_OPTION(nointerlace, "VAAPI_DISABLE_INTERLACE", FALSE); 47 48 #include <va/va_drmcommon.h> 49 50 static 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 55 VAStatus 56 vlVaCreateSurfaces(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 63 VAStatus 64 vlVaDestroySurfaces(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 pipe_mutex_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 pipe_mutex_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 pipe_mutex_unlock(drv->mutex); 87 88 return VA_STATUS_SUCCESS; 89 } 90 91 VAStatus 92 vlVaSyncSurface(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 pipe_mutex_lock(drv->mutex); 106 surf = handle_table_get(drv->htab, render_target); 107 108 if (!surf || !surf->buffer) { 109 pipe_mutex_unlock(drv->mutex); 110 return VA_STATUS_ERROR_INVALID_SURFACE; 111 } 112 113 if (!surf->feedback) { 114 // No outstanding operation: nothing to do. 115 pipe_mutex_unlock(drv->mutex); 116 return VA_STATUS_SUCCESS; 117 } 118 119 context = handle_table_get(drv->htab, surf->ctx); 120 if (!context) { 121 pipe_mutex_unlock(drv->mutex); 122 return VA_STATUS_ERROR_INVALID_CONTEXT; 123 } 124 125 if (context->decoder->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { 126 int frame_diff; 127 if (context->desc.h264enc.frame_num_cnt >= surf->frame_num_cnt) 128 frame_diff = context->desc.h264enc.frame_num_cnt - surf->frame_num_cnt; 129 else 130 frame_diff = 0xFFFFFFFF - surf->frame_num_cnt + 1 + context->desc.h264enc.frame_num_cnt; 131 if ((frame_diff == 0) && 132 (surf->force_flushed == false) && 133 (context->desc.h264enc.frame_num_cnt % 2 != 0)) { 134 context->decoder->flush(context->decoder); 135 context->first_single_submitted = true; 136 } 137 context->decoder->get_feedback(context->decoder, surf->feedback, &(surf->coded_buf->coded_size)); 138 surf->feedback = NULL; 139 } 140 pipe_mutex_unlock(drv->mutex); 141 return VA_STATUS_SUCCESS; 142 } 143 144 VAStatus 145 vlVaQuerySurfaceStatus(VADriverContextP ctx, VASurfaceID render_target, VASurfaceStatus *status) 146 { 147 if (!ctx) 148 return VA_STATUS_ERROR_INVALID_CONTEXT; 149 150 return VA_STATUS_SUCCESS; 151 } 152 153 VAStatus 154 vlVaQuerySurfaceError(VADriverContextP ctx, VASurfaceID render_target, VAStatus error_status, void **error_info) 155 { 156 if (!ctx) 157 return VA_STATUS_ERROR_INVALID_CONTEXT; 158 159 return VA_STATUS_ERROR_UNIMPLEMENTED; 160 } 161 162 static void 163 upload_sampler(struct pipe_context *pipe, struct pipe_sampler_view *dst, 164 const struct pipe_box *dst_box, const void *src, unsigned src_stride, 165 unsigned src_x, unsigned src_y) 166 { 167 struct pipe_transfer *transfer; 168 void *map; 169 170 map = pipe->transfer_map(pipe, dst->texture, 0, PIPE_TRANSFER_WRITE, 171 dst_box, &transfer); 172 if (!map) 173 return; 174 175 util_copy_rect(map, dst->texture->format, transfer->stride, 0, 0, 176 dst_box->width, dst_box->height, 177 src, src_stride, src_x, src_y); 178 179 pipe->transfer_unmap(pipe, transfer); 180 } 181 182 static VAStatus 183 vlVaPutSubpictures(vlVaSurface *surf, vlVaDriver *drv, 184 struct pipe_surface *surf_draw, struct u_rect *dirty_area, 185 struct u_rect *src_rect, struct u_rect *dst_rect) 186 { 187 vlVaSubpicture *sub; 188 int i; 189 190 if (!(surf->subpics.data || surf->subpics.size)) 191 return VA_STATUS_SUCCESS; 192 193 for (i = 0; i < surf->subpics.size/sizeof(vlVaSubpicture *); i++) { 194 struct pipe_blend_state blend; 195 void *blend_state; 196 vlVaBuffer *buf; 197 struct pipe_box box; 198 struct u_rect *s, *d, sr, dr, c; 199 int sw, sh, dw, dh; 200 201 sub = ((vlVaSubpicture **)surf->subpics.data)[i]; 202 if (!sub) 203 continue; 204 205 buf = handle_table_get(drv->htab, sub->image->buf); 206 if (!buf) 207 return VA_STATUS_ERROR_INVALID_IMAGE; 208 209 box.x = 0; 210 box.y = 0; 211 box.z = 0; 212 box.width = sub->dst_rect.x1 - sub->dst_rect.x0; 213 box.height = sub->dst_rect.y1 - sub->dst_rect.y0; 214 box.depth = 1; 215 216 s = &sub->src_rect; 217 d = &sub->dst_rect; 218 sw = s->x1 - s->x0; 219 sh = s->y1 - s->y0; 220 dw = d->x1 - d->x0; 221 dh = d->y1 - d->y0; 222 c.x0 = MAX2(d->x0, s->x0); 223 c.y0 = MAX2(d->y0, s->y0); 224 c.x1 = MIN2(d->x0 + dw, src_rect->x1); 225 c.y1 = MIN2(d->y0 + dh, src_rect->y1); 226 sr.x0 = s->x0 + (c.x0 - d->x0)*(sw/(float)dw); 227 sr.y0 = s->y0 + (c.y0 - d->y0)*(sh/(float)dh); 228 sr.x1 = s->x0 + (c.x1 - d->x0)*(sw/(float)dw); 229 sr.y1 = s->y0 + (c.y1 - d->y0)*(sh/(float)dh); 230 231 s = src_rect; 232 d = dst_rect; 233 sw = s->x1 - s->x0; 234 sh = s->y1 - s->y0; 235 dw = d->x1 - d->x0; 236 dh = d->y1 - d->y0; 237 dr.x0 = d->x0 + c.x0*(dw/(float)sw); 238 dr.y0 = d->y0 + c.y0*(dh/(float)sh); 239 dr.x1 = d->x0 + c.x1*(dw/(float)sw); 240 dr.y1 = d->y0 + c.y1*(dh/(float)sh); 241 242 memset(&blend, 0, sizeof(blend)); 243 blend.independent_blend_enable = 0; 244 blend.rt[0].blend_enable = 1; 245 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; 246 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; 247 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO; 248 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 249 blend.rt[0].rgb_func = PIPE_BLEND_ADD; 250 blend.rt[0].alpha_func = PIPE_BLEND_ADD; 251 blend.rt[0].colormask = PIPE_MASK_RGBA; 252 blend.logicop_enable = 0; 253 blend.logicop_func = PIPE_LOGICOP_CLEAR; 254 blend.dither = 0; 255 blend_state = drv->pipe->create_blend_state(drv->pipe, &blend); 256 257 vl_compositor_clear_layers(&drv->cstate); 258 vl_compositor_set_layer_blend(&drv->cstate, 0, blend_state, false); 259 upload_sampler(drv->pipe, sub->sampler, &box, buf->data, 260 sub->image->pitches[0], 0, 0); 261 vl_compositor_set_rgba_layer(&drv->cstate, &drv->compositor, 0, sub->sampler, 262 &sr, NULL, NULL); 263 vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dr); 264 vl_compositor_render(&drv->cstate, &drv->compositor, surf_draw, dirty_area, false); 265 drv->pipe->delete_blend_state(drv->pipe, blend_state); 266 } 267 268 return VA_STATUS_SUCCESS; 269 } 270 271 VAStatus 272 vlVaPutSurface(VADriverContextP ctx, VASurfaceID surface_id, void* draw, short srcx, short srcy, 273 unsigned short srcw, unsigned short srch, short destx, short desty, 274 unsigned short destw, unsigned short desth, VARectangle *cliprects, 275 unsigned int number_cliprects, unsigned int flags) 276 { 277 vlVaDriver *drv; 278 vlVaSurface *surf; 279 struct pipe_screen *screen; 280 struct pipe_resource *tex; 281 struct pipe_surface surf_templ, *surf_draw; 282 struct vl_screen *vscreen; 283 struct u_rect src_rect, *dirty_area; 284 struct u_rect dst_rect = {destx, destx + destw, desty, desty + desth}; 285 VAStatus status; 286 287 if (!ctx) 288 return VA_STATUS_ERROR_INVALID_CONTEXT; 289 290 drv = VL_VA_DRIVER(ctx); 291 pipe_mutex_lock(drv->mutex); 292 surf = handle_table_get(drv->htab, surface_id); 293 if (!surf) { 294 pipe_mutex_unlock(drv->mutex); 295 return VA_STATUS_ERROR_INVALID_SURFACE; 296 } 297 298 screen = drv->pipe->screen; 299 vscreen = drv->vscreen; 300 301 tex = vscreen->texture_from_drawable(vscreen, draw); 302 if (!tex) { 303 pipe_mutex_unlock(drv->mutex); 304 return VA_STATUS_ERROR_INVALID_DISPLAY; 305 } 306 307 dirty_area = vscreen->get_dirty_area(vscreen); 308 309 memset(&surf_templ, 0, sizeof(surf_templ)); 310 surf_templ.format = tex->format; 311 surf_draw = drv->pipe->create_surface(drv->pipe, tex, &surf_templ); 312 if (!surf_draw) { 313 pipe_resource_reference(&tex, NULL); 314 pipe_mutex_unlock(drv->mutex); 315 return VA_STATUS_ERROR_INVALID_DISPLAY; 316 } 317 318 src_rect.x0 = srcx; 319 src_rect.y0 = srcy; 320 src_rect.x1 = srcw + srcx; 321 src_rect.y1 = srch + srcy; 322 323 vl_compositor_clear_layers(&drv->cstate); 324 vl_compositor_set_buffer_layer(&drv->cstate, &drv->compositor, 0, surf->buffer, &src_rect, NULL, VL_COMPOSITOR_WEAVE); 325 vl_compositor_set_layer_dst_area(&drv->cstate, 0, &dst_rect); 326 vl_compositor_render(&drv->cstate, &drv->compositor, surf_draw, dirty_area, true); 327 328 status = vlVaPutSubpictures(surf, drv, surf_draw, dirty_area, &src_rect, &dst_rect); 329 if (status) { 330 pipe_mutex_unlock(drv->mutex); 331 return status; 332 } 333 334 /* flush before calling flush_frontbuffer so that rendering is flushed 335 * to back buffer so the texture can be copied in flush_frontbuffer 336 */ 337 drv->pipe->flush(drv->pipe, NULL, 0); 338 339 screen->flush_frontbuffer(screen, tex, 0, 0, 340 vscreen->get_private(vscreen), NULL); 341 342 343 pipe_resource_reference(&tex, NULL); 344 pipe_surface_reference(&surf_draw, NULL); 345 pipe_mutex_unlock(drv->mutex); 346 347 return VA_STATUS_SUCCESS; 348 } 349 350 VAStatus 351 vlVaLockSurface(VADriverContextP ctx, VASurfaceID surface, unsigned int *fourcc, 352 unsigned int *luma_stride, unsigned int *chroma_u_stride, unsigned int *chroma_v_stride, 353 unsigned int *luma_offset, unsigned int *chroma_u_offset, unsigned int *chroma_v_offset, 354 unsigned int *buffer_name, void **buffer) 355 { 356 if (!ctx) 357 return VA_STATUS_ERROR_INVALID_CONTEXT; 358 359 return VA_STATUS_ERROR_UNIMPLEMENTED; 360 } 361 362 VAStatus 363 vlVaUnlockSurface(VADriverContextP ctx, VASurfaceID surface) 364 { 365 if (!ctx) 366 return VA_STATUS_ERROR_INVALID_CONTEXT; 367 368 return VA_STATUS_ERROR_UNIMPLEMENTED; 369 } 370 371 VAStatus 372 vlVaQuerySurfaceAttributes(VADriverContextP ctx, VAConfigID config_id, 373 VASurfaceAttrib *attrib_list, unsigned int *num_attribs) 374 { 375 vlVaDriver *drv; 376 vlVaConfig *config; 377 VASurfaceAttrib *attribs; 378 struct pipe_screen *pscreen; 379 int i, j; 380 381 STATIC_ASSERT(ARRAY_SIZE(vpp_surface_formats) <= VL_VA_MAX_IMAGE_FORMATS); 382 383 if (config_id == VA_INVALID_ID) 384 return VA_STATUS_ERROR_INVALID_CONFIG; 385 386 if (!attrib_list && !num_attribs) 387 return VA_STATUS_ERROR_INVALID_PARAMETER; 388 389 if (!attrib_list) { 390 *num_attribs = VL_VA_MAX_IMAGE_FORMATS + VASurfaceAttribCount; 391 return VA_STATUS_SUCCESS; 392 } 393 394 if (!ctx) 395 return VA_STATUS_ERROR_INVALID_CONTEXT; 396 397 drv = VL_VA_DRIVER(ctx); 398 399 if (!drv) 400 return VA_STATUS_ERROR_INVALID_CONTEXT; 401 402 pipe_mutex_lock(drv->mutex); 403 config = handle_table_get(drv->htab, config_id); 404 pipe_mutex_unlock(drv->mutex); 405 406 if (!config) 407 return VA_STATUS_ERROR_INVALID_CONFIG; 408 409 pscreen = VL_VA_PSCREEN(ctx); 410 411 if (!pscreen) 412 return VA_STATUS_ERROR_INVALID_CONTEXT; 413 414 attribs = CALLOC(VL_VA_MAX_IMAGE_FORMATS + VASurfaceAttribCount, 415 sizeof(VASurfaceAttrib)); 416 417 if (!attribs) 418 return VA_STATUS_ERROR_ALLOCATION_FAILED; 419 420 i = 0; 421 422 /* vlVaCreateConfig returns PIPE_VIDEO_PROFILE_UNKNOWN 423 * only for VAEntrypointVideoProc. */ 424 if (config->profile == PIPE_VIDEO_PROFILE_UNKNOWN) { 425 if (config->rt_format & VA_RT_FORMAT_RGB32) { 426 for (j = 0; j < ARRAY_SIZE(vpp_surface_formats); ++j) { 427 attribs[i].type = VASurfaceAttribPixelFormat; 428 attribs[i].value.type = VAGenericValueTypeInteger; 429 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; 430 attribs[i].value.value.i = PipeFormatToVaFourcc(vpp_surface_formats[j]); 431 i++; 432 } 433 } 434 if (config->rt_format & VA_RT_FORMAT_YUV420) { 435 attribs[i].type = VASurfaceAttribPixelFormat; 436 attribs[i].value.type = VAGenericValueTypeInteger; 437 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; 438 attribs[i].value.value.i = VA_FOURCC_NV12; 439 i++; 440 } 441 } else { 442 /* Assume VAEntrypointVLD for now. */ 443 attribs[i].type = VASurfaceAttribPixelFormat; 444 attribs[i].value.type = VAGenericValueTypeInteger; 445 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; 446 attribs[i].value.value.i = VA_FOURCC_NV12; 447 i++; 448 } 449 450 attribs[i].type = VASurfaceAttribMemoryType; 451 attribs[i].value.type = VAGenericValueTypeInteger; 452 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE | VA_SURFACE_ATTRIB_SETTABLE; 453 attribs[i].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_VA | 454 VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; 455 i++; 456 457 attribs[i].type = VASurfaceAttribExternalBufferDescriptor; 458 attribs[i].value.type = VAGenericValueTypePointer; 459 attribs[i].flags = VA_SURFACE_ATTRIB_SETTABLE; 460 attribs[i].value.value.p = NULL; /* ignore */ 461 i++; 462 463 attribs[i].type = VASurfaceAttribMaxWidth; 464 attribs[i].value.type = VAGenericValueTypeInteger; 465 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE; 466 attribs[i].value.value.i = vl_video_buffer_max_size(pscreen); 467 i++; 468 469 attribs[i].type = VASurfaceAttribMaxHeight; 470 attribs[i].value.type = VAGenericValueTypeInteger; 471 attribs[i].flags = VA_SURFACE_ATTRIB_GETTABLE; 472 attribs[i].value.value.i = vl_video_buffer_max_size(pscreen); 473 i++; 474 475 if (i > *num_attribs) { 476 *num_attribs = i; 477 FREE(attribs); 478 return VA_STATUS_ERROR_MAX_NUM_EXCEEDED; 479 } 480 481 *num_attribs = i; 482 memcpy(attrib_list, attribs, i * sizeof(VASurfaceAttrib)); 483 FREE(attribs); 484 485 return VA_STATUS_SUCCESS; 486 } 487 488 static VAStatus 489 suface_from_external_memory(VADriverContextP ctx, vlVaSurface *surface, 490 VASurfaceAttribExternalBuffers *memory_attibute, 491 int index, VASurfaceID *surfaces, 492 struct pipe_video_buffer *templat) 493 { 494 vlVaDriver *drv; 495 struct pipe_screen *pscreen; 496 struct pipe_resource *resource; 497 struct pipe_resource res_templ; 498 struct winsys_handle whandle; 499 struct pipe_resource *resources[VL_NUM_COMPONENTS]; 500 501 if (!ctx) 502 return VA_STATUS_ERROR_INVALID_PARAMETER; 503 504 pscreen = VL_VA_PSCREEN(ctx); 505 drv = VL_VA_DRIVER(ctx); 506 507 if (!memory_attibute || !memory_attibute->buffers || 508 index > memory_attibute->num_buffers) 509 return VA_STATUS_ERROR_INVALID_PARAMETER; 510 511 if (surface->templat.width != memory_attibute->width || 512 surface->templat.height != memory_attibute->height || 513 memory_attibute->num_planes < 1) 514 return VA_STATUS_ERROR_INVALID_PARAMETER; 515 516 switch (memory_attibute->pixel_format) { 517 case VA_FOURCC_RGBA: 518 case VA_FOURCC_RGBX: 519 case VA_FOURCC_BGRA: 520 case VA_FOURCC_BGRX: 521 if (memory_attibute->num_planes != 1) 522 return VA_STATUS_ERROR_INVALID_PARAMETER; 523 break; 524 default: 525 return VA_STATUS_ERROR_INVALID_PARAMETER; 526 } 527 528 memset(&res_templ, 0, sizeof(res_templ)); 529 res_templ.target = PIPE_TEXTURE_2D; 530 res_templ.last_level = 0; 531 res_templ.depth0 = 1; 532 res_templ.array_size = 1; 533 res_templ.width0 = memory_attibute->width; 534 res_templ.height0 = memory_attibute->height; 535 res_templ.format = surface->templat.buffer_format; 536 res_templ.bind = PIPE_BIND_SAMPLER_VIEW; 537 res_templ.usage = PIPE_USAGE_DEFAULT; 538 539 memset(&whandle, 0, sizeof(struct winsys_handle)); 540 whandle.type = DRM_API_HANDLE_TYPE_FD; 541 whandle.handle = memory_attibute->buffers[index]; 542 whandle.stride = memory_attibute->pitches[index]; 543 544 resource = pscreen->resource_from_handle(pscreen, &res_templ, &whandle, 545 PIPE_HANDLE_USAGE_READ_WRITE); 546 547 if (!resource) 548 return VA_STATUS_ERROR_ALLOCATION_FAILED; 549 550 memset(resources, 0, sizeof resources); 551 resources[0] = resource; 552 553 surface->buffer = vl_video_buffer_create_ex2(drv->pipe, templat, resources); 554 if (!surface->buffer) 555 return VA_STATUS_ERROR_ALLOCATION_FAILED; 556 557 util_dynarray_init(&surface->subpics); 558 surfaces[index] = handle_table_add(drv->htab, surface); 559 560 if (!surfaces[index]) { 561 surface->buffer->destroy(surface->buffer); 562 return VA_STATUS_ERROR_ALLOCATION_FAILED; 563 } 564 565 return VA_STATUS_SUCCESS; 566 } 567 568 VAStatus 569 vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format, 570 unsigned int width, unsigned int height, 571 VASurfaceID *surfaces, unsigned int num_surfaces, 572 VASurfaceAttrib *attrib_list, unsigned int num_attribs) 573 { 574 vlVaDriver *drv; 575 VASurfaceAttribExternalBuffers *memory_attibute; 576 struct pipe_video_buffer templat; 577 struct pipe_screen *pscreen; 578 int i; 579 int memory_type; 580 int expected_fourcc; 581 VAStatus vaStatus; 582 583 if (!ctx) 584 return VA_STATUS_ERROR_INVALID_CONTEXT; 585 586 if (!(width && height)) 587 return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; 588 589 drv = VL_VA_DRIVER(ctx); 590 591 if (!drv) 592 return VA_STATUS_ERROR_INVALID_CONTEXT; 593 594 pscreen = VL_VA_PSCREEN(ctx); 595 596 if (!pscreen) 597 return VA_STATUS_ERROR_INVALID_CONTEXT; 598 599 /* Default. */ 600 memory_attibute = NULL; 601 memory_type = VA_SURFACE_ATTRIB_MEM_TYPE_VA; 602 expected_fourcc = 0; 603 604 for (i = 0; i < num_attribs && attrib_list; i++) { 605 if ((attrib_list[i].type == VASurfaceAttribPixelFormat) && 606 (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) { 607 if (attrib_list[i].value.type != VAGenericValueTypeInteger) 608 return VA_STATUS_ERROR_INVALID_PARAMETER; 609 expected_fourcc = attrib_list[i].value.value.i; 610 } 611 612 if ((attrib_list[i].type == VASurfaceAttribMemoryType) && 613 (attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) { 614 615 if (attrib_list[i].value.type != VAGenericValueTypeInteger) 616 return VA_STATUS_ERROR_INVALID_PARAMETER; 617 618 switch (attrib_list[i].value.value.i) { 619 case VA_SURFACE_ATTRIB_MEM_TYPE_VA: 620 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: 621 memory_type = attrib_list[i].value.value.i; 622 break; 623 default: 624 return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE; 625 } 626 } 627 628 if ((attrib_list[i].type == VASurfaceAttribExternalBufferDescriptor) && 629 (attrib_list[i].flags == VA_SURFACE_ATTRIB_SETTABLE)) { 630 if (attrib_list[i].value.type != VAGenericValueTypePointer) 631 return VA_STATUS_ERROR_INVALID_PARAMETER; 632 memory_attibute = (VASurfaceAttribExternalBuffers *)attrib_list[i].value.value.p; 633 } 634 } 635 636 if (VA_RT_FORMAT_YUV420 != format && 637 VA_RT_FORMAT_YUV422 != format && 638 VA_RT_FORMAT_YUV444 != format && 639 VA_RT_FORMAT_RGB32 != format) { 640 return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; 641 } 642 643 switch (memory_type) { 644 case VA_SURFACE_ATTRIB_MEM_TYPE_VA: 645 break; 646 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: 647 if (!memory_attibute) 648 return VA_STATUS_ERROR_INVALID_PARAMETER; 649 650 expected_fourcc = memory_attibute->pixel_format; 651 break; 652 default: 653 assert(0); 654 } 655 656 memset(&templat, 0, sizeof(templat)); 657 658 templat.buffer_format = pscreen->get_video_param( 659 pscreen, 660 PIPE_VIDEO_PROFILE_UNKNOWN, 661 PIPE_VIDEO_ENTRYPOINT_BITSTREAM, 662 PIPE_VIDEO_CAP_PREFERED_FORMAT 663 ); 664 templat.interlaced = pscreen->get_video_param( 665 pscreen, 666 PIPE_VIDEO_PROFILE_UNKNOWN, 667 PIPE_VIDEO_ENTRYPOINT_BITSTREAM, 668 PIPE_VIDEO_CAP_PREFERS_INTERLACED 669 ); 670 671 if (expected_fourcc) { 672 enum pipe_format expected_format = VaFourccToPipeFormat(expected_fourcc); 673 674 if (expected_format != templat.buffer_format || memory_attibute) 675 templat.interlaced = 0; 676 677 templat.buffer_format = expected_format; 678 } 679 680 templat.chroma_format = ChromaToPipe(format); 681 682 templat.width = width; 683 templat.height = height; 684 if (debug_get_option_nointerlace()) 685 templat.interlaced = false; 686 687 memset(surfaces, VA_INVALID_ID, num_surfaces * sizeof(VASurfaceID)); 688 689 pipe_mutex_lock(drv->mutex); 690 for (i = 0; i < num_surfaces; i++) { 691 vlVaSurface *surf = CALLOC(1, sizeof(vlVaSurface)); 692 if (!surf) 693 goto no_res; 694 695 surf->templat = templat; 696 697 switch (memory_type) { 698 case VA_SURFACE_ATTRIB_MEM_TYPE_VA: 699 /* The application will clear the TILING flag when the surface is 700 * intended to be exported as dmabuf. Adding shared flag because not 701 * null memory_attibute means VASurfaceAttribExternalBuffers is used. 702 */ 703 if (memory_attibute && 704 !(memory_attibute->flags & VA_SURFACE_EXTBUF_DESC_ENABLE_TILING)) 705 templat.bind = PIPE_BIND_LINEAR | PIPE_BIND_SHARED; 706 707 surf->buffer = drv->pipe->create_video_buffer(drv->pipe, &templat); 708 if (!surf->buffer) { 709 FREE(surf); 710 goto no_res; 711 } 712 util_dynarray_init(&surf->subpics); 713 surfaces[i] = handle_table_add(drv->htab, surf); 714 break; 715 case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: 716 vaStatus = suface_from_external_memory(ctx, surf, memory_attibute, i, surfaces, &templat); 717 if (vaStatus != VA_STATUS_SUCCESS) { 718 FREE(surf); 719 goto no_res; 720 } 721 break; 722 default: 723 assert(0); 724 } 725 } 726 pipe_mutex_unlock(drv->mutex); 727 728 return VA_STATUS_SUCCESS; 729 730 no_res: 731 pipe_mutex_unlock(drv->mutex); 732 if (i) 733 vlVaDestroySurfaces(ctx, surfaces, i); 734 735 return VA_STATUS_ERROR_ALLOCATION_FAILED; 736 } 737 738 VAStatus 739 vlVaQueryVideoProcFilters(VADriverContextP ctx, VAContextID context, 740 VAProcFilterType *filters, unsigned int *num_filters) 741 { 742 unsigned int num = 0; 743 744 if (!ctx) 745 return VA_STATUS_ERROR_INVALID_CONTEXT; 746 747 if (!num_filters || !filters) 748 return VA_STATUS_ERROR_INVALID_PARAMETER; 749 750 filters[num++] = VAProcFilterDeinterlacing; 751 752 *num_filters = num; 753 754 return VA_STATUS_SUCCESS; 755 } 756 757 VAStatus 758 vlVaQueryVideoProcFilterCaps(VADriverContextP ctx, VAContextID context, 759 VAProcFilterType type, void *filter_caps, 760 unsigned int *num_filter_caps) 761 { 762 unsigned int i; 763 764 if (!ctx) 765 return VA_STATUS_ERROR_INVALID_CONTEXT; 766 767 if (!filter_caps || !num_filter_caps) 768 return VA_STATUS_ERROR_INVALID_PARAMETER; 769 770 i = 0; 771 772 switch (type) { 773 case VAProcFilterNone: 774 break; 775 case VAProcFilterDeinterlacing: { 776 VAProcFilterCapDeinterlacing *deint = filter_caps; 777 778 if (*num_filter_caps < 3) { 779 *num_filter_caps = 3; 780 return VA_STATUS_ERROR_MAX_NUM_EXCEEDED; 781 } 782 783 deint[i++].type = VAProcDeinterlacingBob; 784 deint[i++].type = VAProcDeinterlacingWeave; 785 deint[i++].type = VAProcDeinterlacingMotionAdaptive; 786 break; 787 } 788 789 case VAProcFilterNoiseReduction: 790 case VAProcFilterSharpening: 791 case VAProcFilterColorBalance: 792 case VAProcFilterSkinToneEnhancement: 793 return VA_STATUS_ERROR_UNIMPLEMENTED; 794 default: 795 assert(0); 796 } 797 798 *num_filter_caps = i; 799 800 return VA_STATUS_SUCCESS; 801 } 802 803 static VAProcColorStandardType vpp_input_color_standards[] = { 804 VAProcColorStandardBT601 805 }; 806 807 static VAProcColorStandardType vpp_output_color_standards[] = { 808 VAProcColorStandardBT601 809 }; 810 811 VAStatus 812 vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx, VAContextID context, 813 VABufferID *filters, unsigned int num_filters, 814 VAProcPipelineCaps *pipeline_cap) 815 { 816 unsigned int i = 0; 817 818 if (!ctx) 819 return VA_STATUS_ERROR_INVALID_CONTEXT; 820 821 if (!pipeline_cap) 822 return VA_STATUS_ERROR_INVALID_PARAMETER; 823 824 if (num_filters && !filters) 825 return VA_STATUS_ERROR_INVALID_PARAMETER; 826 827 pipeline_cap->pipeline_flags = 0; 828 pipeline_cap->filter_flags = 0; 829 pipeline_cap->num_forward_references = 0; 830 pipeline_cap->num_backward_references = 0; 831 pipeline_cap->num_input_color_standards = ARRAY_SIZE(vpp_input_color_standards); 832 pipeline_cap->input_color_standards = vpp_input_color_standards; 833 pipeline_cap->num_output_color_standards = ARRAY_SIZE(vpp_output_color_standards); 834 pipeline_cap->output_color_standards = vpp_output_color_standards; 835 836 for (i = 0; i < num_filters; i++) { 837 vlVaBuffer *buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, filters[i]); 838 VAProcFilterParameterBufferBase *filter; 839 840 if (!buf || buf->type != VAProcFilterParameterBufferType) 841 return VA_STATUS_ERROR_INVALID_BUFFER; 842 843 filter = buf->data; 844 switch (filter->type) { 845 case VAProcFilterDeinterlacing: { 846 VAProcFilterParameterBufferDeinterlacing *deint = buf->data; 847 if (deint->algorithm == VAProcDeinterlacingMotionAdaptive) { 848 pipeline_cap->num_forward_references = 1; 849 pipeline_cap->num_backward_references = 2; 850 } 851 break; 852 } 853 default: 854 return VA_STATUS_ERROR_UNIMPLEMENTED; 855 } 856 } 857 858 return VA_STATUS_SUCCESS; 859 } 860