1 #include "nvfx_context.h"
2 #include "nvfx_state.h"
3 #include "nvfx_resource.h"
4 #include "draw/draw_context.h"
7 nvfx_state_viewport_validate(struct nvfx_context
*nvfx
)
9 struct nouveau_channel
*chan
= nvfx
->screen
->base
.channel
;
10 struct nouveau_grobj
*eng3d
= nvfx
->screen
->eng3d
;
11 struct pipe_viewport_state
*vpt
= &nvfx
->viewport
;
13 if(nvfx
->render_mode
== HW
) {
14 BEGIN_RING(chan
, eng3d
, NV30_3D_VIEWPORT_TRANSLATE_X
, 8);
15 OUT_RINGf(chan
, vpt
->translate
[0]);
16 OUT_RINGf(chan
, vpt
->translate
[1]);
17 OUT_RINGf(chan
, vpt
->translate
[2]);
18 OUT_RINGf(chan
, vpt
->translate
[3]);
19 OUT_RINGf(chan
, vpt
->scale
[0]);
20 OUT_RINGf(chan
, vpt
->scale
[1]);
21 OUT_RINGf(chan
, vpt
->scale
[2]);
22 OUT_RINGf(chan
, vpt
->scale
[3]);
23 BEGIN_RING(chan
, eng3d
, 0x1d78, 1);
26 BEGIN_RING(chan
, eng3d
, NV30_3D_VIEWPORT_TRANSLATE_X
, 8);
27 OUT_RINGf(chan
, 0.0f
);
28 OUT_RINGf(chan
, 0.0f
);
29 OUT_RINGf(chan
, 0.0f
);
30 OUT_RINGf(chan
, 0.0f
);
31 OUT_RINGf(chan
, 1.0f
);
32 OUT_RINGf(chan
, 1.0f
);
33 OUT_RINGf(chan
, 1.0f
);
34 OUT_RINGf(chan
, 1.0f
);
35 BEGIN_RING(chan
, eng3d
, 0x1d78, 1);
36 OUT_RING(chan
, nvfx
->is_nv4x
? 0x110 : 1);
41 nvfx_state_scissor_validate(struct nvfx_context
*nvfx
)
43 struct nouveau_channel
*chan
= nvfx
->screen
->base
.channel
;
44 struct nouveau_grobj
*eng3d
= nvfx
->screen
->eng3d
;
45 struct pipe_rasterizer_state
*rast
= &nvfx
->rasterizer
->pipe
;
46 struct pipe_scissor_state
*s
= &nvfx
->scissor
;
48 if ((rast
->scissor
== 0 && nvfx
->state
.scissor_enabled
== 0))
50 nvfx
->state
.scissor_enabled
= rast
->scissor
;
52 BEGIN_RING(chan
, eng3d
, NV30_3D_SCISSOR_HORIZ
, 2);
53 if (nvfx
->state
.scissor_enabled
) {
54 OUT_RING(chan
, ((s
->maxx
- s
->minx
) << 16) | s
->minx
);
55 OUT_RING(chan
, ((s
->maxy
- s
->miny
) << 16) | s
->miny
);
57 OUT_RING(chan
, 4096 << 16);
58 OUT_RING(chan
, 4096 << 16);
63 nvfx_state_sr_validate(struct nvfx_context
*nvfx
)
65 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
66 struct nouveau_grobj
*eng3d
= nvfx
->screen
->eng3d
;
67 struct pipe_stencil_ref
*sr
= &nvfx
->stencil_ref
;
69 BEGIN_RING(chan
, eng3d
, NV30_3D_STENCIL_FUNC_REF(0), 1);
70 OUT_RING(chan
, sr
->ref_value
[0]);
71 BEGIN_RING(chan
, eng3d
, NV30_3D_STENCIL_FUNC_REF(1), 1);
72 OUT_RING(chan
, sr
->ref_value
[1]);
76 nvfx_state_blend_colour_validate(struct nvfx_context
*nvfx
)
78 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
79 struct nouveau_grobj
*eng3d
= nvfx
->screen
->eng3d
;
80 struct pipe_blend_color
*bcol
= &nvfx
->blend_colour
;
82 BEGIN_RING(chan
, eng3d
, NV30_3D_BLEND_COLOR
, 1);
83 OUT_RING(chan
, ((float_to_ubyte(bcol
->color
[3]) << 24) |
84 (float_to_ubyte(bcol
->color
[0]) << 16) |
85 (float_to_ubyte(bcol
->color
[1]) << 8) |
86 (float_to_ubyte(bcol
->color
[2]) << 0)));
90 nvfx_state_stipple_validate(struct nvfx_context
*nvfx
)
92 struct nouveau_channel
*chan
= nvfx
->screen
->base
.channel
;
93 struct nouveau_grobj
*eng3d
= nvfx
->screen
->eng3d
;
95 BEGIN_RING(chan
, eng3d
, NV30_3D_POLYGON_STIPPLE_PATTERN(0), 32);
96 OUT_RINGp(chan
, nvfx
->stipple
, 32);
100 nvfx_coord_conventions_validate(struct nvfx_context
* nvfx
)
102 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
103 struct nouveau_grobj
*eng3d
= nvfx
->screen
->eng3d
;
104 unsigned value
= nvfx
->hw_fragprog
->coord_conventions
;
105 if(value
& NV30_3D_COORD_CONVENTIONS_ORIGIN_INVERTED
)
106 value
|= nvfx
->framebuffer
.height
<< NV30_3D_COORD_CONVENTIONS_HEIGHT__SHIFT
;
108 BEGIN_RING(chan
, eng3d
, NV30_3D_COORD_CONVENTIONS
, 1);
109 OUT_RING(chan
, value
);
113 nvfx_ucp_validate(struct nvfx_context
* nvfx
)
115 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
116 struct nouveau_grobj
*eng3d
= nvfx
->screen
->eng3d
;
119 NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE0
,
120 NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE1
,
121 NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE2
,
122 NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE3
,
123 NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE4
,
124 NV30_3D_VP_CLIP_PLANES_ENABLE_PLANE5
126 unsigned i
, enable
= 0, nr
= 0;
128 for (i
= 0; i
< 6; i
++) {
129 if (nvfx
->rasterizer
->pipe
.clip_plane_enable
& (1 << i
)) {
130 enable
|= enables
[i
];
135 if(!nvfx
->use_vp_clipping
)
137 BEGIN_RING(chan
, eng3d
, NV30_3D_VP_CLIP_PLANES_ENABLE
, 1);
140 BEGIN_RING(chan
, eng3d
, NV30_3D_VP_CLIP_PLANE(0, 0),
142 OUT_RINGp(chan
, &nvfx
->clip
.ucp
[0][0], nr
* 4);
145 BEGIN_RING(chan
, eng3d
, NV30_3D_VP_CLIP_PLANES_ENABLE
, 1);
146 OUT_RING(chan
, enable
);
150 nvfx_vertprog_ucp_validate(struct nvfx_context
* nvfx
)
152 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
153 struct nouveau_grobj
*eng3d
= nvfx
->screen
->eng3d
;
155 struct nvfx_vertex_program
* vp
= nvfx
->hw_vertprog
;
156 unsigned enable
= nvfx
->rasterizer
->pipe
.clip_plane_enable
;
157 unsigned nr
= util_bitcount(enable
);
159 if(nr
!= vp
->clip_nr
)
163 /* remove last instruction bit */
166 idx
= vp
->nr_insns
- 7 + vp
->clip_nr
;
167 BEGIN_RING(chan
, eng3d
, NV30_3D_VP_UPLOAD_FROM_ID
, 1);
168 OUT_RING(chan
, vp
->exec
->start
+ idx
);
169 BEGIN_RING(chan
, eng3d
, NV30_3D_VP_UPLOAD_INST(0), 4);
170 OUT_RINGp (chan
, vp
->insns
[idx
].data
, 4);
173 /* set last instruction bit */
174 idx
= vp
->nr_insns
- 7 + nr
;
175 BEGIN_RING(chan
, eng3d
, NV30_3D_VP_UPLOAD_FROM_ID
, 1);
176 OUT_RING(chan
, vp
->exec
->start
+ idx
);
177 BEGIN_RING(chan
, eng3d
, NV30_3D_VP_UPLOAD_INST(0), 4);
178 OUT_RINGp(chan
, vp
->insns
[idx
].data
, 3);
179 OUT_RING(chan
, vp
->insns
[idx
].data
[3] | 1);
183 // TODO: only do this for the ones changed
184 for(i
= 0; enable
; ++i
)
186 unsigned index
= ffs(enable
) - 1;
187 enable
&= ~(1 << index
);
189 BEGIN_RING(chan
, eng3d
, NV30_3D_VP_UPLOAD_CONST_ID
, 5);
190 OUT_RING(chan
, vp
->data
->start
+ i
);
191 OUT_RINGp (chan
, nvfx
->clip
.ucp
[index
], 4);
196 nvfx_state_validate_common(struct nvfx_context
*nvfx
)
198 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
199 struct nouveau_grobj
*eng3d
= nvfx
->screen
->eng3d
;
201 unsigned still_dirty
= 0;
202 boolean flush_tex_cache
= FALSE
;
204 if(nvfx
!= nvfx
->screen
->cur_ctx
)
207 nvfx
->hw_vtxelt_nr
= 16;
208 nvfx
->hw_pointsprite_control
= -1;
209 nvfx
->hw_vp_output
= -1;
210 nvfx
->screen
->cur_ctx
= nvfx
;
211 nvfx
->relocs_needed
= NVFX_RELOCATE_ALL
;
216 if(nvfx
->render_mode
== HW
)
218 if(dirty
& (NVFX_NEW_VERTPROG
| NVFX_NEW_VERTCONST
))
220 if(!nvfx_vertprog_validate(nvfx
))
224 if(dirty
& NVFX_NEW_ARRAYS
)
226 if(!nvfx_vbo_validate(nvfx
))
230 if(dirty
& NVFX_NEW_INDEX
)
232 if(nvfx
->use_index_buffer
)
233 nvfx_idxbuf_validate(nvfx
);
235 still_dirty
= NVFX_NEW_INDEX
;
240 if(dirty
& NVFX_NEW_VERTPROG
) {
241 assert(nvfx_vertprog_validate(nvfx
));
242 nvfx_vbo_swtnl_validate(nvfx
);
246 if(dirty
& NVFX_NEW_SAMPLER
) {
247 /* XXX: we take the big hammer here, I have no idea why this is needed
248 to make this work properly */
249 nvfx
->dirty
&= ~NVFX_NEW_SAMPLER
;
250 nvfx_fragtex_validate(nvfx
);
252 // TODO: only set this if really necessary
253 flush_tex_cache
= TRUE
;
256 if(dirty
& NVFX_NEW_RAST
)
257 sb_emit(chan
, nvfx
->rasterizer
->sb
, nvfx
->rasterizer
->sb_len
);
259 if(dirty
& NVFX_NEW_SCISSOR
)
260 nvfx_state_scissor_validate(nvfx
);
262 if(dirty
& NVFX_NEW_STIPPLE
)
263 nvfx_state_stipple_validate(nvfx
);
265 if(nvfx
->dirty
& (NVFX_NEW_UCP
| NVFX_NEW_RAST
))
266 nvfx_ucp_validate(nvfx
);
268 if(nvfx
->use_vp_clipping
&& (nvfx
->dirty
&
269 (NVFX_NEW_UCP
| NVFX_NEW_VERTPROG
|
271 nvfx_vertprog_ucp_validate(nvfx
);
273 if(dirty
& (NVFX_NEW_FRAGPROG
| NVFX_NEW_FRAGCONST
|
274 NVFX_NEW_VERTPROG
| NVFX_NEW_SPRITE
))
276 nvfx_fragprog_validate(nvfx
);
277 if(dirty
& NVFX_NEW_FRAGPROG
)
278 flush_tex_cache
= TRUE
; // TODO: do we need this?
283 unsigned vp_output
= nvfx
->hw_vertprog
->or | nvfx
->hw_fragprog
->or;
284 vp_output
|= ((1 << (nvfx
->rasterizer
->pipe
.clip_plane_enable
& 63)) - 1) << 6;
286 if(vp_output
!= nvfx
->hw_vp_output
)
288 BEGIN_RING(chan
, eng3d
, NV40_3D_VP_RESULT_EN
, 1);
289 OUT_RING(chan
, vp_output
);
290 nvfx
->hw_vp_output
= vp_output
;
294 if(dirty
& NVFX_NEW_FB
)
295 nvfx_framebuffer_validate(nvfx
);
297 if(dirty
& NVFX_NEW_BLEND
)
298 sb_emit(chan
, nvfx
->blend
->sb
, nvfx
->blend
->sb_len
);
300 if(dirty
& NVFX_NEW_BCOL
)
301 nvfx_state_blend_colour_validate(nvfx
);
303 if(dirty
& NVFX_NEW_ZSA
)
304 sb_emit(chan
, nvfx
->zsa
->sb
, nvfx
->zsa
->sb_len
);
306 if(dirty
& NVFX_NEW_SR
)
307 nvfx_state_sr_validate(nvfx
);
309 /* XXX: nv3x needs viewport revalidation after RAST or ZSA change */
310 if(dirty
& (NVFX_NEW_VIEWPORT
| NVFX_NEW_RAST
| NVFX_NEW_ZSA
))
312 nvfx_state_viewport_validate(nvfx
);
315 if(dirty
& (NVFX_NEW_ZSA
| NVFX_NEW_FB
))
317 BEGIN_RING(chan
, eng3d
, NV30_3D_DEPTH_WRITE_ENABLE
, 2);
318 OUT_RING(chan
, nvfx
->framebuffer
.zsbuf
&&
319 nvfx
->zsa
->pipe
.depth
.writemask
);
320 OUT_RING(chan
, nvfx
->framebuffer
.zsbuf
&&
321 nvfx
->zsa
->pipe
.depth
.enabled
);
324 if(dirty
& (NVFX_NEW_FRAGPROG
| NVFX_NEW_FB
))
325 nvfx_coord_conventions_validate(nvfx
);
327 if(flush_tex_cache
&& nvfx
->is_nv4x
)
329 BEGIN_RING(chan
, eng3d
, NV40_3D_TEX_CACHE_CTL
, 1);
331 BEGIN_RING(chan
, eng3d
, NV40_3D_TEX_CACHE_CTL
, 1);
335 nvfx
->dirty
= dirty
& still_dirty
;
341 nvfx_state_relocate(struct nvfx_context
*nvfx
, unsigned relocs
)
343 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
344 /* we need to ensure there is enough space to output relocations in one go */
345 const unsigned max_relocs
= 0
346 + 16 /* vertex buffers, incl. dma flag */
347 + 2 /* index buffer plus format+dma flag */
348 + 2 * 5 /* 4 cbufs + zsbuf, plus dma objects */
349 + 2 * 16 /* fragment textures plus format+dma flag */
350 + 2 * 4 /* vertex textures plus format+dma flag */
351 + 1 /* fragprog incl dma flag */
354 MARK_RING(chan
, max_relocs
* 2, max_relocs
* 2);
356 if(relocs
& NVFX_RELOCATE_FRAMEBUFFER
)
357 nvfx_framebuffer_relocate(nvfx
);
358 if(relocs
& NVFX_RELOCATE_FRAGTEX
)
359 nvfx_fragtex_relocate(nvfx
);
360 if(relocs
& NVFX_RELOCATE_FRAGPROG
)
361 nvfx_fragprog_relocate(nvfx
);
362 if(relocs
& NVFX_RELOCATE_VTXBUF
)
363 nvfx_vbo_relocate(nvfx
);
364 if(relocs
& NVFX_RELOCATE_IDXBUF
)
365 nvfx_idxbuf_relocate(nvfx
);
369 nvfx_state_validate(struct nvfx_context
*nvfx
)
371 if (nvfx
->render_mode
!= HW
) {
372 /* Don't even bother trying to go back to hw if none
373 * of the states that caused swtnl previously have changed.
375 if ((nvfx
->fallback_swtnl
& nvfx
->dirty
)
376 != nvfx
->fallback_swtnl
)
379 /* Attempt to go to hwtnl again */
380 nvfx
->dirty
|= (NVFX_NEW_VIEWPORT
|
383 nvfx
->render_mode
= HW
;
386 if(!nvfx_state_validate_common(nvfx
))
393 nvfx_state_validate_swtnl(struct nvfx_context
*nvfx
)
395 struct draw_context
*draw
= nvfx
->draw
;
397 /* Setup for swtnl */
398 if (nvfx
->render_mode
== HW
) {
399 static boolean warned
= FALSE
;
401 NOUVEAU_ERR("hw->swtnl 0x%08x\n", nvfx
->fallback_swtnl
);
404 nvfx
->pipe
.flush(&nvfx
->pipe
, NULL
);
405 nvfx
->dirty
|= (NVFX_NEW_VIEWPORT
|
408 nvfx
->render_mode
= SWTNL
;
411 if (nvfx
->draw_dirty
& NVFX_NEW_VERTPROG
) {
412 if(!nvfx
->vertprog
->draw_vs
)
413 nvfx
->vertprog
->draw_vs
= draw_create_vertex_shader(draw
, &nvfx
->vertprog
->pipe
);
414 draw_bind_vertex_shader(draw
, nvfx
->vertprog
->draw_vs
);
417 if (nvfx
->draw_dirty
& NVFX_NEW_RAST
)
418 draw_set_rasterizer_state(draw
, &nvfx
->rasterizer
->pipe
,
421 if (nvfx
->draw_dirty
& NVFX_NEW_UCP
)
422 draw_set_clip_state(draw
, &nvfx
->clip
);
424 if (nvfx
->draw_dirty
& NVFX_NEW_VIEWPORT
)
425 draw_set_viewport_state(draw
, &nvfx
->viewport
);
427 if (nvfx
->draw_dirty
& NVFX_NEW_ARRAYS
) {
428 draw_set_vertex_buffers(draw
, nvfx
->vtxbuf_nr
, nvfx
->vtxbuf
);
429 draw_set_vertex_elements(draw
, nvfx
->vtxelt
->num_elements
, nvfx
->vtxelt
->pipe
);
432 if (nvfx
->draw_dirty
& NVFX_NEW_INDEX
)
433 draw_set_index_buffer(draw
, &nvfx
->idxbuf
);
435 nvfx_state_validate_common(nvfx
);
437 nvfx
->draw_dirty
= 0;