2 #include "nv50_context.h"
3 #include "os/os_time.h"
6 nv50_validate_fb(struct nv50_context
*nv50
)
8 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
9 struct pipe_framebuffer_state
*fb
= &nv50
->framebuffer
;
11 unsigned ms_mode
= NV50_3D_MULTISAMPLE_MODE_MS1
;
13 nouveau_bufctx_reset(nv50
->bufctx_3d
, NV50_BIND_FB
);
15 BEGIN_NV04(push
, NV50_3D(RT_CONTROL
), 1);
16 PUSH_DATA (push
, (076543210 << 4) | fb
->nr_cbufs
);
17 BEGIN_NV04(push
, NV50_3D(SCREEN_SCISSOR_HORIZ
), 2);
18 PUSH_DATA (push
, fb
->width
<< 16);
19 PUSH_DATA (push
, fb
->height
<< 16);
21 for (i
= 0; i
< fb
->nr_cbufs
; ++i
) {
22 struct nv50_miptree
*mt
= nv50_miptree(fb
->cbufs
[i
]->texture
);
23 struct nv50_surface
*sf
= nv50_surface(fb
->cbufs
[i
]);
24 struct nouveau_bo
*bo
= mt
->base
.bo
;
26 BEGIN_NV04(push
, NV50_3D(RT_ADDRESS_HIGH(i
)), 5);
27 PUSH_DATAh(push
, bo
->offset
+ sf
->offset
);
28 PUSH_DATA (push
, bo
->offset
+ sf
->offset
);
29 PUSH_DATA (push
, nv50_format_table
[sf
->base
.format
].rt
);
30 if (likely(nouveau_bo_memtype(bo
))) {
31 PUSH_DATA (push
, mt
->level
[sf
->base
.u
.tex
.level
].tile_mode
);
32 PUSH_DATA (push
, mt
->layer_stride
>> 2);
33 BEGIN_NV04(push
, NV50_3D(RT_HORIZ(i
)), 2);
34 PUSH_DATA (push
, sf
->width
);
35 PUSH_DATA (push
, sf
->height
);
36 BEGIN_NV04(push
, NV50_3D(RT_ARRAY_MODE
), 1);
37 PUSH_DATA (push
, sf
->depth
);
41 BEGIN_NV04(push
, NV50_3D(RT_HORIZ(i
)), 2);
42 PUSH_DATA (push
, NV50_3D_RT_HORIZ_LINEAR
| mt
->level
[0].pitch
);
43 PUSH_DATA (push
, sf
->height
);
44 BEGIN_NV04(push
, NV50_3D(RT_ARRAY_MODE
), 1);
51 ms_mode
= mt
->ms_mode
;
53 if (mt
->base
.status
& NOUVEAU_BUFFER_STATUS_GPU_READING
)
54 nv50
->state
.rt_serialize
= TRUE
;
55 mt
->base
.status
|= NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
56 mt
->base
.status
&= NOUVEAU_BUFFER_STATUS_GPU_READING
;
58 /* only register for writing, otherwise we'd always serialize here */
59 BCTX_REFN(nv50
->bufctx_3d
, FB
, &mt
->base
, WR
);
63 struct nv50_miptree
*mt
= nv50_miptree(fb
->zsbuf
->texture
);
64 struct nv50_surface
*sf
= nv50_surface(fb
->zsbuf
);
65 struct nouveau_bo
*bo
= mt
->base
.bo
;
66 int unk
= mt
->base
.base
.target
== PIPE_TEXTURE_2D
;
68 BEGIN_NV04(push
, NV50_3D(ZETA_ADDRESS_HIGH
), 5);
69 PUSH_DATAh(push
, bo
->offset
+ sf
->offset
);
70 PUSH_DATA (push
, bo
->offset
+ sf
->offset
);
71 PUSH_DATA (push
, nv50_format_table
[fb
->zsbuf
->format
].rt
);
72 PUSH_DATA (push
, mt
->level
[sf
->base
.u
.tex
.level
].tile_mode
);
73 PUSH_DATA (push
, mt
->layer_stride
>> 2);
74 BEGIN_NV04(push
, NV50_3D(ZETA_ENABLE
), 1);
76 BEGIN_NV04(push
, NV50_3D(ZETA_HORIZ
), 3);
77 PUSH_DATA (push
, sf
->width
);
78 PUSH_DATA (push
, sf
->height
);
79 PUSH_DATA (push
, (unk
<< 16) | sf
->depth
);
81 ms_mode
= mt
->ms_mode
;
83 if (mt
->base
.status
& NOUVEAU_BUFFER_STATUS_GPU_READING
)
84 nv50
->state
.rt_serialize
= TRUE
;
85 mt
->base
.status
|= NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
86 mt
->base
.status
&= NOUVEAU_BUFFER_STATUS_GPU_READING
;
88 BCTX_REFN(nv50
->bufctx_3d
, FB
, &mt
->base
, WR
);
90 BEGIN_NV04(push
, NV50_3D(ZETA_ENABLE
), 1);
94 BEGIN_NV04(push
, NV50_3D(MULTISAMPLE_MODE
), 1);
95 PUSH_DATA (push
, ms_mode
);
97 BEGIN_NV04(push
, NV50_3D(VIEWPORT_HORIZ(0)), 2);
98 PUSH_DATA (push
, fb
->width
<< 16);
99 PUSH_DATA (push
, fb
->height
<< 16);
103 nv50_validate_blend_colour(struct nv50_context
*nv50
)
105 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
107 BEGIN_NV04(push
, NV50_3D(BLEND_COLOR(0)), 4);
108 PUSH_DATAf(push
, nv50
->blend_colour
.color
[0]);
109 PUSH_DATAf(push
, nv50
->blend_colour
.color
[1]);
110 PUSH_DATAf(push
, nv50
->blend_colour
.color
[2]);
111 PUSH_DATAf(push
, nv50
->blend_colour
.color
[3]);
115 nv50_validate_stencil_ref(struct nv50_context
*nv50
)
117 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
119 BEGIN_NV04(push
, NV50_3D(STENCIL_FRONT_FUNC_REF
), 1);
120 PUSH_DATA (push
, nv50
->stencil_ref
.ref_value
[0]);
121 BEGIN_NV04(push
, NV50_3D(STENCIL_BACK_FUNC_REF
), 1);
122 PUSH_DATA (push
, nv50
->stencil_ref
.ref_value
[1]);
126 nv50_validate_stipple(struct nv50_context
*nv50
)
128 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
131 BEGIN_NV04(push
, NV50_3D(POLYGON_STIPPLE_PATTERN(0)), 32);
132 for (i
= 0; i
< 32; ++i
)
133 PUSH_DATA(push
, util_bswap32(nv50
->stipple
.stipple
[i
]));
137 nv50_validate_scissor(struct nv50_context
*nv50
)
139 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
140 struct pipe_scissor_state
*s
= &nv50
->scissor
;
141 #ifdef NV50_SCISSORS_CLIPPING
142 struct pipe_viewport_state
*vp
= &nv50
->viewport
;
143 int minx
, maxx
, miny
, maxy
;
146 (NV50_NEW_SCISSOR
| NV50_NEW_VIEWPORT
| NV50_NEW_FRAMEBUFFER
)) &&
147 nv50
->state
.scissor
== nv50
->rast
->pipe
.scissor
)
149 nv50
->state
.scissor
= nv50
->rast
->pipe
.scissor
;
151 if (nv50
->state
.scissor
) {
158 maxx
= nv50
->framebuffer
.width
;
160 maxy
= nv50
->framebuffer
.height
;
163 minx
= MAX2(minx
, (int)(vp
->translate
[0] - fabsf(vp
->scale
[0])));
164 maxx
= MIN2(maxx
, (int)(vp
->translate
[0] + fabsf(vp
->scale
[0])));
165 miny
= MAX2(miny
, (int)(vp
->translate
[1] - fabsf(vp
->scale
[1])));
166 maxy
= MIN2(maxy
, (int)(vp
->translate
[1] + fabsf(vp
->scale
[1])));
168 BEGIN_NV04(push
, NV50_3D(SCISSOR_HORIZ(0)), 2);
169 PUSH_DATA (push
, (maxx
<< 16) | minx
);
170 PUSH_DATA (push
, (maxy
<< 16) | miny
);
172 BEGIN_NV04(push
, NV50_3D(SCISSOR_HORIZ(0)), 2);
173 PUSH_DATA (push
, (s
->maxx
<< 16) | s
->minx
);
174 PUSH_DATA (push
, (s
->maxy
<< 16) | s
->miny
);
179 nv50_validate_viewport(struct nv50_context
*nv50
)
181 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
184 BEGIN_NV04(push
, NV50_3D(VIEWPORT_TRANSLATE_X(0)), 3);
185 PUSH_DATAf(push
, nv50
->viewport
.translate
[0]);
186 PUSH_DATAf(push
, nv50
->viewport
.translate
[1]);
187 PUSH_DATAf(push
, nv50
->viewport
.translate
[2]);
188 BEGIN_NV04(push
, NV50_3D(VIEWPORT_SCALE_X(0)), 3);
189 PUSH_DATAf(push
, nv50
->viewport
.scale
[0]);
190 PUSH_DATAf(push
, nv50
->viewport
.scale
[1]);
191 PUSH_DATAf(push
, nv50
->viewport
.scale
[2]);
193 zmin
= nv50
->viewport
.translate
[2] - fabsf(nv50
->viewport
.scale
[2]);
194 zmax
= nv50
->viewport
.translate
[2] + fabsf(nv50
->viewport
.scale
[2]);
196 #ifdef NV50_SCISSORS_CLIPPING
197 BEGIN_NV04(push
, NV50_3D(DEPTH_RANGE_NEAR(0)), 2);
198 PUSH_DATAf(push
, zmin
);
199 PUSH_DATAf(push
, zmax
);
204 nv50_check_program_ucps(struct nv50_context
*nv50
,
205 struct nv50_program
*vp
, uint8_t mask
)
207 const unsigned n
= util_logbase2(mask
) + 1;
209 if (vp
->vp
.clpd_nr
>= n
)
211 nv50_program_destroy(nv50
, vp
);
214 if (likely(vp
== nv50
->vertprog
)) {
215 nv50
->dirty
|= NV50_NEW_VERTPROG
;
216 nv50_vertprog_validate(nv50
);
218 nv50
->dirty
|= NV50_NEW_GMTYPROG
;
219 nv50_gmtyprog_validate(nv50
);
221 nv50_fp_linkage_validate(nv50
);
225 nv50_validate_clip(struct nv50_context
*nv50
)
227 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
228 struct nv50_program
*vp
;
231 if (nv50
->dirty
& NV50_NEW_CLIP
) {
232 BEGIN_NV04(push
, NV50_3D(CB_ADDR
), 1);
233 PUSH_DATA (push
, (0 << 8) | NV50_CB_AUX
);
234 BEGIN_NI04(push
, NV50_3D(CB_DATA(0)), PIPE_MAX_CLIP_PLANES
* 4);
235 PUSH_DATAp(push
, &nv50
->clip
.ucp
[0][0], PIPE_MAX_CLIP_PLANES
* 4);
242 clip_enable
= nv50
->rast
->pipe
.clip_plane_enable
;
244 BEGIN_NV04(push
, NV50_3D(CLIP_DISTANCE_ENABLE
), 1);
245 PUSH_DATA (push
, clip_enable
);
248 nv50_check_program_ucps(nv50
, vp
, clip_enable
);
252 nv50_validate_blend(struct nv50_context
*nv50
)
254 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
256 PUSH_SPACE(push
, nv50
->blend
->size
);
257 PUSH_DATAp(push
, nv50
->blend
->state
, nv50
->blend
->size
);
261 nv50_validate_zsa(struct nv50_context
*nv50
)
263 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
265 PUSH_SPACE(push
, nv50
->zsa
->size
);
266 PUSH_DATAp(push
, nv50
->zsa
->state
, nv50
->zsa
->size
);
270 nv50_validate_rasterizer(struct nv50_context
*nv50
)
272 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
274 PUSH_SPACE(push
, nv50
->rast
->size
);
275 PUSH_DATAp(push
, nv50
->rast
->state
, nv50
->rast
->size
);
279 nv50_validate_sample_mask(struct nv50_context
*nv50
)
281 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
285 nv50
->sample_mask
& 0xffff,
286 nv50
->sample_mask
& 0xffff,
287 nv50
->sample_mask
& 0xffff,
288 nv50
->sample_mask
& 0xffff
291 BEGIN_NV04(push
, NV50_3D(MSAA_MASK(0)), 4);
292 PUSH_DATA (push
, mask
[0]);
293 PUSH_DATA (push
, mask
[1]);
294 PUSH_DATA (push
, mask
[2]);
295 PUSH_DATA (push
, mask
[3]);
299 nv50_switch_pipe_context(struct nv50_context
*ctx_to
)
301 struct nv50_context
*ctx_from
= ctx_to
->screen
->cur_ctx
;
304 ctx_to
->state
= ctx_from
->state
;
309 ctx_to
->dirty
&= ~(NV50_NEW_VERTEX
| NV50_NEW_ARRAYS
);
311 if (!ctx_to
->vertprog
)
312 ctx_to
->dirty
&= ~NV50_NEW_VERTPROG
;
313 if (!ctx_to
->fragprog
)
314 ctx_to
->dirty
&= ~NV50_NEW_FRAGPROG
;
317 ctx_to
->dirty
&= ~NV50_NEW_BLEND
;
319 #ifdef NV50_SCISSORS_CLIPPING
320 ctx_to
->dirty
&= ~(NV50_NEW_RASTERIZER
| NV50_NEW_SCISSOR
);
322 ctx_to
->dirty
&= ~NV50_NEW_RASTERIZER
;
325 ctx_to
->dirty
&= ~NV50_NEW_ZSA
;
327 ctx_to
->screen
->cur_ctx
= ctx_to
;
330 static struct state_validate
{
331 void (*func
)(struct nv50_context
*);
333 } validate_list
[] = {
334 { nv50_validate_fb
, NV50_NEW_FRAMEBUFFER
},
335 { nv50_validate_blend
, NV50_NEW_BLEND
},
336 { nv50_validate_zsa
, NV50_NEW_ZSA
},
337 { nv50_validate_sample_mask
, NV50_NEW_SAMPLE_MASK
},
338 { nv50_validate_rasterizer
, NV50_NEW_RASTERIZER
},
339 { nv50_validate_blend_colour
, NV50_NEW_BLEND_COLOUR
},
340 { nv50_validate_stencil_ref
, NV50_NEW_STENCIL_REF
},
341 { nv50_validate_stipple
, NV50_NEW_STIPPLE
},
342 #ifdef NV50_SCISSORS_CLIPPING
343 { nv50_validate_scissor
, NV50_NEW_SCISSOR
| NV50_NEW_VIEWPORT
|
344 NV50_NEW_RASTERIZER
|
345 NV50_NEW_FRAMEBUFFER
},
347 { nv50_validate_scissor
, NV50_NEW_SCISSOR
},
349 { nv50_validate_viewport
, NV50_NEW_VIEWPORT
},
350 { nv50_vertprog_validate
, NV50_NEW_VERTPROG
},
351 { nv50_gmtyprog_validate
, NV50_NEW_GMTYPROG
},
352 { nv50_fragprog_validate
, NV50_NEW_FRAGPROG
},
353 { nv50_fp_linkage_validate
, NV50_NEW_FRAGPROG
| NV50_NEW_VERTPROG
|
354 NV50_NEW_GMTYPROG
| NV50_NEW_RASTERIZER
},
355 { nv50_gp_linkage_validate
, NV50_NEW_GMTYPROG
| NV50_NEW_VERTPROG
},
356 { nv50_validate_derived_rs
, NV50_NEW_FRAGPROG
| NV50_NEW_RASTERIZER
|
357 NV50_NEW_VERTPROG
| NV50_NEW_GMTYPROG
},
358 { nv50_validate_clip
, NV50_NEW_CLIP
| NV50_NEW_RASTERIZER
|
359 NV50_NEW_VERTPROG
| NV50_NEW_GMTYPROG
},
360 { nv50_constbufs_validate
, NV50_NEW_CONSTBUF
},
361 { nv50_validate_textures
, NV50_NEW_TEXTURES
},
362 { nv50_validate_samplers
, NV50_NEW_SAMPLERS
},
363 { nv50_stream_output_validate
, NV50_NEW_STRMOUT
|
364 NV50_NEW_VERTPROG
| NV50_NEW_GMTYPROG
},
365 { nv50_vertex_arrays_validate
, NV50_NEW_VERTEX
| NV50_NEW_ARRAYS
}
367 #define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
370 nv50_state_validate(struct nv50_context
*nv50
, uint32_t mask
, unsigned words
)
376 if (nv50
->screen
->cur_ctx
!= nv50
)
377 nv50_switch_pipe_context(nv50
);
379 state_mask
= nv50
->dirty
& mask
;
382 for (i
= 0; i
< validate_list_len
; ++i
) {
383 struct state_validate
*validate
= &validate_list
[i
];
385 if (state_mask
& validate
->states
)
386 validate
->func(nv50
);
388 nv50
->dirty
&= ~state_mask
;
390 if (nv50
->state
.rt_serialize
) {
391 nv50
->state
.rt_serialize
= FALSE
;
392 BEGIN_NV04(nv50
->base
.pushbuf
, SUBC_3D(NV50_GRAPH_SERIALIZE
), 1);
393 PUSH_DATA (nv50
->base
.pushbuf
, 0);
396 nv50_bufctx_fence(nv50
->bufctx_3d
, FALSE
);
398 nouveau_pushbuf_bufctx(nv50
->base
.pushbuf
, nv50
->bufctx_3d
);
399 ret
= nouveau_pushbuf_validate(nv50
->base
.pushbuf
);
401 if (unlikely(nv50
->state
.flushed
)) {
402 nv50
->state
.flushed
= FALSE
;
403 nv50_bufctx_fence(nv50
->bufctx_3d
, TRUE
);