llvmpipe: handle NULL color buffer pointers

Fixes regression from 9baa45f78b

v2: incorporate a few small changes suggested by Roland.

Reviewed-by: José Fonseca <jfonseca@vmware.com>
Reviewed-by: Roland Scheidegger <sroland@vmware.com>
This commit is contained in:
Brian Paul 2014-01-15 18:09:56 -08:00
parent 7b4ceec0b7
commit d6fa71fbb0
5 changed files with 158 additions and 96 deletions

View file

@ -109,6 +109,25 @@ lp_rast_tile_begin(struct lp_rasterizer_task *task,
} }
/**
* Examine a framebuffer object to determine if any of the colorbuffers
* use a pure integer format.
* XXX this could be a gallium utility function if useful elsewhere.
*/
static boolean
is_fb_pure_integer(const struct pipe_framebuffer_state *fb)
{
unsigned i;
for (i = 0; i < fb->nr_cbufs; i++) {
if (fb->cbufs[i] &&
util_format_is_pure_integer(fb->cbufs[i]->format)) {
return TRUE;
}
}
return FALSE;
}
/** /**
* Clear the rasterizer's current color tile. * Clear the rasterizer's current color tile.
* This is a bin command called during bin processing. * This is a bin command called during bin processing.
@ -124,7 +143,7 @@ lp_rast_clear_color(struct lp_rasterizer_task *task,
unsigned i; unsigned i;
union util_color uc; union util_color uc;
if (util_format_is_pure_integer(scene->fb.cbufs[0]->format)) { if (is_fb_pure_integer(&scene->fb)) {
/* /*
* We expect int/uint clear values here, though some APIs * We expect int/uint clear values here, though some APIs
* might disagree (but in any case util_pack_color() * might disagree (but in any case util_pack_color()
@ -174,20 +193,22 @@ lp_rast_clear_color(struct lp_rasterizer_task *task,
clear_color[3]); clear_color[3]);
for (i = 0; i < scene->fb.nr_cbufs; i++) { for (i = 0; i < scene->fb.nr_cbufs; i++) {
util_pack_color(arg.clear_color.f, if (scene->fb.cbufs[i]) {
scene->fb.cbufs[i]->format, &uc); util_pack_color(arg.clear_color.f,
scene->fb.cbufs[i]->format, &uc);
util_fill_box(scene->cbufs[i].map, util_fill_box(scene->cbufs[i].map,
scene->fb.cbufs[i]->format, scene->fb.cbufs[i]->format,
scene->cbufs[i].stride, scene->cbufs[i].stride,
scene->cbufs[i].layer_stride, scene->cbufs[i].layer_stride,
task->x, task->x,
task->y, task->y,
0, 0,
task->width, task->width,
task->height, task->height,
scene->fb_max_layer + 1, scene->fb_max_layer + 1,
&uc); &uc);
}
} }
} }
} }
@ -444,8 +465,15 @@ lp_rast_shade_quads_mask(struct lp_rasterizer_task *task,
/* color buffer */ /* color buffer */
for (i = 0; i < scene->fb.nr_cbufs; i++) { for (i = 0; i < scene->fb.nr_cbufs; i++) {
stride[i] = scene->cbufs[i].stride; if (scene->fb.cbufs[i]) {
color[i] = lp_rast_get_unswizzled_color_block_pointer(task, i, x, y, inputs->layer); stride[i] = scene->cbufs[i].stride;
color[i] = lp_rast_get_unswizzled_color_block_pointer(task, i, x, y,
inputs->layer);
}
else {
stride[i] = 0;
color[i] = NULL;
}
} }
/* depth buffer */ /* depth buffer */

View file

