Stefan Dösinger : wined3d: Add fixed function sRGB write correction.

Alexandre Julliard julliard at winehq.org
Mon Aug 25 06:21:29 CDT 2008


Module: wine
Branch: master
Commit: f39e1224774a4f975951ccbc7dab6dac55e0670b
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=f39e1224774a4f975951ccbc7dab6dac55e0670b

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Wed Aug 20 10:15:31 2008 -0500

wined3d: Add fixed function sRGB write correction.

---

 dlls/wined3d/arb_program_shader.c |   64 +++++++++++++++++++++++++-----------
 dlls/wined3d/utils.c              |    5 +++
 dlls/wined3d/wined3d_private.h    |    1 +
 3 files changed, 50 insertions(+), 20 deletions(-)

diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index bc8d3b3..a701f36 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -1958,6 +1958,28 @@ static BOOL shader_arb_dirty_const(IWineD3DDevice *iface) {
     return TRUE;
 }
 
+static void arbfp_add_sRGB_correction(SHADER_BUFFER *buffer, const char *fragcolor, const char *tmp1,
+                                      const char *tmp2, const char *tmp3, const char *tmp4) {
+    /* Perform sRGB write correction. See GLX_EXT_framebuffer_sRGB */
+
+    /* Calculate the > 0.0031308 case */
+    shader_addline(buffer, "POW %s.x, %s.x, srgb_pow.x;\n", tmp1, fragcolor);
+    shader_addline(buffer, "POW %s.y, %s.y, srgb_pow.y;\n", tmp1, fragcolor);
+    shader_addline(buffer, "POW %s.z, %s.z, srgb_pow.z;\n", tmp1, fragcolor);
+    shader_addline(buffer, "MUL %s, %s, srgb_mul_hi;\n", tmp1, tmp1);
+    shader_addline(buffer, "SUB %s, %s, srgb_sub_hi;\n", tmp1, tmp1);
+    /* Calculate the < case */
+    shader_addline(buffer, "MUL %s, srgb_mul_low, %s;\n", tmp2, fragcolor);
+    /* Get 1.0 / 0.0 masks for > 0.0031308 and < 0.0031308 */
+    shader_addline(buffer, "SLT %s, srgb_comparison, %s;\n", tmp3, fragcolor);
+    shader_addline(buffer, "SGE %s, srgb_comparison, %s;\n", tmp4, fragcolor);
+    /* Store the components > 0.0031308 in the destination */
+    shader_addline(buffer, "MUL %s, %s, %s;\n", fragcolor, tmp1, tmp3);
+    /* Add the components that are < 0.0031308 */
+    shader_addline(buffer, "MAD result.color.xyz, %s, %s, %s;\n", tmp2, tmp4, fragcolor);
+    /* [0.0;1.0] clamping. Not needed, this is done implicitly */
+}
+
 static void shader_arb_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer) {
     IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
     shader_reg_maps* reg_maps = &This->baseShader.reg_maps;
@@ -2002,24 +2024,7 @@ static void shader_arb_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUFFE
         fragcolor = "TMP_COLOR";
     }
     if(This->srgb_enabled) {
-        /* Perform sRGB write correction. See GLX_EXT_framebuffer_sRGB */
-
-        /* Calculate the > 0.0031308 case */
-        shader_addline(buffer, "POW TMP.x, %s.x, srgb_pow.x;\n", fragcolor);
-        shader_addline(buffer, "POW TMP.y, %s.y, srgb_pow.y;\n", fragcolor);
-        shader_addline(buffer, "POW TMP.z, %s.z, srgb_pow.z;\n", fragcolor);
-        shader_addline(buffer, "MUL TMP, TMP, srgb_mul_hi;\n");
-        shader_addline(buffer, "SUB TMP, TMP, srgb_sub_hi;\n");
-        /* Calculate the < case */
-        shader_addline(buffer, "MUL TMP2, srgb_mul_low, %s;\n", fragcolor);
-        /* Get 1.0 / 0.0 masks for > 0.0031308 and < 0.0031308 */
-        shader_addline(buffer, "SLT TA, srgb_comparison, %s;\n", fragcolor);
-        shader_addline(buffer, "SGE TB, srgb_comparison, %s;\n", fragcolor);
-        /* Store the components > 0.0031308 in the destination */
-        shader_addline(buffer, "MUL %s, TMP, TA;\n", fragcolor);
-        /* Add the components that are < 0.0031308 */
-        shader_addline(buffer, "MAD result.color.xyz, TMP2, TB, %s;\n", fragcolor);
-        /* [0.0;1.0] clamping. Not needed, this is done implicitly */
+        arbfp_add_sRGB_correction(buffer, fragcolor, "TMP", "TMP2", "TA", "TB");
     }
     if (This->baseShader.hex_version < WINED3DPS_VERSION(3,0)) {
         shader_addline(buffer, "LRP result.color.rgb, TMP_FOG.x, %s, state.fog.color;\n", fragcolor);
@@ -2644,7 +2649,7 @@ static GLuint gen_arbfp_ffp_shader(struct ffp_settings *settings, IWineD3DStateB
 
     shader_addline(&buffer, "PARAM const = {1, 2, 4, 0.5};\n");
     shader_addline(&buffer, "TEMP ret;\n");
-    if(tempreg_used) shader_addline(&buffer, "TEMP tempreg;\n");
+    if(tempreg_used || settings->sRGB_write) shader_addline(&buffer, "TEMP tempreg;\n");
     shader_addline(&buffer, "TEMP arg0;\n");
     shader_addline(&buffer, "TEMP arg1;\n");
     shader_addline(&buffer, "TEMP arg2;\n");
@@ -2658,6 +2663,19 @@ static GLuint gen_arbfp_ffp_shader(struct ffp_settings *settings, IWineD3DStateB
         shader_addline(&buffer, "PARAM tfactor = program.env[%u];\n", ARB_FFP_CONST_TFACTOR);
     }
 
+    if(settings->sRGB_write) {
+        shader_addline(&buffer, "PARAM srgb_mul_low = {%f, %f, %f, 1.0};\n",
+                       srgb_mul_low, srgb_mul_low, srgb_mul_low);
+        shader_addline(&buffer, "PARAM srgb_comparison =  {%f, %f, %f, %f};\n",
+                       srgb_cmp, srgb_cmp, srgb_cmp, srgb_cmp);
+        shader_addline(&buffer, "PARAM srgb_pow =  {%f, %f, %f, 1.0};\n",
+                       srgb_pow, srgb_pow, srgb_pow);
+        shader_addline(&buffer, "PARAM srgb_mul_hi =  {%f, %f, %f, 1.0};\n",
+                       srgb_mul_high, srgb_mul_high, srgb_mul_high);
+        shader_addline(&buffer, "PARAM srgb_sub_hi =  {%f, %f, %f, 0.0};\n",
+                       srgb_sub_high, srgb_sub_high, srgb_sub_high);
+    }
+
     /* Generate texture sampling instructions) */
     for(stage = 0; stage < MAX_TEXTURES && settings->op[stage].cop != WINED3DTOP_DISABLE; stage++) {
         if(!tex_read[stage]) continue;
@@ -2714,6 +2732,8 @@ static GLuint gen_arbfp_ffp_shader(struct ffp_settings *settings, IWineD3DStateB
                 shader_addline(&buffer, "MOV result.color, fragment.color.primary;\n");
             }
             break;
+        } else if(settings->sRGB_write) {
+            last = FALSE;
         } else if(stage == (MAX_TEXTURES - 1)) {
             last = TRUE;
         } else if(settings->op[stage + 1].cop == WINED3DTOP_DISABLE) {
@@ -2748,7 +2768,10 @@ static GLuint gen_arbfp_ffp_shader(struct ffp_settings *settings, IWineD3DStateB
         }
     }
 
-    /* TODO: Generate sRGB write color correction */
+    if(settings->sRGB_write) {
+        arbfp_add_sRGB_correction(&buffer, "ret", "arg0", "arg1", "arg2", "tempreg");
+        shader_addline(&buffer, "MOV result.color.a, ret.a;\n");
+    }
 
     /* Footer */
     shader_addline(&buffer, "END\n");
@@ -2976,6 +2999,7 @@ static const struct StateEntryTemplate arbfp_fragmentstate_template[] = {
     { STATE_RENDER(WINED3DRS_FOGENABLE),                  { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_arbfp_fog         }, 0                               },
     { STATE_RENDER(WINED3DRS_FOGTABLEMODE),               { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_arbfp_fog         }, 0                               },
     { STATE_RENDER(WINED3DRS_FOGVERTEXMODE),              { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_arbfp_fog         }, 0                               },
+    { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE),            { STATE_PIXELSHADER,                                  fragment_prog_arbfp     }, 0                               },
     {0 /* Terminate */,                                   { 0,                                                  0                       }, 0                               },
 };
 
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 91c8c37..8501544 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -1976,6 +1976,11 @@ void gen_ffp_op(IWineD3DStateBlockImpl *stateblock, struct ffp_settings *setting
                 break;
         }
     }
+    if(stateblock->renderState[WINED3DRS_SRGBWRITEENABLE]) {
+        settings->sRGB_write = 1;
+    } else {
+        settings->sRGB_write = 0;
+    }
 }
 #undef GLINFO_LOCATION
 
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index e67ec38..c72afe6 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -785,6 +785,7 @@ struct ffp_settings {
         FOG_EXP,
         FOG_EXP2
     } fog;
+    unsigned char sRGB_write;
 };
 
 struct ffp_desc




More information about the wine-cvs mailing list