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.
* This is a bin command called during bin processing.
@ -124,7 +143,7 @@ lp_rast_clear_color(struct lp_rasterizer_task *task,
unsigned i;
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
* 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]);
for (i = 0; i < scene->fb.nr_cbufs; i++) {
util_pack_color(arg.clear_color.f,
scene->fb.cbufs[i]->format, &uc);
if (scene->fb.cbufs[i]) {
util_pack_color(arg.clear_color.f,
scene->fb.cbufs[i]->format, &uc);
util_fill_box(scene->cbufs[i].map,
scene->fb.cbufs[i]->format,
scene->cbufs[i].stride,
scene->cbufs[i].layer_stride,
task->x,
task->y,
0,
task->width,
task->height,
scene->fb_max_layer + 1,
&uc);
util_fill_box(scene->cbufs[i].map,
scene->fb.cbufs[i]->format,
scene->cbufs[i].stride,
scene->cbufs[i].layer_stride,
task->x,
task->y,
0,
task->width,
task->height,
scene->fb_max_layer + 1,
&uc);
}
}
}
}
@ -444,8 +465,15 @@ lp_rast_shade_quads_mask(struct lp_rasterizer_task *task,
/* color buffer */
for (i = 0; i < scene->fb.nr_cbufs; i++) {
stride[i] = scene->cbufs[i].stride;
color[i] = lp_rast_get_unswizzled_color_block_pointer(task, i, x, y, inputs->layer);
if (scene->fb.cbufs[i]) {
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 */

View file

@ -293,8 +293,15 @@ lp_rast_shade_quads_all( struct lp_rasterizer_task *task,
/* color buffer */
for (i = 0; i < scene->fb.nr_cbufs; i++) {
stride[i] = scene->cbufs[i].stride;
color[i] = lp_rast_get_unswizzled_color_block_pointer(task, i, x, y, inputs->layer);
if (scene->fb.cbufs[i]) {
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) {

View file

@ -156,6 +156,14 @@ lp_scene_begin_rasterization(struct lp_scene *scene)
for (i = 0; i < scene->fb.nr_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)) {
scene->cbufs[i].stride = llvmpipe_resource_stride(cbuf->texture,
cbuf->u.tex.level);
@ -171,7 +179,7 @@ lp_scene_begin_rasterization(struct lp_scene *scene)
struct llvmpipe_resource *lpr = llvmpipe_resource(cbuf->texture);
unsigned pixstride = util_format_get_blocksize(cbuf->format);
scene->cbufs[i].stride = cbuf->texture->width0;
scene->cbufs[i].layer_stride = 0;
scene->cbufs[i].map = lpr->data;
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++) {
struct pipe_surface *cbuf = scene->fb.cbufs[i];
if (llvmpipe_resource_is_texture(cbuf->texture)) {
max_layer = MIN2(max_layer, cbuf->u.tex.last_layer - cbuf->u.tex.first_layer);
}
else {
max_layer = 0;
if (cbuf) {
if (llvmpipe_resource_is_texture(cbuf->texture)) {
max_layer = MIN2(max_layer,
cbuf->u.tex.last_layer - cbuf->u.tex.first_layer);
}
else {
max_layer = 0;
}
}
}
if (fb->zsbuf) {

View file

@ -882,7 +882,7 @@ lp_setup_is_resource_referenced( const struct lp_setup_context *setup,
/* check the render targets */
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;
}
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.
*/
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);
stride = LLVMBuildLoad(builder,
LLVMBuildGEP(builder, stride_ptr, &index, 1, ""),
"");
lp_build_name(color_ptr, "color_ptr%d", cbuf);
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,65 +2934,75 @@ 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;
/*
* 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;
}
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;
}
}
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)) {
else {
/* no color buffer for this fragment output */
key->cbuf_format[i] = PIPE_FORMAT_NONE;
blend_rt->colormask = 0x0;
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: