[Mesa-dev] [PATCH] i965/meta-fast-clear: Convert the clear color through the surf format

Neil Roberts neil at linux.intel.com
Fri Dec 11 08:44:16 PST 2015


When programming the fast clear color there was previously a chunk of
code to try to make the color match the constraints of the surface
format such as by filling in missing components and handling luminance
formats. These cases are not handled by the hardware. There are some
additional possible restrictions that the hardware does seem to
handle, such as clamping to [0,1] for normalised formats. However for
whatever reason it doesn't clamp to [0,∞] for the special float
formats that don't have a sign bit. Rather than adding yet another
special case for this format this patch makes it instead convert the
color to the actual surface format and back again so that we can be
sure it will have all of the possible restrictions. Additionally this
would avoid some other potential surprises such as getting more
precision for the clear color when fast clears are used.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=93338
---
 src/mesa/drivers/dri/i965/brw_meta_fast_clear.c | 57 ++++++++++++-------------
 1 file changed, 27 insertions(+), 30 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_meta_fast_clear.c b/src/mesa/drivers/dri/i965/brw_meta_fast_clear.c
index cf0e56b..29ae6f0 100644
--- a/src/mesa/drivers/dri/i965/brw_meta_fast_clear.c
+++ b/src/mesa/drivers/dri/i965/brw_meta_fast_clear.c
@@ -37,6 +37,8 @@
 #include "main/uniforms.h"
 #include "main/fbobject.h"
 #include "main/texobj.h"
+#include "main/format_unpack.h"
+#include "main/format_pack.h"
 
 #include "main/api_validate.h"
 #include "main/state.h"
@@ -397,45 +399,40 @@ set_fast_clear_color(struct brw_context *brw,
                      struct intel_mipmap_tree *mt,
                      const union gl_color_union *color)
 {
+   mesa_format linear_format = _mesa_get_srgb_format_linear(mt->format);
    union gl_color_union override_color = *color;
-
-   /* The sampler doesn't look at the format of the surface when the fast
-    * clear color is used so we need to implement luminance, intensity and
-    * missing components manually.
-    */
-   switch (_mesa_get_format_base_format(mt->format)) {
-   case GL_INTENSITY:
-      override_color.ui[3] = override_color.ui[0];
-      /* flow through */
-   case GL_LUMINANCE:
-   case GL_LUMINANCE_ALPHA:
-      override_color.ui[1] = override_color.ui[0];
-      override_color.ui[2] = override_color.ui[0];
-      break;
-   default:
-      for (int i = 0; i < 3; i++) {
-         if (!_mesa_format_has_color_component(mt->format, i))
-            override_color.ui[i] = 0;
-      }
-      break;
-   }
-
-   if (!_mesa_format_has_color_component(mt->format, 3)) {
-      if (_mesa_is_format_integer_color(mt->format))
-         override_color.ui[3] = 1;
-      else
-         override_color.f[3] = 1.0f;
-   }
+   union gl_color_union tmp_color;
 
    /* Handle linear→SRGB conversion */
-   if (brw->ctx.Color.sRGBEnabled &&
-       _mesa_get_srgb_format_linear(mt->format) != mt->format) {
+   if (brw->ctx.Color.sRGBEnabled && linear_format != mt->format) {
       for (int i = 0; i < 3; i++) {
          override_color.f[i] =
             util_format_linear_to_srgb_float(override_color.f[i]);
       }
    }
 
+   /* Convert the clear color to the surface format and back so that the color
+    * returned when sampling is guaranteed to be a value that could be stored
+    * in the surface. For example if the surface is a luminance format and we
+    * clear to 0.5,0.75,0.1,0.2 we want the color to come back as
+    * 0.5,0.5,0.5,1.0. In general the hardware doesn't seem to look at the
+    * surface format when returning the clear color so we need to do this to
+    * implement luminance, intensity and missing components. However it does
+    * seem to look at it in some cases such as to clamp to the range [0,1] for
+    * unorm formats. Suprisingly however it doesn't clamp to [0,∞] for the
+    * special float formats that don't have a sign bit.
+    */
+   if (!_mesa_is_format_integer_color(linear_format)) {
+      _mesa_pack_float_rgba_row(linear_format,
+                                1, /* n_pixels */
+                                (const GLfloat (*)[4]) override_color.f,
+                                &tmp_color);
+      _mesa_unpack_rgba_row(linear_format,
+                            1, /* n_pixels */
+                            &tmp_color,
+                            (GLfloat (*)[4]) override_color.f);
+   }
+
    if (brw->gen >= 9) {
       mt->gen9_fast_clear_color = override_color;
    } else {
-- 
1.9.3



More information about the mesa-dev mailing list