[vlc-devel] [PATCH] Direct3D: implement HLSL pixel shading in the rendering pipeline

Felix Abecassis felix.abecassis at gmail.com
Tue Jan 28 12:50:09 CET 2014


The user can choose which shader to apply using a selection list in
the options of the Direct3D vout module. The list of shader techniques
is populated by reading the file "pixelShader.fx" from the user data
directory. New shaders can be added easily by extending this file.

Based on the code by Sasha Koruga for GSoC 2010.
---
 modules/video_output/msw/common.h       |   24 +++
 modules/video_output/msw/direct3d.c     |  288 ++++++++++++++++++++++++++++---
 modules/video_output/msw/pixelShader.fx |  181 +++++++++++++++++++
 3 files changed, 467 insertions(+), 26 deletions(-)
 create mode 100644 modules/video_output/msw/pixelShader.fx

diff --git a/modules/video_output/msw/common.h b/modules/video_output/msw/common.h
index 122d80a..50d4461 100644
--- a/modules/video_output/msw/common.h
+++ b/modules/video_output/msw/common.h
@@ -27,6 +27,7 @@
 #endif
 #ifdef MODULE_NAME_IS_direct3d
 # include <d3d9.h>
+# include <d3dx9effect.h>
 #endif
 #ifdef MODULE_NAME_IS_glwin32
 # include "../opengl.h"
@@ -147,6 +148,8 @@ struct vout_display_sys_t
 
     // core objects
     HINSTANCE               hd3d9_dll;       /* handle of the opened d3d9 dll */
+    HINSTANCE               hd3d9x_dll;      /* handle of the opened d3d9x dll */
+    ID3DXEffect*            d3dx_shader;
     LPDIRECT3D9             d3dobj;
     D3DCAPS9                d3dcaps;
     LPDIRECT3DDEVICE9       d3ddev;
@@ -213,3 +216,24 @@ void AlignRect(RECT *, int align_boundary, int align_size);
 #define DX_POSITION_CHANGE 0x1000
 #define DX_WALLPAPER_CHANGE 0x2000
 #define DX_DESKTOP_CHANGE 0x4000
+
+/*****************************************************************************
+ * Functions missing from the mingw headers
+ *****************************************************************************/
+/* If one prototype is missing, assume the others are too. */
+#ifndef ID3DXEffect_Begin
+# define ID3DXEffect_Begin(p, a, b)      (p)->lpVtbl->Begin(p, a, b)
+# define ID3DXEffect_End(p)              (p)->lpVtbl->End(p)
+# define ID3DXEffect_BeginPass(p, a)     (p)->lpVtbl->BeginPass(p, a)
+# define ID3DXEffect_EndPass(p)          (p)->lpVtbl->EndPass(p)
+# define ID3DXEffect_GetDesc(p, a)       (p)->lpVtbl->GetDesc(p, a)
+# define ID3DXEffect_GetTechnique(p, a)  (p)->lpVtbl->GetTechnique(p, a)
+# define ID3DXEffect_GetTechniqueByName(p, a)  (p)->lpVtbl->GetTechniqueByName(p, a)
+# define ID3DXEffect_SetTechnique(p, a)  (p)->lpVtbl->SetTechnique(p, a)
+# define ID3DXEffect_GetTechniqueDesc(p, a, b)  (p)->lpVtbl->GetTechniqueDesc(p, a, b)
+# define ID3DXEffect_Release(p)          (p)->lpVtbl->Release(p)
+#endif
+
+#ifndef ID3DXEffectCompiler_CompileEffect
+# define ID3DXEffectCompiler_CompileEffect(p, a, b, c) (p)->lpVtbl->CompileEffect(p, a, b, c)
+#endif
diff --git a/modules/video_output/msw/direct3d.c b/modules/video_output/msw/direct3d.c
index e2d7387..f49f9a9 100644
--- a/modules/video_output/msw/direct3d.c
+++ b/modules/video_output/msw/direct3d.c
@@ -1,10 +1,12 @@
 /*****************************************************************************
  * direct3d.c: Windows Direct3D video output module
  *****************************************************************************
- * Copyright (C) 2006-2009 VLC authors and VideoLAN
+ * Copyright (C) 2006-2014 VLC authors and VideoLAN
  *$Id$
  *
- * Authors: Damien Fouilleul <damienf at videolan.org>
+ * Authors: Damien Fouilleul <damienf at videolan.org>,
+ *          Sasha Koruga <skoruga at gmail.com>,
+ *          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
@@ -40,6 +42,7 @@
 #include <vlc_common.h>
 #include <vlc_plugin.h>
 #include <vlc_vout_display.h>
+#include <vlc_charset.h> /* ToT function */
 
 #include <windows.h>
 #include <d3d9.h>
