mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-24 06:40:11 +01:00
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:
parent
7b4ceec0b7
commit
d6fa71fbb0
5 changed files with 158 additions and 96 deletions
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue