aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2011-01-09 05:34:36 +0100
committerMarek Olšák <[email protected]>2011-01-09 06:14:23 +0100
commit3332229b3ba7a183a9f120ae4bbf9865e96df110 (patch)
tree244c11039fcd1b48d10c711f4b5534faa2926309
parent69191d41231b95af7565e32393c5487163859d7e (diff)
r300g: fix crash when flushing ZMASK
https://bugs.freedesktop.org/show_bug.cgi?id=32912 The fix is to call update_derived_state before user buffer uploads. I've also moved some code around. Unfortunately, there are still some ZMASK-related bugs which cause misrendering, i.e. flushing doesn't always work and glean/fbo fails.
-rw-r--r--src/gallium/drivers/r300/r300_blit.c62
-rw-r--r--src/gallium/drivers/r300/r300_context.h38
-rw-r--r--src/gallium/drivers/r300/r300_render.c9
-rw-r--r--src/gallium/drivers/r300/r300_state_derived.c34
-rw-r--r--src/gallium/drivers/r300/r300_state_derived.h30
5 files changed, 81 insertions, 92 deletions
diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c
index 017db48485b..a43e83c0d36 100644
--- a/src/gallium/drivers/r300/r300_blit.c
+++ b/src/gallium/drivers/r300/r300_blit.c
@@ -179,6 +179,12 @@ static void r300_clear(struct pipe_context* pipe,
boolean can_hyperz = r300->rws->get_value(r300->rws, R300_CAN_HYPERZ);
uint32_t hyperz_dcv = hyperz->zb_depthclearvalue;
+ /* Decompress zbuffers that are bound as textures. If we didn't flush here,
+ * it would happen inside the blitter when updating derived state,
+ * causing a blitter operation to be called from inside the blitter,
+ * which would overwrite saved states and they would never get restored. */
+ r300_flush_depth_textures(r300);
+
/* Enable fast Z clear.
* The zbuffer must be in micro-tiled mode, otherwise it locks up. */
if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && can_hyperz) {
@@ -274,6 +280,12 @@ static void r300_clear_render_target(struct pipe_context *pipe,
{
struct r300_context *r300 = r300_context(pipe);
+ /* Decompress zbuffers that are bound as textures. If we didn't flush here,
+ * it would happen inside the blitter when updating derived state,
+ * causing a blitter operation to be called from inside the blitter,
+ * which would overwrite saved states and they would never get restored. */
+ r300_flush_depth_textures(r300);
+
r300_blitter_begin(r300, R300_CLEAR_SURFACE);
util_blitter_clear_render_target(r300->blitter, dst, rgba,
dstx, dsty, width, height);
@@ -291,6 +303,12 @@ static void r300_clear_depth_stencil(struct pipe_context *pipe,
{
struct r300_context *r300 = r300_context(pipe);
+ /* Decompress zbuffers that are bound as textures. If we didn't flush here,
+ * it would happen inside the blitter when updating derived state,
+ * causing a blitter operation to be called from inside the blitter,
+ * which would overwrite saved states and they would never get restored. */
+ r300_flush_depth_textures(r300);
+
r300_blitter_begin(r300, R300_CLEAR_SURFACE);
util_blitter_clear_depth_stencil(r300->blitter, dst, clear_flags, depth, stencil,
dstx, dsty, width, height);
@@ -298,10 +316,10 @@ static void r300_clear_depth_stencil(struct pipe_context *pipe,
}
/* Flush a depth stencil buffer. */
-void r300_flush_depth_stencil(struct pipe_context *pipe,
- struct pipe_resource *dst,
- unsigned level,
- unsigned layer)
+static void r300_flush_depth_stencil(struct pipe_context *pipe,
+ struct pipe_resource *dst,
+ unsigned level,
+ unsigned layer)
{
struct r300_context *r300 = r300_context(pipe);
struct pipe_surface *dstsurf, surf_tmpl;
@@ -320,6 +338,7 @@ void r300_flush_depth_stencil(struct pipe_context *pipe,
dstsurf = pipe->create_surface(pipe, dst, &surf_tmpl);
r300->z_decomp_rd = TRUE;
+
r300_blitter_begin(r300, R300_CLEAR_SURFACE);
util_blitter_flush_depth_stencil(r300->blitter, dstsurf);
r300_blitter_end(r300);
@@ -329,6 +348,39 @@ void r300_flush_depth_stencil(struct pipe_context *pipe,
pipe_surface_reference(&dstsurf, NULL);
}
+/* We can't use compressed zbuffers as samplers. */
+void r300_flush_depth_textures(struct r300_context *r300)
+{
+ struct r300_textures_state *state =
+ (struct r300_textures_state*)r300->textures_state.state;
+ unsigned i, level;
+ unsigned count = MIN2(state->sampler_view_count,
+ state->sampler_state_count);
+
+ if (r300->z_decomp_rd)
+ return;
+
+ for (i = 0; i < count; i++)
+ if (state->sampler_views[i] && state->sampler_states[i]) {
+ struct pipe_resource *tex = state->sampler_views[i]->base.texture;
+
+ if (tex->target == PIPE_TEXTURE_3D ||
+ tex->target == PIPE_TEXTURE_CUBE)
+ continue;
+
+ /* Ignore non-depth textures.
+ * Also ignore reinterpreted depth textures, e.g. resource_copy. */
+ if (!util_format_is_depth_or_stencil(tex->format))
+ continue;
+
+ for (level = 0; level <= tex->last_level; level++)
+ if (r300_texture(tex)->zmask_in_use[level]) {
+ /* We don't handle 3D textures and cubemaps yet. */
+ r300_flush_depth_stencil(&r300->context, tex, level, 0);
+ }
+ }
+}
+
/* Copy a block of pixels from one surface to another using HW. */
static void r300_hw_copy_region(struct pipe_context* pipe,
struct pipe_resource *dst,
@@ -360,6 +412,7 @@ static void r300_resource_copy_region(struct pipe_context *pipe,
enum pipe_format old_format = dst->format;
enum pipe_format new_format = old_format;
boolean is_depth;
+
if (!pipe->screen->is_format_supported(pipe->screen,
old_format, src->target,
src->nr_samples,
@@ -390,6 +443,7 @@ static void r300_resource_copy_region(struct pipe_context *pipe,
if (is_depth) {
r300_flush_depth_stencil(pipe, src, src_level, src_box->z);
}
+
if (old_format != new_format) {
r300_texture_reinterpret_format(pipe->screen,
dst, new_format);
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index 1a14d2b79e5..e09cf87f733 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -656,6 +656,22 @@ static INLINE struct r300_fragment_shader *r300_fs(struct r300_context *r300)
return (struct r300_fragment_shader*)r300->fs.state;
}
+static INLINE void r300_mark_atom_dirty(struct r300_context *r300,
+ struct r300_atom *atom)
+{
+ atom->dirty = TRUE;
+
+ if (!r300->first_dirty) {
+ r300->first_dirty = atom;
+ r300->last_dirty = atom+1;
+ } else {
+ if (atom < r300->first_dirty)
+ r300->first_dirty = atom;
+ else if (atom+1 > r300->last_dirty)
+ r300->last_dirty = atom+1;
+ }
+}
+
struct pipe_context* r300_create_context(struct pipe_screen* screen,
void *priv);
@@ -672,10 +688,7 @@ void r300_init_state_functions(struct r300_context* r300);
void r300_init_resource_functions(struct r300_context* r300);
/* r300_blit.c */
-void r300_flush_depth_stencil(struct pipe_context *pipe,
- struct pipe_resource *dst,
- unsigned level,
- unsigned layer);
+void r300_flush_depth_textures(struct r300_context *r300);
/* r300_query.c */
void r300_resume_query(struct r300_context *r300,
@@ -710,21 +723,8 @@ void r300_mark_fb_state_dirty(struct r300_context *r300,
enum r300_fb_state_change change);
void r300_mark_fs_code_dirty(struct r300_context *r300);
-static INLINE void r300_mark_atom_dirty(struct r300_context *r300,
- struct r300_atom *atom)
-{
- atom->dirty = TRUE;
-
- if (!r300->first_dirty) {
- r300->first_dirty = atom;
- r300->last_dirty = atom+1;
- } else {
- if (atom < r300->first_dirty)
- r300->first_dirty = atom;
- if (atom+1 > r300->last_dirty)
- r300->last_dirty = atom+1;
- }
-}
+/* r300_state_derived.c */
+void r300_update_derived_state(struct r300_context* r300);
/* r300_debug.c */
void r500_dump_rs_block(struct r300_rs_block *rs);
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index e660ca68f1b..b35822c82f8 100644
--- a/src/gallium/drivers/r300/r300_render.c
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -39,7 +39,6 @@
#include "r300_screen_buffer.h"
#include "r300_emit.h"
#include "r300_reg.h"
-#include "r300_state_derived.h"
#include <limits.h>
@@ -569,8 +568,6 @@ static void r300_draw_range_elements(struct pipe_context* pipe,
r300_translate_index_buffer(r300, &indexBuffer, &indexSize, index_offset,
&start, count);
- r300_update_derived_state(r300);
-
/* Fallback for misaligned ushort indices. */
if (indexSize == 2 && (start & 1) &&
!r300_is_user_buffer(indexBuffer)) {
@@ -643,8 +640,6 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0);
unsigned short_count;
- r300_update_derived_state(r300);
-
if (immd_is_good_idea(r300, count)) {
r300_emit_draw_arrays_immediate(r300, mode, start, count);
} else {
@@ -720,6 +715,8 @@ static void r300_draw_vbo(struct pipe_context* pipe,
return;
}
+ r300_update_derived_state(r300);
+
/* Set up the fallback for an incompatible vertex layout if needed. */
if (r300->incompatible_vb_layout || r300->velems->incompatible_layout) {
r300_begin_vertex_translate(r300, real_min_index, real_max_index);
@@ -737,6 +734,8 @@ static void r300_draw_vbo(struct pipe_context* pipe,
min_index = MAX2(min_index, info->start);
max_index = MIN2(max_index, info->start + count - 1);
+ r300_update_derived_state(r300);
+
/* Set up the fallback for an incompatible vertex layout if needed. */
if (r300->incompatible_vb_layout || r300->velems->incompatible_layout) {
r300_begin_vertex_translate(r300, min_index, max_index);
diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c
index d3985c11aa8..95be7849f8f 100644
--- a/src/gallium/drivers/r300/r300_state_derived.c
+++ b/src/gallium/drivers/r300/r300_state_derived.c
@@ -32,7 +32,6 @@
#include "r300_hyperz.h"
#include "r300_screen.h"
#include "r300_shader_semantics.h"
-#include "r300_state_derived.h"
#include "r300_state_inlines.h"
#include "r300_texture.h"
#include "r300_vs.h"
@@ -863,39 +862,6 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
}
}
-/* We can't use compressed zbuffers as samplers. */
-static void r300_flush_depth_textures(struct r300_context *r300)
-{
- struct r300_textures_state *state =
- (struct r300_textures_state*)r300->textures_state.state;
- unsigned i, level;
- unsigned count = MIN2(state->sampler_view_count,
- state->sampler_state_count);
-
- if (r300->z_decomp_rd)
- return;
-
- for (i = 0; i < count; i++)
- if (state->sampler_views[i] && state->sampler_states[i]) {
- struct pipe_resource *tex = state->sampler_views[i]->base.texture;
-
- if (tex->target == PIPE_TEXTURE_3D ||
- tex->target == PIPE_TEXTURE_CUBE)
- continue;
-
- /* Ignore non-depth textures.
- * Also ignore reinterpreted depth textures, e.g. resource_copy. */
- if (!util_format_is_depth_or_stencil(tex->format))
- continue;
-
- for (level = 0; level <= tex->last_level; level++)
- if (r300_texture(tex)->zmask_in_use[level]) {
- /* We don't handle 3D textures and cubemaps yet. */
- r300_flush_depth_stencil(&r300->context, tex, level, 0);
- }
- }
-}
-
void r300_update_derived_state(struct r300_context* r300)
{
r300_flush_depth_textures(r300);
diff --git a/src/gallium/drivers/r300/r300_state_derived.h b/src/gallium/drivers/r300/r300_state_derived.h
deleted file mode 100644
index 71a4a47b003..00000000000
--- a/src/gallium/drivers/r300/r300_state_derived.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2008 Corbin Simpson <[email protected]>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * on the rights to use, copy, modify, merge, publish, distribute, sub
- * license, and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- * USE OR OTHER DEALINGS IN THE SOFTWARE. */
-
-#ifndef R300_STATE_DERIVED_H
-#define R300_STATE_DERIVED_H
-
-struct r300_context;
-
-void r300_update_derived_state(struct r300_context* r300);
-
-#endif /* R300_STATE_DERIVED_H */