nv50_state_validate.c revision f80c03e1875fe96ff2f4c022e3cb76357828140d
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 12 nv50_bufctx_reset(nv50, NV50_BUFCTX_FRAME); 13 14 BEGIN_RING(chan, RING_3D(RT_CONTROL), 1); 15 OUT_RING (chan, (076543210 << 4) | fb->nr_cbufs); 16 BEGIN_RING(chan, RING_3D(SCREEN_SCISSOR_HORIZ), 2); 17 OUT_RING (chan, fb->width << 16); 18 OUT_RING (chan, fb->height << 16); 19 20 MARK_RING(chan, 9 * fb->nr_cbufs, 2 * fb->nr_cbufs); 21 22 for (i = 0; i < fb->nr_cbufs; ++i) { 23 struct nv50_miptree *mt = nv50_miptree(fb->cbufs[i]->texture); 24 struct nv50_surface *sf = nv50_surface(fb->cbufs[i]); 25 struct nouveau_bo *bo = mt->base.bo; 26 uint32_t offset = sf->offset; 27 28 BEGIN_RING(chan, RING_3D(RT_ADDRESS_HIGH(i)), 5); 29 OUT_RELOCh(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); 30 OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); 31 OUT_RING (chan, nv50_format_table[sf->base.format].rt); 32 OUT_RING (chan, mt->level[sf->base.u.tex.level].tile_mode << 4); 33 OUT_RING (chan, mt->layer_stride >> 2); 34 BEGIN_RING(chan, RING_3D(RT_HORIZ(i)), 2); 35 OUT_RING (chan, sf->width); 36 OUT_RING (chan, sf->height); 37 BEGIN_RING(chan, RING_3D(RT_ARRAY_MODE), 1); 38 OUT_RING (chan, sf->depth); 39 40 nv50_bufctx_add_resident(nv50, NV50_BUFCTX_FRAME, &mt->base, 41 NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); 42 } 43 44 if (fb->zsbuf) { 45 struct nv50_miptree *mt = nv50_miptree(fb->zsbuf->texture); 46 struct nv50_surface *sf = nv50_surface(fb->zsbuf); 47 struct nouveau_bo *bo = mt->base.bo; 48 int unk = mt->base.base.target == PIPE_TEXTURE_2D; 49 uint32_t offset = sf->offset; 50 51 MARK_RING (chan, 12, 2); 52 BEGIN_RING(chan, RING_3D(ZETA_ADDRESS_HIGH), 5); 53 OUT_RELOCh(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); 54 OUT_RELOCl(chan, bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); 55 OUT_RING (chan, nv50_format_table[fb->zsbuf->format].rt); 56 OUT_RING (chan, mt->level[sf->base.u.tex.level].tile_mode << 4); 57 OUT_RING (chan, mt->layer_stride >> 2); 58 BEGIN_RING(chan, RING_3D(ZETA_ENABLE), 1); 59 OUT_RING (chan, 1); 60 BEGIN_RING(chan, RING_3D(ZETA_HORIZ), 3); 61 OUT_RING (chan, sf->width); 62 OUT_RING (chan, sf->height); 63 OUT_RING (chan, (unk << 16) | sf->depth); 64 65 nv50_bufctx_add_resident(nv50, NV50_BUFCTX_FRAME, &mt->base, 66 NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); 67 } else { 68 BEGIN_RING(chan, RING_3D(ZETA_ENABLE), 1); 69 OUT_RING (chan, 0); 70 } 71 72 BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2); 73 OUT_RING (chan, fb->width << 16); 74 OUT_RING (chan, fb->height << 16); 75} 76 77static void 78nv50_validate_blend_colour(struct nv50_context *nv50) 79{ 80 struct nouveau_channel *chan = nv50->screen->base.channel; 81 82 BEGIN_RING(chan, RING_3D(BLEND_COLOR(0)), 4); 83 OUT_RINGf (chan, nv50->blend_colour.color[0]); 84 OUT_RINGf (chan, nv50->blend_colour.color[1]); 85 OUT_RINGf (chan, nv50->blend_colour.color[2]); 86 OUT_RINGf (chan, nv50->blend_colour.color[3]); 87} 88 89static void 90nv50_validate_stencil_ref(struct nv50_context *nv50) 91{ 92 struct nouveau_channel *chan = nv50->screen->base.channel; 93 94 BEGIN_RING(chan, RING_3D(STENCIL_FRONT_FUNC_REF), 1); 95 OUT_RING (chan, nv50->stencil_ref.ref_value[0]); 96 BEGIN_RING(chan, RING_3D(STENCIL_BACK_FUNC_REF), 1); 97 OUT_RING (chan, nv50->stencil_ref.ref_value[1]); 98} 99 100static void 101nv50_validate_stipple(struct nv50_context *nv50) 102{ 103 struct nouveau_channel *chan = nv50->screen->base.channel; 104 unsigned i; 105 106 BEGIN_RING(chan, RING_3D(POLYGON_STIPPLE_PATTERN(0)), 32); 107 for (i = 0; i < 32; ++i) 108 OUT_RING(chan, util_bswap32(nv50->stipple.stipple[i])); 109} 110 111static void 112nv50_validate_scissor(struct nv50_context *nv50) 113{ 114 struct nouveau_channel *chan = nv50->screen->base.channel; 115 struct pipe_scissor_state *s = &nv50->scissor; 116#ifdef NV50_SCISSORS_CLIPPING 117 struct pipe_viewport_state *vp = &nv50->viewport; 118 int minx, maxx, miny, maxy; 119 120 if (!(nv50->dirty & 121 (NV50_NEW_SCISSOR | NV50_NEW_VIEWPORT | NV50_NEW_FRAMEBUFFER)) && 122 nv50->state.scissor == nv50->rast->pipe.scissor) 123 return; 124 nv50->state.scissor = nv50->rast->pipe.scissor; 125 126 if (nv50->state.scissor) { 127 minx = s->minx; 128 maxx = s->maxx; 129 miny = s->miny; 130 maxy = s->maxy; 131 } else { 132 minx = 0; 133 maxx = nv50->framebuffer.width; 134 miny = 0; 135 maxy = nv50->framebuffer.height; 136 } 137 138 minx = MAX2(minx, (int)(vp->translate[0] - fabsf(vp->scale[0]))); 139 maxx = MIN2(maxx, (int)(vp->translate[0] + fabsf(vp->scale[0]))); 140 miny = MAX2(miny, (int)(vp->translate[1] - fabsf(vp->scale[1]))); 141 maxy = MIN2(maxy, (int)(vp->translate[1] + fabsf(vp->scale[1]))); 142 143 BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2); 144 OUT_RING (chan, (maxx << 16) | minx); 145 OUT_RING (chan, (maxy << 16) | miny); 146#else 147 BEGIN_RING(chan, RING_3D(SCISSOR_HORIZ(0)), 2); 148 OUT_RING (chan, (s->maxx << 16) | s->minx); 149 OUT_RING (chan, (s->maxy << 16) | s->miny); 150#endif 151} 152 153static void 154nv50_validate_viewport(struct nv50_context *nv50) 155{ 156 struct nouveau_channel *chan = nv50->screen->base.channel; 157 float zmin, zmax; 158 159 BEGIN_RING(chan, RING_3D(VIEWPORT_TRANSLATE_X(0)), 3); 160 OUT_RINGf (chan, nv50->viewport.translate[0]); 161 OUT_RINGf (chan, nv50->viewport.translate[1]); 162 OUT_RINGf (chan, nv50->viewport.translate[2]); 163 BEGIN_RING(chan, RING_3D(VIEWPORT_SCALE_X(0)), 3); 164 OUT_RINGf (chan, nv50->viewport.scale[0]); 165 OUT_RINGf (chan, nv50->viewport.scale[1]); 166 OUT_RINGf (chan, nv50->viewport.scale[2]); 167 168 zmin = nv50->viewport.translate[2] - fabsf(nv50->viewport.scale[2]); 169 zmax = nv50->viewport.translate[2] + fabsf(nv50->viewport.scale[2]); 170 171#ifdef NV50_SCISSORS_CLIPPING 172 BEGIN_RING(chan, RING_3D(DEPTH_RANGE_NEAR(0)), 2); 173 OUT_RINGf (chan, zmin); 174 OUT_RINGf (chan, zmax); 175#endif 176} 177 178static void 179nv50_validate_clip(struct nv50_context *nv50) 180{ 181 struct nouveau_channel *chan = nv50->screen->base.channel; 182 uint32_t clip; 183 184 clip = nv50->clip.depth_clamp ? 0x0018 : 0x0000; 185#ifndef NV50_SCISSORS_CLIPPING 186 clip |= 0x1080; 187#endif 188 189 BEGIN_RING(chan, RING_3D(VIEW_VOLUME_CLIP_CTRL), 1); 190 OUT_RING (chan, clip); 191 192 if (nv50->clip.nr) { 193 BEGIN_RING(chan, RING_3D(CB_ADDR), 1); 194 OUT_RING (chan, (0 << 8) | NV50_CB_AUX); 195 BEGIN_RING_NI(chan, RING_3D(CB_DATA(0)), nv50->clip.nr * 4); 196 OUT_RINGp (chan, &nv50->clip.ucp[0][0], nv50->clip.nr * 4); 197 } 198 199 BEGIN_RING(chan, RING_3D(VP_CLIP_DISTANCE_ENABLE), 1); 200 OUT_RING (chan, (1 << nv50->clip.nr) - 1); 201} 202 203static void 204nv50_validate_blend(struct nv50_context *nv50) 205{ 206 struct nouveau_channel *chan = nv50->screen->base.channel; 207 208 WAIT_RING(chan, nv50->blend->size); 209 OUT_RINGp(chan, nv50->blend->state, nv50->blend->size); 210} 211 212static void 213nv50_validate_zsa(struct nv50_context *nv50) 214{ 215 struct nouveau_channel *chan = nv50->screen->base.channel; 216 217 WAIT_RING(chan, nv50->zsa->size); 218 OUT_RINGp(chan, nv50->zsa->state, nv50->zsa->size); 219} 220 221static void 222nv50_validate_rasterizer(struct nv50_context *nv50) 223{ 224 struct nouveau_channel *chan = nv50->screen->base.channel; 225 226 WAIT_RING(chan, nv50->rast->size); 227 OUT_RINGp(chan, nv50->rast->state, nv50->rast->size); 228} 229 230static struct state_validate { 231 void (*func)(struct nv50_context *); 232 uint32_t states; 233} validate_list[] = { 234 { nv50_validate_fb, NV50_NEW_FRAMEBUFFER }, 235 { nv50_validate_blend, NV50_NEW_BLEND }, 236 { nv50_validate_zsa, NV50_NEW_ZSA }, 237 { nv50_validate_rasterizer, NV50_NEW_RASTERIZER }, 238 { nv50_validate_blend_colour, NV50_NEW_BLEND_COLOUR }, 239 { nv50_validate_stencil_ref, NV50_NEW_STENCIL_REF }, 240 { nv50_validate_stipple, NV50_NEW_STIPPLE }, 241#ifdef NV50_SCISSORS_CLIPPING 242 { nv50_validate_scissor, NV50_NEW_SCISSOR | NV50_NEW_VIEWPORT | 243 NV50_NEW_RASTERIZER | 244 NV50_NEW_FRAMEBUFFER }, 245#else 246 { nv50_validate_scissor, NV50_NEW_SCISSOR }, 247#endif 248 { nv50_validate_viewport, NV50_NEW_VIEWPORT }, 249 { nv50_validate_clip, NV50_NEW_CLIP }, 250 { nv50_vertprog_validate, NV50_NEW_VERTPROG }, 251 { nv50_gmtyprog_validate, NV50_NEW_GMTYPROG }, 252 { nv50_fragprog_validate, NV50_NEW_FRAGPROG }, 253 { nv50_fp_linkage_validate, NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG | 254 NV50_NEW_GMTYPROG }, 255 { nv50_gp_linkage_validate, NV50_NEW_GMTYPROG | NV50_NEW_VERTPROG }, 256 { nv50_constbufs_validate, NV50_NEW_CONSTBUF }, 257 { nv50_validate_textures, NV50_NEW_TEXTURES }, 258 { nv50_validate_samplers, NV50_NEW_SAMPLERS }, 259 { nv50_vertex_arrays_validate, NV50_NEW_VERTEX | NV50_NEW_ARRAYS } 260}; 261#define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0])) 262 263boolean 264nv50_state_validate(struct nv50_context *nv50) 265{ 266 unsigned i; 267#if 0 268 if (nv50->screen->cur_ctx != nv50) /* FIXME: not everything is valid */ 269 nv50->dirty = 0xffffffff; 270#endif 271 nv50->screen->cur_ctx = nv50; 272 273 if (nv50->dirty) { 274 for (i = 0; i < validate_list_len; ++i) { 275 struct state_validate *validate = &validate_list[i]; 276 277 if (nv50->dirty & validate->states) 278 validate->func(nv50); 279 } 280 nv50->dirty = 0; 281 } 282 283 nv50_bufctx_emit_relocs(nv50); 284 285 return TRUE; 286} 287