summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/r300/r300_blit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/r300/r300_blit.c')
-rw-r--r--src/gallium/drivers/r300/r300_blit.c62
1 files changed, 44 insertions, 18 deletions
diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c
index 1217488bac7..4ec77df8fb7 100644
--- a/src/gallium/drivers/r300/r300_blit.c
+++ b/src/gallium/drivers/r300/r300_blit.c
@@ -113,7 +113,7 @@ static boolean r300_fast_zclear_allowed(struct r300_context *r300)
struct pipe_framebuffer_state *fb =
(struct pipe_framebuffer_state*)r300->fb_state.state;
- return r300_resource(fb->zsbuf->texture)->tex.zmask_dwords[fb->zsbuf->u.tex.level];
+ return r300_resource(fb->zsbuf->texture)->tex.zmask_dwords[fb->zsbuf->u.tex.level] != 0;
}
static boolean r300_hiz_clear_allowed(struct r300_context *r300)
@@ -121,7 +121,7 @@ static boolean r300_hiz_clear_allowed(struct r300_context *r300)
struct pipe_framebuffer_state *fb =
(struct pipe_framebuffer_state*)r300->fb_state.state;
- return r300_resource(fb->zsbuf->texture)->tex.hiz_dwords[fb->zsbuf->u.tex.level];
+ return r300_resource(fb->zsbuf->texture)->tex.hiz_dwords[fb->zsbuf->u.tex.level] != 0;
}
static uint32_t r300_depth_clear_value(enum pipe_format format,
@@ -206,23 +206,47 @@ static void r300_clear(struct pipe_context* pipe,
(struct r300_hyperz_state*)r300->hyperz_state.state;
uint32_t width = fb->width;
uint32_t height = fb->height;
- boolean can_hyperz = r300->rws->get_value(r300->rws, RADEON_VID_CAN_HYPERZ);
uint32_t hyperz_dcv = hyperz->zb_depthclearvalue;
/* Enable fast Z clear.
* The zbuffer must be in micro-tiled mode, otherwise it locks up. */
- if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && can_hyperz) {
- if (r300_fast_zclear_allowed(r300)) {
- hyperz_dcv = hyperz->zb_depthclearvalue =
- r300_depth_clear_value(fb->zsbuf->format, depth, stencil);
-
- r300_mark_atom_dirty(r300, &r300->zmask_clear);
- buffers &= ~PIPE_CLEAR_DEPTHSTENCIL;
- }
-
- if (r300_hiz_clear_allowed(r300)) {
- r300->hiz_clear_value = r300_hiz_clear_value(depth);
- r300_mark_atom_dirty(r300, &r300->hiz_clear);
+ if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
+ boolean zmask_clear, hiz_clear;
+
+ zmask_clear = r300_fast_zclear_allowed(r300);
+ hiz_clear = r300_hiz_clear_allowed(r300);
+
+ /* If we need Hyper-Z. */
+ if (zmask_clear || hiz_clear) {
+ r300->num_z_clears++;
+
+ /* Try to obtain the access to Hyper-Z buffers if we don't have one. */
+ if (!r300->hyperz_enabled) {
+ r300->hyperz_enabled =
+ r300->rws->cs_request_feature(r300->cs,
+ RADEON_FID_HYPERZ_RAM_ACCESS,
+ TRUE);
+ if (r300->hyperz_enabled) {
+ /* Need to emit HyperZ buffer regs for the first time. */
+ r300_mark_fb_state_dirty(r300, R300_CHANGED_HYPERZ_FLAG);
+ }
+ }
+
+ /* Setup Hyper-Z clears. */
+ if (r300->hyperz_enabled) {
+ if (zmask_clear) {
+ hyperz_dcv = hyperz->zb_depthclearvalue =
+ r300_depth_clear_value(fb->zsbuf->format, depth, stencil);
+
+ r300_mark_atom_dirty(r300, &r300->zmask_clear);
+ buffers &= ~PIPE_CLEAR_DEPTHSTENCIL;
+ }
+
+ if (hiz_clear) {
+ r300->hiz_clear_value = r300_hiz_clear_value(depth);
+ r300_mark_atom_dirty(r300, &r300->hiz_clear);
+ }
+ }
}
}
@@ -323,7 +347,7 @@ static void r300_clear_depth_stencil(struct pipe_context *pipe,
struct pipe_framebuffer_state *fb =
(struct pipe_framebuffer_state*)r300->fb_state.state;
- if (r300->zmask_in_use && !r300->hyperz_locked) {
+ if (r300->zmask_in_use && !r300->locked_zbuffer) {
if (fb->zsbuf->texture == dst->texture) {
r300_decompress_zmask(r300);
}
@@ -341,7 +365,7 @@ void r300_decompress_zmask(struct r300_context *r300)
struct pipe_framebuffer_state *fb =
(struct pipe_framebuffer_state*)r300->fb_state.state;
- if (!r300->zmask_in_use || r300->hyperz_locked)
+ if (!r300->zmask_in_use || r300->locked_zbuffer)
return;
r300->zmask_decompress = TRUE;
@@ -377,6 +401,8 @@ void r300_decompress_zmask_locked(struct r300_context *r300)
r300_decompress_zmask_locked_unsafe(r300);
r300->context.set_framebuffer_state(&r300->context, &saved_fb);
util_unreference_framebuffer_state(&saved_fb);
+
+ pipe_surface_reference(&r300->locked_zbuffer, NULL);
}
/* Copy a block of pixels from one surface to another using HW. */
@@ -423,7 +449,7 @@ static void r300_resource_copy_region(struct pipe_context *pipe,
return;
}
- if (r300->zmask_in_use && !r300->hyperz_locked) {
+ if (r300->zmask_in_use && !r300->locked_zbuffer) {
if (fb->zsbuf->texture == src ||
fb->zsbuf->texture == dst) {
r300_decompress_zmask(r300);