Mesa (master): i965: Use the surface format table to determine render target supportedness.

Eric Anholt anholt at kemper.freedesktop.org
Tue Nov 22 22:09:46 UTC 2011


Module: Mesa
Branch: master
Commit: ca10b2d4494798405a5fd654201291944645af5d
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=ca10b2d4494798405a5fd654201291944645af5d

Author: Eric Anholt <eric at anholt.net>
Date:   Tue Nov 15 11:44:52 2011 -0800

i965: Use the surface format table to determine render target supportedness.

This moves any chipset-dependent logic we want for render target
format choices to init time as well.  There is still logic left at
state update for SRGB handling, where format choices change based on
GL state.

The brw_render_target_supported() function should now return correct
results, instead of relying on the limited results from
intel_span_supports_format() to avoid lying about FBO completeness.

Reviewed-by: Kenneth Graunke <kenneth at whitecape.org>

---

 src/mesa/drivers/dri/i965/brw_context.c           |    2 +
 src/mesa/drivers/dri/i965/brw_context.h           |    6 +
 src/mesa/drivers/dri/i965/brw_wm_surface_state.c  |  122 ++++++++++++++-------
 src/mesa/drivers/dri/i965/gen7_wm_surface_state.c |   25 +---
 4 files changed, 95 insertions(+), 60 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
index 531ce5b..5dcf8dd 100644
--- a/src/mesa/drivers/dri/i965/brw_context.c
+++ b/src/mesa/drivers/dri/i965/brw_context.c
@@ -147,6 +147,8 @@ brwCreateContext(int api,
 
    brwInitVtbl( brw );
 
+   brw_init_surface_formats(brw);
+
    /* Initialize swrast, tnl driver tables: */
    intelInitSpanFuncs(ctx);
 
diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
index ec05fb7..c1b123f 100644
--- a/src/mesa/drivers/dri/i965/brw_context.h
+++ b/src/mesa/drivers/dri/i965/brw_context.h
@@ -936,6 +936,9 @@ struct brw_context
       GLuint fbo;
       struct gl_renderbuffer *depth_rb;
    } hiz;
+
+   uint32_t render_target_format[MESA_FORMAT_COUNT];
+   bool format_supported_as_render_target[MESA_FORMAT_COUNT];
 };
 
 
@@ -1015,6 +1018,9 @@ unsigned
 brw_compute_barycentric_interp_modes(bool shade_model_flat,
                                      const struct gl_fragment_program *fprog);
 
+/* brw_wm_surface_state.c */
+void brw_init_surface_formats(struct brw_context *brw);
+
 /* gen6_clip_state.c */
 bool
 brw_fprog_uses_noperspective(const struct gl_fragment_program *fprog);
diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
index 828d609..04c619c 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -360,35 +360,90 @@ brw_format_for_mesa_format(gl_format mesa_format)
    return table[mesa_format];
 }
 
-bool
-brw_render_target_supported(struct intel_context *intel, gl_format format)
+void
+brw_init_surface_formats(struct brw_context *brw)
 {
-   /* These are not color render targets like the table holds, but we
-    * ask the question for FBO completeness.
-    */
-   if (format == MESA_FORMAT_S8_Z24 ||
-       format == MESA_FORMAT_X8_Z24 ||
-       format == MESA_FORMAT_S8 ||
-       format == MESA_FORMAT_Z16) {
-      return true;
-   }
+   struct intel_context *intel = &brw->intel;
+   int gen;
+   gl_format format;
 
-   /* The value of this BRW_SURFACEFORMAT is 0, so hardcode it.
-    */
-   if (format == MESA_FORMAT_RGBA_FLOAT32)
-      return true;
+   gen = intel->gen * 10;
+   if (intel->is_g4x)
+      gen += 5;
+
+   for (format = MESA_FORMAT_NONE + 1; format < MESA_FORMAT_COUNT; format++) {
+      uint32_t texture, render;
+      const struct surface_format_info *rinfo;
+      bool is_integer = _mesa_is_format_integer_color(format);
+
+      render = texture = brw_format_for_mesa_format(format);
+
+      /* The value of BRW_SURFACEFORMAT_R32G32B32A32_FLOAT is 0, so don't skip
+       * it.
+       */
+      if (texture == 0 && format != MESA_FORMAT_RGBA_FLOAT32)
+	 continue;
+
+      /* Re-map some render target formats to make them supported when they
+       * wouldn't be using their format for texturing.
+       */
+      switch (render) {
+	 /* For these formats, we just need to read/write the first
+	  * channel into R, which is to say that we just treat them as
+	  * GL_RED.
+	  */
+      case BRW_SURFACEFORMAT_I32_FLOAT:
+      case BRW_SURFACEFORMAT_L32_FLOAT:
+	 render = BRW_SURFACEFORMAT_R32_FLOAT;
+	 break;
+      case BRW_SURFACEFORMAT_B8G8R8X8_UNORM:
+	 /* XRGB is handled as ARGB because the chips in this family
+	  * cannot render to XRGB targets.  This means that we have to
+	  * mask writes to alpha (ala glColorMask) and reconfigure the
+	  * alpha blending hardware to use GL_ONE (or GL_ZERO) for
+	  * cases where GL_DST_ALPHA (or GL_ONE_MINUS_DST_ALPHA) is
+	  * used.
+	  */
+	 render = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
+	 break;
+      }
 
-   /* While we can texture from these formats, they're not actually supported
-    * for rendering.
+      rinfo = &surface_formats[render];
+
+      /* Note that GL_EXT_texture_integer says that blending doesn't occur for
+       * integer, so we don't need hardware support for blending on it.  Other
+       * than that, GL in general requires alpha blending for render targets,
+       * even though we don't support it for some formats.
+       *
+       * We don't currently support rendering to SNORM textures because some of
+       * the ARB_color_buffer_float clamping is broken for it
+       * (piglit arb_color_buffer_float-drawpixels GL_RGBA8_SNORM).
+       */
+      if (gen >= rinfo->render_target &&
+	  (gen >= rinfo->alpha_blend || is_integer) &&
+	  _mesa_get_format_datatype(format) != GL_SIGNED_NORMALIZED) {
+	 brw->render_target_format[format] = render;
+	 brw->format_supported_as_render_target[format] = true;
+      }
+   }
+
+   /* We will check this table for FBO completeness, but the surface format
+    * table above only covered color rendering.
     */
-   if (format == MESA_FORMAT_RGB_UINT32 ||
-       format == MESA_FORMAT_RGB_INT32)
-      return false;
+   brw->format_supported_as_render_target[MESA_FORMAT_S8_Z24] = true;
+   brw->format_supported_as_render_target[MESA_FORMAT_X8_Z24] = true;
+   brw->format_supported_as_render_target[MESA_FORMAT_S8] = true;
+   brw->format_supported_as_render_target[MESA_FORMAT_Z16] = true;
+}
 
