1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com> 3bf215546Sopenharmony_ci * Copyright 2009 Marek Olšák <maraeo@gmail.com> 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 8bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 9bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 10bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 14bf215546Sopenharmony_ci * Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 20bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "r300_context.h" 25bf215546Sopenharmony_ci#include "r300_reg.h" 26bf215546Sopenharmony_ci#include "r300_fs.h" 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include "util/format/u_format.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci/* 31bf215546Sopenharmony_ci HiZ rules - taken from various docs 32bf215546Sopenharmony_ci 1. HiZ only works on depth values 33bf215546Sopenharmony_ci 2. Cannot HiZ if stencil fail or zfail is !KEEP 34bf215546Sopenharmony_ci 3. on R300/400, HiZ is disabled if depth test is EQUAL 35bf215546Sopenharmony_ci 4. comparison changes without clears usually mean disabling HiZ 36bf215546Sopenharmony_ci*/ 37bf215546Sopenharmony_ci/*****************************************************************************/ 38bf215546Sopenharmony_ci/* The HyperZ setup */ 39bf215546Sopenharmony_ci/*****************************************************************************/ 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_cistatic enum r300_hiz_func r300_get_hiz_func(struct r300_context *r300) 42bf215546Sopenharmony_ci{ 43bf215546Sopenharmony_ci struct r300_dsa_state *dsa = r300->dsa_state.state; 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci switch (dsa->dsa.depth_func) { 46bf215546Sopenharmony_ci case PIPE_FUNC_NEVER: 47bf215546Sopenharmony_ci case PIPE_FUNC_EQUAL: 48bf215546Sopenharmony_ci case PIPE_FUNC_NOTEQUAL: 49bf215546Sopenharmony_ci case PIPE_FUNC_ALWAYS: 50bf215546Sopenharmony_ci default: 51bf215546Sopenharmony_ci /* Guess MAX for uncertain cases. */ 52bf215546Sopenharmony_ci case PIPE_FUNC_LESS: 53bf215546Sopenharmony_ci case PIPE_FUNC_LEQUAL: 54bf215546Sopenharmony_ci return HIZ_FUNC_MAX; 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci case PIPE_FUNC_GREATER: 57bf215546Sopenharmony_ci case PIPE_FUNC_GEQUAL: 58bf215546Sopenharmony_ci return HIZ_FUNC_MIN; 59bf215546Sopenharmony_ci } 60bf215546Sopenharmony_ci} 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci/* Return what's used for the depth test (either minimum or maximum). */ 63bf215546Sopenharmony_cistatic unsigned r300_get_sc_hz_max(struct r300_context *r300) 64bf215546Sopenharmony_ci{ 65bf215546Sopenharmony_ci struct r300_dsa_state *dsa = r300->dsa_state.state; 66bf215546Sopenharmony_ci unsigned func = dsa->dsa.depth_func; 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci return func >= PIPE_FUNC_GREATER ? R300_SC_HYPERZ_MAX : R300_SC_HYPERZ_MIN; 69bf215546Sopenharmony_ci} 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_cistatic boolean r300_is_hiz_func_valid(struct r300_context *r300) 72bf215546Sopenharmony_ci{ 73bf215546Sopenharmony_ci struct r300_dsa_state *dsa = r300->dsa_state.state; 74bf215546Sopenharmony_ci unsigned func = dsa->dsa.depth_func; 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ci if (r300->hiz_func == HIZ_FUNC_NONE) 77bf215546Sopenharmony_ci return TRUE; 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_ci /* func1 is less/lessthan */ 80bf215546Sopenharmony_ci if (r300->hiz_func == HIZ_FUNC_MAX && 81bf215546Sopenharmony_ci (func == PIPE_FUNC_GEQUAL || func == PIPE_FUNC_GREATER)) 82bf215546Sopenharmony_ci return FALSE; 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci /* func1 is greater/greaterthan */ 85bf215546Sopenharmony_ci if (r300->hiz_func == HIZ_FUNC_MIN && 86bf215546Sopenharmony_ci (func == PIPE_FUNC_LESS || func == PIPE_FUNC_LEQUAL)) 87bf215546Sopenharmony_ci return FALSE; 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci return TRUE; 90bf215546Sopenharmony_ci} 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_cistatic boolean r300_dsa_stencil_op_not_keep(struct pipe_stencil_state *s) 93bf215546Sopenharmony_ci{ 94bf215546Sopenharmony_ci return s->enabled && (s->fail_op != PIPE_STENCIL_OP_KEEP || 95bf215546Sopenharmony_ci s->zfail_op != PIPE_STENCIL_OP_KEEP); 96bf215546Sopenharmony_ci} 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_cistatic boolean r300_hiz_allowed(struct r300_context *r300) 99bf215546Sopenharmony_ci{ 100bf215546Sopenharmony_ci struct r300_dsa_state *dsa = r300->dsa_state.state; 101bf215546Sopenharmony_ci struct r300_screen *r300screen = r300->screen; 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci if (r300_fragment_shader_writes_depth(r300_fs(r300))) 104bf215546Sopenharmony_ci return FALSE; 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ci if (r300->query_current) 107bf215546Sopenharmony_ci return FALSE; 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci /* If the depth function is inverted, HiZ must be disabled. */ 110bf215546Sopenharmony_ci if (!r300_is_hiz_func_valid(r300)) 111bf215546Sopenharmony_ci return FALSE; 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci /* if stencil fail/zfail op is not KEEP */ 114bf215546Sopenharmony_ci if (r300_dsa_stencil_op_not_keep(&dsa->dsa.stencil[0]) || 115bf215546Sopenharmony_ci r300_dsa_stencil_op_not_keep(&dsa->dsa.stencil[1])) 116bf215546Sopenharmony_ci return FALSE; 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci if (dsa->dsa.depth_enabled) { 119bf215546Sopenharmony_ci /* if depth func is EQUAL pre-r500 */ 120bf215546Sopenharmony_ci if (dsa->dsa.depth_func == PIPE_FUNC_EQUAL && !r300screen->caps.is_r500) 121bf215546Sopenharmony_ci return FALSE; 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci /* if depth func is NOTEQUAL */ 124bf215546Sopenharmony_ci if (dsa->dsa.depth_func == PIPE_FUNC_NOTEQUAL) 125bf215546Sopenharmony_ci return FALSE; 126bf215546Sopenharmony_ci } 127bf215546Sopenharmony_ci return TRUE; 128bf215546Sopenharmony_ci} 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_cistatic void r300_update_hyperz(struct r300_context* r300) 131bf215546Sopenharmony_ci{ 132bf215546Sopenharmony_ci struct r300_hyperz_state *z = 133bf215546Sopenharmony_ci (struct r300_hyperz_state*)r300->hyperz_state.state; 134bf215546Sopenharmony_ci struct pipe_framebuffer_state *fb = 135bf215546Sopenharmony_ci (struct pipe_framebuffer_state*)r300->fb_state.state; 136bf215546Sopenharmony_ci struct r300_dsa_state *dsa = r300->dsa_state.state; 137bf215546Sopenharmony_ci struct r300_resource *zstex = 138bf215546Sopenharmony_ci fb->zsbuf ? r300_resource(fb->zsbuf->texture) : NULL; 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci z->gb_z_peq_config = 0; 141bf215546Sopenharmony_ci z->zb_bw_cntl = 0; 142bf215546Sopenharmony_ci z->sc_hyperz = R300_SC_HYPERZ_ADJ_2; 143bf215546Sopenharmony_ci z->flush = 0; 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci if (r300->cbzb_clear) { 146bf215546Sopenharmony_ci z->zb_bw_cntl |= R300_ZB_CB_CLEAR_CACHE_LINE_WRITE_ONLY; 147bf215546Sopenharmony_ci return; 148bf215546Sopenharmony_ci } 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci if (!zstex || !r300->hyperz_enabled) 151bf215546Sopenharmony_ci return; 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci /* Set the size of ZMASK tiles. */ 154bf215546Sopenharmony_ci if (zstex->tex.zcomp8x8[fb->zsbuf->u.tex.level]) { 155bf215546Sopenharmony_ci z->gb_z_peq_config |= R300_GB_Z_PEQ_CONFIG_Z_PEQ_SIZE_8_8; 156bf215546Sopenharmony_ci } 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci /* R500-specific features and optimizations. */ 159bf215546Sopenharmony_ci if (r300->screen->caps.is_r500) { 160bf215546Sopenharmony_ci z->zb_bw_cntl |= R500_PEQ_PACKING_ENABLE | 161bf215546Sopenharmony_ci R500_COVERED_PTR_MASKING_ENABLE; 162bf215546Sopenharmony_ci } 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci /* Setup decompression if needed. No other HyperZ setting is required. */ 165bf215546Sopenharmony_ci if (r300->zmask_decompress) { 166bf215546Sopenharmony_ci z->zb_bw_cntl |= R300_FAST_FILL_ENABLE | 167bf215546Sopenharmony_ci R300_RD_COMP_ENABLE; 168bf215546Sopenharmony_ci return; 169bf215546Sopenharmony_ci } 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci /* Do not set anything if depth and stencil tests are off. */ 172bf215546Sopenharmony_ci if (!dsa->dsa.depth_enabled && 173bf215546Sopenharmony_ci !dsa->dsa.stencil[0].enabled && 174bf215546Sopenharmony_ci !dsa->dsa.stencil[1].enabled) { 175bf215546Sopenharmony_ci assert(!dsa->dsa.depth_writemask); 176bf215546Sopenharmony_ci return; 177bf215546Sopenharmony_ci } 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_ci /* Zbuffer compression. */ 180bf215546Sopenharmony_ci if (r300->zmask_in_use && !r300->locked_zbuffer) { 181bf215546Sopenharmony_ci z->zb_bw_cntl |= R300_FAST_FILL_ENABLE | 182bf215546Sopenharmony_ci R300_RD_COMP_ENABLE | 183bf215546Sopenharmony_ci R300_WR_COMP_ENABLE; 184bf215546Sopenharmony_ci } 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci /* HiZ. */ 187bf215546Sopenharmony_ci if (r300->hiz_in_use && !r300->locked_zbuffer) { 188bf215546Sopenharmony_ci /* HiZ cannot be used under some circumstances. */ 189bf215546Sopenharmony_ci if (!r300_hiz_allowed(r300)) { 190bf215546Sopenharmony_ci /* If writemask is disabled, the HiZ memory will not be changed, 191bf215546Sopenharmony_ci * so we can keep its content for later. */ 192bf215546Sopenharmony_ci if (dsa->dsa.depth_writemask) { 193bf215546Sopenharmony_ci r300->hiz_in_use = FALSE; 194bf215546Sopenharmony_ci } 195bf215546Sopenharmony_ci return; 196bf215546Sopenharmony_ci } 197bf215546Sopenharmony_ci DBG(r300, DBG_HYPERZ, "r300: Z-func: %i\n", dsa->dsa.depth_func); 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci /* Set the HiZ function if needed. */ 200bf215546Sopenharmony_ci if (r300->hiz_func == HIZ_FUNC_NONE) { 201bf215546Sopenharmony_ci r300->hiz_func = r300_get_hiz_func(r300); 202bf215546Sopenharmony_ci } 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci /* Setup the HiZ bits. */ 205bf215546Sopenharmony_ci z->zb_bw_cntl |= R300_HIZ_ENABLE | 206bf215546Sopenharmony_ci (r300->hiz_func == HIZ_FUNC_MIN ? R300_HIZ_MIN : R300_HIZ_MAX); 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci z->sc_hyperz |= R300_SC_HYPERZ_ENABLE | 209bf215546Sopenharmony_ci r300_get_sc_hz_max(r300); 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci if (r300->screen->caps.is_r500) { 212bf215546Sopenharmony_ci z->zb_bw_cntl |= R500_HIZ_EQUAL_REJECT_ENABLE; 213bf215546Sopenharmony_ci } 214bf215546Sopenharmony_ci } 215bf215546Sopenharmony_ci} 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ci/*****************************************************************************/ 218bf215546Sopenharmony_ci/* The ZTOP state */ 219bf215546Sopenharmony_ci/*****************************************************************************/ 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_cistatic boolean r300_dsa_alpha_test_enabled( 222bf215546Sopenharmony_ci struct pipe_depth_stencil_alpha_state *dsa) 223bf215546Sopenharmony_ci{ 224bf215546Sopenharmony_ci /* We are interested only in the cases when alpha testing can kill 225bf215546Sopenharmony_ci * a fragment. */ 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci return dsa->alpha_enabled && dsa->alpha_func != PIPE_FUNC_ALWAYS; 228bf215546Sopenharmony_ci} 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_cistatic void r300_update_ztop(struct r300_context* r300) 231bf215546Sopenharmony_ci{ 232bf215546Sopenharmony_ci struct r300_ztop_state* ztop_state = 233bf215546Sopenharmony_ci (struct r300_ztop_state*)r300->ztop_state.state; 234bf215546Sopenharmony_ci uint32_t old_ztop = ztop_state->z_buffer_top; 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci /* This is important enough that I felt it warranted a comment. 237bf215546Sopenharmony_ci * 238bf215546Sopenharmony_ci * According to the docs, these are the conditions where ZTOP must be 239bf215546Sopenharmony_ci * disabled: 240bf215546Sopenharmony_ci * 1) Alpha testing enabled 241bf215546Sopenharmony_ci * 2) Texture kill instructions in fragment shader 242bf215546Sopenharmony_ci * 3) Chroma key culling enabled 243bf215546Sopenharmony_ci * 4) W-buffering enabled 244bf215546Sopenharmony_ci * 245bf215546Sopenharmony_ci * The docs claim that for the first three cases, if no ZS writes happen, 246bf215546Sopenharmony_ci * then ZTOP can be used. 247bf215546Sopenharmony_ci * 248bf215546Sopenharmony_ci * (3) will never apply since we do not support chroma-keyed operations. 249bf215546Sopenharmony_ci * (4) will need to be re-examined (and this comment updated) if/when 250bf215546Sopenharmony_ci * Hyper-Z becomes supported. 251bf215546Sopenharmony_ci * 252bf215546Sopenharmony_ci * Additionally, the following conditions require disabled ZTOP: 253bf215546Sopenharmony_ci * 5) Depth writes in fragment shader 254bf215546Sopenharmony_ci * 6) Outstanding occlusion queries 255bf215546Sopenharmony_ci * 256bf215546Sopenharmony_ci * This register causes stalls all the way from SC to CB when changed, 257bf215546Sopenharmony_ci * but it is buffered on-chip so it does not hurt to write it if it has 258bf215546Sopenharmony_ci * not changed. 259bf215546Sopenharmony_ci * 260bf215546Sopenharmony_ci * ~C. 261bf215546Sopenharmony_ci */ 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci /* ZS writes */ 264bf215546Sopenharmony_ci if (util_writes_depth_stencil(r300->dsa_state.state) && 265bf215546Sopenharmony_ci (r300_dsa_alpha_test_enabled(r300->dsa_state.state) || /* (1) */ 266bf215546Sopenharmony_ci r300_fs(r300)->shader->info.uses_kill)) { /* (2) */ 267bf215546Sopenharmony_ci ztop_state->z_buffer_top = R300_ZTOP_DISABLE; 268bf215546Sopenharmony_ci } else if (r300_fragment_shader_writes_depth(r300_fs(r300))) { /* (5) */ 269bf215546Sopenharmony_ci ztop_state->z_buffer_top = R300_ZTOP_DISABLE; 270bf215546Sopenharmony_ci } else if (r300->query_current) { /* (6) */ 271bf215546Sopenharmony_ci ztop_state->z_buffer_top = R300_ZTOP_DISABLE; 272bf215546Sopenharmony_ci } else { 273bf215546Sopenharmony_ci ztop_state->z_buffer_top = R300_ZTOP_ENABLE; 274bf215546Sopenharmony_ci } 275bf215546Sopenharmony_ci if (ztop_state->z_buffer_top != old_ztop) 276bf215546Sopenharmony_ci r300_mark_atom_dirty(r300, &r300->ztop_state); 277bf215546Sopenharmony_ci} 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_civoid r300_update_hyperz_state(struct r300_context* r300) 280bf215546Sopenharmony_ci{ 281bf215546Sopenharmony_ci r300_update_ztop(r300); 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci if (r300->hyperz_state.dirty) { 284bf215546Sopenharmony_ci r300_update_hyperz(r300); 285bf215546Sopenharmony_ci } 286bf215546Sopenharmony_ci} 287