[vlc-devel] [PATCH] Direct3D shader support (HLSL)

Jean-Baptiste Kempf jb at videolan.org
Sat Aug 14 13:37:20 CEST 2010


On Sat, Aug 14, 2010 at 03:51:38AM -0700, Sasha Koruga wrote :


Subject: [PATCH] Added Direct3D shader (HLSL) support and GUI


diff --git a/modules/gui/qt4/menus.cpp b/modules/gui/qt4/menus.cpp
index 3e682e0..2e173f1 100644
--- a/modules/gui/qt4/menus.cpp
+++ b/modules/gui/qt4/menus.cpp

Should be in a separate patch, without tabs.


diff --git a/modules/video_output/msw/common.h b/modules/video_output/msw/common.h
index 3a67c7d..a3d495e 100644
--- a/modules/video_output/msw/common.h
+++ b/modules/video_output/msw/common.h

OK.

+#define SHADERFX_MODE_TEXT N_("Shader Effects")
+#define SHADERFX_MODE_LONGTEXT N_( "Shader effect to use for video post-processing.")
 #define D3D_HELP N_("Recommended video output for Windows Vista and later versions")

Should those be comma separated or?

     add_bool("direct3d-desktop", false, NULL, DESKTOP_TEXT, DESKTOP_LONGTEXT, true)
+    add_string( "shader-effects", "Disabled", NULL, SHADERFX_MODE_TEXT, SHADERFX_MODE_LONGTEXT, true )
Why "Disabled" instead of empty?

 
+char shaderCode[] = " \
Can't this be separated in special files?

