diff options
author | Brian Paul <[email protected]> | 2014-01-15 18:09:56 -0800 |
---|---|---|
committer | Brian Paul <[email protected]> | 2014-01-17 08:52:11 -0800 |
commit | d6fa71fbb0d365cefdabfea9de62cfece71f7486 (patch) | |
tree | a92afaaefdd8163c05a1fdbb17d529a635faef5a /src/gallium/drivers/llvmpipe/lp_state_fs.c | |
parent | 7b4ceec0b7591fa7a2dd66c45727341f52bf5258 (diff) |
llvmpipe: handle NULL color buffer pointers
Fixes regression from 9baa45f78b8ca7d66280e36009b6a685055d7cd6
v2: incorporate a few small changes suggested by Roland.
Reviewed-by: José Fonseca <[email protected]>
Reviewed-by: Roland Scheidegger <[email protected]>
Diffstat (limited to 'src/gallium/drivers/llvmpipe/lp_state_fs.c')
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_state_fs.c | 152 |
1 files changed, 84 insertions, 68 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index 31ed8478e9b..504a7aa2901 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -2362,28 +2362,33 @@ generate_fragment(struct llvmpipe_context *lp, /* Loop over color outputs / color buffers to do blending. */ for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++) { - LLVMValueRef color_ptr; - LLVMValueRef stride; - LLVMValueRef index = lp_build_const_int32(gallivm, cbuf); + if (key->cbuf_format[cbuf] != PIPE_FORMAT_NONE) { + LLVMValueRef color_ptr; + LLVMValueRef stride; + LLVMValueRef index = lp_build_const_int32(gallivm, cbuf); - boolean do_branch = ((key->depth.enabled - || key->stencil[0].enabled - || key->alpha.enabled) - && !shader->info.base.uses_kill); + boolean do_branch = ((key->depth.enabled + || key->stencil[0].enabled + || key->alpha.enabled) + && !shader->info.base.uses_kill); - color_ptr = LLVMBuildLoad(builder, - LLVMBuildGEP(builder, color_ptr_ptr, &index, 1, ""), - ""); + color_ptr = LLVMBuildLoad(builder, + LLVMBuildGEP(builder, color_ptr_ptr, + &index, 1, ""), + ""); - lp_build_name(color_ptr, "color_ptr%d", cbuf); + lp_build_name(color_ptr, "color_ptr%d", cbuf); - stride = LLVMBuildLoad(builder, - LLVMBuildGEP(builder, stride_ptr, &index, 1, ""), - ""); + stride = LLVMBuildLoad(builder, + LLVMBuildGEP(builder, stride_ptr, &index, 1, ""), + ""); - 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); + 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); @@ -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) */ if (!lp->framebuffer.nr_cbufs || + !lp->framebuffer.cbufs[0] || !util_format_is_pure_integer(lp->framebuffer.cbufs[0]->format)) { key->alpha.enabled = lp->depth_stencil->alpha.enabled; } @@ -2928,64 +2934,74 @@ make_variant_key(struct llvmpipe_context *lp, } 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]; - 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; - /* - * 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. - */ - if (llvmpipe_resource_is_1d(lp->framebuffer.cbufs[0]->texture)) { - key->resource_1d = TRUE; - } + key->cbuf_format[i] = format; - format_desc = util_format_description(format); - assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || - format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB); + /* + * 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. + */ + if (llvmpipe_resource_is_1d(lp->framebuffer.cbufs[i]->texture)) { + key->resource_1d = TRUE; + } - /* - * Mask out color channels not present in the color buffer. - */ - blend_rt->colormask &= util_format_colormask(format_desc); + format_desc = util_format_description(format); + assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB || + format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB); - /* - * Disable blend for integer formats. - */ - if (util_format_is_pure_integer(format)) { - blend_rt->blend_enable = 0; - } + /* + * Mask out color channels not present in the color buffer. + */ + blend_rt->colormask &= util_format_colormask(format_desc); - /* - * 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; + /* + * 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 { + /* no color buffer for this fragment output */ + key->cbuf_format[i] = PIPE_FORMAT_NONE; + blend_rt->colormask = 0x0; + blend_rt->blend_enable = 0; } } |