static void r600_clear(struct pipe_context *ctx, unsigned buffers, const union pipe_color_union *color, double depth, unsigned stencil) { struct r600_context *rctx = (struct r600_context *)ctx; struct pipe_framebuffer_state *fb = &rctx->framebuffer.state; /* fast color clear on AA framebuffers (EG+) */ if ((buffers & PIPE_CLEAR_COLOR) && can_fast_clear_color(ctx)) { int i; for (i = 0; i < fb->nr_cbufs; i++) { struct r600_texture *tex = (struct r600_texture *)fb->cbufs[i]->texture; evergreen_set_clear_color(fb->cbufs[i], color); r600_clear_buffer(ctx, fb->cbufs[i]->texture, tex->cmask_offset, tex->cmask_size, 0); tex->dirty_level_mask |= 1 << fb->cbufs[i]->u.tex.level; } rctx->framebuffer.atom.dirty = true; buffers &= ~PIPE_CLEAR_COLOR; if (!buffers) return; } /* if hyperz enabled just clear hyperz */ if (fb->zsbuf && (buffers & PIPE_CLEAR_DEPTH)) { struct r600_texture *rtex; unsigned level = fb->zsbuf->u.tex.level; rtex = (struct r600_texture*)fb->zsbuf->texture; /* We can't use hyperz fast clear if each slice of a texture * array are clear to different value. To simplify code just * disable fast clear for texture array. */ /* Only use htile for first level */ if (rtex->htile && !level && rtex->surface.array_size == 1) { if (rtex->depth_clear != depth) { rtex->depth_clear = depth; rctx->db_state.atom.dirty = true; } rctx->db_misc_state.htile_clear = true; rctx->db_misc_state.atom.dirty = true; } } r600_blitter_begin(ctx, R600_CLEAR); util_blitter_clear(rctx->blitter, fb->width, fb->height, buffers, color, depth, stencil); r600_blitter_end(ctx); /* disable fast clear */ if (rctx->db_misc_state.htile_clear) { rctx->db_misc_state.htile_clear = false; rctx->db_misc_state.atom.dirty = true; } }
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; if (rctx->current_render_cond) return; 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; } /* fast color clear with 1D tiling doesn't work on old kernels and CIK */ if (tex->surface.level[0].mode == RADEON_SURF_MODE_1D && rctx->chip_class >= CIK && rctx->screen->info.drm_major == 2 && rctx->screen->info.drm_minor < 38) { 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, true); tex->dirty_level_mask |= 1 << fb->cbufs[i]->u.tex.level; rctx->set_atom_dirty(rctx, fb_state, true); *buffers &= ~clear_bit; } }