-    if (Direct3DCreate(vd)) {
+    if (Direct3DCreate(vd))
+    {

  Why this change?

-    if (Direct3DOpen(vd, &fmt)) {
+    if (Direct3DOpen(vd, &fmt))
+    {

idem

-    if (FAILED(hr)) {
+    if (FAILED(hr))
+    {

  idem

-    if (!sys->use_desktop) {
+    if (!sys->use_desktop)
+    {

  idem

-    if (!sys->use_desktop) {
+    if (!sys->use_desktop)
+    {
  idem

-    if (EventThreadStart(sys->event, &hwnd, &cfg)) {
+    if (EventThreadStart(sys->event, &hwnd, &cfg))
+    {
  idem

-    if (Direct3DOpen(vd, &fmt)) {
+    if (Direct3DOpen(vd, &fmt))
+    {
  idem

-    if (sys->use_desktop) {
+    if (sys->use_desktop)
+    {
  idem

-    switch (query) {
+    switch (query)
+    {
  idem

-        if (sys->reset_device) {
-            if (ControlResetDevice(vd)) {
+        if (sys->reset_device)
+        {
+            if (ControlResetDevice(vd))
+            {
  idem

-        } else if(sys->reopen_device) {
-            if (ControlReopenDevice(vd)) {
+        }
+        else if(sys->reopen_device)
+        {
+            if (ControlReopenDevice(vd))
+            {
  idem

     vlc_mutex_unlock(&sys->lock);
 
-    if (ch_desktop) {
+    if (ch_desktop)
+    {
  idem

-    if (sys->changes & DX_POSITION_CHANGE) {
+    if (sys->changes & DX_POSITION_CHANGE)
+    {
  idem

    -    if (!sys->hd3d9_dll) {
+    if (!sys->hd3d9_dll)
+    {
  idem
-    if (!OurDirect3DCreate9) {
+    if (!OurDirect3DCreate9)
+    {
  idem
-    if (!d3dobj) {
+    if (!d3dobj)
+    {
  idem

+    //load shader support
+    for(int i = 43; i > 23; --i)
+    {
+        char buffer[3], filename[14];
+        strcpy(filename, "D3dx9_");

why not strncpy?

+        strcat(filename, itoa(i,buffer,10));
+        strcat(filename, ".dll");
strncat?

+        sys->hd3d9x_dll = LoadLibrary(filename);
+        msg_Dbg(vd, "Attempting to load: %s", filename);
+        if(sys->hd3d9x_dll)
+        {
+            msg_Dbg(vd, "loaded: %s", filename);
+            break;
+        }
+    }
+    if(!sys->hd3d9x_dll)
+    {
+        msg_Warn(vd, "cannot load D3dx9d_[24-43].dll; HLSL pixel shading will be disabled. (Please install DirectX end-user runtime)");
+        sys->d3dxShader = NULL;
+    }
OK

-    if (FAILED(hr)) {
+    if (FAILED(hr))
+    {
  idem

     vout_display_sys_t *sys = vd->sys;
-       IDirect3D9_Release(sys->d3dobj);
+    {
+        IDirect3D9_Release(sys->d3dobj);
+        sys->d3dobj = NULL;
+    }
     if (sys->hd3d9_dll)
+    {
         FreeLibrary(sys->hd3d9_dll);
+        sys->hd3d9_dll = NULL;
+    }
+    if (sys->hd3d9x_dll)
+    {
+        FreeLibrary(sys->hd3d9x_dll);
+        sys->hd3d9x_dll = NULL;
+    }
 
-    sys->d3dobj = NULL;
-    sys->hd3d9_dll = NULL;
 }
OK.

-    d3dpp->BackBufferWidth        = __MAX(GetSystemMetrics(SM_CXVIRTUALSCREEN),
+    d3dpp->BackBufferWidth        = __MAX((unsigned int)GetSystemMetrics(SM_CXVIRTUALSCREEN),
                                           d3ddm.Width);
-    d3dpp->BackBufferHeight       = __MAX(GetSystemMetrics(SM_CYVIRTUALSCREEN),
+    d3dpp->BackBufferHeight       = __MAX((unsigned int)GetSystemMetrics(SM_CYVIRTUALSCREEN),
                                           d3ddm.Height);
Those 2 things should be in a separate patch

     // Create the D3DDevice
     LPDIRECT3DDEVICE9 d3ddev;
-    HRESULT hr = IDirect3D9_CreateDevice(d3dobj, D3DADAPTER_DEFAULT,
-                                         D3DDEVTYPE_HAL, sys->hvideownd,
+    
+    // Look for 'NVIDIA PerfHUD' adapter
+    // If it is present, override default settings
+    UINT AdapterToUse = D3DADAPTER_DEFAULT;
+    D3DDEVTYPE DeviceType = D3DDEVTYPE_HAL;
+    for (UINT Adapter=0; Adapter< IDirect3D9_GetAdapterCount(d3dobj); ++Adapter)
+    {
+        D3DADAPTER_IDENTIFIER9 Identifier;
+        HRESULT Res;
+        Res = IDirect3D9_GetAdapterIdentifier(d3dobj,Adapter,0,&Identifier);
+        if (strstr(Identifier.Description,"PerfHUD") != 0)
+        {
+            AdapterToUse = Adapter;
+            DeviceType = D3DDEVTYPE_REF;
+            break;
+        }
+    }
+
+    HRESULT hr = IDirect3D9_CreateDevice(d3dobj, AdapterToUse,
+                                         DeviceType, sys->hvideownd,
                                          D3DCREATE_SOFTWARE_VERTEXPROCESSING|
                                          D3DCREATE_MULTITHREADED,
                                          &sys->d3dpp, &d3ddev);

This should be also in a separate patch.

-    if (FAILED(hr)) {
+    if (FAILED(hr))
+    {
  idem

-    if (Direct3DCreateResources(vd, fmt)) {
+    if (Direct3DCreateResources(vd, fmt))
+    {
  idem

+    if(sys->hd3d9x_dll)
+    {
+        HRESULT (WINAPI * OurD3DXCreateEffect)(
+            LPDIRECT3DDEVICE9               pDevice,
+            LPCVOID                         pSrcData,
+            UINT                            SrcDataLen,
+            CONST D3DXMACRO*                pDefines,
+            LPD3DXINCLUDE                   pInclude,
+            DWORD                           Flags,
+            LPD3DXEFFECTPOOL                pPool,
+            LPD3DXEFFECT*                   ppEffect,
+            LPD3DXBUFFER*                   ppCompilationErrors);

Why declaring it here?

+        OurD3DXCreateEffect = (void*)GetProcAddress(sys->hd3d9x_dll, TEXT("D3DXCreateEffect"));
+        if (!OurD3DXCreateEffect)
+        {
+            msg_Warn(vd, "Cannot locate reference to D3DXCreateEffect ABI in DLL; pixel shading will be disabled");
+            sys->d3dxShader = NULL;
+        }
+        else
+        {
+            LPD3DXBUFFER buffer = NULL;
+            DWORD dwShaderFlags = D3DXFX_NOT_CLONEABLE;
+            HRESULT hr = OurD3DXCreateEffect(sys->d3ddev, shaderCode, strlen(shaderCode), NULL, NULL, dwShaderFlags, NULL, ((ID3DXEffect**)(&sys->d3dxShader)), &buffer);
+            if (FAILED(hr))
+            {
+               msg_Warn(vd, "OurD3DXCreateEffect Error (hr=0x%lX) -- pixel shading will be disabled.", hr);

%lX ? %li maybe is better

+               if(buffer)
+                   msg_Warn(vd, "HLSL Compilation Error: %s", (char*)buffer->lpVtbl->GetBufferPointer(buffer));
+               sys->d3dxShader = NULL;
+            }
+        }
+    }
ok.

 
+    if(sys->d3dxShader)
+    {
+        ((ID3DXEffect*)(sys->d3dxShader))->lpVtbl->Release(sys->d3dxShader);
+        sys->d3dxShader = NULL;
+    }
     if (sys->d3ddev)
+    {
        IDirect3DDevice9_Release(sys->d3ddev);
-
-    sys->d3ddev = NULL;
+        sys->d3ddev = NULL;
+    }
 }
Ok.

@@ -771,10 +1072,7 @@ static int Direct3DLockSurface(picture_t *picture)
 static void Direct3DUnlockSurface(picture_t *picture)
 {
     /* Unlock the Surface */
-    HRESULT hr = IDirect3DSurface9_UnlockRect(picture->p_sys->surface);
-    if (FAILED(hr)) {
-        //msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-    }
+    IDirect3DSurface9_UnlockRect(picture->p_sys->surface);
 }

No, this can be helpful for debugging the module.

 
@@ -1016,14 +1323,17 @@ static void Direct3DDestroyScene(vout_display_t *vd)
  */
 static void Direct3DRenderScene(vout_display_t *vd, LPDIRECT3DSURFACE9 surface)
 {
+    UINT shaderPasses;
     vout_display_sys_t *sys = vd->sys;
     LPDIRECT3DDEVICE9 d3ddev = sys->d3ddev;
     HRESULT hr;
ok

-    // Setup our texture. Using textures introduces the texture stage states,
-    // which govern how textures get blended together (in the case of multiple
-    // textures) and lighting information. In this case, we are modulating
-    // (blending) our texture with the diffuse color of the vertices.
-    hr = IDirect3DDevice9_SetTexture(d3ddev, 0, (LPDIRECT3DBASETEXTURE9)d3dtex);
-    if (FAILED(hr)) {
-        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-        IDirect3DDevice9_EndScene(d3ddev);
-        return;
-    }
+    if(((ID3DXEffect*)(sys->d3dxShader)))
+    {
+        hr = ((ID3DXEffect*)(sys->d3dxShader))->lpVtbl->SetTechnique(((ID3DXEffect*)(sys->d3dxShader)), sys->shaderFXOption );
+        if (FAILED(hr))
+        {
+           msg_Err(vd, "SetTechnique failed (hr=0x%lX)", hr);

%li?

+        }
 
-    // Render the vertex buffer contents
-    hr = IDirect3DDevice9_SetStreamSource(d3ddev, 0, d3dvtc, 0, sizeof(CUSTOMVERTEX));
-    if (FAILED(hr)) {
-        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-        IDirect3DDevice9_EndScene(d3ddev);
-        return;
+        hr = ((ID3DXEffect*)(sys->d3dxShader))->lpVtbl->Begin(((ID3DXEffect*)(sys->d3dxShader)), &shaderPasses, 0 );
+        if (FAILED(hr))
+        {
+           msg_Err(vd, "Begin failed (hr=0x%lX)", hr);
+        }
     }
+    else
+        shaderPasses = 1;
 
-    // we use FVF instead of vertex shader
-    hr = IDirect3DDevice9_SetFVF(d3ddev, D3DFVF_CUSTOMVERTEX);
-    if (FAILED(hr)) {
-        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-        IDirect3DDevice9_EndScene(d3ddev);
-        return;
-    }
+    for( UINT uPass = 0; uPass < shaderPasses; ++uPass )
+    {
+        if(((ID3DXEffect*)(sys->d3dxShader)))
+        {
+            hr = ((ID3DXEffect*)(sys->d3dxShader))->lpVtbl->BeginPass(((ID3DXEffect*)(sys->d3dxShader)), uPass);
+            if (FAILED(hr))
+                msg_Err(vd, "BeginPass failed (hr=0x%lX)", hr);
+        }
+
+        // Setup our texture. Using textures introduces the texture stage states,
+        // which govern how textures get blended together (in the case of multiple
+        // textures) and lighting information. In this case, we are modulating
+        // (blending) our texture with the diffuse color of the vertices.
+        hr = IDirect3DDevice9_SetTexture(d3ddev, 0, (LPDIRECT3DBASETEXTURE9)d3dtex);
+        if (FAILED(hr))
+        {
+            msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+            IDirect3DDevice9_EndScene(d3ddev);
+            return;
+        }
+
+        // Render the vertex buffer contents
+        hr = IDirect3DDevice9_SetStreamSource(d3ddev, 0, d3dvtc, 0, sizeof(CUSTOMVERTEX));
+        if (FAILED(hr))
+        {
+            msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+            IDirect3DDevice9_EndScene(d3ddev);
+            return;
+        }
+
+        // we use FVF instead of vertex shader
+        hr = IDirect3DDevice9_SetFVF(d3ddev, D3DFVF_CUSTOMVERTEX);
+        if (FAILED(hr))
+        {
+            msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+            IDirect3DDevice9_EndScene(d3ddev);
+            return;
+        }
+
+        // draw rectangle
+        hr = IDirect3DDevice9_DrawPrimitive(d3ddev, D3DPT_TRIANGLEFAN, 0, 2);
+        if (FAILED(hr))
+        {
+            msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
+            IDirect3DDevice9_EndScene(d3ddev);
+            return;
+        }
+
+
+        if(((ID3DXEffect*)(sys->d3dxShader)))
+        {
+            hr = ((ID3DXEffect*)(sys->d3dxShader))->lpVtbl->EndPass(((ID3DXEffect*)(sys->d3dxShader)));
+            if (FAILED(hr))
+                msg_Err(vd, "EndPass failed (hr=0x%lX)", hr);
+        }
 
-    // draw rectangle
-    hr = IDirect3DDevice9_DrawPrimitive(d3ddev, D3DPT_TRIANGLEFAN, 0, 2);
-    if (FAILED(hr)) {
-        msg_Dbg(vd, "%s:%d (hr=0x%0lX)", __FUNCTION__, __LINE__, hr);
-        IDirect3DDevice9_EndScene(d3ddev);
-        return;
     }
 
+    if(((ID3DXEffect*)(sys->d3dxShader)))
+    {
+        hr = ((ID3DXEffect*)(sys->d3dxShader))->lpVtbl->End(((ID3DXEffect*)(sys->d3dxShader)));
+        if (FAILED(hr))
+           msg_Err(vd, "End failed (hr=0x%lX)", hr);
+    }

Mostly OK, I guess.


vdiff --git a/src/video_output/vout_wrapper.c b/src/video_output/vout_wrapper.c
index 3c2c3f4..cc11fac 100644
--- a/src/video_output/vout_wrapper.c
+++ b/src/video_output/vout_wrapper.c
@@ -84,6 +84,46 @@ int vout_OpenWrapper(vout_thread_t *vout,
     var_AddCallback(vout, "direct3d-desktop", Forward, NULL);
     var_Create(vout, "video-wallpaper", VLC_VAR_BOOL|VLC_VAR_DOINHERIT);
     var_AddCallback(vout, "video-wallpaper", Forward, NULL);
+
+
+    if( var_Type( vout, "shader-effects" ) == 0 )
+    {
+        var_Create(vout, "shader-effects", VLC_VAR_STRING | VLC_VAR_HASCHOICE | VLC_VAR_DOINHERIT);
+        var_AddCallback(vout, "shader-effects", Forward, NULL);
+
+        vlc_value_t val,text;
+        val.psz_string = _("grayscale"); 
+        text.psz_string = _("Grayscale");
+        var_Change( vout, "shader-effects", VLC_VAR_ADDCHOICE, &val, &text );
+    
+        val.psz_string = _("invert"); 
+        text.psz_string = _("Invert Colors");
+        var_Change( vout, "shader-effects", VLC_VAR_ADDCHOICE, &val, &text );
+
+        val.psz_string = _("widencolorspace"); 
+        text.psz_string = _("16-235 -> 0-255");
+        var_Change( vout, "shader-effects", VLC_VAR_ADDCHOICE, &val, &text );
+    
+        val.psz_string = _("detect15"); 
+        text.psz_string = _("Red Detect 0-15 & 236-255");
+        var_Change( vout, "shader-effects", VLC_VAR_ADDCHOICE, &val, &text );
+
+        val.psz_string = _("convert601to709"); 
+        text.psz_string = _("bt601 -> bt709");
+        var_Change( vout, "shader-effects", VLC_VAR_ADDCHOICE, &val, &text );
+    
+        val.psz_string = _("gammacorrection18"); 
+        text.psz_string = _("Gamma Correction (1.8)");
+        var_Change( vout, "shader-effects", VLC_VAR_ADDCHOICE, &val, &text );
+    
+        val.psz_string = _("gammacorrection22"); 
+        text.psz_string = _("Gamma Correction (2.2)");
+        var_Change( vout, "shader-effects", VLC_VAR_ADDCHOICE, &val, &text );
+    
+        val.psz_string = _("gammacorrectionbt709"); 
+        text.psz_string = _("Gamma Correction (BT.709)");
+        var_Change( vout, "shader-effects", VLC_VAR_ADDCHOICE, &val, &text );
+    }
 #endif
 
     /* */
@@ -102,6 +142,8 @@ void vout_CloseWrapper(vout_thread_t *vout, vout_display_state_t *state)
 #ifdef WIN32
     var_DelCallback(vout, "direct3d-desktop", Forward, NULL);
     var_DelCallback(vout, "video-wallpaper", Forward, NULL);
+    var_DelCallback(vout, "shader-effects", Forward, NULL);
+	var_Destroy( vout, "shader-effects" );
 #endif
     sys->decoder_pool = NULL; /* FIXME remove */
}
 
Should all this code be in the wrapper? Laurent, opinion?

Be careful, trailing spaces and tabs here too


-- 
Jean-Baptiste Kempf
http://www.jbkempf.com/
+33 672 704 734



More information about the vlc-devel mailing list