@@ -59,8 +62,17 @@ static void Close(vlc_object_t *);
 #define HW_BLENDING_LONGTEXT N_(\
     "Try to use hardware acceleration for subtitle/OSD blending.")
 
+#define PIXEL_SHADER_TEXT N_("Pixel Shader")
+#define PIXEL_SHADER_LONGTEXT N_(\
+        "Choose a pixel shader to apply.")
+#define PIXEL_SHADER_PATH config_GetUserDir(VLC_DATA_DIR)
+#define PIXEL_SHADER_FILENAME "pixelShader.fx"
+
 #define D3D_HELP N_("Recommended video output for Windows Vista and later versions")
 
+static int FindShadersCallback(vlc_object_t *, const char *,
+                               char ***, char ***);
+
 vlc_module_begin ()
     set_shortname("Direct3D")
     set_description(N_("Direct3D video output"))
@@ -70,6 +82,9 @@ vlc_module_begin ()
 
     add_bool("direct3d-hw-blending", true, HW_BLENDING_TEXT, HW_BLENDING_LONGTEXT, true)
 
+    add_string("direct3d-shader", "", PIXEL_SHADER_TEXT, PIXEL_SHADER_LONGTEXT, true)
+        change_string_cb(FindShadersCallback)
+
     set_capability("vout display", 240)
     add_shortcut("direct3d")
     set_callbacks(Open, Close)
@@ -486,6 +501,21 @@ static void Manage (vout_display_t *vd)
     }
 }
 
+static HINSTANCE Direct3DLoadShaderLibrary()
+{
+    HINSTANCE instance = NULL;
+    for (int i = 43; i > 23; --i) {
+        char *filename = NULL;
+        if (asprintf(&filename, "D3dx9_%d.dll", i) == -1)
+            continue;
+        instance = LoadLibrary(ToT(filename));
+        free(filename);
+        if (instance)
+            break;
+    }
+    return instance;
+}
+
 /**
  * It initializes an instance of Direct3D9
  */
@@ -515,6 +545,10 @@ static int Direct3DCreate(vout_display_t *vd)
     }
     sys->d3dobj = d3dobj;
 
+    sys->hd3d9x_dll = Direct3DLoadShaderLibrary();
+    if (!sys->hd3d9x_dll)
+        msg_Warn(vd, "cannot load Direct3D Shader Library; HLSL pixel shading will be disabled.");
+
     /*
     ** Get device capabilities
     */
@@ -547,9 +581,12 @@ static void Direct3DDestroy(vout_display_t *vd)
        IDirect3D9_Release(sys->d3dobj);
     if (sys->hd3d9_dll)
         FreeLibrary(sys->hd3d9_dll);
+    if (sys->hd3d9x_dll)
+        FreeLibrary(sys->hd3d9x_dll);
 
     sys->d3dobj = NULL;
     sys->hd3d9_dll = NULL;
+    sys->hd3d9x_dll = NULL;
 }
 
 
