[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