implement NV_vdpau_interop v7
authorChristian König <christian.koenig@amd.com>
Wed, 15 May 2013 13:10:11 +0000 (15:10 +0200)
committerChristian König <christian.koenig@amd.com>
Sat, 26 Oct 2013 10:13:36 +0000 (12:13 +0200)
v2: Actually implement interop between the gallium
    state tracker and the VDPAU backend.

v3: Make it also available in non legacy contexts,
    fix video buffer sharing.

v4: deny interop if we don't have the same screen object

v5: rebased on upstream changes

v6: implemented VDPAUGetSurfaceivNV, improved error handling,
    unregister all surfaces in VDPAUFiniNV

v7: squash merge with Mareks changes

Signed-off-by: Christian König <christian.koenig@amd.com>
19 files changed:
src/gallium/include/state_tracker/vdpau_interop.h [new file with mode: 0644]
src/gallium/state_trackers/vdpau/ftab.c
src/gallium/state_trackers/vdpau/output.c
src/gallium/state_trackers/vdpau/surface.c
src/gallium/state_trackers/vdpau/vdpau_private.h
src/mapi/glapi/gen/Makefile.am
src/mapi/glapi/gen/NV_vdpau_interop.xml [new file with mode: 0644]
src/mapi/glapi/gen/gl_API.xml
src/mapi/glapi/gen/gl_genexec.py
src/mesa/Makefile.sources
src/mesa/main/dd.h
src/mesa/main/extensions.c
src/mesa/main/mtypes.h
src/mesa/main/vdpau.c [new file with mode: 0644]
src/mesa/main/vdpau.h [new file with mode: 0644]
src/mesa/state_tracker/st_context.c
src/mesa/state_tracker/st_extensions.c
src/mesa/state_tracker/st_vdpau.c [new file with mode: 0644]
src/mesa/state_tracker/st_vdpau.h [new file with mode: 0644]

diff --git a/src/gallium/include/state_tracker/vdpau_interop.h b/src/gallium/include/state_tracker/vdpau_interop.h
new file mode 100644 (file)
index 0000000..3ca7c9d
--- /dev/null
@@ -0,0 +1,49 @@
+/**************************************************************************
+ *
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/*
+ * Authors:
+ *      Christian König <christian.koenig@amd.com>
+ *
+ */
+
+#ifndef _VDPAU_INTEROP_H_
+#define _VDPAU_INTEROP_H_
+
+/* driver specific functions for NV_vdpau_interop */
+
+#define VDP_FUNC_ID_BASE_DRIVER 0x2000
+#define VDP_FUNC_ID_VIDEO_SURFACE_GALLIUM (VDP_FUNC_ID_BASE_DRIVER + 0)
+#define VDP_FUNC_ID_OUTPUT_SURFACE_GALLIUM (VDP_FUNC_ID_BASE_DRIVER + 1)
+
+struct pipe_resource;
+struct pipe_video_buffer;
+
+typedef struct pipe_video_buffer *VdpVideoSurfaceGallium(uint32_t surface);
+typedef struct pipe_resource *VdpOutputSurfaceGallium(uint32_t surface);
+
+#endif /* _VDPAU_INTEROP_H_ */
index 81d16ec306a98e06aed709fdb3d1a8756e291b29..2c84554cf8371d71d8f2678e20283ac987f93469 100644 (file)
@@ -26,6 +26,9 @@
  **************************************************************************/
 
 #include <assert.h>
+
+#include "util/u_memory.h"
+
 #include "vdpau_private.h"
 
 static void* ftab[67] =
@@ -104,19 +107,31 @@ static void* ftab_winsys[1] =
    &vlVdpPresentationQueueTargetCreateX11  /* VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11 */
 };
 
+static void* ftab_driver[2] =
+{
+   &vlVdpVideoSurfaceGallium, /* VDP_FUNC_ID_SURFACE_GALLIUM */
+   &vlVdpOutputSurfaceGallium /* VDP_FUNC_ID_OUTPUT_SURFACE_GALLIUM */
+};
+
 boolean vlGetFuncFTAB(VdpFuncId function_id, void **func)
 {
    assert(func);
+   *func = NULL;
+
    if (function_id < VDP_FUNC_ID_BASE_WINSYS) {
-      if (function_id > 66)
-         return FALSE;
-      *func = ftab[function_id];
-   }
-   else {
+      if (function_id < Elements(ftab))
+         *func = ftab[function_id];
+
+   } else if (function_id < VDP_FUNC_ID_BASE_DRIVER) {
       function_id -= VDP_FUNC_ID_BASE_WINSYS;
-      if (function_id > 0)
-         return FALSE;
-      *func = ftab_winsys[function_id];
+      if (function_id < Elements(ftab_winsys))
+         *func = ftab_winsys[function_id];
+
+   } else {
+      function_id -= VDP_FUNC_ID_BASE_DRIVER;
+      if (function_id < Elements(ftab_driver))
+         *func = ftab_driver[function_id];
    }
+
    return *func != NULL;
 }
