[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