summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/r300/r300_flush.c
diff options
context:
space:
mode:
authorMarek Olšák <maraeo@gmail.com>2011-05-07 19:55:45 +0200
committerMarek Olšák <maraeo@gmail.com>2011-05-15 03:28:32 +0200
commitfdd37af3f76ea3ac32f21e9a9c41979a9b33cc5c (patch)
tree7296c98673124d2bcc39a530c00f75a00567c15e /src/gallium/drivers/r300/r300_flush.c
parent904f43f1909256956856665acf072db71fb92092 (diff)
r300g: dynamically ask for and release Hyper-Z access
We ask for Hyper-Z access when clearing a zbuffer. We release it if no zbuffer clear has been done for 2 seconds.
Diffstat (limited to 'src/gallium/drivers/r300/r300_flush.c')
-rw-r--r--src/gallium/drivers/r300/r300_flush.c82
1 files changed, 58 insertions, 24 deletions
diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c
index de7d77d608b..34f5419a864 100644
--- a/src/gallium/drivers/r300/r300_flush.c
+++ b/src/gallium/drivers/r300/r300_flush.c
@@ -27,17 +27,46 @@
#include "util/u_simple_list.h"
#include "util/u_upload_mgr.h"
+#include "os/os_time.h"
+
#include "r300_context.h"
#include "r300_cs.h"
#include "r300_emit.h"
+static void r300_flush_and_cleanup(struct r300_context *r300, unsigned flags)
+{
+ struct r300_atom *atom;
+
+ r300_emit_hyperz_end(r300);
+ r300_emit_query_end(r300);
+ if (r300->screen->caps.is_r500)
+ r500_emit_index_bias(r300, 0);
+
+ r300->flush_counter++;
+ r300->rws->cs_flush(r300->cs, flags);
+ r300->dirty_hw = 0;
+
+ /* New kitchen sink, baby. */
+ foreach_atom(r300, atom) {
+ if (atom->state || atom->allow_null_state) {
+ r300_mark_atom_dirty(r300, atom);
+ }
+ }
+ r300->vertex_arrays_dirty = TRUE;
+
+ /* Unmark HWTCL state for SWTCL. */
+ if (!r300->screen->caps.has_tcl) {
+ r300->vs_state.dirty = FALSE;
+ r300->vs_constants.dirty = FALSE;
+ }
+}
+
void r300_flush(struct pipe_context *pipe,
unsigned flags,
struct pipe_fence_handle **fence)
{
struct r300_context *r300 = r300_context(pipe);
- struct r300_atom *atom;
struct pb_buffer **rfence = (struct pb_buffer**)fence;
if (r300->draw && !r300->draw_vbo_locked)
@@ -56,32 +85,11 @@ void r300_flush(struct pipe_context *pipe,
}
if (r300->dirty_hw) {
- r300_emit_hyperz_end(r300);
- r300_emit_query_end(r300);
- if (r300->screen->caps.is_r500)
- r500_emit_index_bias(r300, 0);
-
- r300->flush_counter++;
- r300->rws->cs_flush(r300->cs, flags);
- r300->dirty_hw = 0;
-
- /* New kitchen sink, baby. */
- foreach_atom(r300, atom) {
- if (atom->state || atom->allow_null_state) {
- r300_mark_atom_dirty(r300, atom);
- }
- }
- r300->vertex_arrays_dirty = TRUE;
-
- /* Unmark HWTCL state for SWTCL. */
- if (!r300->screen->caps.has_tcl) {
- r300->vs_state.dirty = FALSE;
- r300->vs_constants.dirty = FALSE;
- }
+ r300_flush_and_cleanup(r300, flags);
} else {
if (rfence) {
/* We have to create a fence object, but the command stream is empty
- * and we cannot emit an empty CS. We must write some regs then. */
+ * and we cannot emit an empty CS. Let's write to some reg. */
CS_LOCALS(r300);
OUT_CS_REG(RB3D_COLOR_CHANNEL_MASK, 0);
r300->rws->cs_flush(r300->cs, flags);
@@ -91,6 +99,32 @@ void r300_flush(struct pipe_context *pipe,
r300->rws->cs_flush(r300->cs, flags);
}
}
+
+ /* Update Hyper-Z status. */
+ if (r300->num_z_clears) {
+ r300->hyperz_time_of_last_flush = os_time_get();
+ } else if (!r300->hyperz_time_of_last_flush > 2000000) {
+ /* 2 seconds without a Z clear pretty much means a dead context
+ * for HyperZ. */
+
+ r300->hiz_in_use = FALSE;
+
+ /* Decompress Z buffer. */
+ if (r300->zmask_in_use) {
+ if (r300->locked_zbuffer) {
+ r300_decompress_zmask_locked(r300);
+ } else {
+ r300_decompress_zmask(r300);
+ }
+
+ r300_flush_and_cleanup(r300, flags);
+ }
+
+ /* Release HyperZ. */
+ r300->rws->cs_request_feature(r300->cs, RADEON_FID_HYPERZ_RAM_ACCESS,
+ FALSE);
+ }
+ r300->num_z_clears = 0;
}
static void r300_flush_wrapped(struct pipe_context *pipe,