index cf77b53248578594231d01c50bda77be3293449d..def01c89d2ab154e439c1247c15001a239b1a9dc 100644 (file)
@@ -725,3 +725,14 @@ vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface,
 
    return VDP_STATUS_OK;
 }
+
+struct pipe_resource *vlVdpOutputSurfaceGallium(VdpOutputSurface surface)
+{
+   vlVdpOutputSurface *vlsurface;
+
+   vlsurface = vlGetDataHTAB(surface);
+   if (!vlsurface || !vlsurface->surface)
+      return NULL;
+
+   return vlsurface->surface->texture;
+}
index 074363bdafb1cdac51be7fa2daeb4793ffcb0b3b..cd798a21a3202374bc61be90bb8980d45749fe62 100644 (file)
@@ -469,3 +469,24 @@ vlVdpVideoSurfaceClear(vlVdpSurface *vlsurf)
    }
    pipe->flush(pipe, NULL, 0);
 }
+
+/**
+ * Interop to mesa state tracker
+ */
+struct pipe_video_buffer *vlVdpVideoSurfaceGallium(VdpVideoSurface surface)
+{
+   vlVdpSurface *p_surf = vlGetDataHTAB(surface);
+   if (!p_surf)
+      return NULL;
+
+   pipe_mutex_lock(p_surf->device->mutex);
+   if (p_surf->video_buffer == NULL) {
+      struct pipe_context *pipe = p_surf->device->context;
+
+      /* try to create a video buffer if we don't already have one */
+      p_surf->video_buffer = pipe->create_video_buffer(pipe, &p_surf->templat);
+   }
+   pipe_mutex_unlock(p_surf->device->mutex);
+
+   return p_surf->video_buffer;
+}
index bb91de13103a288909e1a5278e1c1b3fc870f636..60196acee6dd7189639e399bc8fe2fa202e6e631 100644 (file)
@@ -36,6 +36,8 @@
 #include "pipe/p_compiler.h"
 #include "pipe/p_video_codec.h"
 
+#include "state_tracker/vdpau_interop.h"
+
 #include "util/u_debug.h"
 #include "util/u_rect.h"
 #include "os/os_thread.h"
@@ -498,6 +500,10 @@ VdpVideoMixerGetAttributeValues vlVdpVideoMixerGetAttributeValues;
 VdpVideoMixerDestroy vlVdpVideoMixerDestroy;
 VdpGenerateCSCMatrix vlVdpGenerateCSCMatrix;
 
+/* interop to mesa state tracker */
+VdpVideoSurfaceGallium vlVdpVideoSurfaceGallium;
+VdpOutputSurfaceGallium vlVdpOutputSurfaceGallium;
+
 #define VDPAU_OUT   0
 #define VDPAU_ERR   1
 #define VDPAU_WARN  2
index d71d5d2a852501c824bfd56ab9ff61a210168a84..48af135cb4589771afb31ccad73584c20bbca709 100644 (file)
@@ -141,6 +141,7 @@ API_XML = \
        NV_conditional_render.xml \
        NV_primitive_restart.xml \
        NV_texture_barrier.xml \
+       NV_vdpau_interop.xml \
        OES_EGL_image.xml \
        GL3x.xml
 
