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
This commit is contained in:
Roland Scheidegger 2013-01-10 18:10:20 -08:00
parent 5785f22d23
commit babab28760
6 changed files with 90 additions and 32 deletions

View 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)

View 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 );
}

View 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;
for (i = 0; i < 4; ++i) {
clear_color[i] = float_to_ubyte(arg.clear_color[i]);
}
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++) {
const struct lp_scene *scene = task->scene;
if (scene->fb.nr_cbufs) {
unsigned i;
union util_color uc;
util_pack_color(arg.clear_color,
scene->fb.cbufs[i]->format, &uc);
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]);
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);
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);
}
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 < 4; ++i) {
clear_color[i] = float_to_ubyte(arg.clear_color.f[i]);
}
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);

View 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;

View 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 )

View 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);