llvmpipe: fix clearing integer color buffers
authorRoland Scheidegger <sroland@vmware.com>
Fri, 11 Jan 2013 02:10:20 +0000 (18:10 -0800)
committerRoland Scheidegger <sroland@vmware.com>
Fri, 11 Jan 2013 02:10:20 +0000 (18:10 -0800)
We get int/uint clear color value in this case, and util_pack_color can't
handle these formats at all (even if it could, float input color isn't what
we want).
Pass through the color union appropriately and handle the packing ourselves
(as I couldn't think of a good generic util solution).
This gets piglit fbo_integer_precision_clear and
fbo_integer_readpixels_sint_uint from the ext_texture_integer test group from
segfault to pass (which only leaves fbo-blending from that group not working).

v2: fix up comments

src/gallium/auxiliary/util/u_pack_color.h
src/gallium/drivers/llvmpipe/lp_clear.c
src/gallium/drivers/llvmpipe/lp_rast.c
src/gallium/drivers/llvmpipe/lp_rast.h
src/gallium/drivers/llvmpipe/lp_setup.c
src/gallium/drivers/llvmpipe/lp_setup.h

index 50ec226d88783e8781cee2e3953482ca8e135e01..6c6d9669cbd661f20fa06b43d42b9dbb2c203d59 100644 (file)
@@ -329,6 +329,8 @@ util_unpack_color_ub(enum pipe_format format, union util_color *uc,
 
 /**
  * Note rgba outside [0,1] will be clamped for int pixel formats.
+ * This will not work (and might not really be useful with float input)
+ * for pure integer formats (which lack the pack_rgba_float function).
  */
 static INLINE void
 util_pack_color(const float rgba[4], enum pipe_format format, union util_color *uc)
index cc90dc42c659fa980d8c8be8d1ce85596507a015..b00910a4711324936d2f9c9c9ffa02bc7167f258 100644 (file)
@@ -59,5 +59,5 @@ llvmpipe_clear(struct pipe_context *pipe,
    if (LP_PERF & PERF_NO_DEPTH)
       buffers &= ~PIPE_CLEAR_DEPTHSTENCIL;
 
-   lp_setup_clear( llvmpipe->setup, color->f, depth, stencil, buffers );
+   lp_setup_clear( llvmpipe->setup, color, depth, stencil, buffers );
 }
index 44e8324b2b148c783ffe6fba546852c135cc14d5..2daf2fefa2645124614c69de7dcdf8291fa7a430 100644 (file)
@@ -146,35 +146,91 @@ lp_rast_clear_color(struct lp_rasterizer_task *task,
                     const union lp_rast_cmd_arg arg)
 {
    const struct lp_scene *scene = task->scene;
-   uint8_t clear_color[4];
 
-   unsigned i;
+   if (scene->fb.nr_cbufs) {
+      unsigned i;
+      union util_color uc;
 
-   for (i = 0; i < 4; ++i) {
-      clear_color[i] = float_to_ubyte(arg.clear_color[i]);
-   }
+      if (util_format_is_pure_integer(scene->fb.cbufs[0]->format)) {
+         /*
+          * We expect int/uint clear values here, though some APIs
+          * might disagree (but in any case util_pack_color()
+          * couldn't handle it)...
+          */
+         LP_DBG(DEBUG_RAST, "%s pure int 0x%x,0x%x,0x%x,0x%x\n", __FUNCTION__,
+                    arg.clear_color.ui[0],
+                    arg.clear_color.ui[1],
+                    arg.clear_color.ui[2],
+                    arg.clear_color.ui[3]);
+
+         for (i = 0; i < scene->fb.nr_cbufs; i++) {
+            enum pipe_format format = scene->fb.cbufs[i]->format;
+            /*
+             * XXX the format_write_4i/ui functions do clamping to max value
+             * and I'm not sure that's actually right - spec doesn't seem to
+             * say much about that topic. If it is should probably adjust the
+             * border color handling to do the same. If not and chopping off
+             * bits is the way to go, the write_4i and write_4ui functions
+             * would be identical.
+             */
+            if (util_format_is_pure_sint(format)) {
+               int rgba[4];
+               rgba[0] = arg.clear_color.i[0];
+               rgba[1] = arg.clear_color.i[1];
+               rgba[2] = arg.clear_color.i[2];
+               rgba[3] = arg.clear_color.i[3];
+
+               util_format_write_4i(format, rgba, 0, &uc, 0, 0, 0, 1, 1);
+            }
+            else {
+               unsigned rgba[4];
+               rgba[0] = arg.clear_color.ui[0];
+               rgba[1] = arg.clear_color.ui[1];
+               rgba[2] = arg.clear_color.ui[2];
+               rgba[3] = arg.clear_color.ui[3];
+
+               assert(util_format_is_pure_uint(format));
+               util_format_write_4ui(format, rgba, 0, &uc, 0, 0, 0, 1, 1);
+            }
 
-   LP_DBG(DEBUG_RAST, "%s 0x%x,0x%x,0x%x,0x%x\n", __FUNCTION__,
-              clear_color[0],
-              clear_color[1],
-              clear_color[2],
-              clear_color[3]);
+            util_fill_rect(scene->cbufs[i].map,
+                           scene->fb.cbufs[i]->format,
+                           scene->cbufs[i].stride,
+                           task->x,
+                           task->y,
+                           TILE_SIZE,
+                           TILE_SIZE,
+                           &uc);
+         }
+      }
+      else {
+         uint8_t clear_color[4];
 
-   for (i = 0; i < scene->fb.nr_cbufs; i++) {
-      const struct lp_scene *scene = task->scene;
-      union util_color uc;
+         for (i = 0; i < 4; ++i) {
+            clear_color[i] = float_to_ubyte(arg.clear_color.f[i]);
+         }
 
-      util_pack_color(arg.clear_color,
-                      scene->fb.cbufs[i]->format, &uc);
-
-      util_fill_rect(scene->cbufs[i].map,
-                     scene->fb.cbufs[i]->format,
-                     scene->cbufs[i].stride,
-                     task->x,
-                     task->y,
-                     TILE_SIZE,
-                     TILE_SIZE,
-                     &uc);
+         LP_DBG(DEBUG_RAST, "%s 0x%x,0x%x,0x%x,0x%x\n", __FUNCTION__,
+                    clear_color[0],
+                    clear_color[1],
+                    clear_color[2],
+                    clear_color[3]);
+
+         for (i = 0; i < scene->fb.nr_cbufs; i++) {
+
+            util_pack_color(arg.clear_color.f,
+                            scene->fb.cbufs[i]->format, &uc);
+
+            util_fill_rect(scene->cbufs[i].map,
+                           scene->fb.cbufs[i]->format,
+                           scene->cbufs[i].stride,
+                           task->x,
+                           task->y,
+                           TILE_SIZE,
+                           TILE_SIZE,
+                           &uc);
+         }
+      }
    }
 
    LP_COUNT(nr_color_tile_clear);
index 315601e1b6a97668c74209fd56828f0d93b714f3..2f5fa2276191067690ba680740971f1766649629 100644 (file)
@@ -152,7 +152,7 @@ union lp_rast_cmd_arg {
       unsigned plane_mask;
    } triangle;
    const struct lp_rast_state *set_state;
-   float clear_color[4];
+   union pipe_color_union clear_color;
    struct {
       uint32_t value;
       uint32_t mask;
index 5aba7a2534298994624b93379868de2c9e1f205e..ffa0fe6eaa34e7613b2d1c0f771b2f9661124404 100644 (file)
@@ -385,7 +385,7 @@ lp_setup_bind_framebuffer( struct lp_setup_context *setup,
 
 static boolean
 lp_setup_try_clear( struct lp_setup_context *setup,
-                    const float *color,
+                    const union pipe_color_union *color,
                     double depth,
                     unsigned stencil,
                     unsigned flags )
@@ -399,7 +399,7 @@ lp_setup_try_clear( struct lp_setup_context *setup,
 
    if (flags & PIPE_CLEAR_COLOR) {
       for (i = 0; i < 4; i++)
-         color_arg.clear_color[i] = color[i];
+         color_arg.clear_color.i[i] = color->i[i];
    }
 
    if (flags & PIPE_CLEAR_DEPTHSTENCIL) {
@@ -458,7 +458,7 @@ lp_setup_try_clear( struct lp_setup_context *setup,
       }
 
       if (flags & PIPE_CLEAR_COLOR) {
-         memcpy(setup->clear.color.clear_color,
+         memcpy(&setup->clear.color.clear_color,
                 &color_arg,
                 sizeof setup->clear.color.clear_color);
       }
@@ -469,7 +469,7 @@ lp_setup_try_clear( struct lp_setup_context *setup,
 
 void
 lp_setup_clear( struct lp_setup_context *setup,
-                const float *color,
+                const union pipe_color_union *color,
                 double depth,
                 unsigned stencil,
                 unsigned flags )
index 55b710dd2b4fd421aa05a60f66d54a82168c6103..de29601329fe80c2d777e034eaae0c8e37032115 100644 (file)
@@ -55,7 +55,7 @@ lp_setup_create( struct pipe_context *pipe,
 
 void
 lp_setup_clear(struct lp_setup_context *setup,
-               const float *clear_color,
+               const union pipe_color_union *clear_color,
                double clear_depth,
                unsigned clear_stencil,
                unsigned flags);