[vlc-devel] [PATCH 9/9] direct3D: implement support of NVIDIA 3D Vision

Felix Abecassis felix.abecassis at gmail.com
Fri Aug 8 20:13:34 CEST 2014


---
 modules/video_output/Modules.am            |   3 +-
 modules/video_output/msw/common.h          |  27 +++
 modules/video_output/msw/direct3d.c        |  70 +++++--
 modules/video_output/msw/nvapi.h           |  65 +++++++
 modules/video_output/msw/nvidia_3dvision.c | 295 +++++++++++++++++++++++++++++
 modules/video_output/msw/nvidia_3dvision.h |  46 +++++
 6 files changed, 486 insertions(+), 20 deletions(-)
 create mode 100644 modules/video_output/msw/nvapi.h
 create mode 100644 modules/video_output/msw/nvidia_3dvision.c
 create mode 100644 modules/video_output/msw/nvidia_3dvision.h

diff --git a/modules/video_output/Modules.am b/modules/video_output/Modules.am
index df8fbf6..d0dc784 100644
--- a/modules/video_output/Modules.am
+++ b/modules/video_output/Modules.am
@@ -141,7 +141,8 @@ EXTRA_LTLIBRARIES += libdirect2d_plugin.la
 
 libdirect3d_plugin_la_SOURCES = msw/direct3d.c \
 	msw/common.c msw/common.h msw/events.c msw/events.h msw/builtin_shaders.h \
-	msw/win32touch.c msw/win32touch.h
+	msw/win32touch.c msw/win32touch.h \
+	msw/nvidia_3dvision.c msw/nvidia_3dvision.h msw/nvapi.h
 libdirect3d_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) \
 	-DMODULE_NAME_IS_direct3d
 libdirect3d_plugin_la_LIBADD = -lgdi32 -lole32 -luuid
diff --git a/modules/video_output/msw/common.h b/modules/video_output/msw/common.h
index 5ddf85e..e727860 100644
--- a/modules/video_output/msw/common.h
+++ b/modules/video_output/msw/common.h
@@ -28,6 +28,7 @@
 #ifdef MODULE_NAME_IS_direct3d
 # include <d3d9.h>
 # include <d3dx9effect.h>
+# include "nvapi.h"
 #endif
 #ifdef MODULE_NAME_IS_glwin32
 # include "../opengl.h"
@@ -41,6 +42,26 @@
  *****************************************************************************/
 #include "events.h"
 
+#ifdef MODULE_NAME_IS_direct3d
+typedef struct
+{
+    FLOAT       x,y,z;      // vertex untransformed position
+    FLOAT       rhw;        // eye distance
+    D3DCOLOR    diffuse;    // diffuse color
+    FLOAT       tu, tv;     // texture relative coordinates
+} CUSTOMVERTEX;
+#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
+
+typedef struct d3d_region_t {
+    D3DFORMAT          format;
+    unsigned           width;
+    unsigned           height;
+    CUSTOMVERTEX       vertex[4];
+    LPDIRECT3DTEXTURE9 texture;
+} d3d_region_t;
+#endif
+
+
 /*****************************************************************************
  * vout_sys_t: video output method descriptor
  *****************************************************************************
@@ -155,6 +176,12 @@ struct vout_display_sys_t
     LPDIRECT3DDEVICE9       d3ddev;
     D3DPRESENT_PARAMETERS   d3dpp;
 
+    // NVIDIA 3D Vision objects
+    bool                    nvidia_3dvision_enabled;
+    NvAPIHandle             *nvapi_handle;
+    StereoHandle            nvidia_3dvision_handle;
+    LPDIRECT3DSURFACE9      nvidia_3dvision_surface;
+
     // scene objects
     LPDIRECT3DTEXTURE9      d3dtex;
     LPDIRECT3DVERTEXBUFFER9 d3dvtc;
diff --git a/modules/video_output/msw/direct3d.c b/modules/video_output/msw/direct3d.c
index fc959fc..26b8bbd 100644
--- a/modules/video_output/msw/direct3d.c
+++ b/modules/video_output/msw/direct3d.c
@@ -49,6 +49,7 @@
 
 #include "common.h"
 #include "builtin_shaders.h"
+#include "nvidia_3dvision.h"
 
 /*****************************************************************************
  * Module descriptor
@@ -125,22 +126,6 @@ static int  Direct3DOpen (vout_display_t *, video_format_t *);
 static void Direct3DClose(vout_display_t *);
 
 /* */
