st/va: delay decoder creation until max_references is known
[mesa.git] / src / gallium / state_trackers / va / context.c
index a107cc431d9ca34327e648202f07f6bbcf72020c..192794fefaa00c47c61dfa1e7a8830303b91259b 100644 (file)
@@ -28,7 +28,6 @@
 
 #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"
@@ -36,6 +35,8 @@
 
 #include "va_private.h"
 
+#include <va/va_drmcommon.h>
+
 static struct VADriverVTable vtable =
 {
    &vlVaTerminate,
@@ -84,7 +85,9 @@ static struct VADriverVTable vtable =
    &vlVaUnlockSurface,
    NULL, /* DEPRECATED VaGetSurfaceAttributes */
    &vlVaCreateSurfaces2,
-   &vlVaQuerySurfaceAttributes
+   &vlVaQuerySurfaceAttributes,
+   &vlVaAcquireBufferHandle,
+   &vlVaReleaseBufferHandle
 };
 
 static struct VADriverVTableVPP vtable_vpp =
@@ -99,6 +102,7 @@ PUBLIC VAStatus
 VA_DRIVER_INIT_FUNC(VADriverContextP ctx)
 {
    vlVaDriver *drv;
+   struct drm_state *drm_info;
 
    if (!ctx)
       return VA_STATUS_ERROR_INVALID_CONTEXT;
@@ -107,9 +111,35 @@ 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);
-   if (!drv->vscreen)
-      goto error_screen;
+   switch (ctx->display_type) {
+   case VA_DISPLAY_ANDROID:
+   case VA_DISPLAY_WAYLAND:
+      FREE(drv);
+      return VA_STATUS_ERROR_UNIMPLEMENTED;
+   case VA_DISPLAY_GLX:
+   case VA_DISPLAY_X11:
+      drv->vscreen = vl_dri2_screen_create(ctx->native_dpy, ctx->x11_screen);
+      if (!drv->vscreen)
+         goto error_screen;
+      break;
+   case VA_DISPLAY_DRM:
+   case VA_DISPLAY_DRM_RENDERNODES: {
+      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);
+      if (!drv->vscreen)
+         goto error_screen;
+      }
+      break;
+   default:
+      FREE(drv);
+      return VA_STATUS_ERROR_INVALID_DISPLAY;
+   }
 
    drv->pipe = drv->vscreen->pscreen->context_create(drv->vscreen->pscreen,
                                                      drv->vscreen, 0);
@@ -145,7 +175,7 @@ error_htab:
    drv->pipe->destroy(drv->pipe);
 
 error_pipe:
-   vl_screen_destroy(drv->vscreen);
+   drv->vscreen->destroy(drv->vscreen);
 
 error_screen:
    FREE(drv);
@@ -157,7 +187,6 @@ 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;
    int is_vpp;
@@ -183,27 +212,22 @@ vlVaCreateContext(VADriverContextP ctx, VAConfigID config_id, int picture_width,
          return VA_STATUS_ERROR_INVALID_CONTEXT;
       }
    } else {
-      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;
-
-      if (u_reduce_video_profile(templat.profile) ==
-        PIPE_VIDEO_FORMAT_MPEG4_AVC)
-        templat.level = u_get_h264_level(templat.width, templat.height,
-                             &templat.max_references);
-
-      context->decoder = drv->pipe->create_video_codec(drv->pipe, &templat);
-      if (!context->decoder) {
-         FREE(context);
-         return VA_STATUS_ERROR_ALLOCATION_FAILED;
-      }
-
-      if (u_reduce_video_profile(context->decoder->profile) ==
-         PIPE_VIDEO_FORMAT_MPEG4_AVC) {
+      context->templat.profile = config_id;
+      context->templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM;
+      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;
          context->desc.h264.pps = CALLOC_STRUCT(pipe_h264_pps);
          if (!context->desc.h264.pps) {
             FREE(context);
@@ -215,10 +239,10 @@ vlVaCreateContext(VADriverContextP ctx, VAConfigID config_id, int picture_width,
             FREE(context);
             return VA_STATUS_ERROR_ALLOCATION_FAILED;
          }
-      }
+         break;
 
-      if (u_reduce_video_profile(context->decoder->profile) ==
-            PIPE_VIDEO_FORMAT_HEVC) {
+     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);
@@ -230,6 +254,10 @@ vlVaCreateContext(VADriverContextP ctx, VAConfigID config_id, int picture_width,
             FREE(context);
             return VA_STATUS_ERROR_ALLOCATION_FAILED;
          }
+         break;
+
+      default:
+         break;
       }
    }
 
@@ -282,7 +310,7 @@ 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);
    FREE(drv);