+#include "frontend/vdpau_interop.h"
+#include "frontend/vdpau_dmabuf.h"
+#include "frontend/vdpau_funcs.h"
+#include "frontend/drm_driver.h"
+
+static struct pipe_resource *
+st_vdpau_video_surface_gallium(struct gl_context *ctx, const void *vdpSurface,
+ GLuint index)
+{
+ int (*getProcAddr)(uint32_t device, uint32_t id, void **ptr);
+ uint32_t device = (uintptr_t)ctx->vdpDevice;
+ struct pipe_sampler_view *sv;
+ VdpVideoSurfaceGallium *f;
+
+ struct pipe_video_buffer *buffer;
+ struct pipe_sampler_view **samplers;
+ struct pipe_resource *res = NULL;
+
+ getProcAddr = (void *)ctx->vdpGetProcAddress;
+ if (getProcAddr(device, VDP_FUNC_ID_VIDEO_SURFACE_GALLIUM, (void**)&f))
+ return NULL;
+
+ buffer = f((uintptr_t)vdpSurface);
+ if (!buffer)
+ return NULL;
+
+ samplers = buffer->get_sampler_view_planes(buffer);
+ if (!samplers)
+ return NULL;
+
+ sv = samplers[index >> 1];
+ if (!sv)
+ return NULL;
+
+ pipe_resource_reference(&res, sv->texture);
+ return res;
+}
+
+static struct pipe_resource *
+st_vdpau_output_surface_gallium(struct gl_context *ctx, const void *vdpSurface)
+{
+ int (*getProcAddr)(uint32_t device, uint32_t id, void **ptr);
+ uint32_t device = (uintptr_t)ctx->vdpDevice;
+ struct pipe_resource *res = NULL;
+ VdpOutputSurfaceGallium *f;
+
+ getProcAddr = (void *)ctx->vdpGetProcAddress;
+ if (getProcAddr(device, VDP_FUNC_ID_OUTPUT_SURFACE_GALLIUM, (void**)&f))
+ return NULL;
+
+ pipe_resource_reference(&res, f((uintptr_t)vdpSurface));
+ return res;
+}
+
+static struct pipe_resource *
+st_vdpau_resource_from_description(struct gl_context *ctx,
+ const struct VdpSurfaceDMABufDesc *desc)
+{
+ struct st_context *st = st_context(ctx);
+ struct pipe_resource templ, *res;
+ struct winsys_handle whandle;
+
+ if (desc->handle == -1)
+ return NULL;
+
+ memset(&templ, 0, sizeof(templ));
+ templ.target = PIPE_TEXTURE_2D;
+ templ.last_level = 0;
+ templ.depth0 = 1;
+ templ.array_size = 1;
+ templ.width0 = desc->width;
+ templ.height0 = desc->height;
+ templ.format = VdpFormatRGBAToPipe(desc->format);
+ templ.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
+ templ.usage = PIPE_USAGE_DEFAULT;
+
+ memset(&whandle, 0, sizeof(whandle));
+ whandle.type = WINSYS_HANDLE_TYPE_FD;
+ whandle.handle = desc->handle;
+ whandle.offset = desc->offset;
+ whandle.stride = desc->stride;
+
+ res = st->pipe->screen->resource_from_handle(st->pipe->screen, &templ, &whandle,
+ PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);
+ close(desc->handle);
+
+ return res;
+}
+
+static struct pipe_resource *
+st_vdpau_output_surface_dma_buf(struct gl_context *ctx, const void *vdpSurface)
+{
+ int (*getProcAddr)(uint32_t device, uint32_t id, void **ptr);
+ uint32_t device = (uintptr_t)ctx->vdpDevice;
+
+ struct VdpSurfaceDMABufDesc desc;
+ VdpOutputSurfaceDMABuf *f;
+
+ getProcAddr = (void *)ctx->vdpGetProcAddress;
+ if (getProcAddr(device, VDP_FUNC_ID_OUTPUT_SURFACE_DMA_BUF, (void**)&f))
+ return NULL;
+
+ if (f((uintptr_t)vdpSurface, &desc) != VDP_STATUS_OK)
+ return NULL;
+
+ return st_vdpau_resource_from_description(ctx, &desc);
+}
+
+static struct pipe_resource *
+st_vdpau_video_surface_dma_buf(struct gl_context *ctx, const void *vdpSurface,
+ GLuint index)
+{
+ int (*getProcAddr)(uint32_t device, uint32_t id, void **ptr);
+ uint32_t device = (uintptr_t)ctx->vdpDevice;
+
+ struct VdpSurfaceDMABufDesc desc;
+ VdpVideoSurfaceDMABuf *f;
+
+ getProcAddr = (void *)ctx->vdpGetProcAddress;
+ if (getProcAddr(device, VDP_FUNC_ID_VIDEO_SURFACE_DMA_BUF, (void**)&f))
+ return NULL;
+
+ if (f((uintptr_t)vdpSurface, index, &desc) != VDP_STATUS_OK)
+ return NULL;
+
+ return st_vdpau_resource_from_description(ctx, &desc);
+}