inline void nvfx_state_relocate(struct nvfx_context *nvfx, unsigned relocs) { struct nouveau_channel* chan = nvfx->screen->base.channel; /* we need to ensure there is enough space to output relocations in one go */ const unsigned max_relocs = 0 + 16 /* vertex buffers, incl. dma flag */ + 2 /* index buffer plus format+dma flag */ + 2 * 5 /* 4 cbufs + zsbuf, plus dma objects */ + 2 * 16 /* fragment textures plus format+dma flag */ + 2 * 4 /* vertex textures plus format+dma flag */ + 1 /* fragprog incl dma flag */ ; MARK_RING(chan, max_relocs * 2, max_relocs * 2); if(relocs & NVFX_RELOCATE_FRAMEBUFFER) nvfx_framebuffer_relocate(nvfx); if(relocs & NVFX_RELOCATE_FRAGTEX) nvfx_fragtex_relocate(nvfx); if(relocs & NVFX_RELOCATE_FRAGPROG) nvfx_fragprog_relocate(nvfx); if(relocs & NVFX_RELOCATE_VTXBUF) nvfx_vbo_relocate(nvfx); if(relocs & NVFX_RELOCATE_IDXBUF) nvfx_idxbuf_relocate(nvfx); }
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 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; }
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; }
void nvc0_m2mf_copy_linear(struct nouveau_context *nv, struct nouveau_bo *dst, unsigned dstoff, unsigned dstdom, struct nouveau_bo *src, unsigned srcoff, unsigned srcdom, unsigned size) { struct nouveau_channel *chan = nv->screen->channel; while (size) { unsigned bytes = MIN2(size, 1 << 17); MARK_RING (chan, 11, 4); BEGIN_RING(chan, RING_MF(OFFSET_OUT_HIGH), 2); OUT_RELOCh(chan, dst, dstoff, dstdom | NOUVEAU_BO_WR); OUT_RELOCl(chan, dst, dstoff, dstdom | NOUVEAU_BO_WR); BEGIN_RING(chan, RING_MF(OFFSET_IN_HIGH), 2); OUT_RELOCh(chan, src, srcoff, srcdom | NOUVEAU_BO_RD); OUT_RELOCl(chan, src, srcoff, srcdom | NOUVEAU_BO_RD); BEGIN_RING(chan, RING_MF(LINE_LENGTH_IN), 2); OUT_RING (chan, bytes); OUT_RING (chan, 1); BEGIN_RING(chan, RING_MF(EXEC), 1); OUT_RING (chan, (1 << NVC0_M2MF_EXEC_INC__SHIFT) | NVC0_M2MF_EXEC_LINEAR_IN | NVC0_M2MF_EXEC_LINEAR_OUT); srcoff += bytes; dstoff += bytes; size -= bytes; } }
static void nv50_clear_render_target(struct pipe_context *pipe, struct pipe_surface *dst, const union pipe_color_union *color, unsigned dstx, unsigned dsty, unsigned width, unsigned height) { struct nv50_context *nv50 = nv50_context(pipe); struct nouveau_pushbuf *push = nv50->base.pushbuf; struct nv50_miptree *mt = nv50_miptree(dst->texture); struct nv50_surface *sf = nv50_surface(dst); struct nouveau_bo *bo = mt->base.bo; BEGIN_NV04(push, NV50_3D(CLEAR_COLOR(0)), 4); PUSH_DATAf(push, color->f[0]); PUSH_DATAf(push, color->f[1]); PUSH_DATAf(push, color->f[2]); PUSH_DATAf(push, color->f[3]); #if 0 if (MARK_RING(chan, 18, 2)) return; #endif BEGIN_NV04(push, NV50_3D(RT_CONTROL), 1); PUSH_DATA (push, 1); BEGIN_NV04(push, NV50_3D(RT_ADDRESS_HIGH(0)), 5); PUSH_DATAh(push, bo->offset + sf->offset); PUSH_DATA (push, bo->offset + sf->offset); PUSH_DATA (push, nv50_format_table[dst->format].rt); PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode); PUSH_DATA (push, 0); BEGIN_NV04(push, NV50_3D(RT_HORIZ(0)), 2); if (nouveau_bo_memtype(bo)) PUSH_DATA(push, sf->width); else PUSH_DATA(push, NV50_3D_RT_HORIZ_LINEAR | mt->level[0].pitch); PUSH_DATA (push, sf->height); BEGIN_NV04(push, NV50_3D(RT_ARRAY_MODE), 1); PUSH_DATA (push, 1); if (!nouveau_bo_memtype(bo)) { BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1); PUSH_DATA (push, 0); } /* NOTE: only works with D3D clear flag (5097/0x143c bit 4) */ BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2); PUSH_DATA (push, (width << 16) | dstx); PUSH_DATA (push, (height << 16) | dsty); BEGIN_NV04(push, NV50_3D(CLEAR_BUFFERS), 1); PUSH_DATA (push, 0x3c); nv50->dirty |= NV50_NEW_FRAMEBUFFER; }
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 nouveau_pushbuf *push = nv50->base.pushbuf; 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; assert(nouveau_bo_memtype(bo)); /* ZETA cannot be linear */ if (clear_flags & PIPE_CLEAR_DEPTH) { BEGIN_NV04(push, NV50_3D(CLEAR_DEPTH), 1); PUSH_DATAf(push, depth); mode |= NV50_3D_CLEAR_BUFFERS_Z; } if (clear_flags & PIPE_CLEAR_STENCIL) { BEGIN_NV04(push, NV50_3D(CLEAR_STENCIL), 1); PUSH_DATA (push, stencil & 0xff); mode |= NV50_3D_CLEAR_BUFFERS_S; } #if 0 if (MARK_RING(chan, 17, 2)) return; #endif BEGIN_NV04(push, NV50_3D(ZETA_ADDRESS_HIGH), 5); PUSH_DATAh(push, bo->offset + sf->offset); PUSH_DATA (push, bo->offset + sf->offset); PUSH_DATA (push, nv50_format_table[dst->format].rt); PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode); PUSH_DATA (push, 0); BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1); PUSH_DATA (push, 1); BEGIN_NV04(push, NV50_3D(ZETA_HORIZ), 3); PUSH_DATA (push, sf->width); PUSH_DATA (push, sf->height); PUSH_DATA (push, (1 << 16) | 1); BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2); PUSH_DATA (push, (width << 16) | dstx); PUSH_DATA (push, (height << 16) | dsty); BEGIN_NV04(push, NV50_3D(CLEAR_BUFFERS), 1); PUSH_DATA (push, mode); nv50->dirty |= NV50_NEW_FRAMEBUFFER; }
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; }
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); }
static int nv50_2d_texture_do_copy(struct nouveau_channel *chan, struct nv50_miptree *dst, unsigned dst_level, unsigned dx, unsigned dy, unsigned dz, struct nv50_miptree *src, unsigned src_level, unsigned sx, unsigned sy, unsigned sz, unsigned w, unsigned h) { static const uint32_t duvdxy[5] = { 0x40000000, 0x80000000, 0x00000001, 0x00000002, 0x00000004 }; int ret; uint32_t ctrl; ret = MARK_RING(chan, 2 * 16 + 32, 4); if (ret) return ret; ret = nv50_2d_texture_set(chan, 1, dst, dst_level, dz); if (ret) return ret; ret = nv50_2d_texture_set(chan, 0, src, src_level, sz); if (ret) return ret; /* NOTE: 2D engine doesn't work for MS8 */ if (src->ms_x) ctrl = 0x11; /* 0/1 = CENTER/CORNER, 00/10 = POINT/BILINEAR */ BEGIN_RING(chan, RING_2D(BLIT_CONTROL), 1); OUT_RING (chan, ctrl); BEGIN_RING(chan, RING_2D(BLIT_DST_X), 4); OUT_RING (chan, dx << dst->ms_x); OUT_RING (chan, dy << dst->ms_y); OUT_RING (chan, w << dst->ms_x); OUT_RING (chan, h << dst->ms_y); BEGIN_RING(chan, RING_2D(BLIT_DU_DX_FRACT), 4); OUT_RING (chan, duvdxy[2 + ((int)src->ms_x - (int)dst->ms_x)] & 0xf0000000); OUT_RING (chan, duvdxy[2 + ((int)src->ms_x - (int)dst->ms_x)] & 0x0000000f); OUT_RING (chan, duvdxy[2 + ((int)src->ms_y - (int)dst->ms_y)] & 0xf0000000); OUT_RING (chan, duvdxy[2 + ((int)src->ms_y - (int)dst->ms_y)] & 0x0000000f); BEGIN_RING(chan, RING_2D(BLIT_SRC_X_FRACT), 4); OUT_RING (chan, 0); OUT_RING (chan, sx << src->ms_x); OUT_RING (chan, 0); OUT_RING (chan, sy << src->ms_y); return 0; }
Bool NV10EXAPrepareComposite(int op, PicturePtr pict_src, PicturePtr pict_mask, PicturePtr pict_dst, PixmapPtr src, PixmapPtr mask, PixmapPtr dst) { ScrnInfoPtr pScrn = xf86Screens[dst->drawable.pScreen->myNum]; NVPtr pNv = NVPTR(pScrn); struct nouveau_channel *chan = pNv->chan; if (MARK_RING(chan, 128, 5)) return FALSE; pNv->alu = op; pNv->pspict = pict_src; pNv->pmpict = pict_mask; pNv->pdpict = pict_dst; pNv->pspix = src; pNv->pmpix = mask; pNv->pdpix = dst; /* Set dst format */ if (!setup_render_target(pNv, pict_dst, dst)) goto fail; /* Set src format */ if (!setup_texture(pNv, 0, pict_src, src)) goto fail; /* Set mask format */ if (mask && !setup_texture(pNv, 1, pict_mask, mask)) goto fail; /* Set the register combiners up. */ setup_combiners(pNv, pict_src, pict_mask); /* Set PictOp */ setup_blend_function(pNv); chan->flush_notify = NV10StateCompositeReemit; return TRUE; fail: MARK_UNDO(chan); return FALSE; }
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; }
static void nv50_query_end(struct pipe_context *pipe, struct pipe_query *pq) { struct nv50_context *nv50 = nv50_context(pipe); struct nouveau_channel *chan = nv50->screen->base.channel; struct nouveau_grobj *tesla = nv50->screen->tesla; struct nv50_query *q = nv50_query(pq); MARK_RING (chan, 5, 2); /* flush on lack of space or relocs */ BEGIN_RING(chan, tesla, NV50TCL_QUERY_ADDRESS_HIGH, 4); OUT_RELOCh(chan, q->bo, 0, NOUVEAU_BO_GART | NOUVEAU_BO_WR); OUT_RELOCl(chan, q->bo, 0, NOUVEAU_BO_GART | NOUVEAU_BO_WR); OUT_RING (chan, 0x00000000); OUT_RING (chan, 0x0100f002); BEGIN_RING(chan, tesla, NV50TCL_SAMPLECNT_ENABLE, 1); OUT_RING (chan, 0); }
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 nvc0_m2mf_push_linear(struct nouveau_context *nv, struct nouveau_bo *dst, unsigned offset, unsigned domain, unsigned size, void *data) { struct nouveau_channel *chan = nv->screen->channel; uint32_t *src = (uint32_t *)data; unsigned count = (size + 3) / 4; MARK_RING (chan, 8, 2); BEGIN_RING(chan, RING_MF(OFFSET_OUT_HIGH), 2); OUT_RELOCh(chan, dst, offset, domain | NOUVEAU_BO_WR); OUT_RELOCl(chan, dst, offset, domain | NOUVEAU_BO_WR); BEGIN_RING(chan, RING_MF(LINE_LENGTH_IN), 2); OUT_RING (chan, size); OUT_RING (chan, 1); BEGIN_RING(chan, RING_MF(EXEC), 1); OUT_RING (chan, 0x100111); while (count) { unsigned nr = AVAIL_RING(chan); if (nr < 9) { FIRE_RING(chan); nouveau_bo_validate(chan, dst, NOUVEAU_BO_WR); continue; } nr = MIN2(count, nr - 1); nr = MIN2(nr, NV04_PFIFO_MAX_PACKET_LEN); BEGIN_RING_NI(chan, RING_MF(DATA), nr); OUT_RINGp (chan, src, nr); src += nr; count -= nr; } }
void nvc0_m2mf_push_linear(struct nouveau_context *nv, struct nouveau_bo *dst, unsigned offset, unsigned domain, unsigned size, const void *data) { struct nouveau_channel *chan = nv->screen->channel; uint32_t *src = (uint32_t *)data; unsigned count = (size + 3) / 4; while (count) { unsigned nr; MARK_RING (chan, 16, 2); nr = AVAIL_RING(chan) - 9; nr = MIN2(count, nr); nr = MIN2(nr, NV04_PFIFO_MAX_PACKET_LEN); BEGIN_RING(chan, RING_MF(OFFSET_OUT_HIGH), 2); OUT_RELOCh(chan, dst, offset, domain | NOUVEAU_BO_WR); OUT_RELOCl(chan, dst, offset, domain | NOUVEAU_BO_WR); BEGIN_RING(chan, RING_MF(LINE_LENGTH_IN), 2); OUT_RING (chan, nr * 4); OUT_RING (chan, 1); BEGIN_RING(chan, RING_MF(EXEC), 1); OUT_RING (chan, 0x100111); /* must not be interrupted (trap on QUERY fence, 0x50 works however) */ BEGIN_RING_NI(chan, RING_MF(DATA), nr); OUT_RINGp (chan, src, nr); count -= nr; src += nr; offset += nr * 4; } }
static inline Bool NVAccelDownloadM2MF(PixmapPtr pspix, int x, int y, int w, int h, char *dst, unsigned dst_pitch) { ScrnInfoPtr pScrn = xf86Screens[pspix->drawable.pScreen->myNum]; NVPtr pNv = NVPTR(pScrn); struct nouveau_channel *chan = pNv->chan; struct nouveau_grobj *m2mf = pNv->NvMemFormat; struct nouveau_bo *bo = nouveau_pixmap_bo(pspix); unsigned cpp = pspix->drawable.bitsPerPixel / 8; unsigned line_len = w * cpp; unsigned src_offset = 0, src_pitch = 0, linear = 0; /* Maximum DMA transfer */ unsigned line_count = pNv->GART->size / line_len; if (!nv50_style_tiled_pixmap(pspix)) { linear = 1; src_pitch = exaGetPixmapPitch(pspix); src_offset += (y * src_pitch) + (x * cpp); } /* HW limitations */ if (line_count > 2047) line_count = 2047; while (h) { int i; char *src; if (line_count > h) line_count = h; if (MARK_RING(chan, 32, 6)) return FALSE; BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2); if (OUT_RELOCo(chan, bo, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD) || OUT_RELOCo(chan, pNv->GART, NOUVEAU_BO_GART | NOUVEAU_BO_WR)) { MARK_UNDO(chan); return FALSE; } if (pNv->Architecture >= NV_ARCH_50) { if (!linear) { BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN, 7); OUT_RING (chan, 0); OUT_RING (chan, bo->tile_mode << 4); OUT_RING (chan, pspix->drawable.width * cpp); OUT_RING (chan, pspix->drawable.height); OUT_RING (chan, 1); OUT_RING (chan, 0); OUT_RING (chan, (y << 16) | (x * cpp)); } else { BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN, 1); OUT_RING (chan, 1); } BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_OUT, 1); OUT_RING (chan, 1); BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN_HIGH, 2); if (OUT_RELOCh(chan, bo, src_offset, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD) || OUT_RELOCh(chan, pNv->GART, 0, NOUVEAU_BO_GART | NOUVEAU_BO_WR)) { MARK_UNDO(chan); return FALSE; } } BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); if (OUT_RELOCl(chan, bo, src_offset, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD) || OUT_RELOCl(chan, pNv->GART, 0, NOUVEAU_BO_GART | NOUVEAU_BO_WR)) { MARK_UNDO(chan); return FALSE; } OUT_RING (chan, src_pitch); OUT_RING (chan, line_len); OUT_RING (chan, line_len); OUT_RING (chan, line_count); OUT_RING (chan, (1<<8)|1); OUT_RING (chan, 0); if (nouveau_bo_map(pNv->GART, NOUVEAU_BO_RD)) { MARK_UNDO(chan); return FALSE; } src = pNv->GART->map; if (dst_pitch == line_len) { memcpy(dst, src, dst_pitch * line_count); dst += dst_pitch * line_count; } else { for (i = 0; i < line_count; i++) { memcpy(dst, src, line_len); src += line_len; dst += dst_pitch; } } nouveau_bo_unmap(pNv->GART); if (linear) src_offset += line_count * src_pitch; h -= line_count; y += line_count; } return TRUE; }
void nv50_constbufs_validate(struct nv50_context *nv50) { struct nouveau_channel *chan = nv50->screen->base.channel; unsigned s; for (s = 0; s < 3; ++s) { struct nv04_resource *res; int i; unsigned p, b; if (s == PIPE_SHADER_FRAGMENT) p = NV50_3D_SET_PROGRAM_CB_PROGRAM_FRAGMENT; else if (s == PIPE_SHADER_GEOMETRY) p = NV50_3D_SET_PROGRAM_CB_PROGRAM_GEOMETRY; else p = NV50_3D_SET_PROGRAM_CB_PROGRAM_VERTEX; while (nv50->constbuf_dirty[s]) { struct nouveau_bo *bo; unsigned start = 0; unsigned words = 0; i = ffs(nv50->constbuf_dirty[s]) - 1; nv50->constbuf_dirty[s] &= ~(1 << i); res = nv04_resource(nv50->constbuf[s][i]); if (!res) { if (i != 0) { BEGIN_RING(chan, RING_3D(SET_PROGRAM_CB), 1); OUT_RING (chan, (i << 8) | p | 0); } continue; } if (i == 0) { b = NV50_CB_PVP + s; /* always upload GL uniforms through CB DATA */ bo = nv50->screen->uniforms; words = res->base.width0 / 4; } else { b = s * 16 + i; assert(0); if (!nouveau_resource_mapped_by_gpu(&res->base)) { nouveau_buffer_migrate(&nv50->base, res, NOUVEAU_BO_VRAM); BEGIN_RING(chan, RING_3D(CODE_CB_FLUSH), 1); OUT_RING (chan, 0); } MARK_RING (chan, 6, 2); BEGIN_RING(chan, RING_3D(CB_DEF_ADDRESS_HIGH), 3); OUT_RESRCh(chan, res, 0, NOUVEAU_BO_RD); OUT_RESRCl(chan, res, 0, NOUVEAU_BO_RD); OUT_RING (chan, (b << 16) | (res->base.width0 & 0xffff)); BEGIN_RING(chan, RING_3D(SET_PROGRAM_CB), 1); OUT_RING (chan, (b << 12) | (i << 8) | p | 1); bo = res->bo; nv50_bufctx_add_resident(nv50, NV50_BUFCTX_CONSTANT, res, res->domain | NOUVEAU_BO_RD); } if (words) { MARK_RING(chan, 8, 1); nouveau_bo_validate(chan, bo, res->domain | NOUVEAU_BO_WR); } while (words) { unsigned nr = AVAIL_RING(chan); if (nr < 16) { FIRE_RING(chan); nouveau_bo_validate(chan, bo, res->domain | NOUVEAU_BO_WR); continue; } nr = MIN2(MIN2(nr - 3, words), NV04_PFIFO_MAX_PACKET_LEN); BEGIN_RING(chan, RING_3D(CB_ADDR), 1); OUT_RING (chan, (start << 8) | b); BEGIN_RING_NI(chan, RING_3D(CB_DATA(0)), nr); OUT_RINGp (chan, &res->data[start * 4], nr); start += nr; words -= nr; } } } }
Bool NV40EXAPrepareComposite(int op, PicturePtr psPict, PicturePtr pmPict, PicturePtr pdPict, PixmapPtr psPix, PixmapPtr pmPix, PixmapPtr pdPix) { ScrnInfoPtr pScrn = xf86Screens[psPix->drawable.pScreen->myNum]; NVPtr pNv = NVPTR(pScrn); struct nouveau_channel *chan = pNv->chan; struct nouveau_grobj *curie = pNv->Nv3D; nv_pict_op_t *blend; int fpid = NV40EXA_FPID_PASS_COL0; NV40EXA_STATE; if (MARK_RING(chan, 128, 1 + 1 + 2*2)) return FALSE; blend = NV40_GetPictOpRec(op); NV40_SetupBlend(pScrn, blend, pdPict->format, (pmPict && pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format))); if (!NV40_SetupSurface(pScrn, pdPix, pdPict->format) || !NV40EXATexture(pScrn, psPix, psPict, 0)) { MARK_UNDO(chan); return FALSE; } NV40_LoadVtxProg(pScrn, &nv40_vp_exa_render); if (pmPict) { if (!NV40EXATexture(pScrn, pmPix, pmPict, 1)) { MARK_UNDO(chan); return FALSE; } if (pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format)) { if (blend->src_alpha) fpid = NV40EXA_FPID_COMPOSITE_MASK_SA_CA; else fpid = NV40EXA_FPID_COMPOSITE_MASK_CA; } else { fpid = NV40EXA_FPID_COMPOSITE_MASK; } state->have_mask = TRUE; } else { fpid = NV40EXA_FPID_PASS_TEX0; state->have_mask = FALSE; } if (!NV40_LoadFragProg(pScrn, (pdPict->format == PICT_a8) ? nv40_fp_map_a8[fpid] : nv40_fp_map[fpid])) { MARK_UNDO(chan); return FALSE; } /* Appears to be some kind of cache flush, needed here at least * sometimes.. funky text rendering otherwise :) */ BEGIN_RING(chan, curie, NV40TCL_TEX_CACHE_CTL, 1); OUT_RING (chan, 2); BEGIN_RING(chan, curie, NV40TCL_TEX_CACHE_CTL, 1); OUT_RING (chan, 1); pNv->alu = op; pNv->pspict = psPict; pNv->pmpict = pmPict; pNv->pdpict = pdPict; pNv->pspix = psPix; pNv->pmpix = pmPix; pNv->pdpix = pdPix; chan->flush_notify = NV40EXAStateCompositeReemit; return TRUE; }
void nv50_upload_sifc(struct nv50_context *nv50, struct nouveau_bo *bo, unsigned dst_offset, unsigned reloc, unsigned dst_format, int dst_w, int dst_h, int dst_pitch, void *src, unsigned src_format, int src_pitch, int x, int y, int w, int h, int cpp) { struct nouveau_channel *chan = nv50->screen->base.channel; struct nouveau_grobj *eng2d = nv50->screen->eng2d; unsigned line_dwords = (w * cpp + 3) / 4; reloc |= NOUVEAU_BO_WR; MARK_RING (chan, 32, 2); /* flush on lack of space or relocs */ if (bo->tile_flags) { BEGIN_RING(chan, eng2d, NV50_2D_DST_FORMAT, 5); OUT_RING (chan, dst_format); OUT_RING (chan, 0); OUT_RING (chan, bo->tile_mode << 4); OUT_RING (chan, 1); OUT_RING (chan, 0); } else { BEGIN_RING(chan, eng2d, NV50_2D_DST_FORMAT, 2); OUT_RING (chan, dst_format); OUT_RING (chan, 1); BEGIN_RING(chan, eng2d, NV50_2D_DST_PITCH, 1); OUT_RING (chan, dst_pitch); } BEGIN_RING(chan, eng2d, NV50_2D_DST_WIDTH, 4); OUT_RING (chan, dst_w); OUT_RING (chan, dst_h); OUT_RELOCh(chan, bo, dst_offset, reloc); OUT_RELOCl(chan, bo, dst_offset, reloc); /* NV50_2D_OPERATION_SRCCOPY assumed already set */ BEGIN_RING(chan, eng2d, NV50_2D_SIFC_BITMAP_ENABLE, 2); OUT_RING (chan, 0); OUT_RING (chan, src_format); BEGIN_RING(chan, eng2d, NV50_2D_SIFC_WIDTH, 10); OUT_RING (chan, w); OUT_RING (chan, h); OUT_RING (chan, 0); OUT_RING (chan, 1); OUT_RING (chan, 0); OUT_RING (chan, 1); OUT_RING (chan, 0); OUT_RING (chan, x); OUT_RING (chan, 0); OUT_RING (chan, y); while (h--) { const uint32_t *p = src; unsigned count = line_dwords; while (count) { unsigned nr = MIN2(count, 1792); if (AVAIL_RING(chan) <= nr) { FIRE_RING (chan); BEGIN_RING(chan, eng2d, NV50_2D_DST_ADDRESS_HIGH, 2); OUT_RELOCh(chan, bo, dst_offset, reloc); OUT_RELOCl(chan, bo, dst_offset, reloc); } assert(AVAIL_RING(chan) > nr); BEGIN_RING(chan, eng2d, NV50_2D_SIFC_DATA | (2 << 29), nr); OUT_RINGp (chan, p, nr); p += nr; count -= nr; } src = (uint8_t *) src + src_pitch; } }
static void nv50_transfer_rect_m2mf(struct pipe_screen *pscreen, struct nouveau_bo *src_bo, unsigned src_offset, int src_pitch, unsigned src_tile_mode, int sx, int sy, int sz, int sw, int sh, int sd, struct nouveau_bo *dst_bo, unsigned dst_offset, int dst_pitch, unsigned dst_tile_mode, int dx, int dy, int dz, int dw, int dh, int dd, int cpp, int width, int height, unsigned src_reloc, unsigned dst_reloc) { struct nv50_screen *screen = nv50_screen(pscreen); struct nouveau_channel *chan = screen->m2mf->channel; struct nouveau_grobj *m2mf = screen->m2mf; src_reloc |= NOUVEAU_BO_RD; dst_reloc |= NOUVEAU_BO_WR; WAIT_RING (chan, 14); if (!src_bo->tile_flags) { BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN, 1); OUT_RING (chan, 1); BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_PITCH_IN, 1); OUT_RING (chan, src_pitch); src_offset += (sy * src_pitch) + (sx * cpp); } else { BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN, 6); OUT_RING (chan, 0); OUT_RING (chan, src_tile_mode << 4); OUT_RING (chan, sw * cpp); OUT_RING (chan, sh); OUT_RING (chan, sd); OUT_RING (chan, sz); /* copying only 1 zslice per call */ } if (!dst_bo->tile_flags) { BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_OUT, 1); OUT_RING (chan, 1); BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_PITCH_OUT, 1); OUT_RING (chan, dst_pitch); dst_offset += (dy * dst_pitch) + (dx * cpp); } else { BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_OUT, 6); OUT_RING (chan, 0); OUT_RING (chan, dst_tile_mode << 4); OUT_RING (chan, dw * cpp); OUT_RING (chan, dh); OUT_RING (chan, dd); OUT_RING (chan, dz); /* copying only 1 zslice per call */ } while (height) { int line_count = height > 2047 ? 2047 : height; MARK_RING (chan, 15, 4); /* flush on lack of space or relocs */ BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN_HIGH, 2); OUT_RELOCh(chan, src_bo, src_offset, src_reloc); OUT_RELOCh(chan, dst_bo, dst_offset, dst_reloc); BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 2); OUT_RELOCl(chan, src_bo, src_offset, src_reloc); OUT_RELOCl(chan, dst_bo, dst_offset, dst_reloc); if (src_bo->tile_flags) { BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_TILING_POSITION_IN, 1); OUT_RING (chan, (sy << 16) | (sx * cpp)); } else { src_offset += (line_count * src_pitch); } if (dst_bo->tile_flags) { BEGIN_RING(chan, m2mf, NV50_MEMORY_TO_MEMORY_FORMAT_TILING_POSITION_OUT, 1); OUT_RING (chan, (dy << 16) | (dx * cpp)); } else { dst_offset += (line_count * dst_pitch); } BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_LINE_LENGTH_IN, 4); OUT_RING (chan, width * cpp); OUT_RING (chan, line_count); OUT_RING (chan, 0x00000101); OUT_RING (chan, 0); FIRE_RING (chan); height -= line_count; sy += line_count; dy += line_count; } }
void nvc0_m2mf_transfer_rect(struct pipe_screen *pscreen, const struct nv50_m2mf_rect *dst, const struct nv50_m2mf_rect *src, uint32_t nblocksx, uint32_t nblocksy) { struct nouveau_channel *chan = nouveau_screen(pscreen)->channel; const int cpp = dst->cpp; uint32_t src_ofst = src->base; uint32_t dst_ofst = dst->base; uint32_t height = nblocksy; uint32_t sy = src->y; uint32_t dy = dst->y; uint32_t exec = (1 << 20); assert(dst->cpp == src->cpp); if (nouveau_bo_tile_layout(src->bo)) { BEGIN_RING(chan, RING_MF(TILING_MODE_IN), 5); OUT_RING (chan, src->tile_mode); OUT_RING (chan, src->width * cpp); OUT_RING (chan, src->height); OUT_RING (chan, src->depth); OUT_RING (chan, src->z); } else { src_ofst += src->y * src->pitch + src->x * cpp; BEGIN_RING(chan, RING_MF(PITCH_IN), 1); OUT_RING (chan, src->width * cpp); exec |= NVC0_M2MF_EXEC_LINEAR_IN; } if (nouveau_bo_tile_layout(dst->bo)) { BEGIN_RING(chan, RING_MF(TILING_MODE_OUT), 5); OUT_RING (chan, dst->tile_mode); OUT_RING (chan, dst->width * cpp); OUT_RING (chan, dst->height); OUT_RING (chan, dst->depth); OUT_RING (chan, dst->z); } else { dst_ofst += dst->y * dst->pitch + dst->x * cpp; BEGIN_RING(chan, RING_MF(PITCH_OUT), 1); OUT_RING (chan, dst->width * cpp); exec |= NVC0_M2MF_EXEC_LINEAR_OUT; } while (height) { int line_count = height > 2047 ? 2047 : height; MARK_RING (chan, 17, 4); BEGIN_RING(chan, RING_MF(OFFSET_IN_HIGH), 2); OUT_RELOCh(chan, src->bo, src_ofst, src->domain | NOUVEAU_BO_RD); OUT_RELOCl(chan, src->bo, src_ofst, src->domain | NOUVEAU_BO_RD); BEGIN_RING(chan, RING_MF(OFFSET_OUT_HIGH), 2); OUT_RELOCh(chan, dst->bo, dst_ofst, dst->domain | NOUVEAU_BO_WR); OUT_RELOCl(chan, dst->bo, dst_ofst, dst->domain | NOUVEAU_BO_WR); if (!(exec & NVC0_M2MF_EXEC_LINEAR_IN)) { BEGIN_RING(chan, RING_MF(TILING_POSITION_IN_X), 2); OUT_RING (chan, src->x * cpp); OUT_RING (chan, sy); } else { src_ofst += line_count * src->pitch; } if (!(exec & NVC0_M2MF_EXEC_LINEAR_OUT)) { BEGIN_RING(chan, RING_MF(TILING_POSITION_OUT_X), 2); OUT_RING (chan, dst->x * cpp); OUT_RING (chan, dy); } else { dst_ofst += line_count * dst->pitch; } BEGIN_RING(chan, RING_MF(LINE_LENGTH_IN), 2); OUT_RING (chan, nblocksx * cpp); OUT_RING (chan, line_count); BEGIN_RING(chan, RING_MF(EXEC), 1); OUT_RING (chan, exec); height -= line_count; sy += line_count; dy += line_count; } }
Bool NV30EXAPrepareComposite(int op, PicturePtr psPict, PicturePtr pmPict, PicturePtr pdPict, PixmapPtr psPix, PixmapPtr pmPix, PixmapPtr pdPix) { ScrnInfoPtr pScrn = xf86Screens[psPix->drawable.pScreen->myNum]; NVPtr pNv = NVPTR(pScrn); struct nouveau_channel *chan = pNv->chan; struct nouveau_grobj *rankine = pNv->Nv3D; nv_pict_op_t *blend; int fpid = NV30EXA_FPID_PASS_COL0; NV30EXA_STATE; if (MARK_RING(chan, 128, 1 + 1 + 4)) return FALSE; blend = NV30_GetPictOpRec(op); NV30_SetupBlend(pScrn, blend, pdPict->format, (pmPict && pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format))); if (!NV30_SetupSurface(pScrn, pdPix, pdPict) || !NV30EXATexture(pScrn, psPix, psPict, 0)) { MARK_UNDO(chan); return FALSE; } #if 0 #define printformat(f) ErrorF("(%xh %s %dbpp A%dR%dG%dB%d)",f,(f>>16)&0xf==2?"ARGB":"ABGR",(f>>24),(f&0xf000)>>12,(f&0xf00)>>8,(f&0xf0)>>4,f&0xf) ErrorF("Preparecomposite src(%dx%d)",psPict->pDrawable->width,psPict->pDrawable->height); printformat((psPict->format)); ErrorF(" dst(%dx%d)",pdPict->pDrawable->width,pdPict->pDrawable->height); printformat((pdPict->format)); if (pmPict) { ErrorF(" mask(%dx%d)",pmPict->pDrawable->width,pmPict->pDrawable->height); printformat((pmPict->format)); } ErrorF("\n"); #endif if (pmPict) { if (!NV30EXATexture(pScrn, pmPix, pmPict, 1)) { MARK_UNDO(chan); return FALSE; } if (pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format)) { if (blend->src_alpha) fpid = NV30EXA_FPID_COMPOSITE_MASK_SA_CA; else fpid = NV30EXA_FPID_COMPOSITE_MASK_CA; } else { fpid = NV30EXA_FPID_COMPOSITE_MASK; } state->have_mask = TRUE; } else { fpid = NV30EXA_FPID_PASS_TEX0; state->have_mask = FALSE; } if (!NV30_LoadFragProg(pScrn, (pdPict->format == PICT_a8) ? nv40_fp_map_a8[fpid] : nv40_fp_map[fpid])) { MARK_UNDO(chan); return FALSE; } BEGIN_RING(chan, rankine, 0x23c, 1); OUT_RING (chan, pmPict?3:1); pNv->alu = op; pNv->pspict = psPict; pNv->pmpict = pmPict; pNv->pdpict = pdPict; pNv->pspix = psPix; pNv->pmpix = pmPix; pNv->pdpix = pdPix; chan->flush_notify = NV30EXAStateCompositeReemit; return TRUE; }
boolean nvfx_vbo_validate(struct nvfx_context *nvfx) { struct nouveau_channel* chan = nvfx->screen->base.channel; int i; int elements = MAX2(nvfx->vtxelt->num_elements, nvfx->hw_vtxelt_nr); unsigned vb_flags = nvfx->screen->vertex_buffer_reloc_flags | NOUVEAU_BO_RD; if (!elements) return TRUE; MARK_RING(chan, (5 + 2) * 16 + 2 + 11, 16 + 2); for(unsigned i = 0; i < nvfx->vtxelt->num_constant; ++i) { struct nvfx_low_frequency_element *ve = &nvfx->vtxelt->constant[i]; struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[ve->vertex_buffer_index]; struct nvfx_buffer* buffer = nvfx_buffer(vb->buffer); float v[4]; ve->fetch_rgba_float(v, buffer->data + vb->buffer_offset + ve->src_offset, 0, 0); nvfx_emit_vtx_attr(chan, ve->idx, v, ve->ncomp); } OUT_RING(chan, RING_3D(NV30_3D_VTXFMT(0), elements)); if(nvfx->use_vertex_buffers) { unsigned idx = 0; 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]; if(idx != ve->idx) { assert(idx < ve->idx); OUT_RINGp(chan, &nvfx->vtxelt->vtxfmt[idx], ve->idx - idx); idx = ve->idx; } OUT_RING(chan, nvfx->vtxelt->vtxfmt[idx] | (vb->stride << NV30_3D_VTXFMT_STRIDE__SHIFT)); ++idx; } if(idx != nvfx->vtxelt->num_elements) OUT_RINGp(chan, &nvfx->vtxelt->vtxfmt[idx], nvfx->vtxelt->num_elements - idx); } else OUT_RINGp(chan, nvfx->vtxelt->vtxfmt, nvfx->vtxelt->num_elements); for(i = nvfx->vtxelt->num_elements; 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)); if(nvfx->use_vertex_buffers) { unsigned idx = 0; 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; for(; idx < ve->idx; ++idx) OUT_RING(chan, 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); ++idx; } for(; idx < elements; ++idx) OUT_RING(chan, 0); } else { for (i = 0; i < elements; i++) OUT_RING(chan, 0); } OUT_RING(chan, RING_3D(0x1710, 1)); OUT_RING(chan, 0); nvfx->hw_vtxelt_nr = nvfx->vtxelt->num_elements; nvfx->relocs_needed &=~ NVFX_RELOCATE_VTXBUF; return TRUE; }