-typedef struct
-{
-    FLOAT       x,y,z;      // vertex untransformed position
-    FLOAT       rhw;        // eye distance
-    D3DCOLOR    diffuse;    // diffuse color
-    FLOAT       tu, tv;     // texture relative coordinates
-} CUSTOMVERTEX;
-#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
-
-typedef struct d3d_region_t {
-    D3DFORMAT          format;
-    unsigned           width;
-    unsigned           height;
-    CUSTOMVERTEX       vertex[4];
-    LPDIRECT3DTEXTURE9 texture;
-} d3d_region_t;
 
 static void Direct3DDeleteRegions(int, d3d_region_t *);
 
@@ -241,6 +226,15 @@ static int Open(vlc_object_t *object)
     if (sys->use_desktop && vd->cfg->is_fullscreen)
         vout_display_SendEventFullscreen(vd, false);
 
+    if (sys->nvidia_3dvision_enabled) {
+        if (vd->fmt.stereo_format.mode
+            && vd->fmt.stereo_format.mode != VLC_STEREO3D_SBS
+            && vd->fmt.stereo_format.mode != VLC_STEREO3D_TB) {
+            /* Unsupported stereo mode: request a conversion to SBS */
+            vd->fmt.stereo_format.mode = VLC_STEREO3D_SBS;
+        }
+    }
+
     return VLC_SUCCESS;
 error:
     Direct3DClose(vd);
@@ -589,6 +583,8 @@ static void Direct3DDestroy(vout_display_t *vd)
         FreeLibrary(sys->hd3d9_dll);
     if (sys->hd3d9x_dll)
         FreeLibrary(sys->hd3d9x_dll);
+    if (sys->nvidia_3dvision_enabled)
+        Nvidia3DVisionUnload(vd);
 
     sys->d3dobj = NULL;
     sys->hd3d9_dll = NULL;
@@ -700,6 +696,10 @@ static int Direct3DOpen(vout_display_t *vd, video_format_t *fmt)
 
     UpdateRects(vd, NULL, NULL, true);
 
