/* Validate state derived from shaders and the rasterizer cso. */ void nv50_validate_derived_rs(struct nv50_context *nv50) { struct nouveau_channel *chan = nv50->screen->base.channel; uint32_t color, psize; nv50_sprite_coords_validate(nv50); if (nv50->dirty & NV50_NEW_FRAGPROG) return; psize = nv50->state.semantic_psize & ~NV50_3D_MAP_SEMANTIC_3_PTSZ_EN__MASK; color = nv50->state.semantic_color & ~NV50_3D_MAP_SEMANTIC_0_CLMP_EN; if (nv50->rast->pipe.clamp_vertex_color) color |= NV50_3D_MAP_SEMANTIC_0_CLMP_EN; if (color != nv50->state.semantic_color) { nv50->state.semantic_color = color; BEGIN_RING(chan, RING_3D(MAP_SEMANTIC_0), 1); OUT_RING (chan, color); } if (nv50->rast->pipe.point_size_per_vertex) psize |= NV50_3D_MAP_SEMANTIC_3_PTSZ_EN__MASK; if (psize != nv50->state.semantic_psize) { nv50->state.semantic_psize = psize; BEGIN_RING(chan, RING_3D(MAP_SEMANTIC_3), 1); OUT_RING (chan, psize); } }
void nv40_fragtex_set(struct nvfx_context *nvfx, int unit) { struct nouveau_channel* chan = nvfx->screen->base.channel; struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit]; struct nvfx_sampler_view* sv = (struct nvfx_sampler_view*)nvfx->fragment_sampler_views[unit]; struct nouveau_bo *bo = ((struct nvfx_miptree *)sv->base.texture)->base.bo; unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; unsigned txf; unsigned max_lod = MIN2(ps->max_lod + sv->lod_offset, sv->max_lod_limit); unsigned min_lod = MIN2(ps->min_lod + sv->lod_offset, max_lod); txf = sv->u.nv40.fmt[ps->compare] | ps->fmt; MARK_RING(chan, 11, 2); OUT_RING(chan, RING_3D(NV30_3D_TEX_OFFSET(unit), 8)); OUT_RELOC(chan, bo, sv->offset, tex_flags | NOUVEAU_BO_LOW, 0, 0); OUT_RELOC(chan, bo, txf, tex_flags | NOUVEAU_BO_OR, NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1); OUT_RING(chan, (ps->wrap & sv->wrap_mask) | sv->wrap); OUT_RING(chan, ps->en | (min_lod << 19) | (max_lod << 7)); OUT_RING(chan, sv->swizzle); OUT_RING(chan, ps->filt | sv->filt); OUT_RING(chan, sv->npot_size); OUT_RING(chan, ps->bcol); OUT_RING(chan, RING_3D(NV40_3D_TEX_SIZE1(unit), 1)); OUT_RING(chan, sv->u.nv40.npot_size2); nvfx->hw_txf[unit] = txf; nvfx->hw_samplers |= (1 << unit); }
void nvc0_vertprog_validate(struct nvc0_context *nvc0) { struct nouveau_channel *chan = nvc0->screen->base.channel; struct nvc0_program *vp = nvc0->vertprog; if (nvc0->clip.nr > vp->vp.num_ucps) { assert(nvc0->clip.nr <= 6); vp->vp.num_ucps = 6; if (vp->translated) nvc0_program_destroy(nvc0, vp); } if (!nvc0_program_validate(nvc0, vp)) return; nvc0_program_update_context_state(nvc0, vp, 0); BEGIN_RING(chan, RING_3D(SP_SELECT(1)), 2); OUT_RING (chan, 0x11); OUT_RING (chan, vp->code_base); BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(1)), 1); OUT_RING (chan, vp->max_gpr); if (!nvc0->gmtyprog && !nvc0->tevlprog) nvc0_program_validate_clip(nvc0, vp); // BEGIN_RING(chan, RING_3D_(0x163c), 1); // OUT_RING (chan, 0); }
void nv50_gp_linkage_validate(struct nv50_context *nv50) { struct nouveau_channel *chan = nv50->screen->base.channel; struct nv50_program *vp = nv50->vertprog; struct nv50_program *gp = nv50->gmtyprog; int m = 0; int n; uint8_t map[64]; if (!gp) return; memset(map, 0, sizeof(map)); m = nv50_vp_gp_mapping(map, m, vp, gp); n = (m + 3) / 4; BEGIN_RING(chan, RING_3D(VP_GP_BUILTIN_ATTR_EN), 1); OUT_RING (chan, vp->vp.attrs[2] | gp->vp.attrs[2]); BEGIN_RING(chan, RING_3D(VP_RESULT_MAP_SIZE), 1); OUT_RING (chan, m); BEGIN_RING(chan, RING_3D(VP_RESULT_MAP(0)), n); OUT_RINGp (chan, map, n); }
static INLINE void nvc0_program_update_context_state(struct nvc0_context *nvc0, struct nvc0_program *prog, int stage) { struct nouveau_channel *chan = nvc0->screen->base.channel; if (prog->hdr[1]) nvc0->state.tls_required |= 1 << stage; else nvc0->state.tls_required &= ~(1 << stage); if (prog->immd_size) { const unsigned rl = NOUVEAU_BO_VRAM | NOUVEAU_BO_RD; BEGIN_RING(chan, RING_3D(CB_SIZE), 3); /* NOTE: may overlap code of a different shader */ OUT_RING (chan, align(prog->immd_size, 0x100)); OUT_RELOCh(chan, nvc0->screen->text, prog->immd_base, rl); OUT_RELOCl(chan, nvc0->screen->text, prog->immd_base, rl); BEGIN_RING(chan, RING_3D(CB_BIND(stage)), 1); OUT_RING (chan, (14 << 4) | 1); nvc0->state.c14_bound |= 1 << stage; } else if (nvc0->state.c14_bound & (1 << stage)) { BEGIN_RING(chan, RING_3D(CB_BIND(stage)), 1); OUT_RING (chan, (14 << 4) | 0); nvc0->state.c14_bound &= ~(1 << stage); } }
void nvc0_tevlprog_validate(struct nvc0_context *nvc0) { struct nouveau_channel *chan = nvc0->screen->base.channel; struct nvc0_program *tp = nvc0->tevlprog; if (!tp) { BEGIN_RING(chan, RING_3D(TEP_SELECT), 1); OUT_RING (chan, 0x30); return; } if (!nvc0_program_validate(nvc0, tp)) return; nvc0_program_update_context_state(nvc0, tp, 2); if (tp->tp.tess_mode != ~0) { BEGIN_RING(chan, RING_3D(TESS_MODE), 1); OUT_RING (chan, tp->tp.tess_mode); } BEGIN_RING(chan, RING_3D(TEP_SELECT), 1); OUT_RING (chan, 0x31); BEGIN_RING(chan, RING_3D(SP_START_ID(3)), 1); OUT_RING (chan, tp->code_base); BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(3)), 1); OUT_RING (chan, tp->max_gpr); if (!nvc0->gmtyprog) nvc0_program_validate_clip(nvc0, tp); }
void nvc0_tctlprog_validate(struct nvc0_context *nvc0) { struct nouveau_channel *chan = nvc0->screen->base.channel; struct nvc0_program *tp = nvc0->tctlprog; if (!tp) { BEGIN_RING(chan, RING_3D(SP_SELECT(2)), 1); OUT_RING (chan, 0x20); return; } if (!nvc0_program_validate(nvc0, tp)) return; nvc0_program_update_context_state(nvc0, tp, 1); if (tp->tp.tess_mode != ~0) { BEGIN_RING(chan, RING_3D(TESS_MODE), 1); OUT_RING (chan, tp->tp.tess_mode); } BEGIN_RING(chan, RING_3D(SP_SELECT(2)), 2); OUT_RING (chan, 0x21); OUT_RING (chan, tp->code_base); BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(2)), 1); OUT_RING (chan, tp->max_gpr); if (tp->tp.input_patch_size <= 32) IMMED_RING(chan, RING_3D(PATCH_VERTICES), tp->tp.input_patch_size); }
static void nvc0_texture_barrier(struct pipe_context *pipe) { struct nouveau_channel *chan = nvc0_context(pipe)->screen->base.channel; IMMED_RING(chan, RING_3D(SERIALIZE), 0); IMMED_RING(chan, RING_3D(TEX_CACHE_CTL), 0); }
static void nv50_sprite_coords_validate(struct nv50_context *nv50) { struct nouveau_channel *chan = nv50->screen->base.channel; uint32_t pntc[8], mode; struct nv50_program *fp = nv50->fragprog; unsigned i, c; unsigned m = (nv50->state.interpolant_ctrl >> 8) & 0xff; if (!nv50->rast->pipe.point_quad_rasterization) { if (nv50->state.point_sprite) { BEGIN_RING(chan, RING_3D(POINT_COORD_REPLACE_MAP(0)), 8); for (i = 0; i < 8; ++i) OUT_RING(chan, 0); nv50->state.point_sprite = FALSE; } return; } else { nv50->state.point_sprite = TRUE; } memset(pntc, 0, sizeof(pntc)); for (i = 0; i < fp->in_nr; i++) { unsigned n = util_bitcount(fp->in[i].mask); if (fp->in[i].sn != TGSI_SEMANTIC_GENERIC) { m += n; continue; } if (!(nv50->rast->pipe.sprite_coord_enable & (1 << fp->in[i].si))) { m += n; continue; } for (c = 0; c < 4; ++c) { if (fp->in[i].mask & (1 << c)) { pntc[m / 8] |= (c + 1) << ((m % 8) * 4); ++m; } } } if (nv50->rast->pipe.sprite_coord_mode == PIPE_SPRITE_COORD_LOWER_LEFT) mode = 0x00; else mode = 0x10; BEGIN_RING(chan, RING_3D(POINT_SPRITE_CTRL), 1); OUT_RING (chan, mode); BEGIN_RING(chan, RING_3D(POINT_COORD_REPLACE_MAP(0)), 8); OUT_RINGp (chan, pntc, 8); }
void nv50_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba, double depth, unsigned stencil) { struct nv50_context *nv50 = nv50_context(pipe); struct nouveau_channel *chan = nv50->screen->base.channel; struct pipe_framebuffer_state *fb = &nv50->framebuffer; unsigned i; const unsigned dirty = nv50->dirty; uint32_t mode = 0; /* don't need NEW_BLEND, COLOR_MASK doesn't affect CLEAR_BUFFERS */ nv50->dirty &= NV50_NEW_FRAMEBUFFER; if (!nv50_state_validate(nv50, 9 + (fb->nr_cbufs * 2))) return; if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) { BEGIN_RING(chan, RING_3D(CLEAR_COLOR(0)), 4); OUT_RINGf (chan, rgba[0]); OUT_RINGf (chan, rgba[1]); OUT_RINGf (chan, rgba[2]); OUT_RINGf (chan, rgba[3]); mode = NV50_3D_CLEAR_BUFFERS_R | NV50_3D_CLEAR_BUFFERS_G | NV50_3D_CLEAR_BUFFERS_B | NV50_3D_CLEAR_BUFFERS_A; } if (buffers & PIPE_CLEAR_DEPTH) { BEGIN_RING(chan, RING_3D(CLEAR_DEPTH), 1); OUT_RING (chan, fui(depth)); mode |= NV50_3D_CLEAR_BUFFERS_Z; } if (buffers & PIPE_CLEAR_STENCIL) { BEGIN_RING(chan, RING_3D(CLEAR_STENCIL), 1); OUT_RING (chan, stencil & 0xff); mode |= NV50_3D_CLEAR_BUFFERS_S; } BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1); OUT_RING (chan, mode); for (i = 1; i < fb->nr_cbufs; i++) { BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1); OUT_RING (chan, (i << 6) | 0x3c); } nv50->dirty = dirty & ~NV50_NEW_FRAMEBUFFER; }
static void emit_edgeflag(struct push_context *ctx, boolean enabled) { struct nouveau_channel *chan = ctx->nvc0->screen->base.channel; IMMED_RING(chan, RING_3D(EDGEFLAG_ENABLE), enabled); }
void nvfx_vbo_relocate(struct nvfx_context *nvfx) { struct nouveau_channel* chan; unsigned vb_flags; int i; if(!nvfx->use_vertex_buffers) return; chan = nvfx->screen->base.channel; vb_flags = nvfx->screen->vertex_buffer_reloc_flags | NOUVEAU_BO_RD | NOUVEAU_BO_DUMMY; MARK_RING(chan, 2 * 16 + 3, 2 * 16 + 3); for (i = 0; i < nvfx->vtxelt->num_per_vertex; i++) { struct nvfx_per_vertex_element *ve = &nvfx->vtxelt->per_vertex[i]; struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[ve->vertex_buffer_index]; struct nouveau_bo* bo = nvfx_resource(vb->buffer)->bo; OUT_RELOC(chan, bo, RING_3D(NV30_3D_VTXBUF(ve->idx), 1), vb_flags, 0, 0); OUT_RELOC(chan, bo, vb->buffer_offset + ve->src_offset + nvfx->base_vertex * vb->stride, vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, 0, NV30_3D_VTXBUF_DMA1); } nvfx->relocs_needed &=~ NVFX_RELOCATE_VTXBUF; }
static INLINE void emit_elt16(void* priv, unsigned start, unsigned vc) { struct push_context* ctx = priv; struct nouveau_channel *chan = ctx->chan; uint16_t *elts = (uint16_t *)ctx->idxbuf + start; int idxbias = ctx->idxbias; if (vc & 1) { OUT_RING(chan, RING_3D(NV30_3D_VB_ELEMENT_U32, 1)); OUT_RING (chan, elts[0]); elts++; vc--; } while (vc) { unsigned i; unsigned push = MIN2(vc, 2047 * 2); OUT_RING(chan, RING_3D_NI(NV30_3D_VB_ELEMENT_U16, push >> 1)); for (i = 0; i < push; i+=2) OUT_RING(chan, ((elts[i+1] + idxbias) << 16) | (elts[i] + idxbias)); vc -= push; elts += push; } }
void nvfx_fragtex_relocate(struct nvfx_context *nvfx) { struct nouveau_channel* chan = nvfx->screen->base.channel; unsigned samplers, unit; unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; samplers = nvfx->hw_samplers; while (samplers) { struct nvfx_miptree* mt; struct nouveau_bo *bo; unit = ffs(samplers) - 1; samplers &= ~(1 << unit); mt = (struct nvfx_miptree*)nvfx->fragment_sampler_views[unit]->texture; bo = mt->base.bo; MARK_RING(chan, 3, 3); OUT_RELOC(chan, bo, RING_3D(NV30_3D_TEX_OFFSET(unit), 2), tex_flags | NOUVEAU_BO_DUMMY, 0, 0); OUT_RELOC(chan, bo, 0, tex_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_DUMMY, 0, 0); OUT_RELOC(chan, bo, nvfx->hw_txf[unit], tex_flags | NOUVEAU_BO_OR | NOUVEAU_BO_DUMMY, NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1); } nvfx->relocs_needed &=~ NVFX_RELOCATE_FRAGTEX; }
static void emit_ranges(void* priv, unsigned start, unsigned vc, unsigned reg) { struct push_context* ctx = priv; struct nouveau_channel *chan = ctx->chan; unsigned nr = (vc & 0xff); if (nr) { OUT_RING(chan, RING_3D(reg, 1)); OUT_RING (chan, ((nr - 1) << 24) | start); start += nr; } nr = vc >> 8; while (nr) { unsigned push = nr > 2047 ? 2047 : nr; nr -= push; OUT_RING(chan, RING_3D_NI(reg, push)); while (push--) { OUT_RING(chan, ((0x100 - 1) << 24) | start); start += 0x100; } } }
static void emit_edgeflag(void *priv, boolean enabled) { struct push_context* ctx = priv; struct nouveau_channel *chan = ctx->chan; OUT_RING(chan, RING_3D(NV30_3D_EDGEFLAG, 1)); OUT_RING(chan, enabled ? 1 : 0); }
static void nvc0_program_validate_clip(struct nvc0_context *nvc0, struct nvc0_program *vp) { struct nouveau_channel *chan = nvc0->screen->base.channel; if (nvc0->vertprog->vp.num_ucps) return; if (nvc0->state.clip_enable != vp->vp.clip_enable) { nvc0->state.clip_enable = vp->vp.clip_enable; IMMED_RING(chan, RING_3D(CLIP_DISTANCE_ENABLE), vp->vp.clip_enable); } if (nvc0->state.clip_mode != vp->vp.clip_mode) { nvc0->state.clip_mode = vp->vp.clip_mode; BEGIN_RING(chan, RING_3D(CLIP_DISTANCE_MODE), 1); OUT_RING (chan, vp->vp.clip_mode); } }
void nv50_vertprog_validate(struct nv50_context *nv50) { struct nouveau_channel *chan = nv50->screen->base.channel; struct nv50_program *vp = nv50->vertprog; if (!nv50_program_validate(nv50, vp)) return; BEGIN_RING(chan, RING_3D(VP_ATTR_EN(0)), 2); OUT_RING (chan, vp->vp.attrs[0]); OUT_RING (chan, vp->vp.attrs[1]); BEGIN_RING(chan, RING_3D(VP_REG_ALLOC_RESULT), 1); OUT_RING (chan, vp->max_out); BEGIN_RING(chan, RING_3D(VP_REG_ALLOC_TEMP), 1); OUT_RING (chan, vp->max_gpr); BEGIN_RING(chan, RING_3D(VP_START_ID), 1); OUT_RING (chan, vp->code_base); }
void nv50_fragprog_validate(struct nv50_context *nv50) { struct nouveau_channel *chan = nv50->screen->base.channel; struct nv50_program *fp = nv50->fragprog; if (!nv50_program_validate(nv50, fp)) return; BEGIN_RING(chan, RING_3D(FP_REG_ALLOC_TEMP), 1); OUT_RING (chan, fp->max_gpr); BEGIN_RING(chan, RING_3D(FP_RESULT_COUNT), 1); OUT_RING (chan, fp->max_out); BEGIN_RING(chan, RING_3D(FP_CONTROL), 1); OUT_RING (chan, fp->fp.flags[0]); BEGIN_RING(chan, RING_3D(FP_CTRL_UNK196C), 1); OUT_RING (chan, fp->fp.flags[1]); BEGIN_RING(chan, RING_3D(FP_START_ID), 1); OUT_RING (chan, fp->code_base); }
static void nvfx_idxbuf_emit(struct nvfx_context* nvfx, unsigned ib_flags) { struct nouveau_channel* chan = nvfx->screen->base.channel; unsigned ib_format = (nvfx->idxbuf.index_size == 2) ? NV30_3D_IDXBUF_FORMAT_TYPE_U16 : NV30_3D_IDXBUF_FORMAT_TYPE_U32; struct nouveau_bo* bo = nvfx_resource(nvfx->idxbuf.buffer)->bo; ib_flags |= nvfx->screen->index_buffer_reloc_flags | NOUVEAU_BO_RD; assert(nvfx->screen->index_buffer_reloc_flags); MARK_RING(chan, 3, 3); if(ib_flags & NOUVEAU_BO_DUMMY) OUT_RELOC(chan, bo, RING_3D(NV30_3D_IDXBUF_OFFSET, 2), ib_flags, 0, 0); else OUT_RING(chan, RING_3D(NV30_3D_IDXBUF_OFFSET, 2)); OUT_RELOC(chan, bo, nvfx->idxbuf.offset + 1, ib_flags | NOUVEAU_BO_LOW, 0, 0); OUT_RELOC(chan, bo, ib_format, ib_flags | NOUVEAU_BO_OR, 0, NV30_3D_IDXBUF_FORMAT_DMA1); nvfx->relocs_needed &=~ NVFX_RELOCATE_IDXBUF; }
void nv30_fragtex_set(struct nvfx_context *nvfx, int unit) { struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit]; struct nvfx_sampler_view* sv = (struct nvfx_sampler_view*)nvfx->fragment_sampler_views[unit]; struct nouveau_bo *bo = ((struct nvfx_miptree *)sv->base.texture)->base.bo; struct nouveau_channel* chan = nvfx->screen->base.channel; unsigned txf; unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; unsigned use_rect; unsigned max_lod = MIN2(ps->max_lod + sv->lod_offset, sv->max_lod_limit); unsigned min_lod = MIN2(ps->min_lod + sv->lod_offset, max_lod) ; if(sv->u.nv30.rect < 0) { /* in the case of compressed or 1D textures, we can get away with this, * since the layout is the same */ use_rect = ps->fmt; } else { static boolean warned = FALSE; if( !!ps->fmt != sv->u.nv30.rect && !warned) { warned = TRUE; fprintf(stderr, "Unimplemented: coordinate normalization mismatch. Possible reasons:\n" "1. ARB_texture_non_power_of_two is being used despite the fact it isn't supported\n" "2. The state tracker is not using the appropriate coordinate normalization\n" "3. The state tracker is not supported\n"); } use_rect = sv->u.nv30.rect; } txf = sv->u.nv30.fmt[ps->compare + (use_rect ? 2 : 0)]; MARK_RING(chan, 9, 2); OUT_RING(chan, RING_3D(NV30_3D_TEX_OFFSET(unit), 8)); OUT_RELOC(chan, bo, sv->offset, tex_flags | NOUVEAU_BO_LOW, 0, 0); OUT_RELOC(chan, bo, txf, tex_flags | NOUVEAU_BO_OR, NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1); OUT_RING(chan, (ps->wrap & sv->wrap_mask) | sv->wrap); OUT_RING(chan, ps->en | (min_lod << NV30_3D_TEX_ENABLE_MIPMAP_MIN_LOD__SHIFT) | (max_lod << NV30_3D_TEX_ENABLE_MIPMAP_MAX_LOD__SHIFT)); OUT_RING(chan, sv->swizzle); OUT_RING(chan, ps->filt | sv->filt); OUT_RING(chan, sv->npot_size); OUT_RING(chan, ps->bcol); nvfx->hw_txf[unit] = txf; nvfx->hw_samplers |= (1 << unit); }
void nvc0_gmtyprog_validate(struct nvc0_context *nvc0) { struct nouveau_channel *chan = nvc0->screen->base.channel; struct nvc0_program *gp = nvc0->gmtyprog; if (gp) nvc0_program_validate(nvc0, gp); /* we allow GPs with no code for specifying stream output state only */ if (!gp || !gp->code_size) { BEGIN_RING(chan, RING_3D(GP_SELECT), 1); OUT_RING (chan, 0x40); IMMED_RING(chan, RING_3D(LAYER), 0); return; } nvc0_program_update_context_state(nvc0, gp, 3); BEGIN_RING(chan, RING_3D(GP_SELECT), 1); OUT_RING (chan, 0x41); BEGIN_RING(chan, RING_3D(SP_START_ID(4)), 1); OUT_RING (chan, gp->code_base); BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(4)), 1); OUT_RING (chan, gp->max_gpr); BEGIN_RING(chan, RING_3D(LAYER), 1); OUT_RING (chan, (gp->hdr[13] & (1 << 9)) ? NVC0_3D_LAYER_USE_GP : 0); nvc0_program_validate_clip(nvc0, gp); }
void nvc0_fragprog_validate(struct nvc0_context *nvc0) { struct nouveau_channel *chan = nvc0->screen->base.channel; struct nvc0_program *fp = nvc0->fragprog; if (!nvc0_program_validate(nvc0, fp)) return; nvc0_program_update_context_state(nvc0, fp, 4); BEGIN_RING(chan, RING_3D(SP_SELECT(5)), 2); OUT_RING (chan, 0x51); OUT_RING (chan, fp->code_base); BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(5)), 1); OUT_RING (chan, fp->max_gpr); BEGIN_RING(chan, RING_3D_(0x0360), 2); OUT_RING (chan, 0x20164010); OUT_RING (chan, 0x20); BEGIN_RING(chan, RING_3D_(0x196c), 1); OUT_RING (chan, fp->flags[0]); }
void nv50_gmtyprog_validate(struct nv50_context *nv50) { struct nouveau_channel *chan = nv50->screen->base.channel; struct nv50_program *gp = nv50->gmtyprog; if (!gp) /* GP_ENABLE is updated in linkage validation */ return; if (!nv50_program_validate(nv50, gp)) return; BEGIN_RING(chan, RING_3D(GP_REG_ALLOC_TEMP), 1); OUT_RING (chan, gp->max_gpr); BEGIN_RING(chan, RING_3D(GP_REG_ALLOC_RESULT), 1); OUT_RING (chan, gp->max_out); BEGIN_RING(chan, RING_3D(GP_OUTPUT_PRIMITIVE_TYPE), 1); OUT_RING (chan, gp->gp.prim_type); BEGIN_RING(chan, RING_3D(GP_VERTEX_OUTPUT_COUNT), 1); OUT_RING (chan, gp->gp.vert_count); BEGIN_RING(chan, RING_3D(GP_START_ID), 1); OUT_RING (chan, gp->code_base); }
static void nv50_clear_depth_stencil(struct pipe_context *pipe, struct pipe_surface *dst, unsigned clear_flags, double depth, unsigned stencil, unsigned dstx, unsigned dsty, unsigned width, unsigned height) { struct nv50_context *nv50 = nv50_context(pipe); struct nv50_screen *screen = nv50->screen; struct nouveau_channel *chan = screen->base.channel; struct nv50_miptree *mt = nv50_miptree(dst->texture); struct nv50_surface *sf = nv50_surface(dst); struct nouveau_bo *bo = mt->base.bo; uint32_t mode = 0; if (clear_flags & PIPE_CLEAR_DEPTH) { BEGIN_RING(chan, RING_3D(CLEAR_DEPTH), 1); OUT_RINGf (chan, depth); mode |= NV50_3D_CLEAR_BUFFERS_Z; } if (clear_flags & PIPE_CLEAR_STENCIL) { BEGIN_RING(chan, RING_3D(CLEAR_STENCIL), 1); OUT_RING (chan, stencil & 0xff); mode |= NV50_3D_CLEAR_BUFFERS_S; } if (MARK_RING(chan, 17, 2)) return; BEGIN_RING(chan, RING_3D(ZETA_ADDRESS_HIGH), 5); OUT_RELOCh(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); OUT_RELOCl(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); OUT_RING (chan, nv50_format_table[dst->format].rt); OUT_RING (chan, mt->level[sf->base.u.tex.level].tile_mode << 4); OUT_RING (chan, 0); BEGIN_RING(chan, RING_3D(ZETA_ENABLE), 1); OUT_RING (chan, 1); BEGIN_RING(chan, RING_3D(ZETA_HORIZ), 3); OUT_RING (chan, sf->width); OUT_RING (chan, sf->height); OUT_RING (chan, (1 << 16) | 1); BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2); OUT_RING (chan, (width << 16) | dstx); OUT_RING (chan, (height << 16) | dsty); BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1); OUT_RING (chan, mode); nv50->dirty |= NV50_NEW_FRAMEBUFFER; }
static void nvfx_render_flush(struct draw_stage *stage, unsigned flags) { struct nvfx_render_stage *rs = nvfx_render_stage(stage); struct nvfx_context *nvfx = rs->nvfx; struct nouveau_channel *chan = nvfx->screen->base.channel; if (rs->prim != NV30_3D_VERTEX_BEGIN_END_STOP) { assert(AVAIL_RING(chan) >= 2); OUT_RING(chan, RING_3D(NV30_3D_VERTEX_BEGIN_END, 1)); OUT_RING(chan, NV30_3D_VERTEX_BEGIN_END_STOP); rs->prim = NV30_3D_VERTEX_BEGIN_END_STOP; } }
void nvfx_vbo_swtnl_validate(struct nvfx_context *nvfx) { struct nouveau_channel* chan = nvfx->screen->base.channel; unsigned num_outputs = nvfx->vertprog->draw_elements; int elements = MAX2(num_outputs, nvfx->hw_vtxelt_nr); if (!elements) return; WAIT_RING(chan, (1 + 6 + 1 + 2) + elements * 2); OUT_RING(chan, RING_3D(NV30_3D_VTXFMT(0), elements)); for(unsigned i = 0; i < num_outputs; ++i) OUT_RING(chan, (4 << NV30_3D_VTXFMT_SIZE__SHIFT) | NV30_3D_VTXFMT_TYPE_V32_FLOAT); for(unsigned i = num_outputs; i < elements; ++i) OUT_RING(chan, NV30_3D_VTXFMT_TYPE_V32_FLOAT); if(nvfx->is_nv4x) { unsigned i; /* seems to be some kind of cache flushing */ for(i = 0; i < 3; ++i) { OUT_RING(chan, RING_3D(0x1718, 1)); OUT_RING(chan, 0); } } OUT_RING(chan, RING_3D(NV30_3D_VTXBUF(0), elements)); for (unsigned i = 0; i < elements; i++) OUT_RING(chan, 0); OUT_RING(chan, RING_3D(0x1710, 1)); OUT_RING(chan, 0); nvfx->hw_vtxelt_nr = num_outputs; nvfx->relocs_needed &=~ NVFX_RELOCATE_VTXBUF; }
static INLINE void emit_vertex(struct push_context *ctx, unsigned n) { struct nouveau_channel *chan = ctx->nvc0->screen->base.channel; int i; if (ctx->edgeflag_input < 32) { /* TODO */ } BEGIN_RING_NI(chan, RING_3D(VERTEX_DATA), ctx->vertex_size); for (i = 0; i < ctx->num_attrs; ++i) ctx->attr[i].push(chan, (uint8_t *)ctx->attr[i].map + n * ctx->attr[i].stride); }
void nvc0_cb_push(struct nouveau_context *nv, struct nouveau_bo *bo, unsigned domain, unsigned base, unsigned size, unsigned offset, unsigned words, const uint32_t *data) { struct nouveau_channel *chan = nv->screen->channel; assert(!(offset & 3)); size = align(size, 0x100); MARK_RING (chan, 16, 2); BEGIN_RING(chan, RING_3D(CB_SIZE), 3); OUT_RING (chan, size); OUT_RELOCh(chan, bo, base, domain | NOUVEAU_BO_WR); OUT_RELOCl(chan, bo, base, domain | NOUVEAU_BO_WR); while (words) { unsigned nr = AVAIL_RING(chan); nr = MIN2(nr, words); nr = MIN2(nr, NV04_PFIFO_MAX_PACKET_LEN - 1); BEGIN_RING_1I(chan, RING_3D(CB_POS), nr + 1); OUT_RING (chan, offset); OUT_RINGp (chan, data, nr); words -= nr; data += nr; offset += nr * 4; if (words) { MARK_RING(chan, 6, 1); nouveau_bo_validate(chan, bo, domain | NOUVEAU_BO_WR); } } }
static void nv50_clear_render_target(struct pipe_context *pipe, struct pipe_surface *dst, const float *rgba, unsigned dstx, unsigned dsty, unsigned width, unsigned height) { struct nv50_context *nv50 = nv50_context(pipe); struct nv50_screen *screen = nv50->screen; struct nouveau_channel *chan = screen->base.channel; struct nv50_miptree *mt = nv50_miptree(dst->texture); struct nv50_surface *sf = nv50_surface(dst); struct nouveau_bo *bo = mt->base.bo; BEGIN_RING(chan, RING_3D(CLEAR_COLOR(0)), 4); OUT_RINGf (chan, rgba[0]); OUT_RINGf (chan, rgba[1]); OUT_RINGf (chan, rgba[2]); OUT_RINGf (chan, rgba[3]); if (MARK_RING(chan, 18, 2)) return; BEGIN_RING(chan, RING_3D(RT_CONTROL), 1); OUT_RING (chan, 1); BEGIN_RING(chan, RING_3D(RT_ADDRESS_HIGH(0)), 5); OUT_RELOCh(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); OUT_RELOCl(chan, bo, sf->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); OUT_RING (chan, nv50_format_table[dst->format].rt); OUT_RING (chan, mt->level[sf->base.u.tex.level].tile_mode << 4); OUT_RING (chan, 0); BEGIN_RING(chan, RING_3D(RT_HORIZ(0)), 2); OUT_RING (chan, sf->width); OUT_RING (chan, sf->height); BEGIN_RING(chan, RING_3D(RT_ARRAY_MODE), 1); OUT_RING (chan, 1); /* NOTE: only works with D3D clear flag (5097/0x143c bit 4) */ BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2); OUT_RING (chan, (width << 16) | dstx); OUT_RING (chan, (height << 16) | dsty); BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1); OUT_RING (chan, 0x3c); nv50->dirty |= NV50_NEW_FRAMEBUFFER; }