Merge branch 'glsl2-head' into glsl2
[mesa.git] / src / gallium / drivers / r300 / r300_hyperz.c
1 /*
2 * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com>
3 * Copyright 2009 Marek Olšák <maraeo@gmail.com>
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
23
24
25 #include "r300_hyperz.h"
26 #include "r300_context.h"
27 #include "r300_reg.h"
28 #include "r300_fs.h"
29
30 /*****************************************************************************/
31 /* The ZTOP state */
32 /*****************************************************************************/
33
34 static boolean r300_dsa_writes_stencil(
35 struct pipe_stencil_state *s)
36 {
37 return s->enabled && s->writemask &&
38 (s->fail_op != PIPE_STENCIL_OP_KEEP ||
39 s->zfail_op != PIPE_STENCIL_OP_KEEP ||
40 s->zpass_op != PIPE_STENCIL_OP_KEEP);
41 }
42
43 static boolean r300_dsa_writes_depth_stencil(
44 struct pipe_depth_stencil_alpha_state *dsa)
45 {
46 /* We are interested only in the cases when a depth or stencil value
47 * can be changed. */
48
49 if (dsa->depth.enabled && dsa->depth.writemask &&
50 dsa->depth.func != PIPE_FUNC_NEVER)
51 return TRUE;
52
53 if (r300_dsa_writes_stencil(&dsa->stencil[0]) ||
54 r300_dsa_writes_stencil(&dsa->stencil[1]))
55 return TRUE;
56
57 return FALSE;
58 }
59
60 static boolean r300_dsa_alpha_test_enabled(
61 struct pipe_depth_stencil_alpha_state *dsa)
62 {
63 /* We are interested only in the cases when alpha testing can kill
64 * a fragment. */
65
66 return dsa->alpha.enabled && dsa->alpha.func != PIPE_FUNC_ALWAYS;
67 }
68
69 static void r300_update_ztop(struct r300_context* r300)
70 {
71 struct r300_ztop_state* ztop_state =
72 (struct r300_ztop_state*)r300->ztop_state.state;
73 uint32_t old_ztop = ztop_state->z_buffer_top;
74
75 /* This is important enough that I felt it warranted a comment.
76 *
77 * According to the docs, these are the conditions where ZTOP must be
78 * disabled:
79 * 1) Alpha testing enabled
80 * 2) Texture kill instructions in fragment shader
81 * 3) Chroma key culling enabled
82 * 4) W-buffering enabled
83 *
84 * The docs claim that for the first three cases, if no ZS writes happen,
85 * then ZTOP can be used.
86 *
87 * (3) will never apply since we do not support chroma-keyed operations.
88 * (4) will need to be re-examined (and this comment updated) if/when
89 * Hyper-Z becomes supported.
90 *
91 * Additionally, the following conditions require disabled ZTOP:
92 * 5) Depth writes in fragment shader
93 * 6) Outstanding occlusion queries
94 *
95 * This register causes stalls all the way from SC to CB when changed,
96 * but it is buffered on-chip so it does not hurt to write it if it has
97 * not changed.
98 *
99 * ~C.
100 */
101
102 /* ZS writes */
103 if (r300_dsa_writes_depth_stencil(r300->dsa_state.state) &&
104 (r300_dsa_alpha_test_enabled(r300->dsa_state.state) || /* (1) */
105 r300_fs(r300)->shader->info.uses_kill)) { /* (2) */
106 ztop_state->z_buffer_top = R300_ZTOP_DISABLE;
107 } else if (r300_fragment_shader_writes_depth(r300_fs(r300))) { /* (5) */
108 ztop_state->z_buffer_top = R300_ZTOP_DISABLE;
109 } else if (r300->query_current) { /* (6) */
110 ztop_state->z_buffer_top = R300_ZTOP_DISABLE;
111 } else {
112 ztop_state->z_buffer_top = R300_ZTOP_ENABLE;
113 }
114
115 if (ztop_state->z_buffer_top != old_ztop)
116 r300->ztop_state.dirty = TRUE;
117 }
118
119 void r300_update_hyperz_state(struct r300_context* r300)
120 {
121 r300_update_ztop(r300);
122 }