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 unsigned ms_mode
= NV50_3D_MULTISAMPLE_MODE_MS1
;
12 boolean serialize
= FALSE
;
14 nv50_bufctx_reset(nv50
, NV50_BUFCTX_FRAME
);
16 BEGIN_RING(chan
, RING_3D(RT_CONTROL
), 1);
17 OUT_RING (chan
, (076543210 << 4) | fb
->nr_cbufs
);
18 BEGIN_RING(chan
, RING_3D(SCREEN_SCISSOR_HORIZ
), 2);
19 OUT_RING (chan
, fb
->width
<< 16);
20 OUT_RING (chan
, fb
->height
<< 16);
22 MARK_RING(chan
, 9 * fb
->nr_cbufs
, 2 * fb
->nr_cbufs
);
24 for (i
= 0; i
< fb
->nr_cbufs
; ++i
) {
25 struct nv50_miptree
*mt
= nv50_miptree(fb
->cbufs
[i
]->texture
);
26 struct nv50_surface
*sf
= nv50_surface(fb
->cbufs
[i
]);
27 struct nouveau_bo
*bo
= mt
->base
.bo
;
28 uint32_t offset
= sf
->offset
;
30 BEGIN_RING(chan
, RING_3D(RT_ADDRESS_HIGH(i
)), 5);
31 OUT_RELOCh(chan
, bo
, offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
32 OUT_RELOCl(chan
, bo
, offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
33 OUT_RING (chan
, nv50_format_table
[sf
->base
.format
].rt
);
34 if (likely(nouveau_bo_tile_layout(bo
))) {
35 OUT_RING (chan
, mt
->level
[sf
->base
.u
.tex
.level
].tile_mode
<< 4);
36 OUT_RING (chan
, mt
->layer_stride
>> 2);
37 BEGIN_RING(chan
, RING_3D(RT_HORIZ(i
)), 2);
38 OUT_RING (chan
, sf
->width
);
39 OUT_RING (chan
, sf
->height
);
40 BEGIN_RING(chan
, RING_3D(RT_ARRAY_MODE
), 1);
41 OUT_RING (chan
, sf
->depth
);
45 BEGIN_RING(chan
, RING_3D(RT_HORIZ(i
)), 2);
46 OUT_RING (chan
, NV50_3D_RT_HORIZ_LINEAR
| mt
->level
[0].pitch
);
47 OUT_RING (chan
, sf
->height
);
48 BEGIN_RING(chan
, RING_3D(RT_ARRAY_MODE
), 1);
55 ms_mode
= mt
->ms_mode
;
57 if (mt
->base
.status
& NOUVEAU_BUFFER_STATUS_GPU_READING
)
59 mt
->base
.status
|= NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
60 mt
->base
.status
&= NOUVEAU_BUFFER_STATUS_GPU_READING
;
62 /* only register for writing, otherwise we'd always serialize here */
63 nv50_bufctx_add_resident(nv50
, NV50_BUFCTX_FRAME
, &mt
->base
,
64 NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
68 struct nv50_miptree
*mt
= nv50_miptree(fb
->zsbuf
->texture
);
69 struct nv50_surface
*sf
= nv50_surface(fb
->zsbuf
);
70 struct nouveau_bo
*bo
= mt
->base
.bo
;
71 int unk
= mt
->base
.base
.target
== PIPE_TEXTURE_2D
;
72 uint32_t offset
= sf
->offset
;
74 MARK_RING (chan
, 12, 2);
75 BEGIN_RING(chan
, RING_3D(ZETA_ADDRESS_HIGH
), 5);
76 OUT_RELOCh(chan
, bo
, offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
77 OUT_RELOCl(chan
, bo
, offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RDWR
);
78 OUT_RING (chan
, nv50_format_table
[fb
->zsbuf
->format
].rt
);
79 OUT_RING (chan
, mt
->level
[sf
->base
.u
.tex
.level
].tile_mode
<< 4);
80 OUT_RING (chan
, mt
->layer_stride
>> 2);
81 BEGIN_RING(chan
, RING_3D(ZETA_ENABLE
), 1);
83 BEGIN_RING(chan
, RING_3D(ZETA_HORIZ
), 3);
84 OUT_RING (chan
, sf
->width
);
85 OUT_RING (chan
, sf
->height
);
86 OUT_RING (chan
, (unk
<< 16) | sf
->depth
);
88 ms_mode
= mt
->ms_mode
;
90 if (mt
->base
.status
& NOUVEAU_BUFFER_STATUS_GPU_READING
)
92 mt
->base
.status
|= NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
93 mt
->base
.status
&= NOUVEAU_BUFFER_STATUS_GPU_READING
;
95 nv50_bufctx_add_resident(nv50
, NV50_BUFCTX_FRAME
, &mt
->base
,
96 NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
98 BEGIN_RING(chan
, RING_3D(ZETA_ENABLE
), 1);
102 BEGIN_RING(chan
, RING_3D(MULTISAMPLE_MODE
), 1);
103 OUT_RING (chan
, ms_mode
);
105 BEGIN_RING(chan
, RING_3D(VIEWPORT_HORIZ(0)), 2);
106 OUT_RING (chan
, fb
->width
<< 16);
107 OUT_RING (chan
, fb
->height
<< 16);
110 BEGIN_RING(chan
, RING_3D(SERIALIZE
), 1);
116 nv50_validate_blend_colour(struct nv50_context
*nv50
)
118 struct nouveau_channel
*chan
= nv50
->screen
->base
.channel
;
120 BEGIN_RING(chan
, RING_3D(BLEND_COLOR(0)), 4);
121 OUT_RINGf (chan
, nv50
->blend_colour
.color
[0]);
122 OUT_RINGf (chan
, nv50
->blend_colour
.color
[1]);
123 OUT_RINGf (chan
, nv50
->blend_colour
.color
[2]);
124 OUT_RINGf (chan
, nv50
->blend_colour
.color
[3]);
128 nv50_validate_stencil_ref(struct nv50_context
*nv50
)
130 struct nouveau_channel
*chan
= nv50
->screen
->base
.channel
;
132 BEGIN_RING(chan
, RING_3D(STENCIL_FRONT_FUNC_REF
), 1);
133 OUT_RING (chan
, nv50
->stencil_ref
.ref_value
[0]);
134 BEGIN_RING(chan
, RING_3D(STENCIL_BACK_FUNC_REF
), 1);
135 OUT_RING (chan
, nv50
->stencil_ref
.ref_value
[1]);
139 nv50_validate_stipple(struct nv50_context
*nv50
)
141 struct nouveau_channel
*chan
= nv50
->screen
->base
.channel
;
144 BEGIN_RING(chan
, RING_3D(POLYGON_STIPPLE_PATTERN(0)), 32);
145 for (i
= 0; i
< 32; ++i
)
146 OUT_RING(chan
, util_bswap32(nv50
->stipple
.stipple
[i
]));
150 nv50_validate_scissor(struct nv50_context
*nv50
)
152 struct nouveau_channel
*chan
= nv50
->screen
->base
.channel
;
153 struct pipe_scissor_state
*s
= &nv50
->scissor
;
154 #ifdef NV50_SCISSORS_CLIPPING
155 struct pipe_viewport_state
*vp
= &nv50
->viewport
;
156 int minx
, maxx
, miny
, maxy
;
159 (NV50_NEW_SCISSOR
| NV50_NEW_VIEWPORT
| NV50_NEW_FRAMEBUFFER
)) &&
160 nv50
->state
.scissor
== nv50
->rast
->pipe
.scissor
)
162 nv50
->state
.scissor
= nv50
->rast
->pipe
.scissor
;
164 if (nv50
->state
.scissor
) {
171 maxx
= nv50
->framebuffer
.width
;
173 maxy
= nv50
->framebuffer
.height
;
176 minx
= MAX2(minx
, (int)(vp
->translate
[0] - fabsf(vp
->scale
[0])));
177 maxx
= MIN2(maxx
, (int)(vp
->translate
[0] + fabsf(vp
->scale
[0])));
178 miny
= MAX2(miny
, (int)(vp
->translate
[1] - fabsf(vp
->scale
[1])));
179 maxy
= MIN2(maxy
, (int)(vp
->translate
[1] + fabsf(vp
->scale
[1])));
181 BEGIN_RING(chan
, RING_3D(SCISSOR_HORIZ(0)), 2);
182 OUT_RING (chan
, (maxx
<< 16) | minx
);
183 OUT_RING (chan
, (maxy
<< 16) | miny
);
185 BEGIN_RING(chan
, RING_3D(SCISSOR_HORIZ(0)), 2);
186 OUT_RING (chan
, (s
->maxx
<< 16) | s
->minx
);
187 OUT_RING (chan
, (s
->maxy
<< 16) | s
->miny
);
192 nv50_validate_viewport(struct nv50_context
*nv50
)
194 struct nouveau_channel
*chan
= nv50
->screen
->base
.channel
;
197 BEGIN_RING(chan
, RING_3D(VIEWPORT_TRANSLATE_X(0)), 3);
198 OUT_RINGf (chan
, nv50
->viewport
.translate
[0]);
199 OUT_RINGf (chan
, nv50
->viewport
.translate
[1]);
200 OUT_RINGf (chan
, nv50
->viewport
.translate
[2]);
201 BEGIN_RING(chan
, RING_3D(VIEWPORT_SCALE_X(0)), 3);
202 OUT_RINGf (chan
, nv50
->viewport
.scale
[0]);
203 OUT_RINGf (chan
, nv50
->viewport
.scale
[1]);
204 OUT_RINGf (chan
, nv50
->viewport
.scale
[2]);
206 zmin
= nv50
->viewport
.translate
[2] - fabsf(nv50
->viewport
.scale
[2]);
207 zmax
= nv50
->viewport
.translate
[2] + fabsf(nv50
->viewport
.scale
[2]);
209 #ifdef NV50_SCISSORS_CLIPPING
210 BEGIN_RING(chan
, RING_3D(DEPTH_RANGE_NEAR(0)), 2);
211 OUT_RINGf (chan
, zmin
);
212 OUT_RINGf (chan
, zmax
);
217 nv50_check_program_ucps(struct nv50_context
*nv50
,
218 struct nv50_program
*vp
, uint8_t mask
)
220 const unsigned n
= util_logbase2(mask
) + 1;
222 if (vp
->vp
.clpd_nr
>= n
)
224 nv50_program_destroy(nv50
, vp
);
227 if (likely(vp
== nv50
->vertprog
))
228 nv50_vertprog_validate(nv50
);
230 nv50_gmtyprog_validate(nv50
);
231 nv50_fp_linkage_validate(nv50
);
235 nv50_validate_clip(struct nv50_context
*nv50
)
237 struct nouveau_channel
*chan
= nv50
->screen
->base
.channel
;
238 struct nv50_program
*vp
;
241 if (nv50
->dirty
& NV50_NEW_CLIP
) {
242 BEGIN_RING(chan
, RING_3D(CB_ADDR
), 1);
243 OUT_RING (chan
, (0 << 8) | NV50_CB_AUX
);
244 BEGIN_RING_NI(chan
, RING_3D(CB_DATA(0)), PIPE_MAX_CLIP_PLANES
* 4);
245 OUT_RINGp (chan
, &nv50
->clip
.ucp
[0][0], PIPE_MAX_CLIP_PLANES
* 4);
252 clip_enable
= nv50
->rast
->pipe
.clip_plane_enable
;
254 BEGIN_RING(chan
, RING_3D(VP_CLIP_DISTANCE_ENABLE
), 1);
255 OUT_RING (chan
, clip_enable
);
258 nv50_check_program_ucps(nv50
, vp
, clip_enable
);
262 nv50_validate_blend(struct nv50_context
*nv50
)
264 struct nouveau_channel
*chan
= nv50
->screen
->base
.channel
;
266 WAIT_RING(chan
, nv50
->blend
->size
);
267 OUT_RINGp(chan
, nv50
->blend
->state
, nv50
->blend
->size
);
271 nv50_validate_zsa(struct nv50_context
*nv50
)
273 struct nouveau_channel
*chan
= nv50
->screen
->base
.channel
;
275 WAIT_RING(chan
, nv50
->zsa
->size
);
276 OUT_RINGp(chan
, nv50
->zsa
->state
, nv50
->zsa
->size
);
280 nv50_validate_rasterizer(struct nv50_context
*nv50
)
282 struct nouveau_channel
*chan
= nv50
->screen
->base
.channel
;
284 WAIT_RING(chan
, nv50
->rast
->size
);
285 OUT_RINGp(chan
, nv50
->rast
->state
, nv50
->rast
->size
);
289 nv50_validate_sample_mask(struct nv50_context
*nv50
)
291 struct nouveau_channel
*chan
= nv50
->screen
->base
.channel
;
295 nv50
->sample_mask
& 0xffff,
296 nv50
->sample_mask
& 0xffff,
297 nv50
->sample_mask
& 0xffff,
298 nv50
->sample_mask
& 0xffff
301 BEGIN_RING(chan
, RING_3D(MSAA_MASK(0)), 4);
302 OUT_RING (chan
, mask
[0]);
303 OUT_RING (chan
, mask
[1]);
304 OUT_RING (chan
, mask
[2]);
305 OUT_RING (chan
, mask
[3]);
309 nv50_switch_pipe_context(struct nv50_context
*ctx_to
)
311 struct nv50_context
*ctx_from
= ctx_to
->screen
->cur_ctx
;
314 ctx_to
->state
= ctx_from
->state
;
319 ctx_to
->dirty
&= ~(NV50_NEW_VERTEX
| NV50_NEW_ARRAYS
);
321 if (!ctx_to
->vertprog
)
322 ctx_to
->dirty
&= ~NV50_NEW_VERTPROG
;
323 if (!ctx_to
->fragprog
)
324 ctx_to
->dirty
&= ~NV50_NEW_FRAGPROG
;
327 ctx_to
->dirty
&= ~NV50_NEW_BLEND
;
329 #ifdef NV50_SCISSORS_CLIPPING
330 ctx_to
->dirty
&= ~(NV50_NEW_RASTERIZER
| NV50_NEW_SCISSOR
);
332 ctx_to
->dirty
&= ~NV50_NEW_RASTERIZER
;
335 ctx_to
->dirty
&= ~NV50_NEW_ZSA
;
337 ctx_to
->screen
->cur_ctx
= ctx_to
;
340 static struct state_validate
{
341 void (*func
)(struct nv50_context
*);
343 } validate_list
[] = {
344 { nv50_validate_fb
, NV50_NEW_FRAMEBUFFER
},
345 { nv50_validate_blend
, NV50_NEW_BLEND
},
346 { nv50_validate_zsa
, NV50_NEW_ZSA
},
347 { nv50_validate_sample_mask
, NV50_NEW_SAMPLE_MASK
},
348 { nv50_validate_rasterizer
, NV50_NEW_RASTERIZER
},
349 { nv50_validate_blend_colour
, NV50_NEW_BLEND_COLOUR
},
350 { nv50_validate_stencil_ref
, NV50_NEW_STENCIL_REF
},
351 { nv50_validate_stipple
, NV50_NEW_STIPPLE
},
352 #ifdef NV50_SCISSORS_CLIPPING
353 { nv50_validate_scissor
, NV50_NEW_SCISSOR
| NV50_NEW_VIEWPORT
|
354 NV50_NEW_RASTERIZER
|
355 NV50_NEW_FRAMEBUFFER
},
357 { nv50_validate_scissor
, NV50_NEW_SCISSOR
},
359 { nv50_validate_viewport
, NV50_NEW_VIEWPORT
},
360 { nv50_vertprog_validate
, NV50_NEW_VERTPROG
},
361 { nv50_gmtyprog_validate
, NV50_NEW_GMTYPROG
},
362 { nv50_fragprog_validate
, NV50_NEW_FRAGPROG
},
363 { nv50_fp_linkage_validate
, NV50_NEW_FRAGPROG
| NV50_NEW_VERTPROG
|
365 { nv50_gp_linkage_validate
, NV50_NEW_GMTYPROG
| NV50_NEW_VERTPROG
},
366 { nv50_validate_derived_rs
, NV50_NEW_FRAGPROG
| NV50_NEW_RASTERIZER
|
367 NV50_NEW_VERTPROG
| NV50_NEW_GMTYPROG
},
368 { nv50_validate_clip
, NV50_NEW_CLIP
| NV50_NEW_RASTERIZER
|
369 NV50_NEW_VERTPROG
| NV50_NEW_GMTYPROG
},
370 { nv50_constbufs_validate
, NV50_NEW_CONSTBUF
},
371 { nv50_validate_textures
, NV50_NEW_TEXTURES
},
372 { nv50_validate_samplers
, NV50_NEW_SAMPLERS
},
373 { nv50_vertex_arrays_validate
, NV50_NEW_VERTEX
| NV50_NEW_ARRAYS
}
375 #define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
378 nv50_state_validate(struct nv50_context
*nv50
, uint32_t mask
, unsigned words
)
383 if (nv50
->screen
->cur_ctx
!= nv50
)
384 nv50_switch_pipe_context(nv50
);
386 state_mask
= nv50
->dirty
& mask
;
389 for (i
= 0; i
< validate_list_len
; ++i
) {
390 struct state_validate
*validate
= &validate_list
[i
];
392 if (state_mask
& validate
->states
)
393 validate
->func(nv50
);
395 nv50
->dirty
&= ~state_mask
;
398 MARK_RING(nv50
->screen
->base
.channel
, words
, 0);
400 nv50_bufctx_emit_relocs(nv50
);