2 * Copyright 2010 Christoph Bumiller
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 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 #include "pipe/p_context.h"
24 #include "pipe/p_defines.h"
25 #include "pipe/p_state.h"
26 #include "util/u_inlines.h"
28 #include "nvc0_context.h"
31 nvc0_program_update_context_state(struct nvc0_context
*nvc0
,
32 struct nvc0_program
*prog
, int stage
)
34 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
36 if (prog
&& prog
->need_tls
) {
37 const uint32_t flags
= NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
;
38 if (!nvc0
->state
.tls_required
)
39 BCTX_REFN_bo(nvc0
->bufctx_3d
, TLS
, flags
, nvc0
->screen
->tls
);
40 nvc0
->state
.tls_required
|= 1 << stage
;
42 if (nvc0
->state
.tls_required
== (1 << stage
))
43 nouveau_bufctx_reset(nvc0
->bufctx_3d
, NVC0_BIND_TLS
);
44 nvc0
->state
.tls_required
&= ~(1 << stage
);
47 if (prog
&& prog
->immd_size
) {
48 BEGIN_NVC0(push
, NVC0_3D(CB_SIZE
), 3);
49 /* NOTE: may overlap code of a different shader */
50 PUSH_DATA (push
, align(prog
->immd_size
, 0x100));
51 PUSH_DATAh(push
, nvc0
->screen
->text
->offset
+ prog
->immd_base
);
52 PUSH_DATA (push
, nvc0
->screen
->text
->offset
+ prog
->immd_base
);
53 BEGIN_NVC0(push
, NVC0_3D(CB_BIND(stage
)), 1);
54 PUSH_DATA (push
, (14 << 4) | 1);
56 nvc0
->state
.c14_bound
|= 1 << stage
;
58 if (nvc0
->state
.c14_bound
& (1 << stage
)) {
59 BEGIN_NVC0(push
, NVC0_3D(CB_BIND(stage
)), 1);
60 PUSH_DATA (push
, (14 << 4) | 0);
62 nvc0
->state
.c14_bound
&= ~(1 << stage
);
67 nvc0_program_validate(struct nvc0_context
*nvc0
, struct nvc0_program
*prog
)
72 if (!prog
->translated
) {
73 prog
->translated
= nvc0_program_translate(
74 prog
, nvc0
->screen
->base
.device
->chipset
);
75 if (!prog
->translated
)
79 if (likely(prog
->code_size
))
80 return nvc0_program_upload_code(nvc0
, prog
);
81 return TRUE
; /* stream output info only */
85 nvc0_vertprog_validate(struct nvc0_context
*nvc0
)
87 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
88 struct nvc0_program
*vp
= nvc0
->vertprog
;
90 if (!nvc0_program_validate(nvc0
, vp
))
92 nvc0_program_update_context_state(nvc0
, vp
, 0);
94 BEGIN_NVC0(push
, NVC0_3D(SP_SELECT(1)), 2);
95 PUSH_DATA (push
, 0x11);
96 PUSH_DATA (push
, vp
->code_base
);
97 BEGIN_NVC0(push
, NVC0_3D(SP_GPR_ALLOC(1)), 1);
98 PUSH_DATA (push
, vp
->max_gpr
);
100 // BEGIN_NVC0(push, NVC0_3D_(0x163c), 1);
101 // PUSH_DATA (push, 0);
105 nvc0_fragprog_validate(struct nvc0_context
*nvc0
)
107 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
108 struct nvc0_program
*fp
= nvc0
->fragprog
;
110 if (!nvc0_program_validate(nvc0
, fp
))
112 nvc0_program_update_context_state(nvc0
, fp
, 4);
114 if (fp
->fp
.early_z
!= nvc0
->state
.early_z_forced
) {
115 nvc0
->state
.early_z_forced
= fp
->fp
.early_z
;
116 IMMED_NVC0(push
, NVC0_3D(FORCE_EARLY_FRAGMENT_TESTS
), fp
->fp
.early_z
);
119 BEGIN_NVC0(push
, NVC0_3D(SP_SELECT(5)), 2);
120 PUSH_DATA (push
, 0x51);
121 PUSH_DATA (push
, fp
->code_base
);
122 BEGIN_NVC0(push
, NVC0_3D(SP_GPR_ALLOC(5)), 1);
123 PUSH_DATA (push
, fp
->max_gpr
);
125 BEGIN_NVC0(push
, SUBC_3D(0x0360), 2);
126 PUSH_DATA (push
, 0x20164010);
127 PUSH_DATA (push
, 0x20);
128 BEGIN_NVC0(push
, NVC0_3D(ZCULL_TEST_MASK
), 1);
129 PUSH_DATA (push
, fp
->flags
[0]);
133 nvc0_tctlprog_validate(struct nvc0_context
*nvc0
)
135 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
136 struct nvc0_program
*tp
= nvc0
->tctlprog
;
138 if (tp
&& nvc0_program_validate(nvc0
, tp
)) {
139 if (tp
->tp
.tess_mode
!= ~0) {
140 BEGIN_NVC0(push
, NVC0_3D(TESS_MODE
), 1);
141 PUSH_DATA (push
, tp
->tp
.tess_mode
);
143 BEGIN_NVC0(push
, NVC0_3D(SP_SELECT(2)), 2);
144 PUSH_DATA (push
, 0x21);
145 PUSH_DATA (push
, tp
->code_base
);
146 BEGIN_NVC0(push
, NVC0_3D(SP_GPR_ALLOC(2)), 1);
147 PUSH_DATA (push
, tp
->max_gpr
);
149 if (tp
->tp
.input_patch_size
<= 32)
150 IMMED_NVC0(push
, NVC0_3D(PATCH_VERTICES
), tp
->tp
.input_patch_size
);
152 BEGIN_NVC0(push
, NVC0_3D(SP_SELECT(2)), 1);
153 PUSH_DATA (push
, 0x20);
155 nvc0_program_update_context_state(nvc0
, tp
, 1);
159 nvc0_tevlprog_validate(struct nvc0_context
*nvc0
)
161 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
162 struct nvc0_program
*tp
= nvc0
->tevlprog
;
164 if (tp
&& nvc0_program_validate(nvc0
, tp
)) {
165 if (tp
->tp
.tess_mode
!= ~0) {
166 BEGIN_NVC0(push
, NVC0_3D(TESS_MODE
), 1);
167 PUSH_DATA (push
, tp
->tp
.tess_mode
);
169 BEGIN_NVC0(push
, NVC0_3D(MACRO_TEP_SELECT
), 1);
170 PUSH_DATA (push
, 0x31);
171 BEGIN_NVC0(push
, NVC0_3D(SP_START_ID(3)), 1);
172 PUSH_DATA (push
, tp
->code_base
);
173 BEGIN_NVC0(push
, NVC0_3D(SP_GPR_ALLOC(3)), 1);
174 PUSH_DATA (push
, tp
->max_gpr
);
176 BEGIN_NVC0(push
, NVC0_3D(MACRO_TEP_SELECT
), 1);
177 PUSH_DATA (push
, 0x30);
179 nvc0_program_update_context_state(nvc0
, tp
, 2);
183 nvc0_gmtyprog_validate(struct nvc0_context
*nvc0
)
185 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
186 struct nvc0_program
*gp
= nvc0
->gmtyprog
;
189 nvc0_program_validate(nvc0
, gp
);
191 /* we allow GPs with no code for specifying stream output state only */
192 if (gp
&& gp
->code_size
) {
193 const boolean gp_selects_layer
= gp
->hdr
[13] & (1 << 9);
195 BEGIN_NVC0(push
, NVC0_3D(MACRO_GP_SELECT
), 1);
196 PUSH_DATA (push
, 0x41);
197 BEGIN_NVC0(push
, NVC0_3D(SP_START_ID(4)), 1);
198 PUSH_DATA (push
, gp
->code_base
);
199 BEGIN_NVC0(push
, NVC0_3D(SP_GPR_ALLOC(4)), 1);
200 PUSH_DATA (push
, gp
->max_gpr
);
201 BEGIN_NVC0(push
, NVC0_3D(LAYER
), 1);
202 PUSH_DATA (push
, gp_selects_layer
? NVC0_3D_LAYER_USE_GP
: 0);
204 IMMED_NVC0(push
, NVC0_3D(LAYER
), 0);
205 BEGIN_NVC0(push
, NVC0_3D(MACRO_GP_SELECT
), 1);
206 PUSH_DATA (push
, 0x40);
208 nvc0_program_update_context_state(nvc0
, gp
, 3);
212 nvc0_tfb_validate(struct nvc0_context
*nvc0
)
214 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
215 struct nvc0_transform_feedback_state
*tfb
;
218 if (nvc0
->gmtyprog
) tfb
= nvc0
->gmtyprog
->tfb
;
220 if (nvc0
->tevlprog
) tfb
= nvc0
->tevlprog
->tfb
;
222 tfb
= nvc0
->vertprog
->tfb
;
224 IMMED_NVC0(push
, NVC0_3D(TFB_ENABLE
), (tfb
&& nvc0
->num_tfbbufs
) ? 1 : 0);
226 if (tfb
&& tfb
!= nvc0
->state
.tfb
) {
227 for (b
= 0; b
< 4; ++b
) {
228 if (tfb
->varying_count
[b
]) {
229 unsigned n
= (tfb
->varying_count
[b
] + 3) / 4;
231 BEGIN_NVC0(push
, NVC0_3D(TFB_STREAM(b
)), 3);
233 PUSH_DATA (push
, tfb
->varying_count
[b
]);
234 PUSH_DATA (push
, tfb
->stride
[b
]);
235 BEGIN_NVC0(push
, NVC0_3D(TFB_VARYING_LOCS(b
, 0)), n
);
236 PUSH_DATAp(push
, tfb
->varying_index
[b
], n
);
239 nvc0_so_target(nvc0
->tfbbuf
[b
])->stride
= tfb
->stride
[b
];
241 IMMED_NVC0(push
, NVC0_3D(TFB_VARYING_COUNT(b
)), 0);
245 nvc0
->state
.tfb
= tfb
;
247 if (!(nvc0
->dirty
& NVC0_NEW_TFB_TARGETS
))
249 nouveau_bufctx_reset(nvc0
->bufctx_3d
, NVC0_BIND_TFB
);
251 for (b
= 0; b
< nvc0
->num_tfbbufs
; ++b
) {
252 struct nvc0_so_target
*targ
= nvc0_so_target(nvc0
->tfbbuf
[b
]);
253 struct nv04_resource
*buf
= nv04_resource(targ
->pipe
.buffer
);
256 targ
->stride
= tfb
->stride
[b
];
258 if (!(nvc0
->tfbbuf_dirty
& (1 << b
)))
262 nvc0_query_fifo_wait(push
, targ
->pq
);
263 BEGIN_NVC0(push
, NVC0_3D(TFB_BUFFER_ENABLE(b
)), 5);
265 PUSH_DATAh(push
, buf
->address
+ targ
->pipe
.buffer_offset
);
266 PUSH_DATA (push
, buf
->address
+ targ
->pipe
.buffer_offset
);
267 PUSH_DATA (push
, targ
->pipe
.buffer_size
);
269 nvc0_query_pushbuf_submit(push
, targ
->pq
, 0x4);
271 PUSH_DATA(push
, 0); /* TFB_BUFFER_OFFSET */
274 BCTX_REFN(nvc0
->bufctx_3d
, TFB
, buf
, WR
);
277 IMMED_NVC0(push
, NVC0_3D(TFB_BUFFER_ENABLE(b
)), 0);