diff --git a/meson.build b/meson.build index ff432eb9a41..d99c4565f4b 100644 --- a/meson.build +++ b/meson.build @@ -731,6 +731,10 @@ if _va != 'disabled' if dep_va.found() dep_va_headers = dep_va.partial_dependency(compile_args : true) with_gallium_va = true + if cc.has_header_symbol('va/va.h', 'VASurfaceAttribDRMFormatModifiers', + dependencies: dep_va_headers) + pre_args += '-DHAVE_VA_SURFACE_ATTRIB_DRM_FORMAT_MODIFIERS' + endif endif endif diff --git a/src/gallium/frontends/va/picture.c b/src/gallium/frontends/va/picture.c index 32d8b925036..d3953b1d36c 100644 --- a/src/gallium/frontends/va/picture.c +++ b/src/gallium/frontends/va/picture.c @@ -710,7 +710,7 @@ vlVaEndPicture(VADriverContextP ctx, VAContextID context_id) if (realloc) { struct pipe_video_buffer *old_buf = surf->buffer; - if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat) != VA_STATUS_SUCCESS) { + if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0) != VA_STATUS_SUCCESS) { mtx_unlock(&drv->mutex); return VA_STATUS_ERROR_ALLOCATION_FAILED; } diff --git a/src/gallium/frontends/va/postproc.c b/src/gallium/frontends/va/postproc.c index 7ab56b5f4c2..162994d88fd 100644 --- a/src/gallium/frontends/va/postproc.c +++ b/src/gallium/frontends/va/postproc.c @@ -145,7 +145,7 @@ static VAStatus vlVaPostProcBlit(vlVaDriver *drv, vlVaContext *context, surf->templat.interlaced = false; dst->destroy(dst); - if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat) != VA_STATUS_SUCCESS) + if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0) != VA_STATUS_SUCCESS) return VA_STATUS_ERROR_ALLOCATION_FAILED; dst = context->target = surf->buffer; @@ -317,7 +317,7 @@ vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *contex surf->templat.interlaced = false; dst->destroy(dst); - if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat) != VA_STATUS_SUCCESS) + if (vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0) != VA_STATUS_SUCCESS) return VA_STATUS_ERROR_ALLOCATION_FAILED; dst = context->target = surf->buffer; diff --git a/src/gallium/frontends/va/surface.c b/src/gallium/frontends/va/surface.c index d226575dc08..1110f3eaa9f 100644 --- a/src/gallium/frontends/va/surface.c +++ b/src/gallium/frontends/va/surface.c @@ -512,6 +512,16 @@ vlVaQuerySurfaceAttributes(VADriverContextP ctx, VAConfigID config_id, attribs[i].value.value.p = NULL; /* ignore */ i++; +#ifdef HAVE_VA_SURFACE_ATTRIB_DRM_FORMAT_MODIFIERS + if (drv->pipe->create_video_buffer_with_modifiers) { + attribs[i].type = VASurfaceAttribDRMFormatModifiers; + attribs[i].value.type = VAGenericValueTypePointer; + attribs[i].flags = VA_SURFACE_ATTRIB_SETTABLE; + attribs[i].value.value.p = NULL; /* ignore */ + i++; + } +#endif + if (config->entrypoint != PIPE_VIDEO_ENTRYPOINT_UNKNOWN) { attribs[i].type = VASurfaceAttribMaxWidth; attribs[i].value.type = VAGenericValueTypeInteger; @@ -641,12 +651,23 @@ fail: VAStatus vlVaHandleSurfaceAllocate(vlVaDriver *drv, vlVaSurface *surface, - struct pipe_video_buffer *templat) + struct pipe_video_buffer *templat, + const uint64_t *modifiers, + unsigned int modifiers_count) { struct pipe_surface **surfaces; unsigned i; - surface->buffer = drv->pipe->create_video_buffer(drv->pipe, templat); + if (modifiers_count > 0) { + if (!drv->pipe->create_video_buffer_with_modifiers) + return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED; + surface->buffer = + drv->pipe->create_video_buffer_with_modifiers(drv->pipe, templat, + modifiers, + modifiers_count); + } else { + surface->buffer = drv->pipe->create_video_buffer(drv->pipe, templat); + } if (!surface->buffer) return VA_STATUS_ERROR_ALLOCATION_FAILED; @@ -677,6 +698,9 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format, { vlVaDriver *drv; VASurfaceAttribExternalBuffers *memory_attribute; +#ifdef HAVE_VA_SURFACE_ATTRIB_DRM_FORMAT_MODIFIERS + const VADRMFormatModifierList *modifier_list; +#endif struct pipe_video_buffer templat; struct pipe_screen *pscreen; int i; @@ -685,6 +709,8 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format, VAStatus vaStatus; vlVaSurface *surf; bool protected; + const uint64_t *modifiers; + unsigned int modifiers_count; if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; @@ -706,6 +732,8 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format, memory_attribute = NULL; memory_type = VA_SURFACE_ATTRIB_MEM_TYPE_VA; expected_fourcc = 0; + modifiers = NULL; + modifiers_count = 0; for (i = 0; i < num_attribs && attrib_list; i++) { if (!(attrib_list[i].flags & VA_SURFACE_ATTRIB_SETTABLE)) @@ -735,6 +763,15 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format, return VA_STATUS_ERROR_INVALID_PARAMETER; memory_attribute = (VASurfaceAttribExternalBuffers *)attrib_list[i].value.value.p; break; +#ifdef HAVE_VA_SURFACE_ATTRIB_DRM_FORMAT_MODIFIERS + case VASurfaceAttribDRMFormatModifiers: + if (attrib_list[i].value.type != VAGenericValueTypePointer) + return VA_STATUS_ERROR_INVALID_PARAMETER; + modifier_list = attrib_list[i].value.value.p; + modifiers = modifier_list->modifiers; + modifiers_count = modifier_list->num_modifiers; + break; +#endif default: return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED; } @@ -757,6 +794,8 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format, case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: if (!memory_attribute) return VA_STATUS_ERROR_INVALID_PARAMETER; + if (modifiers) + return VA_STATUS_ERROR_INVALID_PARAMETER; expected_fourcc = memory_attribute->pixel_format; break; @@ -772,12 +811,14 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format, PIPE_VIDEO_ENTRYPOINT_BITSTREAM, PIPE_VIDEO_CAP_PREFERED_FORMAT ); - templat.interlaced = pscreen->get_video_param( - pscreen, - PIPE_VIDEO_PROFILE_UNKNOWN, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_PREFERS_INTERLACED - ); + + if (modifiers) + templat.interlaced = false; + else + templat.interlaced = + pscreen->get_video_param(pscreen, PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_PREFERS_INTERLACED); if (expected_fourcc) { enum pipe_format expected_format = VaFourccToPipeFormat(expected_fourcc); @@ -815,7 +856,8 @@ vlVaCreateSurfaces2(VADriverContextP ctx, unsigned int format, !(memory_attribute->flags & VA_SURFACE_EXTBUF_DESC_ENABLE_TILING)) templat.bind = PIPE_BIND_LINEAR | PIPE_BIND_SHARED; - vaStatus = vlVaHandleSurfaceAllocate(drv, surf, &templat); + vaStatus = vlVaHandleSurfaceAllocate(drv, surf, &templat, modifiers, + modifiers_count); if (vaStatus != VA_STATUS_SUCCESS) goto free_surf; break; @@ -1043,7 +1085,7 @@ vlVaExportSurfaceHandle(VADriverContextP ctx, surf->templat.interlaced = false; - ret = vlVaHandleSurfaceAllocate(drv, surf, &surf->templat); + ret = vlVaHandleSurfaceAllocate(drv, surf, &surf->templat, NULL, 0); if (ret != VA_STATUS_SUCCESS) { mtx_unlock(&drv->mutex); return VA_STATUS_ERROR_ALLOCATION_FAILED; diff --git a/src/gallium/frontends/va/va_private.h b/src/gallium/frontends/va/va_private.h index 17bd024c1a7..a25e24592a1 100644 --- a/src/gallium/frontends/va/va_private.h +++ b/src/gallium/frontends/va/va_private.h @@ -427,7 +427,8 @@ VAStatus vlVaQueryVideoProcPipelineCaps(VADriverContextP ctx, VAContextID contex // internal functions VAStatus vlVaHandleVAProcPipelineParameterBufferType(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); -VAStatus vlVaHandleSurfaceAllocate(vlVaDriver *drv, vlVaSurface *surface, struct pipe_video_buffer *templat); +VAStatus vlVaHandleSurfaceAllocate(vlVaDriver *drv, vlVaSurface *surface, struct pipe_video_buffer *templat, + const uint64_t *modifiers, unsigned int modifiers_count); void vlVaGetReferenceFrame(vlVaDriver *drv, VASurfaceID surface_id, struct pipe_video_buffer **ref_frame); void vlVaHandlePictureParameterBufferMPEG12(vlVaDriver *drv, vlVaContext *context, vlVaBuffer *buf); void vlVaHandleIQMatrixBufferMPEG12(vlVaContext *context, vlVaBuffer *buf); diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h index 13e704de0fb..4ce0e569c89 100644 --- a/src/gallium/include/pipe/p_context.h +++ b/src/gallium/include/pipe/p_context.h @@ -1101,6 +1101,14 @@ struct pipe_context { void (*set_context_param)(struct pipe_context *ctx, enum pipe_context_param param, unsigned value); + + /** + * Creates a video buffer as decoding target, with modifiers. + */ + struct pipe_video_buffer *(*create_video_buffer_with_modifiers)(struct pipe_context *context, + const struct pipe_video_buffer *templat, + const uint64_t *modifiers, + unsigned int modifiers_count); };