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

Jean-Baptiste Kempf jb at videolan.org
Fri Aug 8 20:47:59 CEST 2014


Hmmm:
 - same remark as above for licenses.
 - some removal/adding of empty lines are useless.
 - I'm not too much fan of the common.h/direct3d.c modifications, since they
   are a bit too nVidia specific, when they could be abstracted
   (pf_stereo_unload, pf_stereo_create, etc...)

The rest is good, as usual...

On 08 Aug, Felix Abecassis wrote :
> ---
>  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
> 
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel

-- 
With my kindest regards,

-- 
Jean-Baptiste Kempf
http://www.jbkempf.com/ - +33 672 704 734
Sent from my Electronic Device



More information about the vlc-devel mailing list