+bool
+brw_render_target_supported(struct intel_context *intel, gl_format format)
+{
+   struct brw_context *brw = brw_context(&intel->ctx);
    /* Not exactly true, as some of those formats are not renderable.
     * But at least we know how to translate them.
     */
-   return brw_format_for_mesa_format(format) != 0;
+   return brw->format_supported_as_render_target[format];
 }
 
 GLuint
@@ -663,24 +718,6 @@ brw_update_renderbuffer_surface(struct brw_context *brw,
 			  6 * 4, 32, &brw->bind.surf_offset[unit]);
 
    switch (irb->Base.Format) {
-   case MESA_FORMAT_XRGB8888:
-      /* XRGB is handled as ARGB because the chips in this family
-       * cannot render to XRGB targets.  This means that we have to
-       * mask writes to alpha (ala glColorMask) and reconfigure the
-       * alpha blending hardware to use GL_ONE (or GL_ZERO) for
-       * cases where GL_DST_ALPHA (or GL_ONE_MINUS_DST_ALPHA) is
-       * used.
-       */
-      format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
-      break;
-   case MESA_FORMAT_INTENSITY_FLOAT32:
-   case MESA_FORMAT_LUMINANCE_FLOAT32:
-      /* For these formats, we just need to read/write the first
-       * channel into R, which is to say that we just treat them as
-       * GL_RED.
-       */
-      format = BRW_SURFACEFORMAT_R32_FLOAT;
-      break;
    case MESA_FORMAT_SARGB8:
       /* without GL_EXT_framebuffer_sRGB we shouldn't bind sRGB
 	 surfaces to the blend/update as sRGB */
@@ -690,8 +727,11 @@ brw_update_renderbuffer_surface(struct brw_context *brw,
 	 format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
       break;
    default:
-      assert(brw_render_target_supported(intel, irb->Base.Format));
-      format = brw_format_for_mesa_format(irb->Base.Format);
+      format = brw->render_target_format[irb->Base.Format];
+      if (unlikely(!brw->format_supported_as_render_target[irb->Base.Format])) {
+	 _mesa_problem(ctx, "%s: renderbuffer format %s unsupported\n",
+		       __FUNCTION__, _mesa_get_format_name(irb->Base.Format));
+      }
       break;
    }
 
diff --git a/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c b/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c
index 7084bdc..ec72c1e 100644
--- a/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c
@@ -201,24 +201,6 @@ gen7_update_renderbuffer_surface(struct brw_context *brw,
    memset(surf, 0, sizeof(*surf));
 
    switch (irb->Base.Format) {
-   case MESA_FORMAT_XRGB8888:
-      /* XRGB is handled as ARGB because the chips in this family
-       * cannot render to XRGB targets.  This means that we have to
-       * mask writes to alpha (ala glColorMask) and reconfigure the
-       * alpha blending hardware to use GL_ONE (or GL_ZERO) for
-       * cases where GL_DST_ALPHA (or GL_ONE_MINUS_DST_ALPHA) is
-       * used.
-       */
-      surf->ss0.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
-      break;
-   case MESA_FORMAT_INTENSITY_FLOAT32:
-   case MESA_FORMAT_LUMINANCE_FLOAT32:
-      /* For these formats, we just need to read/write the first
-       * channel into R, which is to say that we just treat them as
-       * GL_RED.
-       */
-      surf->ss0.surface_format = BRW_SURFACEFORMAT_R32_FLOAT;
-      break;
    case MESA_FORMAT_SARGB8:
       /* without GL_EXT_framebuffer_sRGB we shouldn't bind sRGB
 	 surfaces to the blend/update as sRGB */
@@ -229,7 +211,12 @@ gen7_update_renderbuffer_surface(struct brw_context *brw,
       break;
    default:
       assert(brw_render_target_supported(intel, irb->Base.Format));
-      surf->ss0.surface_format = brw_format_for_mesa_format(irb->Base.Format);
+      surf->ss0.surface_format = brw->render_target_format[irb->Base.Format];
+      if (unlikely(!brw->format_supported_as_render_target[irb->Base.Format])) {
+	 _mesa_problem(ctx, "%s: renderbuffer format %s unsupported\n",
+		       __FUNCTION__, _mesa_get_format_name(irb->Base.Format));
+      }
+       break;
    }
 
    surf->ss0.surface_type = BRW_SURFACE_2D;




More information about the mesa-commit mailing list