1 2 #include "nv50_context.h" 3 #include "os/os_time.h" 4 5 static void 6 nv50_validate_fb(struct nv50_context *nv50) 7 { 8 struct nouveau_pushbuf *push = nv50->base.pushbuf; 9 struct pipe_framebuffer_state *fb = &nv50->framebuffer; 10 unsigned i; 11 unsigned ms_mode = NV50_3D_MULTISAMPLE_MODE_MS1; 12 13 nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_FB); 14 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); 20 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; 25 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); 38 } else { 39 PUSH_DATA (push, 0); 40 PUSH_DATA (push, 0); 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); 45 PUSH_DATA (push, 0); 46 47 assert(!fb->zsbuf); 48 assert(!mt->ms_mode); 49 } 50 51 ms_mode = mt->ms_mode; 52 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; 57 58 /* only register for writing, otherwise we'd always serialize here */ 59 BCTX_REFN(nv50->bufctx_3d, FB, &mt->base, WR); 60 } 61 62 if (fb->zsbuf) { 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; 67 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); 75 PUSH_DATA (push, 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); 80 81 ms_mode = mt->ms_mode; 82 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; 87 88 BCTX_REFN(nv50->bufctx_3d, FB, &mt->base, WR); 89 } else { 90 BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1); 91 PUSH_DATA (push, 0); 92 } 93 94 BEGIN_NV04(push, NV50_3D(MULTISAMPLE_MODE), 1); 95 PUSH_DATA (push, ms_mode); 96 97 BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2); 98 PUSH_DATA (push, fb->width << 16); 99 PUSH_DATA (push, fb->height << 16); 100 } 101 102 static void 103 nv50_validate_blend_colour(struct nv50_context *nv50) 104 { 105 struct nouveau_pushbuf *push = nv50->base.pushbuf; 106 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]); 112 } 113 114 static void 115 nv50_validate_stencil_ref(struct nv50_context *nv50) 116 { 117 struct nouveau_pushbuf *push = nv50->base.pushbuf; 118 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]); 123 } 124 125 static void 126 nv50_validate_stipple(struct nv50_context *nv50) 127 { 128 struct nouveau_pushbuf *push = nv50->base.pushbuf; 129 unsigned i; 130 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])); 134 } 135 136 static void 137 nv50_validate_scissor(struct nv50_context *nv50) 138 { 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; 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_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2); 169 PUSH_DATA (push, (maxx << 16) | minx); 170 PUSH_DATA (push, (maxy << 16) | miny); 171 #else 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); 175 #endif 176 } 177 178 static void 179 nv50_validate_viewport(struct nv50_context *nv50) 180 { 181 struct nouveau_pushbuf *push = nv50->base.pushbuf; 182 float zmin, zmax; 183 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]); 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_NV04(push, NV50_3D(DEPTH_RANGE_NEAR(0)), 2); 198 PUSH_DATAf(push, zmin); 199 PUSH_DATAf(push, zmax); 200 #endif 201 } 202 203 static INLINE void 204 nv50_check_program_ucps(struct nv50_context *nv50, 205 struct nv50_program *vp, uint8_t mask) 206 { 207 const unsigned n = util_logbase2(mask) + 1; 208 209 if (vp->vp.clpd_nr >= n) 210 return; 211 nv50_program_destroy(nv50, vp); 212 213 vp->vp.clpd_nr = n; 214 if (likely(vp == nv50->vertprog)) { 215 nv50->dirty |= NV50_NEW_VERTPROG; 216 nv50_vertprog_validate(nv50); 217 } else { 218 nv50->dirty |= NV50_NEW_GMTYPROG; 219 nv50_gmtyprog_validate(nv50); 220 } 221 nv50_fp_linkage_validate(nv50); 222 } 223 224 static void 225 nv50_validate_clip(struct nv50_context *nv50) 226 { 227 struct nouveau_pushbuf *push = nv50->base.pushbuf; 228 struct nv50_program *vp; 229 uint8_t clip_enable; 230 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); 236 } 237 238 vp = nv50->gmtyprog; 239 if (likely(!vp)) 240 vp = nv50->vertprog; 241 242 clip_enable = nv50->rast->pipe.clip_plane_enable; 243 244 BEGIN_NV04(push, NV50_3D(CLIP_DISTANCE_ENABLE), 1); 245 PUSH_DATA (push, clip_enable); 246 247 if (clip_enable) 248 nv50_check_program_ucps(nv50, vp, clip_enable); 249 } 250 251 static void 252 nv50_validate_blend(struct nv50_context *nv50) 253 { 254 struct nouveau_pushbuf *push = nv50->base.pushbuf; 255 256 PUSH_SPACE(push, nv50->blend->size); 257 PUSH_DATAp(push, nv50->blend->state, nv50->blend->size); 258 } 259 260 static void 261 nv50_validate_zsa(struct nv50_context *nv50) 262 { 263 struct nouveau_pushbuf *push = nv50->base.pushbuf; 264 265 PUSH_SPACE(push, nv50->zsa->size); 266 PUSH_DATAp(push, nv50->zsa->state, nv50->zsa->size); 267 } 268 269 static void 270 nv50_validate_rasterizer(struct nv50_context *nv50) 271 { 272 struct nouveau_pushbuf *push = nv50->base.pushbuf; 273 274 PUSH_SPACE(push, nv50->rast->size); 275 PUSH_DATAp(push, nv50->rast->state, nv50->rast->size); 276 } 277 278 static void 279 nv50_validate_sample_mask(struct nv50_context *nv50) 280 { 281 struct nouveau_pushbuf *push = nv50->base.pushbuf; 282 283 unsigned mask[4] = 284 { 285 nv50->sample_mask & 0xffff, 286 nv50->sample_mask & 0xffff, 287 nv50->sample_mask & 0xffff, 288 nv50->sample_mask & 0xffff 289 }; 290 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]); 296 } 297 298 static void 299 nv50_switch_pipe_context(struct nv50_context *ctx_to) 300 { 301 struct nv50_context *ctx_from = ctx_to->screen->cur_ctx; 302 303 if (ctx_from) 304 ctx_to->state = ctx_from->state; 305 306 ctx_to->dirty = ~0; 307 308 if (!ctx_to->vertex) 309 ctx_to->dirty &= ~(NV50_NEW_VERTEX | NV50_NEW_ARRAYS); 310 311 if (!ctx_to->vertprog) 312 ctx_to->dirty &= ~NV50_NEW_VERTPROG; 313 if (!ctx_to->fragprog) 314 ctx_to->dirty &= ~NV50_NEW_FRAGPROG; 315 316 if (!ctx_to->blend) 317 ctx_to->dirty &= ~NV50_NEW_BLEND; 318 if (!ctx_to->rast) 319 #ifdef NV50_SCISSORS_CLIPPING 320 ctx_to->dirty &= ~(NV50_NEW_RASTERIZER | NV50_NEW_SCISSOR); 321 #else 322 ctx_to->dirty &= ~NV50_NEW_RASTERIZER; 323 #endif 324 if (!ctx_to->zsa) 325 ctx_to->dirty &= ~NV50_NEW_ZSA; 326 327 ctx_to->screen->cur_ctx = ctx_to; 328 } 329 330 static struct state_validate { 331 void (*func)(struct nv50_context *); 332 uint32_t states; 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 }, 346 #else 347 { nv50_validate_scissor, NV50_NEW_SCISSOR }, 348 #endif 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 } 366 }; 367 #define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0])) 368 369 boolean 370 nv50_state_validate(struct nv50_context *nv50, uint32_t mask, unsigned words) 371 { 372 uint32_t state_mask; 373 int ret; 374 unsigned i; 375 376 if (nv50->screen->cur_ctx != nv50) 377 nv50_switch_pipe_context(nv50); 378 379 state_mask = nv50->dirty & mask; 380 381 if (state_mask) { 382 for (i = 0; i < validate_list_len; ++i) { 383 struct state_validate *validate = &validate_list[i]; 384 385 if (state_mask & validate->states) 386 validate->func(nv50); 387 } 388 nv50->dirty &= ~state_mask; 389 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); 394 } 395 396 nv50_bufctx_fence(nv50->bufctx_3d, FALSE); 397 } 398 nouveau_pushbuf_bufctx(nv50->base.pushbuf, nv50->bufctx_3d); 399 ret = nouveau_pushbuf_validate(nv50->base.pushbuf); 400 401 if (unlikely(nv50->state.flushed)) { 402 nv50->state.flushed = FALSE; 403 nv50_bufctx_fence(nv50->bufctx_3d, TRUE); 404 } 405 return !ret; 406 } 407