diff options
Diffstat (limited to 'src/gallium/drivers/r300/r300_blit.c')
-rw-r--r-- | src/gallium/drivers/r300/r300_blit.c | 124 |
1 files changed, 91 insertions, 33 deletions
diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index 0ac4e4c..a43e83c 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) { @@ -186,12 +192,12 @@ static void r300_clear(struct pipe_context* pipe, r300_depth_clear_value(fb->zsbuf->format, depth, stencil); r300_mark_fb_state_dirty(r300, R300_CHANGED_ZCLEAR_FLAG); - if (zstex->zmask_mem[fb->zsbuf->level]) { - r300->zmask_clear.dirty = TRUE; + if (zstex->zmask_mem[fb->zsbuf->u.tex.level]) { + r300_mark_atom_dirty(r300, &r300->zmask_clear); buffers &= ~PIPE_CLEAR_DEPTHSTENCIL; } - if (zstex->hiz_mem[fb->zsbuf->level]) - r300->hiz_clear.dirty = TRUE; + if (zstex->hiz_mem[fb->zsbuf->u.tex.level]) + r300_mark_atom_dirty(r300, &r300->hiz_clear); } /* Enable CBZB clear. */ @@ -230,7 +236,7 @@ static void r300_clear(struct pipe_context* pipe, r300_get_num_cs_end_dwords(r300); /* Reserve CS space. */ - if (dwords > (r300->cs->ndw - r300->cs->cdw)) { + if (dwords > (R300_MAX_CMDBUF_DWORDS - r300->cs->cdw)) { r300->context.flush(&r300->context, 0, NULL); } @@ -259,9 +265,9 @@ static void r300_clear(struct pipe_context* pipe, * If we cleared zmask/hiz, it's in use now. The Hyper-Z state update * looks if zmask/hiz is in use and enables fastfill accordingly. */ if (zstex && - (zstex->zmask_in_use[fb->zsbuf->level] || - zstex->hiz_in_use[fb->zsbuf->level])) { - r300->hyperz_state.dirty = TRUE; + (zstex->zmask_in_use[fb->zsbuf->u.tex.level] || + zstex->hiz_in_use[fb->zsbuf->u.tex.level])) { + r300_mark_atom_dirty(r300, &r300->hyperz_state); } } @@ -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,64 +316,103 @@ 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, - struct pipe_subresource subdst, - unsigned zslice) +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; + struct pipe_surface *dstsurf, surf_tmpl; struct r300_texture *tex = r300_texture(dst); - if (!tex->zmask_mem[subdst.level]) + if (!tex->zmask_mem[level]) return; - if (!tex->zmask_in_use[subdst.level]) + if (!tex->zmask_in_use[level]) return; - dstsurf = pipe->screen->get_tex_surface(pipe->screen, dst, - subdst.face, subdst.level, zslice, - PIPE_BIND_DEPTH_STENCIL); + surf_tmpl.format = dst->format; + surf_tmpl.usage = PIPE_BIND_DEPTH_STENCIL; + surf_tmpl.u.tex.level = level; + surf_tmpl.u.tex.first_layer = layer; + surf_tmpl.u.tex.last_layer = layer; + 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); r300->z_decomp_rd = FALSE; - tex->zmask_in_use[subdst.level] = FALSE; + tex->zmask_in_use[level] = FALSE; + 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, - struct pipe_subresource subdst, + unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, struct pipe_resource *src, - struct pipe_subresource subsrc, - unsigned srcx, unsigned srcy, unsigned srcz, - unsigned width, unsigned height) + unsigned src_level, + const struct pipe_box *src_box) { struct r300_context* r300 = r300_context(pipe); r300_blitter_begin(r300, R300_COPY); - util_blitter_copy_region(r300->blitter, dst, subdst, dstx, dsty, dstz, - src, subsrc, srcx, srcy, srcz, width, height, - TRUE); + + /* Do a copy */ + util_blitter_copy_region(r300->blitter, dst, dst_level, dstx, dsty, dstz, + src, src_level, src_box, TRUE); r300_blitter_end(r300); } /* Copy a block of pixels from one surface to another. */ static void r300_resource_copy_region(struct pipe_context *pipe, struct pipe_resource *dst, - struct pipe_subresource subdst, + unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, struct pipe_resource *src, - struct pipe_subresource subsrc, - unsigned srcx, unsigned srcy, unsigned srcz, - unsigned width, unsigned height) + unsigned src_level, + const struct pipe_box *src_box) { 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, @@ -384,8 +441,9 @@ static void r300_resource_copy_region(struct pipe_context *pipe, is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0; if (is_depth) { - r300_flush_depth_stencil(pipe, src, subsrc, srcz); + 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); @@ -393,8 +451,8 @@ static void r300_resource_copy_region(struct pipe_context *pipe, src, new_format); } - r300_hw_copy_region(pipe, dst, subdst, dstx, dsty, dstz, - src, subsrc, srcx, srcy, srcz, width, height); + r300_hw_copy_region(pipe, dst, dst_level, dstx, dsty, dstz, + src, src_level, src_box); if (old_format != new_format) { r300_texture_reinterpret_format(pipe->screen, |