Android: gallium_dri: pass dri.sym to linker
[mesa.git] / src / gallium / state_trackers / va / context.c
index 1819ec562891ccd138e1dd4957a9b663a3a08b1f..f2cb37aa22a71e0c633cf86116a67ad19afe9775 100644 (file)
 
 #include "pipe/p_screen.h"
 #include "pipe/p_video_codec.h"
-
 #include "util/u_memory.h"
 #include "util/u_handle_table.h"
 #include "util/u_video.h"
+#include "vl/vl_deint_filter.h"
 #include "vl/vl_winsys.h"
 
 #include "va_private.h"
 
+#include <va/va_drmcommon.h>
+
 static struct VADriverVTable vtable =
 {
    &vlVaTerminate,
@@ -81,7 +83,20 @@ static struct VADriverVTable vtable =
    &vlVaSetDisplayAttributes,
    &vlVaBufferInfo,
    &vlVaLockSurface,
-   &vlVaUnlockSurface
+   &vlVaUnlockSurface,
+   NULL, /* DEPRECATED VaGetSurfaceAttributes */
+   &vlVaCreateSurfaces2,
+   &vlVaQuerySurfaceAttributes,
+   &vlVaAcquireBufferHandle,
+   &vlVaReleaseBufferHandle
+};
+
+static struct VADriverVTableVPP vtable_vpp =
+{
+   1,
+   &vlVaQueryVideoProcFilters,
+   &vlVaQueryVideoProcFilterCaps,
+   &vlVaQueryVideoProcPipelineCaps
 };
 
 PUBLIC VAStatus
@@ -96,11 +111,39 @@ VA_DRIVER_INIT_FUNC(VADriverContextP ctx)
    if (!drv)
       return VA_STATUS_ERROR_ALLOCATION_FAILED;
 
-   drv->vscreen = vl_screen_create(ctx->native_dpy, ctx->x11_screen);
+   switch (ctx->display_type) {
+   case VA_DISPLAY_ANDROID:
+      FREE(drv);
+      return VA_STATUS_ERROR_UNIMPLEMENTED;
+   case VA_DISPLAY_GLX:
+   case VA_DISPLAY_X11:
+      drv->vscreen = vl_dri3_screen_create(ctx->native_dpy, ctx->x11_screen);
+      if (!drv->vscreen)
+         drv->vscreen = vl_dri2_screen_create(ctx->native_dpy, ctx->x11_screen);
+      break;
+   case VA_DISPLAY_WAYLAND:
+   case VA_DISPLAY_DRM:
+   case VA_DISPLAY_DRM_RENDERNODES: {
+      const struct drm_state *drm_info = (struct drm_state *) ctx->drm_state;
+
+      if (!drm_info || drm_info->fd < 0) {
+         FREE(drv);
+         return VA_STATUS_ERROR_INVALID_PARAMETER;
+      }
+
+      drv->vscreen = vl_drm_screen_create(drm_info->fd);
+      break;
+   }
+   default:
+      FREE(drv);
+      return VA_STATUS_ERROR_INVALID_DISPLAY;
+   }
+
    if (!drv->vscreen)
       goto error_screen;
 
-   drv->pipe = drv->vscreen->pscreen->context_create(drv->vscreen->pscreen, drv->vscreen);
+   drv->pipe = drv->vscreen->pscreen->context_create(drv->vscreen->pscreen,
+                                                     NULL, 0);
    if (!drv->pipe)
       goto error_pipe;
 
@@ -108,31 +151,45 @@ VA_DRIVER_INIT_FUNC(VADriverContextP ctx)
    if (!drv->htab)
       goto error_htab;
 
-   vl_compositor_init(&drv->compositor, drv->pipe);
-   vl_compositor_init_state(&drv->cstate, drv->pipe);
+   if (!vl_compositor_init(&drv->compositor, drv->pipe))
+      goto error_compositor;
+   if (!vl_compositor_init_state(&drv->cstate, drv->pipe))
+      goto error_compositor_state;
 
    vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, true, &drv->csc);
-   vl_compositor_set_csc_matrix(&drv->cstate, (const vl_csc_matrix *)&drv->csc);
+   if (!vl_compositor_set_csc_matrix(&drv->cstate, (const vl_csc_matrix *)&drv->csc, 1.0f, 0.0f))
+      goto error_csc_matrix;
+   (void) mtx_init(&drv->mutex, mtx_plain);
 
    ctx->pDriverData = (void *)drv;
    ctx->version_major = 0;
    ctx->version_minor = 1;
    *ctx->vtable = vtable;