+    Nvidia3DVisionLoad(vd);
+    if (sys->nvidia_3dvision_enabled)
+        Nvidia3DVisionCreateHandle(vd);
+
     if (Direct3DCreateResources(vd, fmt)) {
         msg_Err(vd, "Failed to allocate resources");
         return VLC_EGENERIC;
@@ -721,6 +721,9 @@ static void Direct3DClose(vout_display_t *vd)
 
     Direct3DDestroyResources(vd);
 
+    if (sys->nvidia_3dvision_enabled)
+        Nvidia3DVisionDestroyHandle(vd);
+
     if (sys->d3ddev)
        IDirect3DDevice9_Release(sys->d3ddev);
 
@@ -741,6 +744,9 @@ static int Direct3DReset(vout_display_t *vd)
     /* release all D3D objects */
     Direct3DDestroyResources(vd);
 
+    if (sys->nvidia_3dvision_enabled)
+        Nvidia3DVisionDestroyHandle(vd);
+
     /* */
     HRESULT hr = IDirect3DDevice9_Reset(d3ddev, &sys->d3dpp);
     if (FAILED(hr)) {
@@ -748,6 +754,9 @@ static int Direct3DReset(vout_display_t *vd)
         return VLC_EGENERIC;
     }
 
+    if (sys->nvidia_3dvision_enabled)
+        Nvidia3DVisionCreateHandle(vd);
+
     UpdateRects(vd, NULL, NULL, true);
 
     /* re-create them */
@@ -775,6 +784,7 @@ static int Direct3DCreateResources(vout_display_t *vd, video_format_t *fmt)
 {
     vout_display_sys_t *sys = vd->sys;
 
+
     if (Direct3DCreatePool(vd, fmt)) {
         msg_Err(vd, "Direct3D picture pool initialization failed");
         return VLC_EGENERIC;
@@ -1048,6 +1058,13 @@ static int Direct3DCreateScene(vout_display_t *vd, const video_format_t *fmt)
     LPDIRECT3DDEVICE9       d3ddev = sys->d3ddev;
     HRESULT hr;
 
+    if (sys->nvidia_3dvision_enabled) {
+        if (Nvidia3DVisionCreateScene(vd, fmt)) {
+            msg_Err(vd, "Failed to create NVIDIA 3D Vision scene.");
+            return VLC_EGENERIC;
+        }
+    }
+
     /*
      * Create a texture for use when rendering a scene
      * for performance reason, texture format is identical to backbuffer
@@ -1088,7 +1105,6 @@ static int Direct3DCreateScene(vout_display_t *vd, const video_format_t *fmt)
     /* */
     sys->d3dtex = d3dtex;
     sys->d3dvtc = d3dvtc;
-
     sys->d3dregion_count = 0;
     sys->d3dregion       = NULL;
 
@@ -1166,6 +1182,9 @@ static void Direct3DDestroyScene(vout_display_t *vd)
 
     Direct3DDeleteRegions(sys->d3dregion_count, sys->d3dregion);
 
+    if (sys->nvidia_3dvision_enabled)
+        Nvidia3DVisionDestroyScene(vd);
+
     LPDIRECT3DVERTEXBUFFER9 d3dvtc = sys->d3dvtc;
     if (d3dvtc)
         IDirect3DVertexBuffer9_Release(d3dvtc);
@@ -1463,13 +1482,20 @@ static int Direct3DImportPicture(vout_display_t *vd,
     /* Copy picture surface into texture surface
      * color space conversion happen here */
     hr = IDirect3DDevice9_StretchRect(sys->d3ddev, source, NULL, destination, NULL, D3DTEXF_LINEAR);
+    // 3D: check!
     IDirect3DSurface9_Release(destination);
+
     if (FAILED(hr)) {
         msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
         return VLC_EGENERIC;
     }
 
     /* */
+/*    if(sys->left_tex_filled && sys->right_tex_filled &&
+        sys->nvidia_3dvision_enabled)
+        return VLC_SUCCESS;*/
+
+    /* only needed for 3d, but if we rapidly turn off 2d we require this to exist */
     region->texture = sys->d3dtex;
     Direct3DSetupVertices(region->vertex,
                           vd->sys->rect_src,
@@ -1608,7 +1634,6 @@ static int Direct3DRenderRegion(vout_display_t *vd,
     vout_display_sys_t *sys = vd->sys;
 
     LPDIRECT3DDEVICE9 d3ddev = vd->sys->d3ddev;
-
     LPDIRECT3DVERTEXBUFFER9 d3dvtc = sys->d3dvtc;
     LPDIRECT3DTEXTURE9      d3dtex = region->texture;
 
@@ -1713,15 +1738,22 @@ static void Direct3DRenderScene(vout_display_t *vd,
         return;
     }
 
-    Direct3DRenderRegion(vd, picture, true);
+    if (sys->nvidia_3dvision_enabled && Nvidia3DVisionCanRender(vd))
+        Nvidia3DVisionRenderRegion(vd, picture);
+    else
+        Direct3DRenderRegion(vd, picture, true);
 
     if (subpicture_count > 0)
         IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_ALPHABLENDENABLE, TRUE);
+
+    sys->nvidia_3dvision_enabled = false;
     for (int i = 0; i < subpicture_count; i++) {
         d3d_region_t *r = &subpicture[i];
         if (r->texture)
             Direct3DRenderRegion(vd, r, false);
     }
+    sys->nvidia_3dvision_enabled = true;
+
     if (subpicture_count > 0)
         IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_ALPHABLENDENABLE, FALSE);
 
diff --git a/modules/video_output/msw/nvapi.h b/modules/video_output/msw/nvapi.h
new file mode 100644
index 0000000..c32d7a8
--- /dev/null
+++ b/modules/video_output/msw/nvapi.h
@@ -0,0 +1,65 @@
+/*****************************************************************************
+ * nvapi.h: NVIDIA stereoscopic API
+ *****************************************************************************
+ * Copyright (C) 2014 the VideoLAN team
+ *
+ * Authors: Felix Abecassis <felix.abecassis at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef NVAPI_H_
+# define NVAPI_H_
+
+# define NVSTEREO_IMAGE_SIGNATURE 0x4433564e
+# define DXNV_SWAP_EYES 0x01
+# define DXNV_SCALE_TO_FIT 0x02
+
+typedef struct
+{
+    uint32_t dwSignature;
+    uint32_t dwWidth;
+    uint32_t dwHeight;
+    uint32_t dwBPP;
+    uint32_t dwFlags;
+} NVSTEREOIMAGEHEADER;
+
+typedef enum
+{
+    NVAPI_OK = 0,
+} NvAPI_Status;
+
+typedef void* StereoHandle;
+
+typedef struct
+{
+    HINSTANCE    instance;
+    bool         initialized;
+
+    void*        (__cdecl *QueryInterface)(unsigned offset);
+    NvAPI_Status (__cdecl *Initialize)(void);
+    NvAPI_Status (__cdecl *Unload)(void);
+    NvAPI_Status (__cdecl *Stereo_IsEnabled)(uint8_t *pIsStereoEnabled);
+
+    NvAPI_Status (__cdecl *Stereo_CreateHandleFromIUnknown)(IUnknown *pDevice,
+                                                            StereoHandle *pStereoHandle);
+    NvAPI_Status (__cdecl *Stereo_DestroyHandle)(StereoHandle stereoHandle);
+
+    NvAPI_Status (__cdecl *Stereo_IsActivated)(StereoHandle stereoHandle, uint8_t *pIsStereoOn);
+    NvAPI_Status (__cdecl *Stereo_Activate)(StereoHandle stereoHandle);
+    NvAPI_Status (__cdecl *Stereo_Deactivate)(StereoHandle stereoHandle);
+} NvAPIHandle;
+
+#endif
diff --git a/modules/video_output/msw/nvidia_3dvision.c b/modules/video_output/msw/nvidia_3dvision.c
new file mode 100644
index 0000000..b0ceffe
--- /dev/null
+++ b/modules/video_output/msw/nvidia_3dvision.c
@@ -0,0 +1,295 @@
+/*****************************************************************************
+ * nvidia_3dvision.h
+ *****************************************************************************
+ * Copyright (C) 2014 the VideoLAN team
+ *
+ * Authors: Felix Abecassis <felix.abecassis at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include "nvidia_3dvision.h"
+
+#include <vlc_charset.h> /* ToT function */
+
+#include "common.h"
+#include "nvapi.h"
+
+int Nvidia3DVisionLoad(vout_display_t *vd)
+{
+    vout_display_sys_t *sys = vd->sys;
+
+    sys->nvidia_3dvision_enabled = false;
+
+    HINSTANCE nvapi_dll = LoadLibrary(ToT("nvapi.dll"));
+    if (!nvapi_dll)
+    {
+        msg_Dbg(vd, "Could not load NvAPI library (nvapi.dll)");
+        return VLC_EGENERIC;
+    }
+
+    sys->nvapi_handle = calloc(1, sizeof(*sys->nvapi_handle));
+    if (!sys->nvapi_handle)
+    {
+        msg_Warn(vd, "Initialization of NVIDIA stereoscopy failed: could not find NvAPI dll.");
+        return VLC_EGENERIC;
+
+    }
+    NvAPIHandle *nvapi_handle = sys->nvapi_handle;
+    nvapi_handle->instance = nvapi_dll;
+    nvapi_handle->initialized = false;
+
+    nvapi_handle->QueryInterface = (void *)GetProcAddress(nvapi_handle->instance, "nvapi_QueryInterface");
+
+    /* FIXME: check if everything was fine. */
+    if (!nvapi_handle->QueryInterface)
+    {
+        msg_Err(vd, "Could not find NvAPI_QueryInterface in the NvAPI dll.");
+        goto error;
+    }
+
+    nvapi_handle->Initialize = nvapi_handle->QueryInterface(0x0150E828);
+    nvapi_handle->Unload = nvapi_handle->QueryInterface(0xD22BDD7E);
+    nvapi_handle->Stereo_IsEnabled = nvapi_handle->QueryInterface(0x348FF8E1);
+    nvapi_handle->Stereo_CreateHandleFromIUnknown = nvapi_handle->QueryInterface(0xAC7E37F4);
+    nvapi_handle->Stereo_DestroyHandle = nvapi_handle->QueryInterface(0x3A153134);
+    nvapi_handle->Stereo_IsActivated = nvapi_handle->QueryInterface(0x1FB0BC30);
+    nvapi_handle->Stereo_Activate = nvapi_handle->QueryInterface(0xF6A1AD68);
+    nvapi_handle->Stereo_Deactivate = nvapi_handle->QueryInterface(0x2D68DE96);
+
+    if (!nvapi_handle->Initialize || !nvapi_handle->Unload || !nvapi_handle->Stereo_IsEnabled
+        || !nvapi_handle->Stereo_CreateHandleFromIUnknown || !nvapi_handle->Stereo_DestroyHandle
+        || !nvapi_handle->Stereo_IsActivated || !nvapi_handle->Stereo_Activate
+        || !nvapi_handle->Stereo_Deactivate)
+    {
+        msg_Err(vd, "Could not load all NvAPI functions.");
+        goto error;
+    }
+
+    NvAPI_Status status = nvapi_handle->Initialize();
+    if (status != NVAPI_OK)
+    {
+        msg_Warn(vd, "Could not initialize NvAPI (err=%d).", status);
+        goto error;
+    }
+    nvapi_handle->initialized = true;
+
+    uint8_t stereoEnabled;
+    status = nvapi_handle->Stereo_IsEnabled(&stereoEnabled);
+    if (status != NVAPI_OK)
+    {
+        msg_Warn(vd, "Could not get NVIDIA 3D Vision status (err=%d).", status);
+        goto error;
+    }
+
+    if (!stereoEnabled)
+    {
+        msg_Warn(vd, "NVIDIA 3D Vision should be enabled from the NVIDIA Control Panel");
+        goto error;
+    }
+
+    sys->nvidia_3dvision_enabled = true;
+
+    return VLC_SUCCESS;
+
+error:
+    Nvidia3DVisionUnload(vd);
+    return VLC_EGENERIC;
+}
+
+void Nvidia3DVisionUnload(vout_display_t *vd)
+{
+    vout_display_sys_t *sys = vd->sys;
+    NvAPIHandle *nvapi_handle = sys->nvapi_handle;
+
+    sys->nvidia_3dvision_enabled = false;
+
+    if (!nvapi_handle)
+        return;
+
+    if (nvapi_handle->instance)
+    {
+        if (nvapi_handle->initialized)
+            nvapi_handle->Unload();
+        FreeLibrary(nvapi_handle->instance);
+    }
+
+    free(nvapi_handle);
+    sys->nvapi_handle = NULL;
+    sys->nvidia_3dvision_handle = NULL;
+}
+
+int Nvidia3DVisionCreateHandle(vout_display_t *vd)
+{
+    vout_display_sys_t *sys = vd->sys;
+    NvAPIHandle *nvapi_handle = sys->nvapi_handle;
+    NvAPI_Status status;
+
+    status = nvapi_handle->Stereo_CreateHandleFromIUnknown((IUnknown*)sys->d3ddev,
+                                                           &sys->nvidia_3dvision_handle);
+    if (status != NVAPI_OK)
+    {
+        msg_Err(vd, "could not create NVIDIA 3D Vision handle (err=%d)", status);
+        goto error;
+    }
+
+    status = nvapi_handle->Stereo_Activate(sys->nvidia_3dvision_handle);
+    if (status != NVAPI_OK)
+        goto error;
+
+    return VLC_SUCCESS;
+
+
+error:
+    Nvidia3DVisionUnload(vd);
+    return VLC_EGENERIC;
+}
+
+void Nvidia3DVisionDestroyHandle(vout_display_t *vd)
+{
+    vout_display_sys_t *sys = vd->sys;
+    NvAPIHandle *nvapi_handle = sys->nvapi_handle;
+
+    nvapi_handle->Stereo_DestroyHandle(sys->nvidia_3dvision_handle);
+    sys->nvidia_3dvision_handle = NULL;
+}
+
+int Nvidia3DVisionCreateScene(vout_display_t *vd,
+                              const video_format_t *fmt)
+{
+    VLC_UNUSED(fmt);
+
+    vout_display_sys_t *sys = vd->sys;
+    LPDIRECT3DDEVICE9 d3ddev = sys->d3ddev;
+    HRESULT hr;
+
+    LPDIRECT3DSURFACE9 nvidia_3dvision_surface;
+    hr = IDirect3DDevice9_CreateRenderTarget(d3ddev, sys->rect_display.right * 2,
+                                             sys->rect_display.bottom + 1,
+                                             D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE,
+                                             0, TRUE, &nvidia_3dvision_surface, NULL);
+    if (FAILED(hr)) {
+        msg_Err(vd, "Failed to create stereo surface. (hr=0x%lx)", hr);
+        return VLC_EGENERIC;
+    }
+
+    sys->nvidia_3dvision_surface = nvidia_3dvision_surface;
+
+    return VLC_SUCCESS;
+}
+
+void Nvidia3DVisionDestroyScene(vout_display_t *vd)
+{
+    vout_display_sys_t *sys = vd->sys;
+
+    if (sys->nvidia_3dvision_surface)
+        IDirect3DSurface9_Release(sys->nvidia_3dvision_surface);
+    sys->nvidia_3dvision_surface = NULL;
+}
+
+bool Nvidia3DVisionCanRender(vout_display_t *vd)
+{
+    vout_display_sys_t *sys = vd->sys;
+
+    if (vd->fmt.stereo_format.mode != VLC_STEREO3D_2D) {
+        uint8_t stereo_enabled = 0;
+        NvAPI_Status status;
+        status = sys->nvapi_handle->Stereo_IsActivated(sys->nvidia_3dvision_handle, &stereo_enabled);
+        return status == NVAPI_OK && stereo_enabled;
+    }
+
+    return false;
+}
+
+int Nvidia3DVisionRenderRegion(vout_display_t *vd,
+                               d3d_region_t *region)
+{
+    vout_display_sys_t *sys = vd->sys;
+    LPDIRECT3DDEVICE9 d3ddev = sys->d3ddev;
+    HRESULT hr;
+
+    LPDIRECT3DSURFACE9 stereo_picture;
+    hr = IDirect3DTexture9_GetSurfaceLevel(sys->d3dtex, 0, &stereo_picture);
+    if (FAILED(hr)) {
+        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+        return VLC_EGENERIC;
+    }
+
+    int width = region->width;
+    int height = region->height;
+    RECT src_left;
+    RECT src_right;
+    if (vd->fmt.stereo_format.mode == VLC_STEREO3D_SBS) {
+        src_left = (RECT){ 0, 0, width / 2, height };
+        src_right = (RECT){ width / 2, 0, width, height };
+    }
+    else {
+        src_left = (RECT){ 0, 0, width, height / 2 };
+        src_right = (RECT){ 0, height / 2, width, height };
+    }
+
+    RECT dst_left = sys->rect_dest_clipped;
+    IDirect3DDevice9_StretchRect(sys->d3ddev, stereo_picture, &src_left,
+                                 sys->nvidia_3dvision_surface, &dst_left,
+                                 D3DTEXF_POINT);
+
+    RECT dst_right = { sys->rect_display.right, dst_left.top,
+                       dst_left.right + sys->rect_display.right, dst_left.bottom };
+    IDirect3DDevice9_StretchRect(sys->d3ddev, stereo_picture, &src_right,
+                                 sys->nvidia_3dvision_surface, &dst_right,
+                                 D3DTEXF_POINT);
+
+    IDirect3DSurface9_Release(stereo_picture);
+
+    /*
+     * Write the 3D Vision signature at the beginning of the extra
+     * line at the bottom of the stereoscopy surface.
+     */
+    D3DLOCKED_RECT lock;
+    IDirect3DSurface9_LockRect(sys->nvidia_3dvision_surface, &lock, NULL, 0);
+    uint8_t *surface_data = lock.pBits;
+    NVSTEREOIMAGEHEADER *stereo_header = (NVSTEREOIMAGEHEADER *)(surface_data + lock.Pitch * sys->rect_display.bottom);
+
+
+    stereo_header->dwSignature = NVSTEREO_IMAGE_SIGNATURE;
+    /* 3D Vision is Right-Left by default. */
+    if (vd->fmt.stereo_format.flags & VLC_STEREO3D_SWAP_EYES)
+        stereo_header->dwFlags = 0;
+    else
+        stereo_header->dwFlags = DXNV_SWAP_EYES;
+
+    /* These fields seems to be currently ignored and could be omitted. */
+    stereo_header->dwBPP = 32;
+    stereo_header->dwWidth = sys->rect_display.right * 2;
+    stereo_header->dwHeight = sys->rect_display.bottom;
+
+    IDirect3DSurface9_UnlockRect(sys->nvidia_3dvision_surface);
+
+    LPDIRECT3DSURFACE9 d3dback_buffer;
+    hr = IDirect3DDevice9_GetBackBuffer(d3ddev, 0, 0, D3DBACKBUFFER_TYPE_MONO,
+                                        &d3dback_buffer);
+    if (FAILED(hr)) {
+        msg_Err(vd, "Failed to get device back buffer. (hr=0x%lx)", hr);
+        return VLC_EGENERIC;
+    }
+
+    /* copy stereo surface into back buffer */
+    IDirect3DDevice9_StretchRect(sys->d3ddev, sys->nvidia_3dvision_surface, NULL,
+                                 d3dback_buffer, NULL, D3DTEXF_POINT);
+
+    IDirect3DSurface9_Release(d3dback_buffer);
+
+    return VLC_SUCCESS;
+}
diff --git a/modules/video_output/msw/nvidia_3dvision.h b/modules/video_output/msw/nvidia_3dvision.h
new file mode 100644
index 0000000..1cf0fe7
--- /dev/null
+++ b/modules/video_output/msw/nvidia_3dvision.h
@@ -0,0 +1,46 @@
+/*****************************************************************************
+ * nvidia_3dvision.h
+ *****************************************************************************
+ * Copyright (C) 2014 the VideoLAN team
+ *
+ * Authors: Felix Abecassis <felix.abecassis at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef NVIDIA_3DVISION_H_
+# define NVIDIA_3DVISION_H_
+
+# ifdef HAVE_CONFIG_H
+#  include "config.h"
+# endif
+
+# include <vlc_common.h>
+# include <vlc_vout_display.h>
+
+int  Nvidia3DVisionLoad(vout_display_t *);
+void Nvidia3DVisionUnload(vout_display_t *);
+
+int  Nvidia3DVisionCreateHandle(vout_display_t *);
+void Nvidia3DVisionDestroyHandle(vout_display_t *);
+
+int  Nvidia3DVisionCreateScene(vout_display_t *, const video_format_t *);
+void Nvidia3DVisionDestroyScene(vout_display_t *);
+
+typedef struct d3d_region_t d3d_region_t;
+bool Nvidia3DVisionCanRender(vout_display_t *);
+int  Nvidia3DVisionRenderRegion(vout_display_t *, d3d_region_t *);
+
+#endif
-- 
1.9.1




More information about the vlc-devel mailing list