2 * Copyright 2010 Marek Olšák <maraeo@gmail.com>
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE. */
24 * The two-sided stencil reference value fallback for r3xx-r4xx chips.
25 * These chips support two-sided stencil functions but they do not support
26 * a two-sided reference value.
28 * The functions below split every draw call which uses the two-sided
29 * reference value into two draw calls -- the first one renders front faces
30 * and the second renders back faces with the other reference value.
33 #include "r300_context.h"
36 struct r300_stencilref_context
{
37 void (*draw_vbo
)(struct pipe_context
*pipe
,
38 const struct pipe_draw_info
*info
);
40 uint32_t rs_cull_mode
;
41 uint32_t zb_stencilrefmask
;
42 ubyte ref_value_front
;
45 static boolean
r300_stencilref_needed(struct r300_context
*r300
)
47 struct r300_dsa_state
*dsa
= (struct r300_dsa_state
*)r300
->dsa_state
.state
;
49 return dsa
->two_sided_stencil_ref
||
51 r300
->stencil_ref
.ref_value
[0] != r300
->stencil_ref
.ref_value
[1]);
54 /* Set drawing for front faces. */
55 static void r300_stencilref_begin(struct r300_context
*r300
)
57 struct r300_stencilref_context
*sr
= r300
->stencilref_fallback
;
58 struct r300_rs_state
*rs
= (struct r300_rs_state
*)r300
->rs_state
.state
;
59 struct r300_dsa_state
*dsa
= (struct r300_dsa_state
*)r300
->dsa_state
.state
;
62 sr
->rs_cull_mode
= rs
->cb_main
[rs
->cull_mode_index
];
63 sr
->zb_stencilrefmask
= dsa
->stencil_ref_mask
;
64 sr
->ref_value_front
= r300
->stencil_ref
.ref_value
[0];
66 /* We *cull* pixels, therefore no need to mask out the bits. */
67 rs
->cb_main
[rs
->cull_mode_index
] |= R300_CULL_BACK
;
69 r300_mark_atom_dirty(r300
, &r300
->rs_state
);
72 /* Set drawing for back faces. */
73 static void r300_stencilref_switch_side(struct r300_context
*r300
)
75 struct r300_stencilref_context
*sr
= r300
->stencilref_fallback
;
76 struct r300_rs_state
*rs
= (struct r300_rs_state
*)r300
->rs_state
.state
;
77 struct r300_dsa_state
*dsa
= (struct r300_dsa_state
*)r300
->dsa_state
.state
;
79 rs
->cb_main
[rs
->cull_mode_index
] = sr
->rs_cull_mode
| R300_CULL_FRONT
;
80 dsa
->stencil_ref_mask
= dsa
->stencil_ref_bf
;
81 r300
->stencil_ref
.ref_value
[0] = r300
->stencil_ref
.ref_value
[1];
83 r300_mark_atom_dirty(r300
, &r300
->rs_state
);
84 r300_mark_atom_dirty(r300
, &r300
->dsa_state
);
87 /* Restore the original state. */
88 static void r300_stencilref_end(struct r300_context
*r300
)
90 struct r300_stencilref_context
*sr
= r300
->stencilref_fallback
;
91 struct r300_rs_state
*rs
= (struct r300_rs_state
*)r300
->rs_state
.state
;
92 struct r300_dsa_state
*dsa
= (struct r300_dsa_state
*)r300
->dsa_state
.state
;
95 rs
->cb_main
[rs
->cull_mode_index
] = sr
->rs_cull_mode
;
96 dsa
->stencil_ref_mask
= sr
->zb_stencilrefmask
;
97 r300
->stencil_ref
.ref_value
[0] = sr
->ref_value_front
;
99 r300_mark_atom_dirty(r300
, &r300
->rs_state
);
100 r300_mark_atom_dirty(r300
, &r300
->dsa_state
);
103 static void r300_stencilref_draw_vbo(struct pipe_context
*pipe
,
104 const struct pipe_draw_info
*info
)
106 struct r300_context
*r300
= r300_context(pipe
);
107 struct r300_stencilref_context
*sr
= r300
->stencilref_fallback
;
109 if (!r300_stencilref_needed(r300
)) {
110 sr
->draw_vbo(pipe
, info
);
112 r300_stencilref_begin(r300
);
113 sr
->draw_vbo(pipe
, info
);
114 r300_stencilref_switch_side(r300
);
115 sr
->draw_vbo(pipe
, info
);
116 r300_stencilref_end(r300
);
120 void r300_plug_in_stencil_ref_fallback(struct r300_context
*r300
)
122 r300
->stencilref_fallback
= CALLOC_STRUCT(r300_stencilref_context
);
124 /* Save original draw function. */
125 r300
->stencilref_fallback
->draw_vbo
= r300
->context
.draw_vbo
;
127 /* Override the draw function. */
128 r300
->context
.draw_vbo
= r300_stencilref_draw_vbo
;