From: Marek Olšák Date: Thu, 6 Mar 2014 01:38:57 +0000 (+0100) Subject: r600g: move fast color clear code to a common place X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=28eb0bcf19a2a82166f685bf68bb0366bc560ba9;p=mesa.git r600g: move fast color clear code to a common place Reviewed-by: Michel Dänzer --- diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c index e0f3373ce05..98c07b5afdb 100644 --- a/src/gallium/drivers/r600/r600_blit.c +++ b/src/gallium/drivers/r600/r600_blit.c @@ -386,85 +386,6 @@ static bool r600_decompress_subresource(struct pipe_context *ctx, return true; } -static void r600_clear_buffer(struct pipe_context *ctx, struct pipe_resource *dst, - unsigned offset, unsigned size, unsigned value); - -static void evergreen_set_clear_color(struct pipe_surface *cbuf, - const union pipe_color_union *color) -{ - unsigned *clear_value = ((struct r600_texture *)cbuf->texture)->color_clear_value; - union util_color uc; - - memset(&uc, 0, sizeof(uc)); - - if (util_format_is_pure_uint(cbuf->format)) { - util_format_write_4ui(cbuf->format, color->ui, 0, &uc, 0, 0, 0, 1, 1); - } else if (util_format_is_pure_sint(cbuf->format)) { - util_format_write_4i(cbuf->format, color->i, 0, &uc, 0, 0, 0, 1, 1); - } else { - util_pack_color(color->f, cbuf->format, &uc); - } - - memcpy(clear_value, &uc, 2 * sizeof(uint32_t)); -} - -static void r600_try_fast_color_clear(struct r600_context *rctx, unsigned *buffers, - const union pipe_color_union *color) -{ - struct pipe_framebuffer_state *fb = &rctx->framebuffer.state; - int i; - - for (i = 0; i < fb->nr_cbufs; i++) { - struct r600_texture *tex; - unsigned clear_bit = PIPE_CLEAR_COLOR0 << i; - - if (!fb->cbufs[i]) - continue; - - /* if this colorbuffer is not being cleared */ - if (!(*buffers & clear_bit)) - continue; - - tex = (struct r600_texture *)fb->cbufs[i]->texture; - - /* 128-bit formats are unusupported */ - if (util_format_get_blocksizebits(fb->cbufs[i]->format) > 64) { - continue; - } - - /* the clear is allowed if all layers are bound */ - if (fb->cbufs[i]->u.tex.first_layer != 0 || - fb->cbufs[i]->u.tex.last_layer != util_max_layer(&tex->resource.b.b, 0)) { - continue; - } - - /* cannot clear mipmapped textures */ - if (fb->cbufs[i]->texture->last_level != 0) { - continue; - } - - /* only supported on tiled surfaces */ - if (tex->surface.level[0].mode < RADEON_SURF_MODE_1D) { - continue; - } - - /* ensure CMASK is enabled */ - r600_texture_alloc_cmask_separate(&rctx->screen->b, tex); - if (tex->cmask.size == 0) { - continue; - } - - /* Do the fast clear. */ - evergreen_set_clear_color(fb->cbufs[i], color); - r600_clear_buffer(&rctx->b.b, &tex->cmask_buffer->b.b, - tex->cmask.offset, tex->cmask.size, 0); - - tex->dirty_level_mask |= 1 << fb->cbufs[i]->u.tex.level; - rctx->framebuffer.atom.dirty = true; - *buffers &= ~clear_bit; - } -} - static void r600_clear(struct pipe_context *ctx, unsigned buffers, const union pipe_color_union *color, double depth, unsigned stencil) @@ -473,7 +394,8 @@ static void r600_clear(struct pipe_context *ctx, unsigned buffers, struct pipe_framebuffer_state *fb = &rctx->framebuffer.state; if (buffers & PIPE_CLEAR_COLOR && rctx->b.chip_class >= EVERGREEN) { - r600_try_fast_color_clear(rctx, &buffers, color); + evergreen_do_fast_color_clear(&rctx->b, fb, &rctx->framebuffer.atom, + &buffers, color); } if (buffers & PIPE_CLEAR_COLOR) { diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h b/src/gallium/drivers/radeon/r600_pipe_common.h index 5808ec30b6a..f858b8c9345 100644 --- a/src/gallium/drivers/radeon/r600_pipe_common.h +++ b/src/gallium/drivers/radeon/r600_pipe_common.h @@ -426,8 +426,6 @@ void r600_texture_get_fmask_info(struct r600_common_screen *rscreen, void r600_texture_get_cmask_info(struct r600_common_screen *rscreen, struct r600_texture *rtex, struct r600_cmask_info *out); -void r600_texture_alloc_cmask_separate(struct r600_common_screen *rscreen, - struct r600_texture *rtex); bool r600_init_flushed_depth_texture(struct pipe_context *ctx, struct pipe_resource *texture, struct r600_texture **staging); @@ -438,6 +436,11 @@ struct pipe_surface *r600_create_surface_custom(struct pipe_context *pipe, const struct pipe_surface *templ, unsigned width, unsigned height); unsigned r600_translate_colorswap(enum pipe_format format); +void evergreen_do_fast_color_clear(struct r600_common_context *rctx, + struct pipe_framebuffer_state *fb, + struct r600_atom *fb_state, + unsigned *buffers, + const union pipe_color_union *color); void r600_init_screen_texture_functions(struct r600_common_screen *rscreen); void r600_init_context_texture_functions(struct r600_common_context *rctx); diff --git a/src/gallium/drivers/radeon/r600_texture.c b/src/gallium/drivers/radeon/r600_texture.c index 011efb0442b..0ff43e7bae4 100644 --- a/src/gallium/drivers/radeon/r600_texture.c +++ b/src/gallium/drivers/radeon/r600_texture.c @@ -28,6 +28,7 @@ #include "r600_cs.h" #include "util/u_format.h" #include "util/u_memory.h" +#include "util/u_pack_color.h" #include #include @@ -449,8 +450,8 @@ static void r600_texture_allocate_cmask(struct r600_common_screen *rscreen, rtex->cb_color_info |= EG_S_028C70_FAST_CLEAR(1); } -void r600_texture_alloc_cmask_separate(struct r600_common_screen *rscreen, - struct r600_texture *rtex) +static void r600_texture_alloc_cmask_separate(struct r600_common_screen *rscreen, + struct r600_texture *rtex) { if (rtex->cmask_buffer) return; @@ -1197,6 +1198,84 @@ unsigned r600_translate_colorswap(enum pipe_format format) return ~0U; } +static void evergreen_set_clear_color(struct r600_texture *rtex, + enum pipe_format surface_format, + const union pipe_color_union *color) +{ + union util_color uc; + + memset(&uc, 0, sizeof(uc)); + + if (util_format_is_pure_uint(surface_format)) { + util_format_write_4ui(surface_format, color->ui, 0, &uc, 0, 0, 0, 1, 1); + } else if (util_format_is_pure_sint(surface_format)) { + util_format_write_4i(surface_format, color->i, 0, &uc, 0, 0, 0, 1, 1); + } else { + util_pack_color(color->f, surface_format, &uc); + } + + memcpy(rtex->color_clear_value, &uc, 2 * sizeof(uint32_t)); +} + +void evergreen_do_fast_color_clear(struct r600_common_context *rctx, + struct pipe_framebuffer_state *fb, + struct r600_atom *fb_state, + unsigned *buffers, + const union pipe_color_union *color) +{ + int i; + + for (i = 0; i < fb->nr_cbufs; i++) { + struct r600_texture *tex; + unsigned clear_bit = PIPE_CLEAR_COLOR0 << i; + + if (!fb->cbufs[i]) + continue; + + /* if this colorbuffer is not being cleared */ + if (!(*buffers & clear_bit)) + continue; + + tex = (struct r600_texture *)fb->cbufs[i]->texture; + + /* 128-bit formats are unusupported */ + if (util_format_get_blocksizebits(fb->cbufs[i]->format) > 64) { + continue; + } + + /* the clear is allowed if all layers are bound */ + if (fb->cbufs[i]->u.tex.first_layer != 0 || + fb->cbufs[i]->u.tex.last_layer != util_max_layer(&tex->resource.b.b, 0)) { + continue; + } + + /* cannot clear mipmapped textures */ + if (fb->cbufs[i]->texture->last_level != 0) { + continue; + } + + /* only supported on tiled surfaces */ + if (tex->surface.level[0].mode < RADEON_SURF_MODE_1D) { + continue; + } + + /* ensure CMASK is enabled */ + r600_texture_alloc_cmask_separate(rctx->screen, tex); + if (tex->cmask.size == 0) { + continue; + } + + /* Do the fast clear. */ + evergreen_set_clear_color(tex, fb->cbufs[i]->format, color); + rctx->clear_buffer(&rctx->b, &tex->cmask_buffer->b.b, + tex->cmask.offset, tex->cmask.size, 0); + + tex->dirty_level_mask |= 1 << fb->cbufs[i]->u.tex.level; + fb_state->dirty = true; + *buffers &= ~clear_bit; + } +} + void r600_init_screen_texture_functions(struct r600_common_screen *rscreen) { rscreen->b.resource_from_handle = r600_texture_from_handle;