st/mesa: Try re-importing resource if necessary in st_vdpau_map_surface
[mesa.git] / src / mesa / state_tracker / st_vdpau.c
index bfc6adf7f77fe7eb3d23982200ae1bad3f75b730..6a439b89d5935b668f5650ccf3bd2a41574463cd 100644 (file)
@@ -185,6 +185,7 @@ st_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access,
                      const void *vdpSurface, GLuint index)
 {
    struct st_context *st = st_context(ctx);
+   struct pipe_screen *screen = st->pipe->screen;
    struct st_texture_object *stObj = st_texture_object(texObj);
    struct st_texture_image *stImage = st_texture_image(texImage);
 
@@ -207,15 +208,26 @@ st_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access,
       }
    }
 
-   if (!res) {
-      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
-      return;
+   /* If the resource is from a different screen, try re-importing it */
+   if (res && res->screen != screen) {
+      struct pipe_resource *new_res = NULL;
+      struct winsys_handle whandle = { .type = WINSYS_HANDLE_TYPE_FD };
+      unsigned usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE;
+
+      if (screen->get_param(screen, PIPE_CAP_DMABUF) &&
+          res->screen->get_param(res->screen, PIPE_CAP_DMABUF) &&
+          res->screen->resource_get_handle(res->screen, NULL, res, &whandle,
+                                           usage)) {
+         new_res = screen->resource_from_handle(screen, res, &whandle, usage);
+         close(whandle.handle);
+      }
+
+      pipe_resource_reference(&res, NULL);
+      res = new_res;
    }
 
-   /* do we have different screen objects ? */
-   if (res->screen != st->pipe->screen) {
+   if (!res) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
-      pipe_resource_reference(&res, NULL);
       return;
    }