@ -293,8 +293,15 @@ lp_rast_shade_quads_all( struct lp_rasterizer_task *task,
/* color buffer */ /* color buffer */
for (i = 0; i < scene->fb.nr_cbufs; i++) { for (i = 0; i < scene->fb.nr_cbufs; i++) {
stride[i] = scene->cbufs[i].stride; if (scene->fb.cbufs[i]) {
color[i] = lp_rast_get_unswizzled_color_block_pointer(task, i, x, y, inputs->layer); stride[i] = scene->cbufs[i].stride;
color[i] = lp_rast_get_unswizzled_color_block_pointer(task, i, x, y,
inputs->layer);
}
else {
stride[i] = 0;
color[i] = NULL;
}
} }
if (scene->zsbuf.map) { if (scene->zsbuf.map) {

View file

@ -156,6 +156,14 @@ lp_scene_begin_rasterization(struct lp_scene *scene)
for (i = 0; i < scene->fb.nr_cbufs; i++) { for (i = 0; i < scene->fb.nr_cbufs; i++) {
struct pipe_surface *cbuf = scene->fb.cbufs[i]; struct pipe_surface *cbuf = scene->fb.cbufs[i];
if (!cbuf) {
scene->cbufs[i].stride = 0;
scene->cbufs[i].layer_stride = 0;
scene->cbufs[i].map = NULL;
continue;
}
if (llvmpipe_resource_is_texture(cbuf->texture)) { if (llvmpipe_resource_is_texture(cbuf->texture)) {
scene->cbufs[i].stride = llvmpipe_resource_stride(cbuf->texture, scene->cbufs[i].stride = llvmpipe_resource_stride(cbuf->texture,
cbuf->u.tex.level); cbuf->u.tex.level);
@ -171,7 +179,7 @@ lp_scene_begin_rasterization(struct lp_scene *scene)
struct llvmpipe_resource *lpr = llvmpipe_resource(cbuf->texture); struct llvmpipe_resource *lpr = llvmpipe_resource(cbuf->texture);
unsigned pixstride = util_format_get_blocksize(cbuf->format); unsigned pixstride = util_format_get_blocksize(cbuf->format);
scene->cbufs[i].stride = cbuf->texture->width0; scene->cbufs[i].stride = cbuf->texture->width0;
scene->cbufs[i].layer_stride = 0;
scene->cbufs[i].map = lpr->data; scene->cbufs[i].map = lpr->data;
scene->cbufs[i].map += cbuf->u.buf.first_element * pixstride; scene->cbufs[i].map += cbuf->u.buf.first_element * pixstride;
} }
@ -521,11 +529,14 @@ void lp_scene_begin_binning( struct lp_scene *scene,
*/ */
for (i = 0; i < scene->fb.nr_cbufs; i++) { for (i = 0; i < scene->fb.nr_cbufs; i++) {
struct pipe_surface *cbuf = scene->fb.cbufs[i]; struct pipe_surface *cbuf = scene->fb.cbufs[i];
if (llvmpipe_resource_is_texture(cbuf->texture)) { if (cbuf) {
max_layer = MIN2(max_layer, cbuf->u.tex.last_layer - cbuf->u.tex.first_layer); if (llvmpipe_resource_is_texture(cbuf->texture)) {
} max_layer = MIN2(max_layer,
else { cbuf->u.tex.last_layer - cbuf->u.tex.first_layer);
max_layer = 0; }
else {
max_layer = 0;
}
} }
} }
if (fb->zsbuf) { if (fb->zsbuf) {

View file

@ -882,7 +882,7 @@ lp_setup_is_resource_referenced( const struct lp_setup_context *setup,
/* check the render targets */ /* check the render targets */
for (i = 0; i < setup->fb.nr_cbufs; i++) { for (i = 0; i < setup->fb.nr_cbufs; i++) {
if (setup->fb.cbufs[i]->texture == texture) if (setup->fb.cbufs[i] && setup->fb.cbufs[i]->texture == texture)
return LP_REFERENCED_FOR_READ | LP_REFERENCED_FOR_WRITE; return LP_REFERENCED_FOR_READ | LP_REFERENCED_FOR_WRITE;
} }
if (setup->fb.zsbuf && setup->fb.zsbuf->texture == texture) { if (setup->fb.zsbuf && setup->fb.zsbuf->texture == texture) {

View file

@ -2362,28 +2362,33 @@ generate_fragment(struct llvmpipe_context *lp,
/* Loop over color outputs / color buffers to do blending. /* Loop over color outputs / color buffers to do blending.
*/ */
for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++) { for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++) {
LLVMValueRef color_ptr; if (key->cbuf_format[cbuf] != PIPE_FORMAT_NONE) {
LLVMValueRef stride; LLVMValueRef color_ptr;
LLVMValueRef index = lp_build_const_int32(gallivm, cbuf); LLVMValueRef stride;
LLVMValueRef index = lp_build_const_int32(gallivm, cbuf);
boolean do_branch = ((key->depth.enabled boolean do_branch = ((key->depth.enabled
|| key->stencil[0].enabled || key->stencil[0].enabled
|| key->alpha.enabled) || key->alpha.enabled)
&& !shader->info.base.uses_kill); && !shader->info.base.uses_kill);
color_ptr = LLVMBuildLoad(builder, color_ptr = LLVMBuildLoad(builder,
LLVMBuildGEP(builder, color_ptr_ptr, &index, 1, ""), LLVMBuildGEP(builder, color_ptr_ptr,
&index, 1, ""),
"");
lp_build_name(color_ptr, "color_ptr%d", cbuf);
stride = LLVMBuildLoad(builder,
LLVMBuildGEP(builder, stride_ptr, &index, 1, ""),
""); "");
lp_build_name(color_ptr, "color_ptr%d", cbuf); generate_unswizzled_blend(gallivm, cbuf, variant,
key->cbuf_format[cbuf],
stride = LLVMBuildLoad(builder, num_fs, fs_type, fs_mask, fs_out_color,
LLVMBuildGEP(builder, stride_ptr, &index, 1, ""), context_ptr, color_ptr, stride,
""); partial_mask, do_branch);
}
generate_unswizzled_blend(gallivm, cbuf, variant, key->cbuf_format[cbuf],
num_fs, fs_type, fs_mask, fs_out_color,
context_ptr, color_ptr, stride, partial_mask, do_branch);
} }
LLVMBuildRetVoid(builder); LLVMBuildRetVoid(builder);
@ -2901,6 +2906,7 @@ make_variant_key(struct llvmpipe_context *lp,
/* alpha test only applies if render buffer 0 is non-integer (or does not exist) */ /* alpha test only applies if render buffer 0 is non-integer (or does not exist) */
if (!lp->framebuffer.nr_cbufs || if (!lp->framebuffer.nr_cbufs ||
!lp->framebuffer.cbufs[0] ||
!util_format_is_pure_integer(lp->framebuffer.cbufs[0]->format)) { !util_format_is_pure_integer(lp->framebuffer.cbufs[0]->format)) {
key->alpha.enabled = lp->depth_stencil->alpha.enabled; key->alpha.enabled = lp->depth_stencil->alpha.enabled;
} }
@ -2928,65 +2934,75 @@ make_variant_key(struct llvmpipe_context *lp,
} }
for (i = 0; i < lp->framebuffer.nr_cbufs; i++) { for (i = 0; i < lp->framebuffer.nr_cbufs; i++) {
enum pipe_format format = lp->framebuffer.cbufs[i]->format;
struct pipe_rt_blend_state *blend_rt = &key->blend.rt[i]; struct pipe_rt_blend_state *blend_rt = &key->blend.rt[i];
const struct util_format_description *format_desc;
key->cbuf_format[i] = format; if (lp->framebuffer.cbufs[i]) {
enum pipe_format format = lp->framebuffer.cbufs[i]->format;
const struct util_format_description *format_desc;
/* key->cbuf_format[i] = format;
* Figure out if this is a 1d resource. Note that OpenGL allows crazy
* mixing of 2d textures with height 1 and 1d textures, so make sure /*
* we pick 1d if any cbuf or zsbuf is 1d. * Figure out if this is a 1d resource. Note that OpenGL allows crazy
*/ * mixing of 2d textures with height 1 and 1d textures, so make sure
if (llvmpipe_resource_is_1d(lp->framebuffer.cbufs[0]->texture)) { * we pick 1d if any cbuf or zsbuf is 1d.
key->resource_1d = TRUE; */
if (llvmpipe_resource_is_1d(lp->framebuffer.cbufs[i]->texture)) {
key->resource_1d = TRUE;
}
format_desc = util_format_description(format);
assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB);
/*
* Mask out color channels not present in the color buffer.
*/
blend_rt->colormask &= util_format_colormask(format_desc);
/*
* Disable blend for integer formats.
*/
if (util_format_is_pure_integer(format)) {
blend_rt->blend_enable = 0;
}
/*
* Our swizzled render tiles always have an alpha channel, but the
* linear render target format often does not, so force here the dst
* alpha to be one.
*
* This is not a mere optimization. Wrong results will be produced if
* the dst alpha is used, the dst format does not have alpha, and the
* previous rendering was not flushed from the swizzled to linear
* buffer. For example, NonPowTwo DCT.
*
* TODO: This should be generalized to all channels for better
* performance, but only alpha causes correctness issues.
*
* Also, force rgb/alpha func/factors match, to make AoS blending
* easier.
*/
if (format_desc->swizzle[3] > UTIL_FORMAT_SWIZZLE_W ||
format_desc->swizzle[3] == format_desc->swizzle[0]) {
/* Doesn't cover mixed snorm/unorm but can't render to them anyway */
boolean clamped_zero = !util_format_is_float(format) &&
!util_format_is_snorm(format);
blend_rt->rgb_src_factor =
force_dst_alpha_one(blend_rt->rgb_src_factor, clamped_zero);
blend_rt->rgb_dst_factor =
force_dst_alpha_one(blend_rt->rgb_dst_factor, clamped_zero);
blend_rt->alpha_func = blend_rt->rgb_func;
blend_rt->alpha_src_factor = blend_rt->rgb_src_factor;
blend_rt->alpha_dst_factor = blend_rt->rgb_dst_factor;
}
} }
else {
format_desc = util_format_description(format); /* no color buffer for this fragment output */
assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || key->cbuf_format[i] = PIPE_FORMAT_NONE;
format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB); blend_rt->colormask = 0x0;
/*
* Mask out color channels not present in the color buffer.
*/
blend_rt->colormask &= util_format_colormask(format_desc);
/*
* Disable blend for integer formats.
*/
if (util_format_is_pure_integer(format)) {
blend_rt->blend_enable = 0; blend_rt->blend_enable = 0;
} }
/*
* Our swizzled render tiles always have an alpha channel, but the linear
* render target format often does not, so force here the dst alpha to be
* one.
*
* This is not a mere optimization. Wrong results will be produced if the
* dst alpha is used, the dst format does not have alpha, and the previous
* rendering was not flushed from the swizzled to linear buffer. For
* example, NonPowTwo DCT.
*
* TODO: This should be generalized to all channels for better
* performance, but only alpha causes correctness issues.
*
* Also, force rgb/alpha func/factors match, to make AoS blending easier.
*/
if (format_desc->swizzle[3] > UTIL_FORMAT_SWIZZLE_W ||
format_desc->swizzle[3] == format_desc->swizzle[0]) {
/* Doesn't cover mixed snorm/unorm but can't render to them anyway */
boolean clamped_zero = !util_format_is_float(format) &&
!util_format_is_snorm(format);
blend_rt->rgb_src_factor = force_dst_alpha_one(blend_rt->rgb_src_factor,
clamped_zero);
blend_rt->rgb_dst_factor = force_dst_alpha_one(blend_rt->rgb_dst_factor,
clamped_zero);
blend_rt->alpha_func = blend_rt->rgb_func;
blend_rt->alpha_src_factor = blend_rt->rgb_src_factor;
blend_rt->alpha_dst_factor = blend_rt->rgb_dst_factor;
}
} }
/* This value will be the same for all the variants of a given shader: /* This value will be the same for all the variants of a given shader: