[vlc-devel] [PATCH 10/14] direct3D: implement support of NVIDIA 3D Vision
Felix Abecassis
felix.abecassis at gmail.com
Tue Sep 9 19:08:29 CEST 2014
---
modules/video_output/Modules.am | 4 +-
modules/video_output/msw/common.h | 24 ++
modules/video_output/msw/direct3d.c | 62 +++--
modules/video_output/msw/nvidia_3dvision.c | 360 +++++++++++++++++++++++++++++
modules/video_output/msw/nvidia_3dvision.h | 34 +++
modules/video_output/msw/stereo3d_api.c | 51 ++++
modules/video_output/msw/stereo3d_api.h | 87 +++++++
7 files changed, 604 insertions(+), 18 deletions(-)
create mode 100644 modules/video_output/msw/nvidia_3dvision.c
create mode 100644 modules/video_output/msw/nvidia_3dvision.h
create mode 100644 modules/video_output/msw/stereo3d_api.c
create mode 100644 modules/video_output/msw/stereo3d_api.h
diff --git a/modules/video_output/Modules.am b/modules/video_output/Modules.am
index ad5737f..e791e53 100644
--- a/modules/video_output/Modules.am
+++ b/modules/video_output/Modules.am
@@ -157,7 +157,9 @@ 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/stereo3d_api.c msw/stereo3d_api.h \
+ msw/nvidia_3dvision.c msw/nvidia_3dvision.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..f353b51 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 "stereo3d_api.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,9 @@ struct vout_display_sys_t
LPDIRECT3DDEVICE9 d3ddev;
D3DPRESENT_PARAMETERS d3dpp;
+ // Stereo 3D API
+ Stereo3DAPI *stereo3d_api;
+
// scene objects
LPDIRECT3DTEXTURE9 d3dtex;
LPDIRECT3DVERTEXBUFFER9 d3dvtc;
diff --git a/modules/video_output/msw/direct3d.c b/modules/video_output/msw/direct3d.c
index 7fa4585..0d00bb1 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 "stereo3d_api.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 *);
@@ -588,6 +573,8 @@ static void Direct3DDestroy(vout_display_t *vd)
FreeLibrary(sys->hd3d9_dll);
if (sys->hd3d9x_dll)
FreeLibrary(sys->hd3d9x_dll);
+ if (sys->stereo3d_api)
+ Stereo3DAPI_Unload(sys->stereo3d_api);
sys->d3dobj = NULL;
sys->hd3d9_dll = NULL;
@@ -699,6 +686,17 @@ static int Direct3DOpen(vout_display_t *vd, video_format_t *fmt)
UpdateRects(vd, NULL, NULL, true);
+ if (vd->fmt.stereo.mode != VLC_STEREO3D_2D)
+ sys->stereo3d_api = Stereo3DAPI_Load(vd);
+ if (sys->stereo3d_api)
+ {
+ if (Stereo3DAPI_CreateResources(sys->stereo3d_api))
+ {
+ Stereo3DAPI_Unload(sys->stereo3d_api);
+ sys->stereo3d_api = NULL;
+ }
+ }
+
if (Direct3DCreateResources(vd, fmt)) {
msg_Err(vd, "Failed to allocate resources");
return VLC_EGENERIC;
@@ -720,6 +718,9 @@ static void Direct3DClose(vout_display_t *vd)
Direct3DDestroyResources(vd);
+ if (sys->stereo3d_api)
+ Stereo3DAPI_DestroyResources(sys->stereo3d_api);
+
if (sys->d3ddev)
IDirect3DDevice9_Release(sys->d3ddev);
@@ -740,6 +741,9 @@ static int Direct3DReset(vout_display_t *vd)
/* release all D3D objects */
Direct3DDestroyResources(vd);
+ if (sys->stereo3d_api)
+ Stereo3DAPI_DestroyResources(sys->stereo3d_api);
+
/* */
HRESULT hr = IDirect3DDevice9_Reset(d3ddev, &sys->d3dpp);
if (FAILED(hr)) {
@@ -747,6 +751,9 @@ static int Direct3DReset(vout_display_t *vd)
return VLC_EGENERIC;
}
+ if (sys->stereo3d_api)
+ Stereo3DAPI_CreateResources(sys->stereo3d_api);
+
UpdateRects(vd, NULL, NULL, true);
/* re-create them */
@@ -774,6 +781,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;
@@ -1047,6 +1055,13 @@ static int Direct3DCreateScene(vout_display_t *vd, const video_format_t *fmt)
LPDIRECT3DDEVICE9 d3ddev = sys->d3ddev;
HRESULT hr;
+ if (sys->stereo3d_api) {
+ if (Stereo3DAPI_CreateScene(sys->stereo3d_api, fmt)) {
+ msg_Err(vd, "Failed to create Stereo 3D scene.");
+ return VLC_EGENERIC;
+ }
+ }
+
/*
* Create a texture for use when rendering a scene
* for performance reason, texture format is identical to backbuffer
@@ -1165,6 +1180,9 @@ static void Direct3DDestroyScene(vout_display_t *vd)
Direct3DDeleteRegions(sys->d3dregion_count, sys->d3dregion);
+ if (sys->stereo3d_api)
+ Stereo3DAPI_DestroyScene(sys->stereo3d_api);
+
LPDIRECT3DVERTEXBUFFER9 d3dvtc = sys->d3dvtc;
if (d3dvtc)
IDirect3DVertexBuffer9_Release(d3dvtc);
@@ -1463,6 +1481,7 @@ static int Direct3DImportPicture(vout_display_t *vd,
* color space conversion happen here */
hr = IDirect3DDevice9_StretchRect(sys->d3ddev, source, NULL, destination, NULL, D3DTEXF_LINEAR);
IDirect3DSurface9_Release(destination);
+
if (FAILED(hr)) {
msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
return VLC_EGENERIC;
@@ -1712,15 +1731,24 @@ static void Direct3DRenderScene(vout_display_t *vd,
return;
}
- Direct3DRenderRegion(vd, picture, true);
+ if (sys->stereo3d_api && Stereo3DAPI_CanRender(sys->stereo3d_api))
+ Stereo3DAPI_RenderRegion(sys->stereo3d_api, picture);
+ else
+ Direct3DRenderRegion(vd, picture, true);
if (subpicture_count > 0)
IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_ALPHABLENDENABLE, TRUE);
+
+ /* Disable stereo 3D when rendering subpictures */
+ Stereo3DAPI *stereo3d_api = sys->stereo3d_api;
+ sys->stereo3d_api = NULL;
for (int i = 0; i < subpicture_count; i++) {
d3d_region_t *r = &subpicture[i];
if (r->texture)
Direct3DRenderRegion(vd, r, false);
}
+ sys->stereo3d_api = stereo3d_api;
+
if (subpicture_count > 0)
IDirect3DDevice9_SetRenderState(d3ddev, D3DRS_ALPHABLENDENABLE, FALSE);
diff --git a/modules/video_output/msw/nvidia_3dvision.c b/modules/video_output/msw/nvidia_3dvision.c
new file mode 100644
index 0000000..861d1ec
--- /dev/null
+++ b/modules/video_output/msw/nvidia_3dvision.c
@@ -0,0 +1,360 @@
+/*****************************************************************************
+ * nvidia_3dvision.c
+ *****************************************************************************
+ * 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 Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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 "common.h"
+
+static void Nvidia3DVisionUnload(Stereo3DAPI *);
+
+static int Nvidia3DVisionCreateResources(Stereo3DAPI *);
+static void Nvidia3DVisionDestroyResources(Stereo3DAPI *);
+
+static int Nvidia3DVisionCreateScene(Stereo3DAPI *, const video_format_t *);
+static void Nvidia3DVisionDestroyScene(Stereo3DAPI *);
+
+static bool Nvidia3DVisionCanRender(Stereo3DAPI *);
+static int Nvidia3DVisionRenderRegion(Stereo3DAPI *, d3d_region_t *);
+
+# 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;
+
+struct stereo3d_api_sys_t
+{
+ NvAPIHandle *nvapi_handle;
+ StereoHandle nvidia_3dvision_handle;
+ LPDIRECT3DSURFACE9 nvidia_3dvision_surface;
+};
+
+int Nvidia3DVisionLoad(Stereo3DAPI *s)
+{
+ stereo3d_api_sys_t *sys = calloc(1, sizeof(*sys));
+ if (!sys)
+ return VLC_ENOMEM;
+ s->sys = sys;
+
+ sys->nvapi_handle = calloc(1, sizeof(*sys->nvapi_handle));
+ if (!sys->nvapi_handle)
+ {
+ msg_Warn(s->vd, "Initialization of NVIDIA 3D Vision failed: could not find NvAPI dll.");
+ goto error;
+
+ }
+ NvAPIHandle *nvapi_handle = sys->nvapi_handle;
+
+ HINSTANCE nvapi_dll = LoadLibraryA("nvapi.dll");
+ if (!nvapi_dll)
+ {
+ msg_Dbg(s->vd, "Could not load NvAPI library (nvapi.dll)");
+ goto error;
+ }
+ nvapi_handle->instance = nvapi_dll;
+
+ nvapi_handle->initialized = false;
+ nvapi_handle->QueryInterface = (void *)GetProcAddress(nvapi_handle->instance, "nvapi_QueryInterface");
+
+ if (!nvapi_handle->QueryInterface)
+ {
+ msg_Err(s->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(s->vd, "Could not load all NvAPI functions.");
+ goto error;
+ }
+
+ NvAPI_Status status = nvapi_handle->Initialize();
+ if (status != NVAPI_OK)
+ {
+ msg_Warn(s->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(s->vd, "Could not get NVIDIA 3D Vision status (err=%d).", status);
+ goto error;
+ }
+
+ if (!stereoEnabled)
+ {
+ msg_Warn(s->vd, "NVIDIA 3D Vision should be enabled from the NVIDIA Control Panel");
+ goto error;
+ }
+
+ s->unload = Nvidia3DVisionUnload;
+ s->create_resources = Nvidia3DVisionCreateResources;
+ s->destroy_resources = Nvidia3DVisionDestroyResources;
+ s->create_scene = Nvidia3DVisionCreateScene;
+ s->destroy_scene = Nvidia3DVisionDestroyScene;
+ s->can_render = Nvidia3DVisionCanRender;
+ s->render_region = Nvidia3DVisionRenderRegion;
+
+ if (s->vd->fmt.stereo.mode != VLC_STEREO3D_SBS
+ && s->vd->fmt.stereo.mode != VLC_STEREO3D_TB)
+ {
+ /* Unsupported stereo mode: request a conversion to SBS */
+ s->vd->fmt.stereo.mode = VLC_STEREO3D_SBS;
+ }
+
+ return VLC_SUCCESS;
+
+error:
+ Nvidia3DVisionUnload(s);
+ return VLC_EGENERIC;
+}
+
+static void Nvidia3DVisionUnload(Stereo3DAPI *s)
+{
+ stereo3d_api_sys_t *sys = s->sys;
+ NvAPIHandle *nvapi_handle = sys->nvapi_handle;
+
+ 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;
+}
+
+static int Nvidia3DVisionCreateResources(Stereo3DAPI *s)
+{
+ vout_display_sys_t *vd_sys = s->vd->sys;
+ stereo3d_api_sys_t *sys = s->sys;
+ NvAPIHandle *nvapi_handle = sys->nvapi_handle;
+ NvAPI_Status status;
+
+ status = nvapi_handle->Stereo_CreateHandleFromIUnknown((IUnknown*)vd_sys->d3ddev,
+ &sys->nvidia_3dvision_handle);
+ if (status != NVAPI_OK)
+ {
+ msg_Err(s->vd, "could not create NVIDIA 3D Vision handle (err=%d)", status);
+ return VLC_EGENERIC;
+ }
+
+ status = nvapi_handle->Stereo_Activate(sys->nvidia_3dvision_handle);
+ if (status != NVAPI_OK)
+ {
+ Nvidia3DVisionDestroyResources(s);
+ return VLC_EGENERIC;
+ }
+
+ return VLC_SUCCESS;
+}
+
+static void Nvidia3DVisionDestroyResources(Stereo3DAPI *s)
+{
+ stereo3d_api_sys_t *sys = s->sys;
+ NvAPIHandle *nvapi_handle = sys->nvapi_handle;
+
+ nvapi_handle->Stereo_DestroyHandle(sys->nvidia_3dvision_handle);
+ sys->nvidia_3dvision_handle = NULL;
+}
+
+static int Nvidia3DVisionCreateScene(Stereo3DAPI *s,
+ const video_format_t *fmt)
+{
+ VLC_UNUSED(fmt);
+
+ vout_display_sys_t *vd_sys = s->vd->sys;
+ stereo3d_api_sys_t *sys = s->sys;
+ LPDIRECT3DDEVICE9 d3ddev = vd_sys->d3ddev;
+ HRESULT hr;
+
+ LPDIRECT3DSURFACE9 nvidia_3dvision_surface;
+ hr = IDirect3DDevice9_CreateRenderTarget(d3ddev, vd_sys->rect_display.right * 2,
+ vd_sys->rect_display.bottom + 1,
+ D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE,
+ 0, TRUE, &nvidia_3dvision_surface, NULL);
+ if (FAILED(hr))
+ {
+ msg_Err(s->vd, "Failed to create stereo surface. (hr=0x%lx)", hr);
+ return VLC_EGENERIC;
+ }
+
+ sys->nvidia_3dvision_surface = nvidia_3dvision_surface;
+
+ return VLC_SUCCESS;
+}
+
+static void Nvidia3DVisionDestroyScene(Stereo3DAPI *s)
+{
+ stereo3d_api_sys_t *sys = s->sys;
+
+ if (sys->nvidia_3dvision_surface)
+ IDirect3DSurface9_Release(sys->nvidia_3dvision_surface);
+ sys->nvidia_3dvision_surface = NULL;
+}
+
+static bool Nvidia3DVisionCanRender(Stereo3DAPI *s)
+{
+ stereo3d_api_sys_t *sys = s->sys;
+
+ 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;
+}
+
+static int Nvidia3DVisionRenderRegion(Stereo3DAPI *s,
+ d3d_region_t *region)
+{
+ vout_display_sys_t *vd_sys = s->vd->sys;
+ stereo3d_api_sys_t *sys = s->sys;
+ LPDIRECT3DDEVICE9 d3ddev = vd_sys->d3ddev;
+ HRESULT hr;
+
+ LPDIRECT3DSURFACE9 stereo_picture;
+ hr = IDirect3DTexture9_GetSurfaceLevel(vd_sys->d3dtex, 0, &stereo_picture);
+ if (FAILED(hr))
+ {
+ msg_Dbg(s->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 (s->vd->fmt.stereo.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 = vd_sys->rect_dest_clipped;
+ IDirect3DDevice9_StretchRect(d3ddev, stereo_picture, &src_left,
+ sys->nvidia_3dvision_surface, &dst_left,
+ D3DTEXF_LINEAR);
+
+ RECT dst_right = { vd_sys->rect_display.right, dst_left.top,
+ dst_left.right + vd_sys->rect_display.right, dst_left.bottom };
+ IDirect3DDevice9_StretchRect(d3ddev, stereo_picture, &src_right,
+ sys->nvidia_3dvision_surface, &dst_right,
+ D3DTEXF_LINEAR);
+
+ 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 * vd_sys->rect_display.bottom);
+ stereo_header->dwSignature = NVSTEREO_IMAGE_SIGNATURE;
+ /* 3D Vision is Right-Left by default. */
+ if (s->vd->fmt.stereo.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 = vd_sys->rect_display.right * 2;
+ stereo_header->dwHeight = vd_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(s->vd, "Failed to get device back buffer. (hr=0x%lx)", hr);
+ return VLC_EGENERIC;
+ }
+
+ /* copy stereo surface into back buffer */
+ IDirect3DDevice9_StretchRect(d3ddev, sys->nvidia_3dvision_surface, NULL,
+ d3dback_buffer, NULL, D3DTEXF_LINEAR);
+
+ 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..91a9983
--- /dev/null
+++ b/modules/video_output/msw/nvidia_3dvision.h
@@ -0,0 +1,34 @@
+/*****************************************************************************
+ * 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 Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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 "stereo3d_api.h"
+
+int Nvidia3DVisionLoad(Stereo3DAPI *);
+
+#endif
diff --git a/modules/video_output/msw/stereo3d_api.c b/modules/video_output/msw/stereo3d_api.c
new file mode 100644
index 0000000..441f8ce
--- /dev/null
+++ b/modules/video_output/msw/stereo3d_api.c
@@ -0,0 +1,51 @@
+/*****************************************************************************
+ * stereo3d_api.c
+ *****************************************************************************
+ * 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 Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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 "stereo3d_api.h"
+
+/* The APIs */
+#include "nvidia_3dvision.h"
+
+Stereo3DAPI *Stereo3DAPI_Load(vout_display_t *vd)
+{
+ Stereo3DAPI *s = calloc(1, sizeof(*s));
+ if (!s)
+ return NULL;
+
+ s->vd = vd;
+
+ /* NVIDIA 3D Vision is the only available API currently */
+ if (Nvidia3DVisionLoad(s))
+ goto error;
+
+ return s;
+
+error:
+ free(s);
+ return NULL;
+}
+
+void Stereo3DAPI_Unload(Stereo3DAPI *s)
+{
+ s->unload(s);
+ free(s);
+}
diff --git a/modules/video_output/msw/stereo3d_api.h b/modules/video_output/msw/stereo3d_api.h
new file mode 100644
index 0000000..457dc84
--- /dev/null
+++ b/modules/video_output/msw/stereo3d_api.h
@@ -0,0 +1,87 @@
+/*****************************************************************************
+ * stereo3d_api.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 Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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 STEREO3D_API_H_
+# define STEREO3D_API_H_
+
+# ifdef HAVE_CONFIG_H
+# include "config.h"
+# endif
+
+# include <vlc_common.h>
+# include <vlc_vout_display.h>
+
+typedef struct Stereo3DAPI Stereo3DAPI;
+typedef struct stereo3d_api_sys_t stereo3d_api_sys_t;
+typedef struct d3d_region_t d3d_region_t;
+
+struct Stereo3DAPI
+{
+ void (*unload)(Stereo3DAPI *);
+
+ int (*create_resources)(Stereo3DAPI *);
+ void (*destroy_resources)(Stereo3DAPI *);
+
+ int (*create_scene)(Stereo3DAPI *, const video_format_t *);
+ void (*destroy_scene)(Stereo3DAPI *);
+
+ bool (*can_render)(Stereo3DAPI *);
+ int (*render_region)(Stereo3DAPI *, d3d_region_t *);
+
+ vout_display_t *vd;
+ stereo3d_api_sys_t *sys;
+};
+
+Stereo3DAPI *Stereo3DAPI_Load(vout_display_t *);
+void Stereo3DAPI_Unload(Stereo3DAPI *s);
+
+static inline int Stereo3DAPI_CreateResources(Stereo3DAPI *s)
+{
+ return s->create_resources(s);
+}
+
+static inline void Stereo3DAPI_DestroyResources(Stereo3DAPI *s)
+{
+ s->destroy_resources(s);
+}
+
+static inline int Stereo3DAPI_CreateScene(Stereo3DAPI *s, const video_format_t *fmt)
+{
+ return s->create_scene(s, fmt);
+}
+
+static inline void Stereo3DAPI_DestroyScene(Stereo3DAPI *s)
+{
+ s->destroy_scene(s);
+}
+
+static inline bool Stereo3DAPI_CanRender(Stereo3DAPI *s)
+{
+ return s->can_render(s);
+}
+
+static inline int Stereo3DAPI_RenderRegion(Stereo3DAPI *s, d3d_region_t *r)
+{
+ return s->render_region(s, r);
+}
+
+#endif
--
1.9.1
More information about the vlc-devel
mailing list