diff --git a/src/mapi/glapi/gen/NV_vdpau_interop.xml b/src/mapi/glapi/gen/NV_vdpau_interop.xml
new file mode 100644 (file)
index 0000000..cf5f0ed
--- /dev/null
@@ -0,0 +1,69 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<OpenGLAPI>
+
+<category name="GL_NV_vdpau_interop" number="396">
+
+    <function name="VDPAUInitNV" offset="assign">
+       <param name="vdpDevice" type="const GLvoid *"/>
+       <param name="getProcAddress" type="const GLvoid *"/>
+    </function>
+
+    <function name="VDPAUFiniNV" offset="assign"/>
+
+    <function name="VDPAURegisterVideoSurfaceNV" offset="assign">
+        <return type="GLintptr"/>
+       <param name="vdpSurface" type="const GLvoid *"/>
+       <param name="target" type="GLenum"/>
+       <param name="numTextureNames" type="GLsizei"/>
+       <param name="textureNames" type="const GLuint *"/>
+    </function>
+
+    <function name="VDPAURegisterOutputSurfaceNV" offset="assign">
+        <return type="GLintptr"/>
+       <param name="vdpSurface" type="const GLvoid *"/>
+       <param name="target" type="GLenum"/>
+       <param name="numTextureNames" type="GLsizei"/>
+       <param name="textureNames" type="const GLuint *"/>
+    </function>
+
+    <function name="VDPAUIsSurfaceNV" offset="assign">
+       <param name="surface" type="GLintptr"/>
+    </function>
+
+    <function name="VDPAUUnregisterSurfaceNV" offset="assign">
+       <param name="surface" type="GLintptr"/>
+    </function>
+
+    <function name="VDPAUGetSurfaceivNV" offset="assign">
+       <param name="surface" type="GLintptr"/>
+       <param name="pname" type="GLenum"/>
+       <param name="bufSize" type="GLsizei"/>
+       <param name="length" type="GLsizei *"/>
+       <param name="values" type="GLint *"/>
+    </function>
+
+    <function name="VDPAUSurfaceAccessNV" offset="assign">
+       <param name="surface" type="GLintptr"/>
+       <param name="access" type="GLenum"/>
+    </function>
+
+    <function name="VDPAUMapSurfacesNV" offset="assign">
+       <param name="numSurfaces" type="GLsizei"/>
+       <param name="surfaces" type="const GLintptr *"/>
+    </function>
+
+    <function name="VDPAUUnmapSurfacesNV" offset="assign">
+       <param name="numSurfaces" type="GLsizei"/>
+       <param name="surfaces" type="const GLintptr *"/>
+    </function>
+
+    <enum name="SURFACE_STATE_NV"      value="0x86EB"/>
+    <enum name="SURFACE_REGISTERED_NV" value="0x86FD"/>
+    <enum name="SURFACE_MAPPED_NV"     value="0x8700"/>
+    <enum name="WRITE_DISCARD_NV"      value="0x88BE"/>
+
+</category>
+
+</OpenGLAPI>
index 30ab9c9c116f4655f7f3dc5ac0eacf1760abce0c..994ed8d1358715b9be52c576598245d05e183b65 100644 (file)
 
 <xi:include href="EXT_transform_feedback.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
 
+<xi:include href="NV_vdpau_interop.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
 </OpenGLAPI>
