From babab2876080af0fe65249dff559244aebd0b87e Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Thu, 10 Jan 2013 18:10:20 -0800 Subject: [PATCH] llvmpipe: fix clearing integer color buffers 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 | 2 + src/gallium/drivers/llvmpipe/lp_clear.c | 2 +- src/gallium/drivers/llvmpipe/lp_rast.c | 104 +++++++++++++++++----- src/gallium/drivers/llvmpipe/lp_rast.h | 2 +- src/gallium/drivers/llvmpipe/lp_setup.c | 8 +- src/gallium/drivers/llvmpipe/lp_setup.h | 2 +- 6 files changed, 89 insertions(+), 31 deletions(-) diff --git a/src/gallium/auxiliary/util/u_pack_color.h b/src/gallium/auxiliary/util/u_pack_color.h index 50ec226d887..6c6d9669cbd 100644 --- a/src/gallium/auxiliary/util/u_pack_color.h +++ b/src/gallium/auxiliary/util/u_pack_color.h @@ -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) diff --git a/src/gallium/drivers/llvmpipe/lp_clear.c b/src/gallium/drivers/llvmpipe/lp_clear.c index cc90dc42c65..b00910a4711 100644 --- a/src/gallium/drivers/llvmpipe/lp_clear.c +++ b/src/gallium/drivers/llvmpipe/lp_clear.c @@ -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 ); } diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c index 44e8324b2b1..2daf2fefa26 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.c +++ b/src/gallium/drivers/llvmpipe/lp_rast.c @@ -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); diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h index 315601e1b6a..2f5fa227619 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.h +++ b/src/gallium/drivers/llvmpipe/lp_rast.h @@ -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; diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index 5aba7a25342..ffa0fe6eaa3 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -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 ) diff --git a/src/gallium/drivers/llvmpipe/lp_setup.h b/src/gallium/drivers/llvmpipe/lp_setup.h index 55b710dd2b4..de29601329f 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.h +++ b/src/gallium/drivers/llvmpipe/lp_setup.h @@ -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); -- 2.30.2