2 #include "nv50_context.h"
3 #include "os/os_time.h"
6 nv50_validate_fb(struct nv50_context
*nv50
)
8 struct nouveau_channel
*chan
= nv50
->screen
->base
.channel
;
9 struct pipe_framebuffer_state
*fb
= &nv50
->framebuffer
;
11 boolean serialize
= FALSE
;
13 nv50_bufctx_reset(nv50
, NV50_BUFCTX_FRAME
);
15 BEGIN_RING(chan
, RING_3D(RT_CONTROL
), 1);
16 OUT_RING (chan
, (076543210 << 4) | fb
->nr_cbufs
);
17 BEGIN_RING(chan
, RING_3D(SCREEN_SCISSOR_HORIZ
), 2);
18 OUT_RING (chan
, fb
->width
<< 16);
19 OUT_RING (chan
, fb
->height
<< 16);
21 MARK_RING(chan
, 9 * fb
->nr_cbufs
, 2 * fb
->nr_cbufs
);
23 for (i
= 0; i
< fb
->nr_cbufs
; ++i
) {
24 struct nv50_miptree
*mt
= nv50_miptree(fb
->cbufs
[i
]->texture
);
25 struct nv50_surface
*sf
= nv50_surface(fb
->cbufs
[i
]);
26 struct nouveau_bo
*bo
= mt
->base
.bo
;
27 uint32_t offset
= sf
->offset
;
29 BEGIN_RING(chan
, RING_3D(RT_ADDRESS_HIGH(i
)), 5);
30 OUT_RELOCh(chan
, bo
, offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
31 OUT_RELOCl(chan
, bo
, offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
32 OUT_RING (chan
, nv50_format_table
[sf
->base
.format
].rt
);
33 OUT_RING (chan
, mt
->level
[sf
->base
.u
.tex
.level
].tile_mode
<< 4);
34 OUT_RING (chan
, mt
->layer_stride
>> 2);
35 BEGIN_RING(chan
, RING_3D(RT_HORIZ(i
)), 2);
36 OUT_RING (chan
, sf
->width
);
37 OUT_RING (chan
, sf
->height
);
38 BEGIN_RING(chan
, RING_3D(RT_ARRAY_MODE
), 1);
39 OUT_RING (chan
, sf
->depth
);
41 if (mt
->base
.status
& NOUVEAU_BUFFER_STATUS_GPU_READING
)
43 mt
->base
.status
|= NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
44 mt
->base
.status
&= NOUVEAU_BUFFER_STATUS_GPU_READING
;
46 /* only register for writing, otherwise we'd always serialize here */
47 nv50_bufctx_add_resident(nv50
, NV50_BUFCTX_FRAME
, &mt
->base
,
48 NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
52 struct nv50_miptree
*mt
= nv50_miptree(fb
->zsbuf
->texture
);
53 struct nv50_surface
*sf
= nv50_surface(fb
->zsbuf
);
54 struct nouveau_bo
*bo
= mt
->base
.bo
;
55 int unk
= mt
->base
.base
.target
== PIPE_TEXTURE_2D
;
56 uint32_t offset
= sf
->offset
;
58 MARK_RING (chan
, 12, 2);
59 BEGIN_RING(chan
, RING_3D(ZETA_ADDRESS_HIGH
), 5);
60 OUT_RELOCh(chan
, bo
, offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
61 OUT_RELOCl(chan
, bo
, offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
62 OUT_RING (chan
, nv50_format_table
[fb
->zsbuf
->format
].rt
);
63 OUT_RING (chan
, mt
->level
[sf
->base
.u
.tex
.level
].tile_mode
<< 4);
64 OUT_RING (chan
, mt
->layer_stride
>> 2);
65 BEGIN_RING(chan
, RING_3D(ZETA_ENABLE
), 1);
67 BEGIN_RING(chan
, RING_3D(ZETA_HORIZ
), 3);
68 OUT_RING (chan
, sf
->width
);
69 OUT_RING (chan
, sf
->height
);
70 OUT_RING (chan
, (unk
<< 16) | sf
->depth
);
72 if (mt
->base
.status
& NOUVEAU_BUFFER_STATUS_GPU_READING
)
74 mt
->base
.status
|= NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
75 mt
->base
.status
&= NOUVEAU_BUFFER_STATUS_GPU_READING
;
77 nv50_bufctx_add_resident(nv50
, NV50_BUFCTX_FRAME
, &mt
->base
,
78 NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
80 BEGIN_RING(chan
, RING_3D(ZETA_ENABLE
), 1);
84 BEGIN_RING(chan
, RING_3D(VIEWPORT_HORIZ(0)), 2);
85 OUT_RING (chan
, fb
->width
<< 16);
86 OUT_RING (chan
, fb
->height
<< 16);
89 BEGIN_RING(chan
, RING_3D(SERIALIZE
), 1);
95 nv50_validate_blend_colour(struct nv50_context
*nv50
)
97 struct nouveau_channel
*chan
= nv50
->screen
->base
.channel
;
99 BEGIN_RING(chan
, RING_3D(BLEND_COLOR(0)), 4);
100 OUT_RINGf (chan
, nv50
->blend_colour
.color
[0]);
101 OUT_RINGf (chan
, nv50
->blend_colour
.color
[1]);
102 OUT_RINGf (chan
, nv50
->blend_colour
.color
[2]);
103 OUT_RINGf (chan
, nv50
->blend_colour
.color
[3]);
107 nv50_validate_stencil_ref(struct nv50_context
*nv50
)
109 struct nouveau_channel
*chan
= nv50
->screen
->base
.channel
;
111 BEGIN_RING(chan
, RING_3D(STENCIL_FRONT_FUNC_REF
), 1);
112 OUT_RING (chan
, nv50
->stencil_ref
.ref_value
[0]);
113 BEGIN_RING(chan
, RING_3D(STENCIL_BACK_FUNC_REF
), 1);
114 OUT_RING (chan
, nv50
->stencil_ref
.ref_value
[1]);
118 nv50_validate_stipple(struct nv50_context
*nv50
)
120 struct nouveau_channel
*chan
= nv50
->screen
->base
.channel
;
123 BEGIN_RING(chan
, RING_3D(POLYGON_STIPPLE_PATTERN(0)), 32);
124 for (i
= 0; i
< 32; ++i
)
125 OUT_RING(chan
, util_bswap32(nv50
->stipple
.stipple
[i
]));
129 nv50_validate_scissor(struct nv50_context
*nv50
)
131 struct nouveau_channel
*chan
= nv50
->screen
->base
.channel
;
132 struct pipe_scissor_state
*s
= &nv50
->scissor
;
133 #ifdef NV50_SCISSORS_CLIPPING
134 struct pipe_viewport_state
*vp
= &nv50
->viewport
;
135 int minx
, maxx
, miny
, maxy
;
138 (NV50_NEW_SCISSOR
| NV50_NEW_VIEWPORT
| NV50_NEW_FRAMEBUFFER
)) &&
139 nv50
->state
.scissor
== nv50
->rast
->pipe
.scissor
)
141 nv50
->state
.scissor
= nv50
->rast
->pipe
.scissor
;
143 if (nv50
->state
.scissor
) {
150 maxx
= nv50
->framebuffer
.width
;
152 maxy
= nv50
->framebuffer
.height
;
155 minx
= MAX2(minx
, (int)(vp
->translate
[0] - fabsf(vp
->scale
[0])));
156 maxx
= MIN2(maxx
, (int)(vp
->translate
[0] + fabsf(vp
->scale
[0])));
157 miny
= MAX2(miny
, (int)(vp
->translate
[1] - fabsf(vp
->scale
[1])));
158 maxy
= MIN2(maxy
, (int)(vp
->translate
[1] + fabsf(vp
->scale
[1])));
160 BEGIN_RING(chan
, RING_3D(SCISSOR_HORIZ(0)), 2);
161 OUT_RING (chan
, (maxx
<< 16) | minx
);
162 OUT_RING (chan
, (maxy
<< 16) | miny
);
164 BEGIN_RING(chan
, RING_3D(SCISSOR_HORIZ(0)), 2);
165 OUT_RING (chan
, (s
->maxx
<< 16) | s
->minx
);
166 OUT_RING (chan
, (s
->maxy
<< 16) | s
->miny
);
171 nv50_validate_viewport(struct nv50_context
*nv50
)
173 struct nouveau_channel
*chan
= nv50
->screen
->base
.channel
;
176 BEGIN_RING(chan
, RING_3D(VIEWPORT_TRANSLATE_X(0)), 3);
177 OUT_RINGf (chan
, nv50
->viewport
.translate
[0]);
178 OUT_RINGf (chan
, nv50
->viewport
.translate
[1]);
179 OUT_RINGf (chan
, nv50
->viewport
.translate
[2]);
180 BEGIN_RING(chan
, RING_3D(VIEWPORT_SCALE_X(0)), 3);
181 OUT_RINGf (chan
, nv50
->viewport
.scale
[0]);
182 OUT_RINGf (chan
, nv50
->viewport
.scale
[1]);
183 OUT_RINGf (chan
, nv50
->viewport
.scale
[2]);
185 zmin
= nv50
->viewport
.translate
[2] - fabsf(nv50
->viewport
.scale
[2]);
186 zmax
= nv50
->viewport
.translate
[2] + fabsf(nv50
->viewport
.scale
[2]);
188 #ifdef NV50_SCISSORS_CLIPPING
189 BEGIN_RING(chan
, RING_3D(DEPTH_RANGE_NEAR(0)), 2);
190 OUT_RINGf (chan
, zmin
);
191 OUT_RINGf (chan
, zmax
);
196 nv50_validate_clip(struct nv50_context
*nv50
)
198 struct nouveau_channel
*chan
= nv50
->screen
->base
.channel
;
201 if (nv50
->clip
.depth_clamp
) {
203 NV50_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_NEAR
|
204 NV50_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_FAR
|
205 NV50_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK1
;
210 #ifndef NV50_SCISSORS_CLIPPING
212 NV50_3D_VIEW_VOLUME_CLIP_CTRL_UNK7
|
213 NV50_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK1
;
216 BEGIN_RING(chan
, RING_3D(VIEW_VOLUME_CLIP_CTRL
), 1);
217 OUT_RING (chan
, clip
);
220 BEGIN_RING(chan
, RING_3D(CB_ADDR
), 1);
221 OUT_RING (chan
, (0 << 8) | NV50_CB_AUX
);
222 BEGIN_RING_NI(chan
, RING_3D(CB_DATA(0)), nv50
->clip
.nr
* 4);
223 OUT_RINGp (chan
, &nv50
->clip
.ucp
[0][0], nv50
->clip
.nr
* 4);
226 BEGIN_RING(chan
, RING_3D(VP_CLIP_DISTANCE_ENABLE
), 1);
227 OUT_RING (chan
, (1 << nv50
->clip
.nr
) - 1);
229 if (nv50
->vertprog
&& nv50
->clip
.nr
> nv50
->vertprog
->vp
.clpd_nr
)
230 nv50
->dirty
|= NV50_NEW_VERTPROG
;
234 nv50_validate_blend(struct nv50_context
*nv50
)
236 struct nouveau_channel
*chan
= nv50
->screen
->base
.channel
;
238 WAIT_RING(chan
, nv50
->blend
->size
);
239 OUT_RINGp(chan
, nv50
->blend
->state
, nv50
->blend
->size
);
243 nv50_validate_zsa(struct nv50_context
*nv50
)
245 struct nouveau_channel
*chan
= nv50
->screen
->base
.channel
;
247 WAIT_RING(chan
, nv50
->zsa
->size
);
248 OUT_RINGp(chan
, nv50
->zsa
->state
, nv50
->zsa
->size
);
252 nv50_validate_rasterizer(struct nv50_context
*nv50
)
254 struct nouveau_channel
*chan
= nv50
->screen
->base
.channel
;
256 WAIT_RING(chan
, nv50
->rast
->size
);
257 OUT_RINGp(chan
, nv50
->rast
->state
, nv50
->rast
->size
);
261 nv50_switch_pipe_context(struct nv50_context
*ctx_to
)
263 struct nv50_context
*ctx_from
= ctx_to
->screen
->cur_ctx
;
266 ctx_to
->state
= ctx_from
->state
;
271 ctx_to
->dirty
&= ~(NV50_NEW_VERTEX
| NV50_NEW_ARRAYS
);
273 if (!ctx_to
->vertprog
)
274 ctx_to
->dirty
&= ~NV50_NEW_VERTPROG
;
275 if (!ctx_to
->fragprog
)
276 ctx_to
->dirty
&= ~NV50_NEW_FRAGPROG
;
279 ctx_to
->dirty
&= ~NV50_NEW_BLEND
;
281 ctx_to
->dirty
&= ~NV50_NEW_RASTERIZER
;
283 ctx_to
->dirty
&= ~NV50_NEW_ZSA
;
285 ctx_to
->screen
->base
.channel
->user_private
= ctx_to
->screen
->cur_ctx
=
289 static struct state_validate
{
290 void (*func
)(struct nv50_context
*);
292 } validate_list
[] = {
293 { nv50_validate_fb
, NV50_NEW_FRAMEBUFFER
},
294 { nv50_validate_blend
, NV50_NEW_BLEND
},
295 { nv50_validate_zsa
, NV50_NEW_ZSA
},
296 { nv50_validate_rasterizer
, NV50_NEW_RASTERIZER
},
297 { nv50_validate_blend_colour
, NV50_NEW_BLEND_COLOUR
},
298 { nv50_validate_stencil_ref
, NV50_NEW_STENCIL_REF
},
299 { nv50_validate_stipple
, NV50_NEW_STIPPLE
},
300 #ifdef NV50_SCISSORS_CLIPPING
301 { nv50_validate_scissor
, NV50_NEW_SCISSOR
| NV50_NEW_VIEWPORT
|
302 NV50_NEW_RASTERIZER
|
303 NV50_NEW_FRAMEBUFFER
},
305 { nv50_validate_scissor
, NV50_NEW_SCISSOR
},
307 { nv50_validate_viewport
, NV50_NEW_VIEWPORT
},
308 { nv50_validate_clip
, NV50_NEW_CLIP
},
309 { nv50_vertprog_validate
, NV50_NEW_VERTPROG
},
310 { nv50_gmtyprog_validate
, NV50_NEW_GMTYPROG
},
311 { nv50_fragprog_validate
, NV50_NEW_FRAGPROG
},
312 { nv50_fp_linkage_validate
, NV50_NEW_FRAGPROG
| NV50_NEW_VERTPROG
|
314 { nv50_gp_linkage_validate
, NV50_NEW_GMTYPROG
| NV50_NEW_VERTPROG
},
315 { nv50_validate_derived_rs
, NV50_NEW_FRAGPROG
| NV50_NEW_RASTERIZER
|
316 NV50_NEW_VERTPROG
| NV50_NEW_GMTYPROG
},
317 { nv50_constbufs_validate
, NV50_NEW_CONSTBUF
},
318 { nv50_validate_textures
, NV50_NEW_TEXTURES
},
319 { nv50_validate_samplers
, NV50_NEW_SAMPLERS
},
320 { nv50_vertex_arrays_validate
, NV50_NEW_VERTEX
| NV50_NEW_ARRAYS
}
322 #define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
325 nv50_state_validate(struct nv50_context
*nv50
)
329 if (nv50
->screen
->cur_ctx
!= nv50
)
330 nv50_switch_pipe_context(nv50
);
333 for (i
= 0; i
< validate_list_len
; ++i
) {
334 struct state_validate
*validate
= &validate_list
[i
];
336 if (nv50
->dirty
& validate
->states
)
337 validate
->func(nv50
);
342 nv50_bufctx_emit_relocs(nv50
);