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 #include "util/u_memory.h" 32 #include "util/u_handle_table.h" 33 #include "util/u_video.h" 34 #include "vl/vl_deint_filter.h" 35 #include "vl/vl_winsys.h" 36 37 #include "va_private.h" 38 39 #include <va/va_drmcommon.h> 40 41 static struct VADriverVTable vtable = 42 { 43 &vlVaTerminate, 44 &vlVaQueryConfigProfiles, 45 &vlVaQueryConfigEntrypoints, 46 &vlVaGetConfigAttributes, 47 &vlVaCreateConfig, 48 &vlVaDestroyConfig, 49 &vlVaQueryConfigAttributes, 50 &vlVaCreateSurfaces, 51 &vlVaDestroySurfaces, 52 &vlVaCreateContext, 53 &vlVaDestroyContext, 54 &vlVaCreateBuffer, 55 &vlVaBufferSetNumElements, 56 &vlVaMapBuffer, 57 &vlVaUnmapBuffer, 58 &vlVaDestroyBuffer, 59 &vlVaBeginPicture, 60 &vlVaRenderPicture, 61 &vlVaEndPicture, 62 &vlVaSyncSurface, 63 &vlVaQuerySurfaceStatus, 64 &vlVaQuerySurfaceError, 65 &vlVaPutSurface, 66 &vlVaQueryImageFormats, 67 &vlVaCreateImage, 68 &vlVaDeriveImage, 69 &vlVaDestroyImage, 70 &vlVaSetImagePalette, 71 &vlVaGetImage, 72 &vlVaPutImage, 73 &vlVaQuerySubpictureFormats, 74 &vlVaCreateSubpicture, 75 &vlVaDestroySubpicture, 76 &vlVaSubpictureImage, 77 &vlVaSetSubpictureChromakey, 78 &vlVaSetSubpictureGlobalAlpha, 79 &vlVaAssociateSubpicture, 80 &vlVaDeassociateSubpicture, 81 &vlVaQueryDisplayAttributes, 82 &vlVaGetDisplayAttributes, 83 &vlVaSetDisplayAttributes, 84 &vlVaBufferInfo, 85 &vlVaLockSurface, 86 &vlVaUnlockSurface, 87 NULL, /* DEPRECATED VaGetSurfaceAttributes */ 88 &vlVaCreateSurfaces2, 89 &vlVaQuerySurfaceAttributes, 90 &vlVaAcquireBufferHandle, 91 &vlVaReleaseBufferHandle 92 }; 93 94 static struct VADriverVTableVPP vtable_vpp = 95 { 96 1, 97 &vlVaQueryVideoProcFilters, 98 &vlVaQueryVideoProcFilterCaps, 99 &vlVaQueryVideoProcPipelineCaps 100 }; 101 102 PUBLIC VAStatus 103 VA_DRIVER_INIT_FUNC(VADriverContextP ctx) 104 { 105 vlVaDriver *drv; 106 struct drm_state *drm_info; 107 108 if (!ctx) 109 return VA_STATUS_ERROR_INVALID_CONTEXT; 110 111 drv = CALLOC(1, sizeof(vlVaDriver)); 112 if (!drv) 113 return VA_STATUS_ERROR_ALLOCATION_FAILED; 114 115 switch (ctx->display_type) { 116 case VA_DISPLAY_ANDROID: 117 FREE(drv); 118 return VA_STATUS_ERROR_UNIMPLEMENTED; 119 case VA_DISPLAY_GLX: 120 case VA_DISPLAY_X11: 121 #if defined(HAVE_DRI3) 122 drv->vscreen = vl_dri3_screen_create(ctx->native_dpy, ctx->x11_screen); 123 #endif 124 if (!drv->vscreen) 125 drv->vscreen = vl_dri2_screen_create(ctx->native_dpy, ctx->x11_screen); 126 if (!drv->vscreen) 127 goto error_screen; 128 break; 129 case VA_DISPLAY_WAYLAND: 130 case VA_DISPLAY_DRM: 131 case VA_DISPLAY_DRM_RENDERNODES: { 132 drm_info = (struct drm_state *) ctx->drm_state; 133 134 if (!drm_info || drm_info->fd < 0) { 135 FREE(drv); 136 return VA_STATUS_ERROR_INVALID_PARAMETER; 137 } 138 139 drv->vscreen = vl_drm_screen_create(drm_info->fd); 140 if (!drv->vscreen) 141 goto error_screen; 142 } 143 break; 144 default: 145 FREE(drv); 146 return VA_STATUS_ERROR_INVALID_DISPLAY; 147 } 148 149 drv->pipe = drv->vscreen->pscreen->context_create(drv->vscreen->pscreen, 150 drv->vscreen, 0); 151 if (!drv->pipe) 152 goto error_pipe; 153 154 drv->htab = handle_table_create(); 155 if (!drv->htab) 156 goto error_htab; 157 158 if (!vl_compositor_init(&drv->compositor, drv->pipe)) 159 goto error_compositor; 160 if (!vl_compositor_init_state(&drv->cstate, drv->pipe)) 161 goto error_compositor_state; 162 163 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, true, &drv->csc); 164 if (!vl_compositor_set_csc_matrix(&drv->cstate, (const vl_csc_matrix *)&drv->csc, 1.0f, 0.0f)) 165 goto error_csc_matrix; 166 pipe_mutex_init(drv->mutex); 167 168 ctx->pDriverData = (void *)drv; 169 ctx->version_major = 0; 170 ctx->version_minor = 1; 171 *ctx->vtable = vtable; 172 *ctx->vtable_vpp = vtable_vpp; 173 ctx->max_profiles = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH - PIPE_VIDEO_PROFILE_UNKNOWN; 174 ctx->max_entrypoints = 1; 175 ctx->max_attributes = 1; 176 ctx->max_image_formats = VL_VA_MAX_IMAGE_FORMATS; 177 ctx->max_subpic_formats = 1; 178 ctx->max_display_attributes = 1; 179 ctx->str_vendor = "mesa gallium vaapi"; 180 181 return VA_STATUS_SUCCESS; 182 183 error_csc_matrix: 184 vl_compositor_cleanup_state(&drv->cstate); 185 186 error_compositor_state: 187 vl_compositor_cleanup(&drv->compositor); 188 189 error_compositor: 190 handle_table_destroy(drv->htab); 191 192 error_htab: 193 drv->pipe->destroy(drv->pipe); 194 195 error_pipe: 196 drv->vscreen->destroy(drv->vscreen); 197 198 error_screen: 199 FREE(drv); 200 return VA_STATUS_ERROR_ALLOCATION_FAILED; 201 } 202 203 VAStatus 204 vlVaCreateContext(VADriverContextP ctx, VAConfigID config_id, int picture_width, 205 int picture_height, int flag, VASurfaceID *render_targets, 206 int num_render_targets, VAContextID *context_id) 207 { 208 vlVaDriver *drv; 209 vlVaContext *context; 210 vlVaConfig *config; 211 int is_vpp; 212 213 if (!ctx) 214 return VA_STATUS_ERROR_INVALID_CONTEXT; 215 216 drv = VL_VA_DRIVER(ctx); 217 pipe_mutex_lock(drv->mutex); 218 config = handle_table_get(drv->htab, config_id); 219 pipe_mutex_unlock(drv->mutex); 220 221 is_vpp = config->profile == PIPE_VIDEO_PROFILE_UNKNOWN && !picture_width && 222 !picture_height && !flag && !render_targets && !num_render_targets; 223 224 if (!(picture_width && picture_height) && !is_vpp) 225 return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; 226 227 context = CALLOC(1, sizeof(vlVaContext)); 228 if (!context) 229 return VA_STATUS_ERROR_ALLOCATION_FAILED; 230 231 if (is_vpp) { 232 context->decoder = NULL; 233 if (!drv->compositor.upload) { 234 FREE(context); 235 return VA_STATUS_ERROR_INVALID_CONTEXT; 236 } 237 } else { 238 context->templat.profile = config->profile; 239 context->templat.entrypoint = config->entrypoint; 240 context->templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; 241 context->templat.width = picture_width; 242 context->templat.height = picture_height; 243 context->templat.expect_chunked_decode = true; 244 245 switch (u_reduce_video_profile(context->templat.profile)) { 246 case PIPE_VIDEO_FORMAT_MPEG12: 247 case PIPE_VIDEO_FORMAT_VC1: 248 case PIPE_VIDEO_FORMAT_MPEG4: 249 context->templat.max_references = 2; 250 break; 251 252 case PIPE_VIDEO_FORMAT_MPEG4_AVC: 253 context->templat.max_references = 0; 254 if (config->entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE) { 255 context->desc.h264.pps = CALLOC_STRUCT(pipe_h264_pps); 256 if (!context->desc.h264.pps) { 257 FREE(context); 258 return VA_STATUS_ERROR_ALLOCATION_FAILED; 259 } 260 context->desc.h264.pps->sps = CALLOC_STRUCT(pipe_h264_sps); 261 if (!context->desc.h264.pps->sps) { 262 FREE(context->desc.h264.pps); 263 FREE(context); 264 return VA_STATUS_ERROR_ALLOCATION_FAILED; 265 } 266 } 267 break; 268 269 case PIPE_VIDEO_FORMAT_HEVC: 270 context->templat.max_references = num_render_targets; 271 context->desc.h265.pps = CALLOC_STRUCT(pipe_h265_pps); 272 if (!context->desc.h265.pps) { 273 FREE(context); 274 return VA_STATUS_ERROR_ALLOCATION_FAILED; 275 } 276 context->desc.h265.pps->sps = CALLOC_STRUCT(pipe_h265_sps); 277 if (!context->desc.h265.pps->sps) { 278 FREE(context->desc.h265.pps); 279 FREE(context); 280 return VA_STATUS_ERROR_ALLOCATION_FAILED; 281 } 282 break; 283 284 default: 285 break; 286 } 287 } 288 289 context->desc.base.profile = config->profile; 290 context->desc.base.entry_point = config->entrypoint; 291 if (config->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) 292 context->desc.h264enc.rate_ctrl.rate_ctrl_method = config->rc; 293 294 pipe_mutex_lock(drv->mutex); 295 *context_id = handle_table_add(drv->htab, context); 296 pipe_mutex_unlock(drv->mutex); 297 298 return VA_STATUS_SUCCESS; 299 } 300 301 VAStatus 302 vlVaDestroyContext(VADriverContextP ctx, VAContextID context_id) 303 { 304 vlVaDriver *drv; 305 vlVaContext *context; 306 307 if (!ctx) 308 return VA_STATUS_ERROR_INVALID_CONTEXT; 309 310 drv = VL_VA_DRIVER(ctx); 311 pipe_mutex_lock(drv->mutex); 312 context = handle_table_get(drv->htab, context_id); 313 if (!context) { 314 pipe_mutex_unlock(drv->mutex); 315 return VA_STATUS_ERROR_INVALID_CONTEXT; 316 } 317 318 if (context->decoder) { 319 if (context->desc.base.entry_point != PIPE_VIDEO_ENTRYPOINT_ENCODE) { 320 if (u_reduce_video_profile(context->decoder->profile) == 321 PIPE_VIDEO_FORMAT_MPEG4_AVC) { 322 FREE(context->desc.h264.pps->sps); 323 FREE(context->desc.h264.pps); 324 } 325 if (u_reduce_video_profile(context->decoder->profile) == 326 PIPE_VIDEO_FORMAT_HEVC) { 327 FREE(context->desc.h265.pps->sps); 328 FREE(context->desc.h265.pps); 329 } 330 } 331 context->decoder->destroy(context->decoder); 332 } 333 if (context->deint) { 334 vl_deint_filter_cleanup(context->deint); 335 FREE(context->deint); 336 } 337 FREE(context); 338 handle_table_remove(drv->htab, context_id); 339 pipe_mutex_unlock(drv->mutex); 340 341 return VA_STATUS_SUCCESS; 342 } 343 344 VAStatus 345 vlVaTerminate(VADriverContextP ctx) 346 { 347 vlVaDriver *drv; 348 349 if (!ctx) 350 return VA_STATUS_ERROR_INVALID_CONTEXT; 351 352 drv = ctx->pDriverData; 353 vl_compositor_cleanup_state(&drv->cstate); 354 vl_compositor_cleanup(&drv->compositor); 355 drv->pipe->destroy(drv->pipe); 356 drv->vscreen->destroy(drv->vscreen); 357 handle_table_destroy(drv->htab); 358 pipe_mutex_destroy(drv->mutex); 359 FREE(drv); 360 361 return VA_STATUS_SUCCESS; 362 } 363