@@ -722,6 +759,9 @@ static void Direct3DDestroyPool(vout_display_t *vd);
 static int  Direct3DCreateScene(vout_display_t *vd, const video_format_t *fmt);
 static void Direct3DDestroyScene(vout_display_t *vd);
 
+static int  Direct3DCreateShaders(vout_display_t *vd);
+static void Direct3DDestroyShaders(vout_display_t *vd);
+
 /**
  * It creates the picture and scene resources.
  */
@@ -737,6 +777,11 @@ static int Direct3DCreateResources(vout_display_t *vd, video_format_t *fmt)
         msg_Err(vd, "Direct3D scene initialization failed !");
         return VLC_EGENERIC;
     }
+    if (Direct3DCreateShaders(vd)) {
+        /* Failing to initialize shaders is not fatal. */
+        msg_Warn(vd, "Direct3D shaders initialization failed !");
+    }
+
     sys->d3dregion_format = D3DFMT_UNKNOWN;
     for (int i = 0; i < 2; i++) {
         D3DFORMAT fmt = i == 0 ? D3DFMT_A8B8G8R8 : D3DFMT_A8R8G8B8;
@@ -760,6 +805,7 @@ static void Direct3DDestroyResources(vout_display_t *vd)
 {
     Direct3DDestroyScene(vd);
     Direct3DDestroyPool(vd);
+    Direct3DDestroyShaders(vd);
 }
 
 /**
@@ -1131,6 +1177,87 @@ static void Direct3DDestroyScene(vout_display_t *vd)
     msg_Dbg(vd, "Direct3D scene released successfully");
 }
 
+static char* Direct3DGetShaderFile()
+{
+    char* filename = NULL;
+    if (asprintf(&filename, "%s\\%s", PIXEL_SHADER_PATH, PIXEL_SHADER_FILENAME) == -1)
+        return NULL;
+    return filename;
+}
+
+static int Direct3DCreateShaders(vout_display_t *vd)
+{
+    vout_display_sys_t *sys = vd->sys;
+
+    /* Find which shader was enabled. */
+    char *selected_shader = var_InheritString(vd, "direct3d-shader");
+    if (!selected_shader)
+        return VLC_SUCCESS; /* Nothing to do */
+
+    if (!sys->hd3d9x_dll)
+        goto error;
+
+    HRESULT (WINAPI * OurD3DXCreateEffectFromFile)(
+        LPDIRECT3DDEVICE9               pDevice,
+        LPCSTR                          pSrcFile,
+        CONST D3DXMACRO*                pDefines,
+        LPD3DXINCLUDE                   pInclude,
+        DWORD                           Flags,
+        LPD3DXEFFECTPOOL                pPool,
+        LPD3DXEFFECT*                   ppEffect,
+        LPD3DXBUFFER*                   ppCompilationErrors);
+
+    OurD3DXCreateEffectFromFile = (void*)GetProcAddress(sys->hd3d9x_dll, "D3DXCreateEffectFromFileA");
+    if (!OurD3DXCreateEffectFromFile) {
+        msg_Warn(vd, "Cannot locate reference to D3DXCreateEffectFromFile; pixel shading will be disabled");
+        goto error;
+    }
+
+    LPD3DXBUFFER buffer = NULL;
+    char *shader_file = Direct3DGetShaderFile();
+    if (!shader_file)
+        goto error;
+    DWORD shader_flags = D3DXFX_NOT_CLONEABLE;
+    HRESULT hr = OurD3DXCreateEffectFromFile(sys->d3ddev, shader_file, NULL, NULL,
+                                             shader_flags, NULL, &sys->d3dx_shader, &buffer);
+    if (FAILED(hr)) {
+        msg_Warn(vd, "D3DXCreateEffectFromFile Error (hr=0x%lX) -- pixel shader file probably missing.", hr);
+        if (buffer)
+            msg_Warn(vd, "HLSL Compilation Error: %s", (char*)ID3DXBuffer_GetBufferPointer(buffer));
+        goto error;
+    }
+
+    D3DXHANDLE technique = ID3DXEffect_GetTechniqueByName(sys->d3dx_shader, selected_shader);
+    if (!technique) {
+        msg_Warn(vd, "Could not find requested technique from shader file.");
+        goto error;
+    }
+    hr = ID3DXEffect_SetTechnique(sys->d3dx_shader, technique);
+    if (FAILED(hr)) {
+        msg_Warn(vd, "Could not set requested shader technique.");
+        goto error;
+    }
+
+    free(selected_shader);
+
+    return VLC_SUCCESS;
+
+error:
+    if (sys->d3dx_shader)
+        Direct3DDestroyShaders(vd);
+    free(selected_shader);
+    return VLC_EGENERIC;
+}
+
+static void Direct3DDestroyShaders(vout_display_t *vd)
+{
+    vout_display_sys_t *sys = vd->sys;
+
+    if (sys->d3dx_shader)
+        ID3DXEffect_Release(sys->d3dx_shader);
+    sys->d3dx_shader = NULL;
+}
+
 static void Direct3DSetupVertices(CUSTOMVERTEX *vertices,
                                   const RECT src_full,
                                   const RECT src_crop,
@@ -1360,35 +1487,69 @@ static int Direct3DRenderRegion(vout_display_t *vd,
         return -1;
     }
 
-    // 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);
-        return -1;
+    unsigned shader_passes;
+    if (sys->d3dx_shader)
+    {
+        hr = ID3DXEffect_Begin(sys->d3dx_shader, &shader_passes, 0);
+        if (FAILED(hr))
+           msg_Err(vd, "Begin failed (hr=0x%lX)", hr);
     }
+    else
+        shader_passes = 1;
 
-    // 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);
-        return -1;
-    }
+    for (UINT uPass = 0; uPass < shader_passes; ++uPass) {
+        if (sys->d3dx_shader) {
+            hr = ID3DXEffect_BeginPass(sys->d3dx_shader, uPass);
+            if (FAILED(hr))
+                msg_Err(vd, "BeginPass failed (hr=0x%lX)", hr);
+        }
 
-    // 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);
-        return -1;
+        // 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 -1;
+        }
+
+        // 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 -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 -1;
+        }
+
+        // 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 -1;
+        }
+
+        if (sys->d3dx_shader) {
+            hr = ID3DXEffect_EndPass(sys->d3dx_shader);
+            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);
-        return -1;
+    if (sys->d3dx_shader) {
+        hr = ID3DXEffect_End(sys->d3dx_shader);
+        if (FAILED(hr))
+           msg_Err(vd, "End failed (hr=0x%lX)", hr);
     }
     return 0;
 }
