nv50_state_validate.c revision b2dcf880e8bcd61be59602f5a2d18c77a5fc60c1
1 2#include "nv50_context.h" 3#include "os/os_time.h" 4 5static void 6nv50_validate_fb(struct nv50_context *nv50) 7{ 8 struct nouveau_channel *chan = nv50->screen->base.channel; 9 struct pipe_framebuffer_state *fb = &nv50->framebuffer; 10 unsigned i; 11 unsigned ms_mode = NV50_3D_MULTISAMPLE_MODE_MS1; 12 boolean serialize = FALSE; 13 14 nv50_bufctx_reset(nv50, NV50_BUFCTX_FRAME); 15 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); 21 22 MARK_RING(chan, 9 * fb->nr_cbufs, 2 * fb->nr_cbufs); 23 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; 29 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 OUT_RING (chan, mt->level[sf->base.u.tex.level].tile_mode << 4); 35 OUT_RING (chan, mt->layer_stride >> 2); 36 BEGIN_RING(chan, RING_3D(RT_HORIZ(i)), 2); 37 OUT_RING (chan, sf->width); 38 OUT_RING (chan, sf->height); 39 BEGIN_RING(chan, RING_3D(RT_ARRAY_MODE), 1); 40 OUT_RING (chan, sf->depth); 41 42 ms_mode = mt->ms_mode; 43 44 if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING) 45 serialize = TRUE; 46 mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING; 47 mt->base.status &= NOUVEAU_BUFFER_STATUS_GPU_READING; 48 49 /* only register for writing, otherwise we'd always serialize here */ 50 nv50_bufctx_add_resident(nv50, NV50_BUFCTX_FRAME, &mt->base, 51 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); 52 } 53 54 if (fb->zsbuf) { 55 struct nv50_miptree *mt = nv50_miptree(fb->zsbuf->texture); 56 struct nv50_surface *sf = nv50_surface(fb->zsbuf); 57 struct nouveau_bo *bo = mt->base.bo; 58 int unk = mt->base.base.target == PIPE_TEXTURE_2D; 59 uint32_t offset = sf->offset; 60 61 MARK_RING (chan, 12, 2); 62 BEGIN_RING(chan, RING_3D(ZETA_ADDRESS_HIGH), 5); 63 OUT_RELOCh(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); 64 OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); 65 OUT_RING (chan, nv50_format_table[fb->zsbuf->format].rt); 66 OUT_RING (chan, mt->level[sf->base.u.tex.level].tile_mode << 4); 67 OUT_RING (chan, mt->layer_stride >> 2); 68 BEGIN_RING(chan, RING_3D(ZETA_ENABLE), 1); 69 OUT_RING (chan, 1); 70 BEGIN_RING(chan, RING_3D(ZETA_HORIZ), 3); 71 OUT_RING (chan, sf->width); 72 OUT_RING (chan, sf->height); 73 OUT_RING (chan, (unk << 16) | sf->depth); 74 75 ms_mode = mt->ms_mode; 76 77 if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING) 78 serialize = TRUE; 79 mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING; 80 mt->base.status &= NOUVEAU_BUFFER_STATUS_GPU_READING; 81 82 nv50_bufctx_add_resident(nv50, NV50_BUFCTX_FRAME, &mt->base, 83 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); 84 } else { 85 BEGIN_RING(chan, RING_3D(ZETA_ENABLE), 1); 86 OUT_RING (chan, 0); 87 } 88 89 BEGIN_RING(chan, RING_3D(MULTISAMPLE_MODE), 1); 90 OUT_RING (chan, ms_mode); 91 92 BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2); 93 OUT_RING (chan, fb->width << 16); 94 OUT_RING (chan, fb->height << 16); 95 96 if (serialize) { 97 BEGIN_RING(chan, RING_3D(SERIALIZE), 1); 98 OUT_RING (chan, 0); 99 } 100} 101 102static void 103nv50_validate_blend_colour(struct nv50_context *nv50) 104{ 105 struct nouveau_channel *chan = nv50->screen->base.channel; 106 107 BEGIN_RING(chan, RING_3D(BLEND_COLOR(0)), 4); 108 OUT_RINGf (chan, nv50->blend_colour.color[0]); 109 OUT_RINGf (chan, nv50->blend_colour.color[1]); 110 OUT_RINGf (chan, nv50->blend_colour.color[2]); 111 OUT_RINGf (chan, nv50->blend_colour.color[3]); 112} 113 114static void 115nv50_validate_stencil_ref(struct nv50_context *nv50) 116{ 117 struct nouveau_channel *chan = nv50->screen->base.channel; 118 119 BEGIN_RING(chan, RING_3D(STENCIL_FRONT_FUNC_REF), 1); 120 OUT_RING (chan, nv50->stencil_ref.ref_value[0]); 121 BEGIN_RING(chan, RING_3D(STENCIL_BACK_FUNC_REF), 1); 122 OUT_RING (chan, nv50->stencil_ref.ref_value[1]); 123} 124 125static void 126nv50_validate_stipple(struct nv50_context *nv50) 127{ 128 struct nouveau_channel *chan = nv50->screen->base.channel; 129 unsigned i; 130 131 BEGIN_RING(chan, RING_3D(POLYGON_STIPPLE_PATTERN(0)), 32); 132 for (i = 0; i < 32; ++i) 133 OUT_RING(chan, util_bswap32(nv50->stipple.stipple[i])); 134} 135 136static void 137nv50_validate_scissor(struct nv50_context *nv50) 138{ 139 struct nouveau_channel *chan = nv50->screen->base.channel; 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; 144 145 if (!(nv50->dirty & 146 (NV50_NEW_SCISSOR | NV50_NEW_VIEWPORT | NV50_NEW_FRAMEBUFFER)) && 147 nv50->state.scissor == nv50->rast->pipe.scissor) 148 return; 149 nv50->state.scissor = nv50->rast->pipe.scissor; 150 151 if (nv50->state.scissor) { 152 minx = s->minx; 153 maxx = s->maxx; 154 miny = s->miny; 155 maxy = s->maxy; 156 } else { 157 minx = 0; 158 maxx = nv50->framebuffer.width; 159 miny = 0; 160 maxy = nv50->framebuffer.height; 161 } 162 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]))); 167 168 BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2); 169 OUT_RING (chan, (maxx << 16) | minx); 170 OUT_RING (chan, (maxy << 16) | miny); 171#else 172 BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2); 173 OUT_RING (chan, (s->maxx << 16) | s->minx); 174 OUT_RING (chan, (s->maxy << 16) | s->miny); 175#endif 176} 177 178static void 179nv50_validate_viewport(struct nv50_context *nv50) 180{ 181 struct nouveau_channel *chan = nv50->screen->base.channel; 182 float zmin, zmax; 183 184 BEGIN_RING(chan, RING_3D(VIEWPORT_TRANSLATE_X(0)), 3); 185 OUT_RINGf (chan, nv50->viewport.translate[0]); 186 OUT_RINGf (chan, nv50->viewport.translate[1]); 187 OUT_RINGf (chan, nv50->viewport.translate[2]); 188 BEGIN_RING(chan, RING_3D(VIEWPORT_SCALE_X(0)), 3); 189 OUT_RINGf (chan, nv50->viewport.scale[0]); 190 OUT_RINGf (chan, nv50->viewport.scale[1]); 191 OUT_RINGf (chan, nv50->viewport.scale[2]); 192 193 zmin = nv50->viewport.translate[2] - fabsf(nv50->viewport.scale[2]); 194 zmax = nv50->viewport.translate[2] + fabsf(nv50->viewport.scale[2]); 195 196#ifdef NV50_SCISSORS_CLIPPING 197 BEGIN_RING(chan, RING_3D(DEPTH_RANGE_NEAR(0)), 2); 198 OUT_RINGf (chan, zmin); 199 OUT_RINGf (chan, zmax); 200#endif 201} 202 203static void 204nv50_validate_clip(struct nv50_context *nv50) 205{ 206 struct nouveau_channel *chan = nv50->screen->base.channel; 207 uint32_t clip; 208 209 if (nv50->clip.depth_clamp) { 210 clip = 211 NV50_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_NEAR | 212 NV50_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_FAR | 213 NV50_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK1; 214 } else { 215 clip = 0; 216 } 217 218#ifndef NV50_SCISSORS_CLIPPING 219 clip |= 220 NV50_3D_VIEW_VOLUME_CLIP_CTRL_UNK7 | 221 NV50_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK1; 222#endif 223 224 BEGIN_RING(chan, RING_3D(VIEW_VOLUME_CLIP_CTRL), 1); 225 OUT_RING (chan, clip); 226 227 if (nv50->clip.nr) { 228 BEGIN_RING(chan, RING_3D(CB_ADDR), 1); 229 OUT_RING (chan, (0 << 8) | NV50_CB_AUX); 230 BEGIN_RING_NI(chan, RING_3D(CB_DATA(0)), nv50->clip.nr * 4); 231 OUT_RINGp (chan, &nv50->clip.ucp[0][0], nv50->clip.nr * 4); 232 } 233 234 BEGIN_RING(chan, RING_3D(VP_CLIP_DISTANCE_ENABLE), 1); 235 OUT_RING (chan, (1 << nv50->clip.nr) - 1); 236 237 if (nv50->vertprog && nv50->clip.nr > nv50->vertprog->vp.clpd_nr) 238 nv50->dirty |= NV50_NEW_VERTPROG; 239} 240 241static void 242nv50_validate_blend(struct nv50_context *nv50) 243{ 244 struct nouveau_channel *chan = nv50->screen->base.channel; 245 246 WAIT_RING(chan, nv50->blend->size); 247 OUT_RINGp(chan, nv50->blend->state, nv50->blend->size); 248} 249 250static void 251nv50_validate_zsa(struct nv50_context *nv50) 252{ 253 struct nouveau_channel *chan = nv50->screen->base.channel; 254 255 WAIT_RING(chan, nv50->zsa->size); 256 OUT_RINGp(chan, nv50->zsa->state, nv50->zsa->size); 257} 258 259static void 260nv50_validate_rasterizer(struct nv50_context *nv50) 261{ 262 struct nouveau_channel *chan = nv50->screen->base.channel; 263 264 WAIT_RING(chan, nv50->rast->size); 265 OUT_RINGp(chan, nv50->rast->state, nv50->rast->size); 266} 267 268static void 269nv50_validate_sample_mask(struct nv50_context *nv50) 270{ 271 struct nouveau_channel *chan = nv50->screen->base.channel; 272 273 unsigned mask[4] = 274 { 275 nv50->sample_mask & 0xffff, 276 nv50->sample_mask & 0xffff, 277 nv50->sample_mask & 0xffff, 278 nv50->sample_mask & 0xffff 279 }; 280 281 BEGIN_RING(chan, RING_3D(MSAA_MASK(0)), 4); 282 OUT_RING (chan, mask[0]); 283 OUT_RING (chan, mask[1]); 284 OUT_RING (chan, mask[2]); 285 OUT_RING (chan, mask[3]); 286} 287 288static void 289nv50_switch_pipe_context(struct nv50_context *ctx_to) 290{ 291 struct nv50_context *ctx_from = ctx_to->screen->cur_ctx; 292 293 if (ctx_from) 294 ctx_to->state = ctx_from->state; 295 296 ctx_to->dirty = ~0; 297 298 if (!ctx_to->vertex) 299 ctx_to->dirty &= ~(NV50_NEW_VERTEX | NV50_NEW_ARRAYS); 300 301 if (!ctx_to->vertprog) 302 ctx_to->dirty &= ~NV50_NEW_VERTPROG; 303 if (!ctx_to->fragprog) 304 ctx_to->dirty &= ~NV50_NEW_FRAGPROG; 305 306 if (!ctx_to->blend) 307 ctx_to->dirty &= ~NV50_NEW_BLEND; 308 if (!ctx_to->rast) 309 ctx_to->dirty &= ~NV50_NEW_RASTERIZER; 310 if (!ctx_to->zsa) 311 ctx_to->dirty &= ~NV50_NEW_ZSA; 312 313 ctx_to->screen->cur_ctx = ctx_to; 314} 315 316static struct state_validate { 317 void (*func)(struct nv50_context *); 318 uint32_t states; 319} validate_list[] = { 320 { nv50_validate_fb, NV50_NEW_FRAMEBUFFER }, 321 { nv50_validate_blend, NV50_NEW_BLEND }, 322 { nv50_validate_zsa, NV50_NEW_ZSA }, 323 { nv50_validate_sample_mask, NV50_NEW_SAMPLE_MASK }, 324 { nv50_validate_rasterizer, NV50_NEW_RASTERIZER }, 325 { nv50_validate_blend_colour, NV50_NEW_BLEND_COLOUR }, 326 { nv50_validate_stencil_ref, NV50_NEW_STENCIL_REF }, 327 { nv50_validate_stipple, NV50_NEW_STIPPLE }, 328#ifdef NV50_SCISSORS_CLIPPING 329 { nv50_validate_scissor, NV50_NEW_SCISSOR | NV50_NEW_VIEWPORT | 330 NV50_NEW_RASTERIZER | 331 NV50_NEW_FRAMEBUFFER }, 332#else 333 { nv50_validate_scissor, NV50_NEW_SCISSOR }, 334#endif 335 { nv50_validate_viewport, NV50_NEW_VIEWPORT }, 336 { nv50_validate_clip, NV50_NEW_CLIP }, 337 { nv50_vertprog_validate, NV50_NEW_VERTPROG }, 338 { nv50_gmtyprog_validate, NV50_NEW_GMTYPROG }, 339 { nv50_fragprog_validate, NV50_NEW_FRAGPROG }, 340 { nv50_fp_linkage_validate, NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG | 341 NV50_NEW_GMTYPROG }, 342 { nv50_gp_linkage_validate, NV50_NEW_GMTYPROG | NV50_NEW_VERTPROG }, 343 { nv50_validate_derived_rs, NV50_NEW_FRAGPROG | NV50_NEW_RASTERIZER | 344 NV50_NEW_VERTPROG | NV50_NEW_GMTYPROG }, 345 { nv50_constbufs_validate, NV50_NEW_CONSTBUF }, 346 { nv50_validate_textures, NV50_NEW_TEXTURES }, 347 { nv50_validate_samplers, NV50_NEW_SAMPLERS }, 348 { nv50_vertex_arrays_validate, NV50_NEW_VERTEX | NV50_NEW_ARRAYS } 349}; 350#define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0])) 351 352boolean 353nv50_state_validate(struct nv50_context *nv50) 354{ 355 unsigned i; 356 357 if (nv50->screen->cur_ctx != nv50) 358 nv50_switch_pipe_context(nv50); 359 360 if (nv50->dirty) { 361 for (i = 0; i < validate_list_len; ++i) { 362 struct state_validate *validate = &validate_list[i]; 363 364 if (nv50->dirty & validate->states) 365 validate->func(nv50); 366 } 367 nv50->dirty = 0; 368 } 369 370 nv50_bufctx_emit_relocs(nv50); 371 372 return TRUE; 373} 374