+   *ctx->vtable_vpp = vtable_vpp;
    ctx->max_profiles = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH - PIPE_VIDEO_PROFILE_UNKNOWN;
-   ctx->max_entrypoints = 1;
+   ctx->max_entrypoints = 2;
    ctx->max_attributes = 1;
-   ctx->max_image_formats = 1;
+   ctx->max_image_formats = VL_VA_MAX_IMAGE_FORMATS;
    ctx->max_subpic_formats = 1;
    ctx->max_display_attributes = 1;
    ctx->str_vendor = "mesa gallium vaapi";
 
    return VA_STATUS_SUCCESS;
 
+error_csc_matrix:
+   vl_compositor_cleanup_state(&drv->cstate);
+
+error_compositor_state:
+   vl_compositor_cleanup(&drv->compositor);
+
+error_compositor:
+   handle_table_destroy(drv->htab);
+
 error_htab:
    drv->pipe->destroy(drv->pipe);
 
 error_pipe:
-   vl_screen_destroy(drv->vscreen);
+   drv->vscreen->destroy(drv->vscreen);
 
 error_screen:
    FREE(drv);
@@ -144,52 +201,93 @@ vlVaCreateContext(VADriverContextP ctx, VAConfigID config_id, int picture_width,
                   int picture_height, int flag, VASurfaceID *render_targets,
                   int num_render_targets, VAContextID *context_id)
 {
-   struct pipe_video_codec templat = {};
    vlVaDriver *drv;
    vlVaContext *context;
+   vlVaConfig *config;
+   int is_vpp;
 
    if (!ctx)
       return VA_STATUS_ERROR_INVALID_CONTEXT;
 
-   if (!(picture_width && picture_height))
+   drv = VL_VA_DRIVER(ctx);
+   mtx_lock(&drv->mutex);
+   config = handle_table_get(drv->htab, config_id);
+   mtx_unlock(&drv->mutex);
+
+   is_vpp = config->profile == PIPE_VIDEO_PROFILE_UNKNOWN && !picture_width &&
+            !picture_height && !flag && !render_targets && !num_render_targets;
+
+   if (!(picture_width && picture_height) && !is_vpp)
       return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
 
-   drv = VL_VA_DRIVER(ctx);
    context = CALLOC(1, sizeof(vlVaContext));
    if (!context)
       return VA_STATUS_ERROR_ALLOCATION_FAILED;
 
-   templat.profile = config_id;
-   templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM;
-   templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
-   templat.width = picture_width;
-   templat.height = picture_height;
-   templat.max_references = num_render_targets;
-   templat.expect_chunked_decode = true;
-
-   context->decoder = drv->pipe->create_video_codec(drv->pipe, &templat);
-   if (!context->decoder) {
-      FREE(context);
-      return VA_STATUS_ERROR_ALLOCATION_FAILED;
+   if (is_vpp) {
+      context->decoder = NULL;
+   } else {
+      context->templat.profile = config->profile;
+      context->templat.entrypoint = config->entrypoint;
+      context->templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
+      context->templat.width = picture_width;
+      context->templat.height = picture_height;
+      context->templat.expect_chunked_decode = true;
+
+      switch (u_reduce_video_profile(context->templat.profile)) {
+      case PIPE_VIDEO_FORMAT_MPEG12:
+      case PIPE_VIDEO_FORMAT_VC1:
+      case PIPE_VIDEO_FORMAT_MPEG4:
+         context->templat.max_references = 2;
+         break;
+
+      case PIPE_VIDEO_FORMAT_MPEG4_AVC:
+         context->templat.max_references = 0;
+         if (config->entrypoint != PIPE_VIDEO_ENTRYPOINT_ENCODE) {
+            context->desc.h264.pps = CALLOC_STRUCT(pipe_h264_pps);
+            if (!context->desc.h264.pps) {
+               FREE(context);
+               return VA_STATUS_ERROR_ALLOCATION_FAILED;
+            }
+            context->desc.h264.pps->sps = CALLOC_STRUCT(pipe_h264_sps);
+            if (!context->desc.h264.pps->sps) {
+               FREE(context->desc.h264.pps);
+               FREE(context);
+               return VA_STATUS_ERROR_ALLOCATION_FAILED;
+            }
+         }
+         break;
+
+     case PIPE_VIDEO_FORMAT_HEVC:
+         context->templat.max_references = num_render_targets;
+         context->desc.h265.pps = CALLOC_STRUCT(pipe_h265_pps);
+         if (!context->desc.h265.pps) {
+            FREE(context);
+            return VA_STATUS_ERROR_ALLOCATION_FAILED;
+         }
+         context->desc.h265.pps->sps = CALLOC_STRUCT(pipe_h265_sps);
+         if (!context->desc.h265.pps->sps) {
+            FREE(context->desc.h265.pps);
+            FREE(context);
+            return VA_STATUS_ERROR_ALLOCATION_FAILED;
+         }
+         break;
+
+      default:
+         break;
+      }
    }
 
-   if (u_reduce_video_profile(context->decoder->profile) ==
-         PIPE_VIDEO_FORMAT_MPEG4_AVC) {
-      context->desc.h264.pps = CALLOC_STRUCT(pipe_h264_pps);
-      if (!context->desc.h264.pps) {
-         FREE(context);
-         return VA_STATUS_ERROR_ALLOCATION_FAILED;
-      }
-      context->desc.h264.pps->sps = CALLOC_STRUCT(pipe_h264_sps);
-      if (!context->desc.h264.pps->sps) {
-         FREE(context->desc.h264.pps);
-         FREE(context);
-         return VA_STATUS_ERROR_ALLOCATION_FAILED;
-      }
+   context->desc.base.profile = config->profile;
+   context->desc.base.entry_point = config->entrypoint;
+   if (config->entrypoint == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
+      context->desc.h264enc.rate_ctrl.rate_ctrl_method = config->rc;
+      context->desc.h264enc.frame_idx = util_hash_table_create(handle_hash, handle_compare);
    }
 
-   context->desc.base.profile = config_id;
+   mtx_lock(&drv->mutex);
    *context_id = handle_table_add(drv->htab, context);
+   mtx_unlock(&drv->mutex);
 
    return VA_STATUS_SUCCESS;
 }
@@ -204,14 +302,38 @@ vlVaDestroyContext(VADriverContextP ctx, VAContextID context_id)
       return VA_STATUS_ERROR_INVALID_CONTEXT;
 
    drv = VL_VA_DRIVER(ctx);
+   mtx_lock(&drv->mutex);
    context = handle_table_get(drv->htab, context_id);
-   if (u_reduce_video_profile(context->decoder->profile) ==
-         PIPE_VIDEO_FORMAT_MPEG4_AVC) {
-      FREE(context->desc.h264.pps->sps);
-      FREE(context->desc.h264.pps);
+   if (!context) {
+      mtx_unlock(&drv->mutex);
+      return VA_STATUS_ERROR_INVALID_CONTEXT;
+   }
+
+   if (context->decoder) {
+      if (context->desc.base.entry_point == PIPE_VIDEO_ENTRYPOINT_ENCODE) {
+         if (context->desc.h264enc.frame_idx)
+            util_hash_table_destroy (context->desc.h264enc.frame_idx);
+      } else {
+         if (u_reduce_video_profile(context->decoder->profile) ==
+               PIPE_VIDEO_FORMAT_MPEG4_AVC) {
+            FREE(context->desc.h264.pps->sps);
+            FREE(context->desc.h264.pps);
+         }
+         if (u_reduce_video_profile(context->decoder->profile) ==
+               PIPE_VIDEO_FORMAT_HEVC) {
+            FREE(context->desc.h265.pps->sps);
+            FREE(context->desc.h265.pps);
+         }
+      }
+      context->decoder->destroy(context->decoder);
+   }
+   if (context->deint) {
+      vl_deint_filter_cleanup(context->deint);
+      FREE(context->deint);
    }
-   context->decoder->destroy(context->decoder);
    FREE(context);
+   handle_table_remove(drv->htab, context_id);
+   mtx_unlock(&drv->mutex);
 
    return VA_STATUS_SUCCESS;
 }
@@ -228,8 +350,9 @@ vlVaTerminate(VADriverContextP ctx)
    vl_compositor_cleanup_state(&drv->cstate);
    vl_compositor_cleanup(&drv->compositor);
    drv->pipe->destroy(drv->pipe);
-   vl_screen_destroy(drv->vscreen);
+   drv->vscreen->destroy(drv->vscreen);
    handle_table_destroy(drv->htab);
+   mtx_destroy(&drv->mutex);
    FREE(drv);
 
    return VA_STATUS_SUCCESS;