@@ -1466,3 +1627,78 @@ static int DesktopCallback(vlc_object_t *object, char const *psz_cmd,
     vlc_mutex_unlock(&sys->lock);
     return VLC_SUCCESS;
 }
+
+typedef struct
+{
+    char **values;
+    char **descs;
+    size_t count;
+} enum_context_t;
+
+static void ListTechniquesFromFile(enum_context_t *ctx)
+{
+    HINSTANCE hd3d9x_dll = Direct3DLoadShaderLibrary();
+    char* shader_file = NULL;
+    if (!hd3d9x_dll)
+        goto end;
+
+    HRESULT (WINAPI * OurD3DXCreateEffectCompilerFromFile)(
+        LPCSTR pSrcFile,
+        const D3DXMACRO *pDefines,
+        LPD3DXINCLUDE pInclude,
+        DWORD Flags,
+        LPD3DXEFFECTCOMPILER *ppEffectCompiler,
+        LPD3DXBUFFER *ppParseErrors);
+    /* We use CreateEffectCompilerFromFile since it does not creating a D3D device. */
+    OurD3DXCreateEffectCompilerFromFile = (void*)GetProcAddress(hd3d9x_dll, "D3DXCreateEffectCompilerFromFileA");
+    if (!OurD3DXCreateEffectCompilerFromFile)
+        goto end;
+
+    shader_file = Direct3DGetShaderFile();
+    if (!shader_file)
+        goto end;
+    DWORD shader_flags = D3DXFX_NOT_CLONEABLE;
+    LPD3DXEFFECTCOMPILER d3dx_effect;
+    HRESULT hr = OurD3DXCreateEffectCompilerFromFile(shader_file, NULL, NULL,
+                                                     shader_flags, &d3dx_effect, NULL);
+    if (FAILED(hr))
+        goto end;
+
+    D3DXEFFECT_DESC d3ddesc;
+    hr = ID3DXEffect_GetDesc(d3dx_effect, &d3ddesc);
+    if (FAILED(hr))
+        goto end;
+
+    int num_techniques = d3ddesc.Techniques;
+    ctx->values = xrealloc(ctx->values, (ctx->count + num_techniques) * sizeof(char *));
+    ctx->descs = xrealloc(ctx->descs, (ctx->count + num_techniques) * sizeof(char *));
+    for (UINT i = 0; i < d3ddesc.Techniques; ++i) {
+        D3DXHANDLE hTechnique = ID3DXEffect_GetTechnique(d3dx_effect, i);
+        D3DXTECHNIQUE_DESC d3ddesc;
+        ID3DXEffect_GetTechniqueDesc(d3dx_effect, hTechnique, &d3ddesc);
+        ctx->values[ctx->count] = strdup(d3ddesc.Name);
+        ctx->descs[ctx->count] = strdup(d3ddesc.Name);
+        ctx->count++;
+    }
+
+end:
+    if (hd3d9x_dll)
+        FreeLibrary(hd3d9x_dll);
+    free(shader_file);
+}
+
+/* Populate the list of available shader techniques in the options */
+static int FindShadersCallback(vlc_object_t *object, const char *name,
+                               char ***values, char ***descs)
+{
+    VLC_UNUSED(object);
+    VLC_UNUSED(name);
+
+    enum_context_t ctx = { NULL, NULL, 0 };
+
+    ListTechniquesFromFile(&ctx);
+
+    *values = ctx.values;
+    *descs = ctx.descs;
+    return ctx.count;
+}
diff --git a/modules/video_output/msw/pixelShader.fx b/modules/video_output/msw/pixelShader.fx
new file mode 100644
index 0000000..c0db367
--- /dev/null
+++ b/modules/video_output/msw/pixelShader.fx
@@ -0,0 +1,181 @@
+/*****************************************************************************
+ * pixelShader.fx: Direct3D Shader Code
+ *****************************************************************************
+ * Copyright (C) 2014 the VideoLAN team
+ *
+ * Authors: Sasha Koruga <skoruga at gmail.com>,
+ *          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.
+ *****************************************************************************/
+sampler2D screen;
+
+float4 disabled(float2 screenCoords : TEXCOORD0) : COLOR0
+{
+    return saturate(tex2D(screen, screenCoords.xy));
+}
+
+technique Disabled
+{
+    pass p1
+    {
+        PixelShader = compile ps_2_0 disabled();
+    }
+}
+
+float4 invert(float2 screenCoords : TEXCOORD0) : COLOR0
+{
+    float4 color = tex2D(screen, screenCoords.xy);
+    color.r = 1.0 - color.r;
+    color.g = 1.0 - color.g;
+    color.b = 1.0 - color.b;
+    return color;
+}
+
+technique Invert
+{
+    pass p1
+    {
+        PixelShader = compile ps_2_0 invert();
+    }
+}
+
+float4 rgb_to_yuv601(float4 RGB)
+{
+    float Kr = 0.299;
+    float Kg = 0.587;
+    float Kb = 0.114;
+    float Y = Kr*RGB.r + Kg*RGB.g + Kb*RGB.b;
+    float V = (RGB.r-Y)/(1-Kr);
+    float U = (RGB.b-Y)/(1-Kb);
+    return float4(Y,U,V,1);
+}
+
+float4 yuv709_to_rgb(float4 YUV)
+{
+    float Kr = 0.2125;
+    float Kg = 0.7154;
+    float Kb = 0.0721;
+    float Y = YUV.x;
+    float U = YUV.y;
+    float V = YUV.z;
+    float R = Y + V*(1-Kr);
+    float G = Y - U*(1-Kb)*Kb/Kg - V*(1-Kr)*Kr/Kg;
+    float B = Y + U*(1-Kb);
+    return float4(R,G,B,1);
+}
+
+float4 convert601to709(float2 screenCoords : TEXCOORD0) : COLOR0
+{
+    float4 color = tex2D(screen, screenCoords.xy);
+    return yuv709_to_rgb(rgb_to_yuv601(color));
+}
+
+technique Convert601to709
+{
+    pass p1
+    {
+        PixelShader = compile ps_2_0 convert601to709();
+    }
+}
+
+float4 gammacorrection18(float2 screenCoords : TEXCOORD0) : COLOR0
+{
+    float4 color = tex2D( screen, screenCoords.xy);
+    color = pow(color,1.0/1.8);
+    return color;
+}
+
+technique GammaCorrection18
+{
+    pass p1
+    {
+        PixelShader = compile ps_2_0 gammacorrection18();
+    }
+}
+
+float4 gammacorrection22(float2 screenCoords : TEXCOORD0) : COLOR0
+{
+    float4 color = tex2D(screen, screenCoords.xy);
+    color = pow(color,1.0/2.2);
+    return color;
+}
+
+technique GammaCorrection22
+{
+    pass p1
+    {
+        PixelShader = compile ps_2_0 gammacorrection22();
+    }
+}
+
+float4 gammacorrectionbt709(float2 screenCoords : TEXCOORD0) : COLOR0
+{
+    float4 color = tex2D(screen, screenCoords.xy);
+        if(color.r > 0.018)
+            color.r = 1.099 * pow(color.r,0.45) - 0.099;
+        else
+            color.r = 4.5138 * color.r;
+        if(color.g > 0.018)
+            color.g = 1.099 * pow(color.g,0.45) - 0.099;
+        else
+            color.g = 4.5138 * color.g;
+        if(color.b > 0.018)
+            color.b = 1.099 * pow(color.b,0.45) - 0.099;
+        else
+            color.b = 4.5138 * color.b;
+        return color;
+}
+
+technique GammaCorrectionBT709
+{
+    pass p1
+    {
+        PixelShader = compile ps_2_0 gammacorrectionbt709();
+    }
+}
+
+float4 widencolorspace(float2 screenCoords : TEXCOORD0) : COLOR0
+{
+    float4 color = tex2D(screen, screenCoords.xy);
+    color.r = max(color.r - 0.0627450980392157,0) * 1.164383561643836;
+    color.g = max(color.g - 0.0627450980392157,0) * 1.164383561643836;
+    color.b = max(color.b - 0.0627450980392157,0) * 1.164383561643836;
+    return saturate(color);
+}
+
+technique WidenColorSpace
+{
+    pass p1
+    {
+        PixelShader = compile ps_2_0 widencolorspace();
+    }
+}
+
+float4 grayscale(float2 screenCoords : TEXCOORD0) : COLOR0
+{
+    float4 color = tex2D(screen, screenCoords.xy);
+    float gray = 0.2989 * color.r + 0.5870 * color.g + 0.1140 * color.b;
+    color.r = color.g = color.b = gray;
+    return saturate(color);
+}
+
+technique Grayscale
+{
+    pass p1
+    {
+        PixelShader = compile ps_2_0 grayscale();
+    }
+}
-- 
1.7.10.4




More information about the vlc-devel mailing list