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_arrays
)(struct pipe_context
*pipe
,
38 unsigned mode
, unsigned start
, unsigned count
);
40 void (*draw_range_elements
)(
41 struct pipe_context
*pipe
, struct pipe_resource
*indexBuffer
,
42 unsigned indexSize
, int indexBias
, unsigned minIndex
, unsigned maxIndex
,
43 unsigned mode
, unsigned start
, unsigned count
);
45 uint32_t rs_cull_mode
;
46 uint32_t zb_stencilrefmask
;
47 ubyte ref_value_front
;
50 static boolean
r300_stencilref_needed(struct r300_context
*r300
)
52 struct r300_dsa_state
*dsa
= (struct r300_dsa_state
*)r300
->dsa_state
.state
;
54 return dsa
->two_sided_stencil_ref
||
56 r300
->stencil_ref
.ref_value
[0] != r300
->stencil_ref
.ref_value
[1]);
59 /* Set drawing for front faces. */
60 static void r300_stencilref_begin(struct r300_context
*r300
)
62 struct r300_stencilref_context
*sr
= r300
->stencilref_fallback
;
63 struct r300_rs_state
*rs
= (struct r300_rs_state
*)r300
->rs_state
.state
;
64 struct r300_dsa_state
*dsa
= (struct r300_dsa_state
*)r300
->dsa_state
.state
;
67 sr
->rs_cull_mode
= rs
->cull_mode
;
68 sr
->zb_stencilrefmask
= dsa
->stencil_ref_mask
;
69 sr
->ref_value_front
= r300
->stencil_ref
.ref_value
[0];
71 /* We *cull* pixels, therefore no need to mask out the bits. */
72 rs
->cull_mode
|= R300_CULL_BACK
;
74 r300
->rs_state
.dirty
= TRUE
;
77 /* Set drawing for back faces. */
78 static void r300_stencilref_switch_side(struct r300_context
*r300
)
80 struct r300_stencilref_context
*sr
= r300
->stencilref_fallback
;
81 struct r300_rs_state
*rs
= (struct r300_rs_state
*)r300
->rs_state
.state
;
82 struct r300_dsa_state
*dsa
= (struct r300_dsa_state
*)r300
->dsa_state
.state
;
84 rs
->cull_mode
= sr
->rs_cull_mode
| R300_CULL_FRONT
;
85 dsa
->stencil_ref_mask
= dsa
->stencil_ref_bf
;
86 r300
->stencil_ref
.ref_value
[0] = r300
->stencil_ref
.ref_value
[1];
88 r300
->rs_state
.dirty
= TRUE
;
89 r300
->dsa_state
.dirty
= TRUE
;
92 /* Restore the original state. */
93 static void r300_stencilref_end(struct r300_context
*r300
)
95 struct r300_stencilref_context
*sr
= r300
->stencilref_fallback
;
96 struct r300_rs_state
*rs
= (struct r300_rs_state
*)r300
->rs_state
.state
;
97 struct r300_dsa_state
*dsa
= (struct r300_dsa_state
*)r300
->dsa_state
.state
;
100 rs
->cull_mode
= sr
->rs_cull_mode
;
101 dsa
->stencil_ref_mask
= sr
->zb_stencilrefmask
;
102 r300
->stencil_ref
.ref_value
[0] = sr
->ref_value_front
;
104 r300
->rs_state
.dirty
= TRUE
;
105 r300
->dsa_state
.dirty
= TRUE
;
108 static void r300_stencilref_draw_arrays(struct pipe_context
*pipe
, unsigned mode
,
109 unsigned start
, unsigned count
)
111 struct r300_context
*r300
= r300_context(pipe
);
112 struct r300_stencilref_context
*sr
= r300
->stencilref_fallback
;
114 if (!r300_stencilref_needed(r300
)) {
115 sr
->draw_arrays(pipe
, mode
, start
, count
);
117 r300_stencilref_begin(r300
);
118 sr
->draw_arrays(pipe
, mode
, start
, count
);
119 r300_stencilref_switch_side(r300
);
120 sr
->draw_arrays(pipe
, mode
, start
, count
);
121 r300_stencilref_end(r300
);
125 static void r300_stencilref_draw_range_elements(
126 struct pipe_context
*pipe
, struct pipe_resource
*indexBuffer
,
127 unsigned indexSize
, int indexBias
, unsigned minIndex
, unsigned maxIndex
,
128 unsigned mode
, unsigned start
, unsigned count
)
130 struct r300_context
*r300
= r300_context(pipe
);
131 struct r300_stencilref_context
*sr
= r300
->stencilref_fallback
;
133 if (!r300_stencilref_needed(r300
)) {
134 sr
->draw_range_elements(pipe
, indexBuffer
, indexSize
, indexBias
,
135 minIndex
, maxIndex
, mode
, start
, count
);
137 r300_stencilref_begin(r300
);
138 sr
->draw_range_elements(pipe
, indexBuffer
, indexSize
, indexBias
,
139 minIndex
, maxIndex
, mode
, start
, count
);
140 r300_stencilref_switch_side(r300
);
141 sr
->draw_range_elements(pipe
, indexBuffer
, indexSize
, indexBias
,
142 minIndex
, maxIndex
, mode
, start
, count
);
143 r300_stencilref_end(r300
);
147 void r300_plug_in_stencil_ref_fallback(struct r300_context
*r300
)
149 r300
->stencilref_fallback
= CALLOC_STRUCT(r300_stencilref_context
);
151 /* Save original draw functions. */
152 r300
->stencilref_fallback
->draw_arrays
= r300
->context
.draw_arrays
;
153 r300
->stencilref_fallback
->draw_range_elements
= r300
->context
.draw_range_elements
;
155 /* Override the draw functions. */
156 r300
->context
.draw_arrays
= r300_stencilref_draw_arrays
;
157 r300
->context
.draw_range_elements
= r300_stencilref_draw_range_elements
;