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#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 41static 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#if VA_CHECK_VERSION(1, 1, 0) 93 NULL, /* vaCreateMFContext */ 94 NULL, /* vaMFAddContext */ 95 NULL, /* vaMFReleaseContext */ 96 NULL, /* vaMFSubmit */ 97 NULL, /* vaCreateBuffer2 */ 98 NULL, /* vaQueryProcessingRate */ 99 &vlVaExportSurfaceHandle, 100#endif 101}; 102 103static struct VADriverVTableVPP vtable_vpp = 104{ 105 1, 106 &vlVaQueryVideoProcFilters, 107 &vlVaQueryVideoProcFilterCaps, 108 &vlVaQueryVideoProcPipelineCaps 109}; 110 111PUBLIC VAStatus 112VA_DRIVER_INIT_FUNC(VADriverContextP ctx) 113{ 114 vlVaDriver *drv; 115 116 if (!ctx) 117 return VA_STATUS_ERROR_INVALID_CONTEXT; 118 119 drv = CALLOC(1, sizeof(vlVaDriver)); 120 if (!drv) 121 return VA_STATUS_ERROR_ALLOCATION_FAILED; 122 123 switch (ctx->display_type) { 124 case VA_DISPLAY_ANDROID: 125 FREE(drv); 126 return VA_STATUS_ERROR_UNIMPLEMENTED; 127 case VA_DISPLAY_GLX: 128 case VA_DISPLAY_X11: 129 drv->vscreen = vl_dri3_screen_create(ctx->native_dpy, ctx->x11_screen); 130 if (!drv->vscreen) 131 drv->vscreen = vl_dri2_screen_create(ctx->native_dpy, ctx->x11_screen); 132 break; 133 case VA_DISPLAY_WAYLAND: 134 case VA_DISPLAY_DRM: 135 case VA_DISPLAY_DRM_RENDERNODES: { 136 const struct drm_state *drm_info = (struct drm_state *) ctx->drm_state; 137 138 if (!drm_info || drm_info->fd < 0) { 139 FREE(drv); 140 return VA_STATUS_ERROR_INVALID_PARAMETER; 141 } 142 143 drv->vscreen = vl_drm_screen_create(drm_info->fd); 144 break; 145 } 146 default: 147 FREE(drv); 148 return VA_STATUS_ERROR_INVALID_DISPLAY; 149 } 150 151 if (!drv->vscreen) 152 goto error_screen; 153 154 drv->pipe = drv->vscreen->pscreen->context_create(drv->vscreen->pscreen, 155 NULL, 0); 156 if (!drv->pipe) 157 goto error_pipe; 158 159 drv->htab = handle_table_create(); 160 if (!drv->htab) 161 goto error_htab; 162 163 if (!vl_compositor_init(&drv->compositor, drv->pipe)) 164 goto error_compositor; 165 if (!vl_compositor_init_state(&drv->cstate, drv->pipe)) 166 goto error_compositor_state; 167 168 vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, true, &drv->csc); 169 if (!vl_compositor_set_csc_matrix(&drv->cstate, (const vl_csc_matrix *)&drv->csc, 1.0f, 0.0f)) 170 goto error_csc_matrix; 171 (void) mtx_init(&drv->mutex, mtx_plain); 172 173 ctx->pDriverData = (void *)drv; 174 ctx->version_major = 0; 175 ctx->version_minor = 1; 176 *ctx->vtable = vtable; 177 *ctx->vtable_vpp = vtable_vpp; 178 ctx->max_profiles = PIPE_VIDEO_PROFILE_MAX - PIPE_VIDEO_PROFILE_UNKNOWN - 1; 179 ctx->max_entrypoints = 2; 180 ctx->max_attributes = 1; 181 ctx->max_image_formats = VL_VA_MAX_IMAGE_FORMATS; 182 ctx->max_subpic_formats = 1; 183 ctx->max_display_attributes = 1; 184 185 snprintf(drv->vendor_string, sizeof(drv->vendor_string), 186 "Mesa Gallium driver " PACKAGE_VERSION " for %s", 187 drv->vscreen->pscreen->get_name(drv->vscreen->pscreen)); 188 ctx->str_vendor = drv->vendor_string; 189 190 return VA_STATUS_SUCCESS; 191 192error_csc_matrix: 193 vl_compositor_cleanup_state(&drv->cstate); 194 195error_compositor_state: 196 vl_compositor_cleanup(&drv->compositor); 197 198error_compositor: 199 handle_table_destroy(drv->htab); 200 201error_htab: 202 drv->pipe->destroy(drv->pipe); 203 204error_pipe: 205 drv->vscreen->destroy(drv->vscreen); 206 207error_screen: 208 FREE(drv); 209 return VA_STATUS_ERROR_ALLOCATION_FAILED; 210} 211 212VAStatus 213vlVaCreateContext(VADriverContextP ctx, VAConfigID config_id, int picture_width, 214 int picture_height, int flag, VASurfaceID *render_targets, 215 int num_render_targets, VAContextID *context_id) 216{ 217 vlVaDriver *drv; 218 vlVaContext *context; 219 vlVaConfig *config; 220 int is_vpp; 221 222 if (!ctx) 223 return VA_STATUS_ERROR_INVALID_CONTEXT; 224 225 drv = VL_VA_DRIVER(ctx); 226 mtx_lock(&drv->mutex); 227 config = handle_table_get(drv->htab, config_id); 228 mtx_unlock(&drv->mutex); 229 230 is_vpp = config->profile == PIPE_VIDEO_PROFILE_UNKNOWN && !picture_width && 231 !picture_height && !flag && !render_targets && !num_render_targets; 232 233 if (!(picture_width && picture_height) && !is_vpp) 234 return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; 235 236 context = CALLOC(1, sizeof(vlVaContext)); 237 if (!context) 238 return VA_STATUS_ERROR_ALLOCATION_FAILED; 239 240 if (is_vpp) { 241 context->decoder = NULL; 242 } else { 243 context->templat.profile = config->profile; 244 context->templat.entrypoint = config->entrypoint; 245 context->templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; 246 context->templat.width = picture_width; 247 context->templat.height = picture_height; 248 context->templat.expect_chunked_decode = true; 249 250 switch (u_reduce_video_profile(context->templat.profile)) { 251 case PIPE_VIDEO_FORMAT_MPEG12: 252 case PIPE_VIDEO_FORMAT_VC1: 253 case PIPE_VIDEO_FORMAT_MPEG4: 254 context->templat.max_references = 2; 255 break; 256 257 case PIPE_VIDEO_FORMAT_MPEG4_AVC: 258 context->templat.max_references = 0; 259 if (config->entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE) { 260 context->desc.h264.pps = CALLOC_STRUCT(pipe_h264_pps); 261 if (!context->desc.h264.pps) { 262 FREE(context); 263 return VA_STATUS_ERROR_ALLOCATION_FAILED; 264 } 265 context->desc.h264.pps->sps = CALLOC_STRUCT(pipe_h264_sps); 266 if (!context->desc.h264.pps->sps) { 267 FREE(context->desc.h264.pps); 268 FREE(context); 269 return VA_STATUS_ERROR_ALLOCATION_FAILED; 270 } 271 } 272 break; 273 274 case PIPE_VIDEO_FORMAT_HEVC: 275 context->templat.max_references = num_render_targets; 276 if (config->entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE) { 277 context->desc.h265.pps = CALLOC_STRUCT(pipe_h265_pps); 278 if (!context->desc.h265.pps) { 279 FREE(context); 280 return VA_STATUS_ERROR_ALLOCATION_FAILED; 281 } 282 context->desc.h265.pps->sps = CALLOC_STRUCT(pipe_h265_sps); 283 if (!context->desc.h265.pps->sps) { 284 FREE(context->desc.h265.pps); 285 FREE(context); 286 return VA_STATUS_ERROR_ALLOCATION_FAILED; 287 } 288 } 289 break; 290 291 case PIPE_VIDEO_FORMAT_VP9: 292 context->templat.max_references = num_render_targets; 293 break; 294 295 default: 296 break; 297 } 298 } 299 300 context->desc.base.profile = config->profile; 301 context->desc.base.entry_point = config->entrypoint; 302 if (config->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) { 303 switch (u_reduce_video_profile(context->templat.profile)) { 304 case PIPE_VIDEO_FORMAT_MPEG4_AVC: 305 context->desc.h264enc.rate_ctrl.rate_ctrl_method = config->rc; 306 context->desc.h264enc.frame_idx = util_hash_table_create(handle_hash, handle_compare); 307 break; 308 case PIPE_VIDEO_FORMAT_HEVC: 309 context->desc.h265enc.rc.rate_ctrl_method = config->rc; 310 context->desc.h265enc.frame_idx = util_hash_table_create(handle_hash, handle_compare); 311 break; 312 default: 313 break; 314 } 315 } 316 317 mtx_lock(&drv->mutex); 318 *context_id = handle_table_add(drv->htab, context); 319 mtx_unlock(&drv->mutex); 320 321 return VA_STATUS_SUCCESS; 322} 323 324VAStatus 325vlVaDestroyContext(VADriverContextP ctx, VAContextID context_id) 326{ 327 vlVaDriver *drv; 328 vlVaContext *context; 329 330 if (!ctx) 331 return VA_STATUS_ERROR_INVALID_CONTEXT; 332 333 drv = VL_VA_DRIVER(ctx); 334 mtx_lock(&drv->mutex); 335 context = handle_table_get(drv->htab, context_id); 336 if (!context) { 337 mtx_unlock(&drv->mutex); 338 return VA_STATUS_ERROR_INVALID_CONTEXT; 339 } 340 341 if (context->decoder) { 342 if (context->desc.base.entry_point == PIPE_VIDEO_ENTRYPOINT_ENCODE) { 343 if (u_reduce_video_profile(context->decoder->profile) == 344 PIPE_VIDEO_FORMAT_MPEG4_AVC) { 345 if (context->desc.h264enc.frame_idx) 346 util_hash_table_destroy (context->desc.h264enc.frame_idx); 347 } 348 if (u_reduce_video_profile(context->decoder->profile) == 349 PIPE_VIDEO_FORMAT_HEVC) { 350 if (context->desc.h265enc.frame_idx) 351 util_hash_table_destroy (context->desc.h265enc.frame_idx); 352 } 353 } else { 354 if (u_reduce_video_profile(context->decoder->profile) == 355 PIPE_VIDEO_FORMAT_MPEG4_AVC) { 356 FREE(context->desc.h264.pps->sps); 357 FREE(context->desc.h264.pps); 358 } 359 if (u_reduce_video_profile(context->decoder->profile) == 360 PIPE_VIDEO_FORMAT_HEVC) { 361 FREE(context->desc.h265.pps->sps); 362 FREE(context->desc.h265.pps); 363 } 364 } 365 context->decoder->destroy(context->decoder); 366 } 367 if (context->blit_cs) 368 drv->pipe->delete_compute_state(drv->pipe, context->blit_cs); 369 if (context->deint) { 370 vl_deint_filter_cleanup(context->deint); 371 FREE(context->deint); 372 } 373 FREE(context); 374 handle_table_remove(drv->htab, context_id); 375 mtx_unlock(&drv->mutex); 376 377 return VA_STATUS_SUCCESS; 378} 379 380VAStatus 381vlVaTerminate(VADriverContextP ctx) 382{ 383 vlVaDriver *drv; 384 385 if (!ctx) 386 return VA_STATUS_ERROR_INVALID_CONTEXT; 387 388 drv = ctx->pDriverData; 389 vl_compositor_cleanup_state(&drv->cstate); 390 vl_compositor_cleanup(&drv->compositor); 391 drv->pipe->destroy(drv->pipe); 392 drv->vscreen->destroy(drv->vscreen); 393 handle_table_destroy(drv->htab); 394 mtx_destroy(&drv->mutex); 395 FREE(drv); 396 397 return VA_STATUS_SUCCESS; 398} 399