index a074c234829498993be0023d732a7d7ed29ecefa..3ce190fe3ac31cdecbe9d554806e3b2bb109ec93 100644 (file)
@@ -111,6 +111,7 @@ header = """/**
 #include "main/syncobj.h"
 #include "main/formatquery.h"
 #include "main/dispatch.h"
+#include "main/vdpau.h"
 #include "vbo/vbo.h"
 
 
index ff242b4ab9f873f8405e3975f75bdd2bdff4b9bc..a84f8a78857bffd49c17aa30403716f0088ecdc5 100644 (file)
@@ -108,6 +108,7 @@ MAIN_FILES = \
        $(SRCDIR)main/uniforms.c \
        $(SRCDIR)main/uniform_query.cpp \
        $(SRCDIR)main/varray.c \
+       $(SRCDIR)main/vdpau.c \
        $(SRCDIR)main/version.c \
        $(SRCDIR)main/viewport.c \
        $(SRCDIR)main/vtxfmt.c \
@@ -248,7 +249,8 @@ STATETRACKER_FILES = \
        $(SRCDIR)state_tracker/st_manager.c \
        $(SRCDIR)state_tracker/st_mesa_to_tgsi.c \
        $(SRCDIR)state_tracker/st_program.c \
-       $(SRCDIR)state_tracker/st_texture.c
+       $(SRCDIR)state_tracker/st_texture.c \
+       $(SRCDIR)state_tracker/st_vdpau.c
 
 PROGRAM_FILES = \
        $(SRCDIR)program/arbprogparse.c \
index 29469ce33145ea8eb49bb67673aa550fae7e61d5..501192199064fc21288054c275168409c37ef437 100644 (file)
@@ -868,6 +868,20 @@ struct dd_function_table {
                              struct gl_framebuffer *fb,
                              GLuint index,
                              GLfloat *outValue);
+
+   /**
+    * \name NV_vdpau_interop interface
+    */
+   void (*VDPAUMapSurface)(struct gl_context *ctx, GLenum target,
+                           GLenum access, GLboolean output,
+                           struct gl_texture_object *texObj,
+                           struct gl_texture_image *texImage,
+                           const GLvoid *vdpSurface, GLuint index);
+   void (*VDPAUUnmapSurface)(struct gl_context *ctx, GLenum target,
+                             GLenum access, GLboolean output,
+                             struct gl_texture_object *texObj,
+                             struct gl_texture_image *texImage,
+                             const GLvoid *vdpSurface, GLuint index);
 };
 
 
index e8e0a20d8b23843c2f3bf515558b9c0f7523d284..00d65ccb04dc75010e198d3fd69e3f4da9b26252 100644 (file)
@@ -335,6 +335,7 @@ static const struct extension extension_table[] = {
    { "GL_NV_texture_barrier",                      o(NV_texture_barrier),                      GL,             2009 },
    { "GL_NV_texture_env_combine4",                 o(NV_texture_env_combine4),                 GLL,            1999 },
    { "GL_NV_texture_rectangle",                    o(NV_texture_rectangle),                    GLL,            2000 },
+   { "GL_NV_vdpau_interop",                        o(NV_vdpau_interop),                        GL,             2010 },
    { "GL_S3_s3tc",                                 o(ANGLE_texture_compression_dxt),           GL,             1999 },
    { "GL_SGIS_generate_mipmap",                    o(dummy_true),                              GLL,            1997 },
    { "GL_SGIS_texture_border_clamp",               o(ARB_texture_border_clamp),                GLL,            1997 },
index 97ed1bd6a14310e873c850420df13b1ee4176a5a..824e33906fdf08befcbd6a32bb5df4261418eee5 100644 (file)
@@ -3302,6 +3302,7 @@ struct gl_extensions
    GLboolean NV_texture_barrier;
    GLboolean NV_texture_env_combine4;
    GLboolean NV_texture_rectangle;
+   GLboolean NV_vdpau_interop;
    GLboolean TDFX_texture_compression_FXT1;
    GLboolean OES_EGL_image;
    GLboolean OES_draw_texture;
@@ -3832,6 +3833,15 @@ struct gl_context
    struct st_context *st;
    void *aelt_context;
    /*@}*/
+
+   /**
+    * \name NV_vdpau_interop
+    */
+   /*@{*/
+   const void *vdpDevice;
+   const void *vdpGetProcAddress;
+   struct set *vdpSurfaces;
+   /*@}*/
 };
 
 
diff --git a/src/mesa/main/vdpau.c b/src/mesa/main/vdpau.c
new file mode 100644 (file)
index 0000000..414afe2
--- /dev/null
@@ -0,0 +1,424 @@
+/**************************************************************************
+ *
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/*
+ * Authors:
+ *      Christian König <christian.koenig@amd.com>
+ *
+ */
+
+#include <stdbool.h>
+#include "context.h"
+#include "glformats.h"
+#include "hash_table.h"
+#include "set.h"
+#include "texobj.h"
+#include "teximage.h"
+#include "vdpau.h"
+
+#define MAX_TEXTURES 4
+
+struct vdp_surface
+{
+   GLenum target;
+   struct gl_texture_object *textures[MAX_TEXTURES];
+   GLenum access, state;
+   GLboolean output;
+   const GLvoid *vdpSurface;
+};
+
+void GLAPIENTRY
+_mesa_VDPAUInitNV(const GLvoid *vdpDevice, const GLvoid *getProcAddress)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (!vdpDevice) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "vdpDevice");
+      return;
+   }
+
+   if (!getProcAddress) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "getProcAddress");
+      return;
+   }
+
+   if (ctx->vdpDevice || ctx->vdpGetProcAddress || ctx->vdpSurfaces) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUInitNV");
+      return;
+   }
+
+   ctx->vdpDevice = vdpDevice;
+   ctx->vdpGetProcAddress = getProcAddress;
+   ctx->vdpSurfaces = _mesa_set_create(NULL, _mesa_key_pointer_equal);
+}
+
+static void
+unregister_surface(struct set_entry *entry)
+{
+   struct vdp_surface *surf = (struct vdp_surface *)entry->key;
+   GET_CURRENT_CONTEXT(ctx);
+   
+   if (surf->state == GL_SURFACE_MAPPED_NV) {
+      GLintptr surfaces[] = { (GLintptr)surf };
+      _mesa_VDPAUUnmapSurfacesNV(1, surfaces);
+   }
+
+   _mesa_set_remove(ctx->vdpSurfaces, entry);
+   FREE(surf);
+}
+
+void GLAPIENTRY
+_mesa_VDPAUFiniNV()
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUFiniNV");
+      return;
+   }
+
+   _mesa_set_destroy(ctx->vdpSurfaces, unregister_surface);
+
+   ctx->vdpDevice = 0;
+   ctx->vdpGetProcAddress = 0;
+   ctx->vdpSurfaces = NULL;
+}
+
+static GLintptr
+register_surface(struct gl_context *ctx, GLboolean isOutput,
+                 const GLvoid *vdpSurface, GLenum target,
+                 GLsizei numTextureNames, const GLuint *textureNames)
+{
+   struct vdp_surface *surf;
+   int i;
+
+   if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAURegisterSurfaceNV");
+      return (GLintptr)NULL;
+   }
+
+   if (target != GL_TEXTURE_2D && target != GL_TEXTURE_RECTANGLE) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "VDPAURegisterSurfaceNV");
+      return (GLintptr)NULL;
+   }
+
+   if (target == GL_TEXTURE_RECTANGLE && !ctx->Extensions.NV_texture_rectangle) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "VDPAURegisterSurfaceNV");
+      return (GLintptr)NULL;
+   }
+
+   surf = CALLOC_STRUCT( vdp_surface );
+   surf->vdpSurface = vdpSurface;
+   surf->target = target;
+   surf->access = GL_READ_WRITE;
+   surf->state = GL_SURFACE_REGISTERED_NV;
+   surf->output = isOutput;
+   for (i = 0; i < numTextureNames; ++i) {
+      struct gl_texture_object *tex;
+      tex  = _mesa_lookup_texture(ctx, textureNames[i]);
+
+      _mesa_lock_texture(ctx, tex);
+
+      if (tex->Immutable) {
+         _mesa_unlock_texture(ctx, tex);
+         FREE(surf);
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "VDPAURegisterSurfaceNV(texture is immutable)");
+         return (GLintptr)NULL;
+      }
+
+      if (tex->Target == 0)
+         tex->Target = target;
+      else if (tex->Target != target) {
+         _mesa_unlock_texture(ctx, tex);
+         FREE(surf);
+         _mesa_error(ctx, GL_INVALID_OPERATION,
+                     "VDPAURegisterSurfaceNV(target mismatch)");
+         return (GLintptr)NULL;
+      }
+
+      /* This will disallow respecifying the storage. */
+      tex->Immutable = GL_TRUE;
+      _mesa_unlock_texture(ctx, tex);
+
+      _mesa_reference_texobj(&surf->textures[i], tex);
+   }
+
+   _mesa_set_add(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf);
+
+   return (GLintptr)surf;
+}
+
+GLintptr GLAPIENTRY
+_mesa_VDPAURegisterVideoSurfaceNV(const GLvoid *vdpSurface, GLenum target,
+                                  GLsizei numTextureNames,
+                                  const GLuint *textureNames)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (numTextureNames != 4) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "VDPAURegisterVideoSurfaceNV");
+      return (GLintptr)NULL;
+   }
+
+   return register_surface(ctx, false, vdpSurface, target,
+                           numTextureNames, textureNames);
+}
+
+GLintptr GLAPIENTRY
+_mesa_VDPAURegisterOutputSurfaceNV(const GLvoid *vdpSurface, GLenum target,
+                                   GLsizei numTextureNames,
+                                   const GLuint *textureNames)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (numTextureNames != 1) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "VDPAURegisterVideoSurfaceNV");
+      return (GLintptr)NULL;
+   }
+
+   return register_surface(ctx, true, vdpSurface, target,
+                           numTextureNames, textureNames);
+}
+
+void GLAPIENTRY
+_mesa_VDPAUIsSurfaceNV(GLintptr surface)
+{
+   struct vdp_surface *surf = (struct vdp_surface *)surface;
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUIsSurfaceNV");
+      return;
+   }
+
+   if (!_mesa_set_search(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf)) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUIsSurfaceNV");
+      return;
+   }
+}
+
+void GLAPIENTRY
+_mesa_VDPAUUnregisterSurfaceNV(GLintptr surface)
+{
+   struct vdp_surface *surf = (struct vdp_surface *)surface;
+   struct set_entry *entry;
+   int i;
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnregisterSurfaceNV");
+      return;
+   }
+
+   /* according to the spec it's ok when this is zero */
+   if (surface == 0)
+      return;
+
+   entry = _mesa_set_search(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf);
+   if (!entry) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUUnregisterSurfaceNV");
+      return;
+   }
+
+   for (i = 0; i < MAX_TEXTURES; i++) {
+      if (surf->textures[i]) {
+         surf->textures[i]->Immutable = GL_FALSE;
+         _mesa_reference_texobj(&surf->textures[i], NULL);
+      }
+   }
+
+   _mesa_set_remove(ctx->vdpSurfaces, entry);
+   FREE(surf);
+}
+
+void GLAPIENTRY
+_mesa_VDPAUGetSurfaceivNV(GLintptr surface, GLenum pname, GLsizei bufSize,
+                          GLsizei *length, GLint *values)
+{
+   struct vdp_surface *surf = (struct vdp_surface *)surface;
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUGetSurfaceivNV");
+      return;
+   }
+
+   if (!_mesa_set_search(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf)) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUGetSurfaceivNV");
+      return;
+   }
+
+   if (pname != GL_SURFACE_STATE_NV) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "VDPAUGetSurfaceivNV");
+      return;
+   }
+
+   if (bufSize < 1) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUGetSurfaceivNV");
+      return;
+   }
+
+   values[0] = surf->state;
+
+   if (length != NULL)
+      *length = 1;
+}
+
+void GLAPIENTRY
+_mesa_VDPAUSurfaceAccessNV(GLintptr surface, GLenum access)
+{
+   struct vdp_surface *surf = (struct vdp_surface *)surface;
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV");
+      return;
+   }
+
+   if (!_mesa_set_search(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf)) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV");
+      return;
+   }
+
+   if (access != GL_READ_ONLY && access != GL_WRITE_ONLY &&
+       access != GL_READ_WRITE) {
+
+      _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV");
+      return;
+   }
+
+   if (surf->state == GL_SURFACE_MAPPED_NV) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV");
+      return;
+   }
+
+   surf->access = access;
+}
+
+void GLAPIENTRY
+_mesa_VDPAUMapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   int i, j;
+
+   if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnmapSurfacesNV");
+      return;
+   }
+
+   for (i = 0; i < numSurfaces; ++i) {
+      struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
+
+      if (!_mesa_set_search(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf)) {
+         _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV");
+         return;
+      }
+
+      if (surf->state == GL_SURFACE_MAPPED_NV) {
+         _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV");
+         return;
+      }
+   }
+
+   for (i = 0; i < numSurfaces; ++i) {
+      struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
+      unsigned numTextureNames = surf->output ? 1 : 4;
+
+      for (j = 0; j < numTextureNames; ++j) {
+         struct gl_texture_object *tex = surf->textures[j];
+         struct gl_texture_image *image;
+
+         _mesa_lock_texture(ctx, tex);
+         image = _mesa_get_tex_image(ctx, tex, surf->target, 0);
+         if (!image) {
+            _mesa_error(ctx, GL_OUT_OF_MEMORY, "VDPAUMapSurfacesNV");
+            _mesa_unlock_texture(ctx, tex);
+            return;
+         }
+
+         ctx->Driver.FreeTextureImageBuffer(ctx, image);
+
+         ctx->Driver.VDPAUMapSurface(ctx, surf->target, surf->access,
+                                     surf->output, tex, image,
+                                     surf->vdpSurface, j);
+
+         _mesa_unlock_texture(ctx, tex);
+      }
+      surf->state = GL_SURFACE_MAPPED_NV;
+   }
+}
+
+void GLAPIENTRY
+_mesa_VDPAUUnmapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   int i, j;
+
+   if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnmapSurfacesNV");
+      return;
+   }
+
+   for (i = 0; i < numSurfaces; ++i) {
+      struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
+
+      if (!_mesa_set_search(ctx->vdpSurfaces, _mesa_hash_pointer(surf), surf)) {
+         _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV");
+         return;
+      }
+
+      if (surf->state != GL_SURFACE_MAPPED_NV) {
+         _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV");
+         return;
+      }
+   }
+
+   for (i = 0; i < numSurfaces; ++i) {
+      struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
+      unsigned numTextureNames = surf->output ? 1 : 4;
+
+      for (j = 0; j < numTextureNames; ++j) {
+         struct gl_texture_object *tex = surf->textures[j];
+         struct gl_texture_image *image;
+
+         _mesa_lock_texture(ctx, tex);
+
+         image = _mesa_select_tex_image(ctx, tex, surf->target, 0);
+
+         ctx->Driver.VDPAUUnmapSurface(ctx, surf->target, surf->access,
+                                       surf->output, tex, image,
+                                       surf->vdpSurface, j);
+
+         if (image)
+            ctx->Driver.FreeTextureImageBuffer(ctx, image);
+
+         _mesa_unlock_texture(ctx, tex);
+      }
+      surf->state = GL_SURFACE_REGISTERED_NV;
+   }
+}
diff --git a/src/mesa/main/vdpau.h b/src/mesa/main/vdpau.h
new file mode 100644 (file)
index 0000000..f32d6da
--- /dev/null
@@ -0,0 +1,72 @@
+/**************************************************************************
+ *
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/*
+ * Authors:
+ *      Christian König <christian.koenig@amd.com>
+ *
+ */
+
+#ifndef VDPAU_H
+#define VDPAU_H
+
+extern void GLAPIENTRY
+_mesa_VDPAUInitNV(const GLvoid *vdpDevice, const GLvoid *getProcAddress);
+
+extern void GLAPIENTRY
+_mesa_VDPAUFiniNV(void);
+
+extern GLintptr GLAPIENTRY
+_mesa_VDPAURegisterVideoSurfaceNV(const GLvoid *vdpSurface, GLenum target,
+                                  GLsizei numTextureNames,
+                                  const GLuint *textureNames);
+
+extern GLintptr GLAPIENTRY
+_mesa_VDPAURegisterOutputSurfaceNV(const GLvoid *vdpSurface, GLenum target,
+                                   GLsizei numTextureNames,
+                                   const GLuint *textureNames);
+
+extern void GLAPIENTRY
+_mesa_VDPAUIsSurfaceNV(GLintptr surface);
+
+extern void GLAPIENTRY
+_mesa_VDPAUUnregisterSurfaceNV(GLintptr surface);
+
+extern void GLAPIENTRY
+_mesa_VDPAUGetSurfaceivNV(GLintptr surface, GLenum pname, GLsizei bufSize,
+                          GLsizei *length, GLint *values);
+
+extern void GLAPIENTRY
+_mesa_VDPAUSurfaceAccessNV(GLintptr surface, GLenum access);
+
+extern void GLAPIENTRY
+_mesa_VDPAUMapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces);
+
+extern void GLAPIENTRY
+_mesa_VDPAUUnmapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces);
+
+#endif /* VDPAU_H */
index 4e0d98cc3b097f432bcf0ca27dd8e70db7fddfa8..2cc3567e0c7853ef914f52aa1e0e3d214978c433 100644 (file)
@@ -65,6 +65,7 @@
 #include "st_extensions.h"
 #include "st_gen_mipmap.h"
 #include "st_program.h"
+#include "st_vdpau.h"
 #include "pipe/p_context.h"
 #include "util/u_inlines.h"
 #include "util/u_upload_mgr.h"
@@ -360,5 +361,7 @@ void st_init_driver_functions(struct dd_function_table *functions)
    st_init_xformfb_functions(functions);
    st_init_syncobj_functions(functions);
 
+   st_init_vdpau_functions(functions);
+
    functions->UpdateState = st_invalidate_state;
 }
index 6635d624e65fc29de08a77331cf834fec11d72db..97c5d55e1b12a2f201dc4f35ac62965be790f9f5 100644 (file)
@@ -564,6 +564,7 @@ void st_init_extensions(struct st_context *st)
    ctx->Extensions.NV_fog_distance = GL_TRUE;
    ctx->Extensions.NV_texture_env_combine4 = GL_TRUE;
    ctx->Extensions.NV_texture_rectangle = GL_TRUE;
+   ctx->Extensions.NV_vdpau_interop = GL_TRUE;
 
    ctx->Extensions.OES_EGL_image = GL_TRUE;
    ctx->Extensions.OES_EGL_image_external = GL_TRUE;
diff --git a/src/mesa/state_tracker/st_vdpau.c b/src/mesa/state_tracker/st_vdpau.c
new file mode 100644 (file)
index 0000000..9b165ee
--- /dev/null
@@ -0,0 +1,181 @@
+/**************************************************************************
+ *
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/*
+ * Authors:
+ *      Christian König <christian.koenig@amd.com>
+ *
+ */
+
+#include "main/texobj.h"
+#include "main/teximage.h"
+#include "main/errors.h"
+#include "program/prog_instruction.h"
+
+#include "pipe/p_state.h"
+#include "pipe/p_video_codec.h"
+
+#include "state_tracker/vdpau_interop.h"
+
+#include "util/u_inlines.h"
+
+#include "st_vdpau.h"
+#include "st_context.h"
+#include "st_texture.h"
+#include "st_format.h"
+
+static void
+st_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access,
+                     GLboolean output, struct gl_texture_object *texObj,
+                     struct gl_texture_image *texImage,
+                     const GLvoid *vdpSurface, GLuint index)
+{
+   int (*getProcAddr)(uint32_t device, uint32_t id, void **ptr);
+   uint32_t device = (uintptr_t)ctx->vdpDevice;
+
+   struct st_context *st = st_context(ctx);
+   struct st_texture_object *stObj = st_texture_object(texObj);
+   struct st_texture_image *stImage = st_texture_image(texImage);
+   struct pipe_resource *res;
+   struct pipe_sampler_view *sv, templ;
+   gl_format texFormat;
+
+   getProcAddr = ctx->vdpGetProcAddress;
+   if (output) {
+      VdpOutputSurfaceGallium *f;
+      
+      if (getProcAddr(device, VDP_FUNC_ID_OUTPUT_SURFACE_GALLIUM, (void**)&f)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
+         return;
+      }
+
+      res = f((uintptr_t)vdpSurface);
+
+      if (!res) {
+         _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
+         return;
+      }
+
+   } else {
+      VdpVideoSurfaceGallium *f;
+
+      struct pipe_video_buffer *buffer;
+      struct pipe_sampler_view **samplers;
+
+      if (getProcAddr(device, VDP_FUNC_ID_VIDEO_SURFACE_GALLIUM, (void**)&f)) {
+         _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
+         return;
+      }
+
+      buffer = f((uintptr_t)vdpSurface);
+      if (!buffer) {
+         _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
+         return;
+      }
+
+      samplers = buffer->get_sampler_view_planes(buffer);
+      if (!samplers) {
+         _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
+         return;
+      }
+
+      sv = samplers[index >> 1];
+      if (!sv) {
+         _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
+         return;
+      }
+
+      res = sv->texture;
+   }
+
+   if (!res) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
+      return;
+   }
+
+   /* do we have different screen objects ? */
+   if (res->screen != st->pipe->screen) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV");
+      return;
+   }
+
+   /* switch to surface based */
+   if (!stObj->surface_based) {
+      _mesa_clear_texture_object(ctx, texObj);
+      stObj->surface_based = GL_TRUE;
+   }
+
+   texFormat = st_pipe_format_to_mesa_format(res->format);
+
+   _mesa_init_teximage_fields(ctx, texImage,
+                              res->width0, res->height0, 1, 0, GL_RGBA,
+                              texFormat);
+
+   pipe_resource_reference(&stObj->pt, res);
+   pipe_sampler_view_reference(&stObj->sampler_view, NULL);
+   pipe_resource_reference(&stImage->pt, res);
+
+   u_sampler_view_default_template(&templ, res, res->format);
+   templ.u.tex.first_layer = index & 1;
+   templ.u.tex.last_layer = index & 1;
+   templ.swizzle_r = GET_SWZ(stObj->base._Swizzle, 0);
+   templ.swizzle_g = GET_SWZ(stObj->base._Swizzle, 1);
+   templ.swizzle_b = GET_SWZ(stObj->base._Swizzle, 2);
+   templ.swizzle_a = GET_SWZ(stObj->base._Swizzle, 3);
+   stObj->sampler_view = st->pipe->create_sampler_view(st->pipe, res, &templ);
+
+   stObj->width0 = res->width0;
+   stObj->height0 = res->height0;
+   stObj->depth0 = 1;
+   stObj->surface_format = res->format;
+
+   _mesa_dirty_texobj(ctx, texObj);
+}
+
+static void
+st_vdpau_unmap_surface(struct gl_context *ctx, GLenum target, GLenum access,
+                       GLboolean output, struct gl_texture_object *texObj,
+                       struct gl_texture_image *texImage,
+                       const GLvoid *vdpSurface, GLuint index)
+{
+   struct st_texture_object *stObj = st_texture_object(texObj);
+   struct st_texture_image *stImage = st_texture_image(texImage);
+
+   pipe_resource_reference(&stObj->pt, NULL);
+   pipe_sampler_view_reference(&stObj->sampler_view, NULL);
+   pipe_resource_reference(&stImage->pt, NULL);
+
+   _mesa_dirty_texobj(ctx, texObj);
+}
+
+void
+st_init_vdpau_functions(struct dd_function_table *functions)
+{
+   functions->VDPAUMapSurface = st_vdpau_map_surface;
+   functions->VDPAUUnmapSurface = st_vdpau_unmap_surface;
+}
diff --git a/src/mesa/state_tracker/st_vdpau.h b/src/mesa/state_tracker/st_vdpau.h
new file mode 100644 (file)
index 0000000..59c7443
--- /dev/null
@@ -0,0 +1,42 @@
+/**************************************************************************
+ *
+ * Copyright 2013 Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/*
+ * Authors:
+ *      Christian König <christian.koenig@amd.com>
+ *
+ */
+
+#ifndef ST_VDPAU_H
+#define ST_VDPAU_H
+
+struct dd_function_table;
+
+extern void
+st_init_vdpau_functions(struct dd_function_table *functions);
+
+#endif /* ST_VDPAU_H */