static void emit_vertices_i08(struct push_context *ctx, unsigned start, unsigned count) { uint8_t *elts = (uint8_t *)ctx->idxbuf + start; while (count) { unsigned push = MIN2(count, ctx->packet_vertex_limit); unsigned size, nr; nr = push; if (ctx->primitive_restart) nr = prim_restart_search_i08(elts, push, ctx->restart_index); size = ctx->vertex_words * nr; BEGIN_NI04(ctx->push, NV30_3D(VERTEX_DATA), size); ctx->translate->run_elts8(ctx->translate, elts, nr, 0, 0, ctx->push->cur); ctx->push->cur += size; count -= nr; elts += nr; if (nr != push) { BEGIN_NV04(ctx->push, NV30_3D(VB_ELEMENT_U32), 1); PUSH_DATA (ctx->push, ctx->restart_index); count--; elts++; } } }
static void nv30_query_begin(struct pipe_context *pipe, struct pipe_query *pq) { struct nv30_context *nv30 = nv30_context(pipe); struct nv30_query *q = nv30_query(pq); struct nouveau_pushbuf *push = nv30->base.pushbuf; switch (q->type) { case PIPE_QUERY_TIME_ELAPSED: q->qo[0] = nv30_query_object_new(nv30->screen); if (q->qo[0]) { BEGIN_NV04(push, NV30_3D(QUERY_GET), 1); PUSH_DATA (push, (q->report << 24) | q->qo[0]->hw->start); } break; case PIPE_QUERY_TIMESTAMP: return; default: BEGIN_NV04(push, NV30_3D(QUERY_RESET), 1); PUSH_DATA (push, q->report); break; } if (q->enable) { BEGIN_NV04(push, SUBC_3D(q->enable), 1); PUSH_DATA (push, 1); } }
void NV40EXAComposite(PixmapPtr pdPix, int sx, int sy, int mx, int my, int dx, int dy, int w, int h) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pdPix->drawable.pScreen); NVPtr pNv = NVPTR(pScrn); struct nouveau_pushbuf *push = pNv->pushbuf; if (!PUSH_SPACE(push, 64)) return; /* We're drawing a triangle, we need to scissor it to a quad. */ /* The scissors are here for a good reason, we don't get the full * image, but just a part. */ /* Handling the cliprects is done for us already. */ BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2); PUSH_DATA (push, (w << 16) | dx); PUSH_DATA (push, (h << 16) | dy); BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_TRIANGLES); PUSH_VTX2s(push, sx, sy + (h * 2), mx, my + (h * 2), dx, dy + (h * 2)); PUSH_VTX2s(push, sx, sy, mx, my, dx, dy); PUSH_VTX2s(push, sx + (w * 2), sy, mx + (w * 2), my, dx + (w * 2), dy); BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP); }
static void nv30_draw_arrays(struct nv30_context *nv30, unsigned mode, unsigned start, unsigned count, unsigned instance_count) { struct nouveau_pushbuf *push = nv30->base.pushbuf; unsigned prim; prim = nv30_prim_gl(mode); BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, prim); while (count) { const unsigned mpush = 2047 * 256; unsigned npush = (count > mpush) ? mpush : count; unsigned wpush = ((npush + 255) & ~255) >> 8; count -= npush; BEGIN_NI04(push, NV30_3D(VB_VERTEX_BATCH), wpush); while (npush >= 256) { PUSH_DATA (push, 0xff000000 | start); start += 256; npush -= 256; } if (npush) PUSH_DATA (push, ((npush - 1) << 24) | start); } BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP); }
static void nv30_clear_render_target(struct pipe_context *pipe, struct pipe_surface *ps, const union pipe_color_union *color, unsigned x, unsigned y, unsigned w, unsigned h) { struct nv30_context *nv30 = nv30_context(pipe); struct nv30_surface *sf = nv30_surface(ps); struct nv30_miptree *mt = nv30_miptree(ps->texture); struct nouveau_pushbuf *push = nv30->base.pushbuf; struct nouveau_object *eng3d = nv30->screen->eng3d; struct nouveau_pushbuf_refn refn; uint32_t rt_format; rt_format = nv30_format(pipe->screen, ps->format)->hw; if (util_format_get_blocksize(ps->format) == 4) rt_format |= NV30_3D_RT_FORMAT_ZETA_Z24S8; else rt_format |= NV30_3D_RT_FORMAT_ZETA_Z16; if (nv30_miptree(ps->texture)->swizzled) { rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED; rt_format |= util_logbase2(sf->width) << 16; rt_format |= util_logbase2(sf->height) << 24; } else { rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR; } refn.bo = mt->base.bo; refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR; if (nouveau_pushbuf_space(push, 16, 1, 0) || nouveau_pushbuf_refn (push, &refn, 1)) return; BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1); PUSH_DATA (push, NV30_3D_RT_ENABLE_COLOR0); BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3); PUSH_DATA (push, sf->width << 16); PUSH_DATA (push, sf->height << 16); PUSH_DATA (push, rt_format); BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 2); if (eng3d->oclass < NV40_3D_CLASS) PUSH_DATA (push, (sf->pitch << 16) | sf->pitch); else PUSH_DATA (push, sf->pitch); PUSH_RELOC(push, mt->base.bo, sf->offset, NOUVEAU_BO_LOW, 0, 0); BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2); PUSH_DATA (push, (w << 16) | x); PUSH_DATA (push, (h << 16) | y); BEGIN_NV04(push, NV30_3D(CLEAR_COLOR_VALUE), 2); PUSH_DATA (push, pack_rgba(ps->format, color->f)); PUSH_DATA (push, NV30_3D_CLEAR_BUFFERS_COLOR_R | NV30_3D_CLEAR_BUFFERS_COLOR_G | NV30_3D_CLEAR_BUFFERS_COLOR_B | NV30_3D_CLEAR_BUFFERS_COLOR_A); nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR; }
static __inline__ void PUSH_VTX2s(struct nouveau_pushbuf *push, int x1, int y1, int x2, int y2, int dx, int dy) { BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(8)), 2); PUSH_DATA (push, (y1 << 16) | x1); PUSH_DATA (push, (y2 << 16) | x2); BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1); PUSH_DATA (push, (dy << 16) | dx); }
static __inline__ void PUSH_VTX2s(struct nouveau_pushbuf *push, int x1, int y1, int x2, int y2, int dx, int dy) { BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(8)), 2); PUSH_DATA (push, ((y1 & 0xffff) << 16) | (x1 & 0xffff)); PUSH_DATA (push, ((y2 & 0xffff) << 16) | (x2 & 0xffff)); BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1); PUSH_DATA (push, ((dy & 0xffff) << 16) | (dx & 0xffff)); }
static Bool NV40EXAPictSolid(NVPtr pNv, PicturePtr pPict, int unit) { struct nouveau_pushbuf *push = pNv->pushbuf; PUSH_DATAu(push, pNv->scratch, SOLID(unit), 2); PUSH_DATA (push, pPict->pSourcePict->solidFill.color); PUSH_DATA (push, 0); BEGIN_NV04(push, NV30_3D(TEX_OFFSET(unit)), 8); PUSH_MTHDl(push, NV30_3D(TEX_OFFSET(unit)), pNv->scratch, SOLID(unit), NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); PUSH_DATA (push, NV40_3D_TEX_FORMAT_FORMAT_A8R8G8B8 | 0x8000 | NV40_3D_TEX_FORMAT_LINEAR | NV30_3D_TEX_FORMAT_DIMS_2D | NV30_3D_TEX_FORMAT_NO_BORDER | (1 << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT) | NV30_3D_TEX_FORMAT_DMA0); PUSH_DATA (push, NV30_3D_TEX_WRAP_S_REPEAT | NV30_3D_TEX_WRAP_T_REPEAT | NV30_3D_TEX_WRAP_R_REPEAT); PUSH_DATA (push, NV40_3D_TEX_ENABLE_ENABLE); PUSH_DATA (push, 0x0000aae4); PUSH_DATA (push, NV30_3D_TEX_FILTER_MIN_NEAREST | NV30_3D_TEX_FILTER_MAG_NEAREST | 0x3fd6); PUSH_DATA (push, 0x00010001); PUSH_DATA (push, 0x00000000); BEGIN_NV04(push, NV40_3D(TEX_SIZE1(unit)), 1); PUSH_DATA (push, 0x00100040); BEGIN_NV04(push, NV30_3D(VP_UPLOAD_CONST_ID), 17); PUSH_DATA (push, unit * 4); PUSH_DATAf(push, 1.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 1.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 1.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 1.0); PUSH_DATAf(push, 1.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); return TRUE; }
static void NV40_SetupBlend(ScrnInfoPtr pScrn, nv_pict_op_t *blend, PictFormatShort dest_format, Bool component_alpha) { NVPtr pNv = NVPTR(pScrn); struct nouveau_pushbuf *push = pNv->pushbuf; uint32_t sblend, dblend; sblend = blend->src_card_op; dblend = blend->dst_card_op; if (blend->dst_alpha) { if (!PICT_FORMAT_A(dest_format)) { if (sblend == SF(DST_ALPHA)) { sblend = SF(ONE); } else if (sblend == SF(ONE_MINUS_DST_ALPHA)) { sblend = SF(ZERO); } } else if (dest_format == PICT_a8) { if (sblend == SF(DST_ALPHA)) { sblend = SF(DST_COLOR); } else if (sblend == SF(ONE_MINUS_DST_ALPHA)) { sblend = SF(ONE_MINUS_DST_COLOR); } } } if (blend->src_alpha && (component_alpha || dest_format == PICT_a8)) { if (dblend == DF(SRC_ALPHA)) { dblend = DF(SRC_COLOR); } else if (dblend == DF(ONE_MINUS_SRC_ALPHA)) { dblend = DF(ONE_MINUS_SRC_COLOR); } } if (sblend == SF(ONE) && dblend == DF(ZERO)) { BEGIN_NV04(push, NV30_3D(BLEND_FUNC_ENABLE), 1); PUSH_DATA (push, 0); } else { BEGIN_NV04(push, NV30_3D(BLEND_FUNC_ENABLE), 5); PUSH_DATA (push, 1); PUSH_DATA (push, sblend); PUSH_DATA (push, dblend); PUSH_DATA (push, 0x00000000); PUSH_DATA (push, NV40_3D_BLEND_EQUATION_ALPHA_FUNC_ADD | NV40_3D_BLEND_EQUATION_RGB_FUNC_ADD); } }
static void nv30_emit_vtxattr(struct nv30_context *nv30, struct pipe_vertex_buffer *vb, struct pipe_vertex_element *ve, unsigned attr) { const unsigned nc = util_format_get_nr_components(ve->src_format); struct nouveau_pushbuf *push = nv30->base.pushbuf; struct nv04_resource *res = nv04_resource(vb->buffer); const struct util_format_description *desc = util_format_description(ve->src_format); const void *data; float v[4]; data = nouveau_resource_map_offset(&nv30->base, res, vb->buffer_offset + ve->src_offset, NOUVEAU_BO_RD); desc->unpack_rgba_float(v, 0, data, 0, 1, 1); switch (nc) { case 4: BEGIN_NV04(push, NV30_3D(VTX_ATTR_4F(attr)), 4); PUSH_DATAf(push, v[0]); PUSH_DATAf(push, v[1]); PUSH_DATAf(push, v[2]); PUSH_DATAf(push, v[3]); break; case 3: BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(attr)), 3); PUSH_DATAf(push, v[0]); PUSH_DATAf(push, v[1]); PUSH_DATAf(push, v[2]); break; case 2: BEGIN_NV04(push, NV30_3D(VTX_ATTR_2F(attr)), 2); PUSH_DATAf(push, v[0]); PUSH_DATAf(push, v[1]); break; case 1: BEGIN_NV04(push, NV30_3D(VTX_ATTR_1F(attr)), 1); PUSH_DATAf(push, v[0]); break; default: assert(0); break; } }
static void nv30_clear(struct pipe_context *pipe, unsigned buffers, const union pipe_color_union *color, double depth, unsigned stencil) { struct nv30_context *nv30 = nv30_context(pipe); struct nouveau_pushbuf *push = nv30->base.pushbuf; struct pipe_framebuffer_state *fb = &nv30->framebuffer; uint32_t colr = 0, zeta = 0, mode = 0; if (!nv30_state_validate(nv30, TRUE)) return; if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) { colr = pack_rgba(fb->cbufs[0]->format, color->f); mode |= NV30_3D_CLEAR_BUFFERS_COLOR_R | NV30_3D_CLEAR_BUFFERS_COLOR_G | NV30_3D_CLEAR_BUFFERS_COLOR_B | NV30_3D_CLEAR_BUFFERS_COLOR_A; } if (fb->zsbuf) { zeta = pack_zeta(fb->zsbuf->format, depth, stencil); if (buffers & PIPE_CLEAR_DEPTH) mode |= NV30_3D_CLEAR_BUFFERS_DEPTH; if (buffers & PIPE_CLEAR_STENCIL) mode |= NV30_3D_CLEAR_BUFFERS_STENCIL; } /*XXX: wtf? fixes clears sometimes not clearing on nv3x... */ if (nv30->screen->eng3d->oclass < NV40_3D_CLASS) { BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 3); PUSH_DATA (push, zeta); PUSH_DATA (push, colr); PUSH_DATA (push, mode); } BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 3); PUSH_DATA (push, zeta); PUSH_DATA (push, colr); PUSH_DATA (push, mode); nv30_state_release(nv30); }
static void nv30_screen_fence_emit(struct pipe_screen *pscreen, uint32_t *sequence) { struct nv30_screen *screen = nv30_screen(pscreen); struct nouveau_pushbuf *push = screen->base.pushbuf; *sequence = ++screen->base.fence.sequence; BEGIN_NV04(push, NV30_3D(FENCE_OFFSET), 2); PUSH_DATA (push, 0); PUSH_DATA (push, *sequence); }
static void nv30_draw_elements(struct nv30_context *nv30, boolean shorten, unsigned mode, unsigned start, unsigned count, unsigned instance_count, int32_t index_bias) { const unsigned index_size = nv30->idxbuf.index_size; struct nouveau_pushbuf *push = nv30->base.pushbuf; struct nouveau_object *eng3d = nv30->screen->eng3d; unsigned prim = nv30_prim_gl(mode); #if 0 /*XXX*/ if (index_bias != nv30->state.index_bias) { BEGIN_NV04(push, NV30_3D(VB_ELEMENT_BASE), 1); PUSH_DATA (push, index_bias); nv30->state.index_bias = index_bias; } #endif if (eng3d->oclass == NV40_3D_CLASS && index_size > 1 && nv30->idxbuf.buffer) { struct nv04_resource *res = nv04_resource(nv30->idxbuf.buffer); unsigned offset = nv30->idxbuf.offset; assert(nouveau_resource_mapped_by_gpu(&res->base)); BEGIN_NV04(push, NV30_3D(IDXBUF_OFFSET), 2); PUSH_RESRC(push, NV30_3D(IDXBUF_OFFSET), BUFCTX_IDXBUF, res, offset, NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, 0); PUSH_MTHD (push, NV30_3D(IDXBUF_FORMAT), BUFCTX_IDXBUF, res->bo, (index_size == 2) ? 0x00000010 : 0x00000000, res->domain | NOUVEAU_BO_RD, 0, NV30_3D_IDXBUF_FORMAT_DMA1); BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, prim); while (count) { const unsigned mpush = 2047 * 256; unsigned npush = (count > mpush) ? mpush : count; unsigned wpush = ((npush + 255) & ~255) >> 8; count -= npush; BEGIN_NI04(push, NV30_3D(VB_INDEX_BATCH), wpush); while (npush >= 256) { PUSH_DATA (push, 0xff000000 | start); start += 256; npush -= 256; } if (npush) PUSH_DATA (push, ((npush - 1) << 24) | start); } BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP); PUSH_RESET(push, BUFCTX_IDXBUF); } else {
static inline struct nouveau_heap * nv30_transfer_rect_vertprog(struct nv30_context *nv30) { struct nouveau_heap *heap = nv30->screen->vp_exec_heap; struct nouveau_heap *vp; vp = nv30->blit_vp; if (!vp) { if (nouveau_heap_alloc(heap, 2, &nv30->blit_vp, &nv30->blit_vp)) { while (heap->next && heap->size < 2) { struct nouveau_heap **evict = heap->next->priv; nouveau_heap_free(evict); } if (nouveau_heap_alloc(heap, 2, &nv30->blit_vp, &nv30->blit_vp)) return NULL; } vp = nv30->blit_vp; if (vp) { struct nouveau_pushbuf *push = nv30->base.pushbuf; BEGIN_NV04(push, NV30_3D(VP_UPLOAD_FROM_ID), 1); PUSH_DATA (push, vp->start); BEGIN_NV04(push, NV30_3D(VP_UPLOAD_INST(0)), 4); PUSH_DATA (push, 0x401f9c6c); /* mov o[hpos], a[0]; */ PUSH_DATA (push, 0x0040000d); PUSH_DATA (push, 0x8106c083); PUSH_DATA (push, 0x6041ff80); BEGIN_NV04(push, NV30_3D(VP_UPLOAD_INST(0)), 4); PUSH_DATA (push, 0x401f9c6c); /* mov o[tex0], a[8]; end; */ PUSH_DATA (push, 0x0040080d); PUSH_DATA (push, 0x8106c083); PUSH_DATA (push, 0x6041ff9d); } } return vp; }
static Bool NV30_SetupSurface(ScrnInfoPtr pScrn, PixmapPtr pPix, PicturePtr pPict) { NVPtr pNv = NVPTR(pScrn); struct nouveau_pushbuf *push = pNv->pushbuf; struct nouveau_bo *bo = nouveau_pixmap_bo(pPix); uint32_t pitch = exaGetPixmapPitch(pPix); nv_pict_surface_format_t *fmt; fmt = NV30_GetPictSurfaceFormat(pPict->format); if (!fmt) { ErrorF("AIII no format\n"); return FALSE; } BEGIN_NV04(push, NV30_3D(RT_FORMAT), 3); PUSH_DATA (push, fmt->card_fmt); /* format */ PUSH_DATA (push, pitch << 16 | pitch); PUSH_MTHDl(push, NV30_3D(COLOR0_OFFSET), bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); return TRUE; }
static Bool NV40_SetupSurface(ScrnInfoPtr pScrn, PixmapPtr pPix, PictFormatShort format) { NVPtr pNv = NVPTR(pScrn); struct nouveau_pushbuf *push = pNv->pushbuf; struct nouveau_bo *bo = nouveau_pixmap_bo(pPix); nv_pict_surface_format_t *fmt; fmt = NV40_GetPictSurfaceFormat(format); if (!fmt) { ErrorF("AIII no format\n"); return FALSE; } BEGIN_NV04(push, NV30_3D(RT_FORMAT), 3); PUSH_DATA (push, NV30_3D_RT_FORMAT_TYPE_LINEAR | NV30_3D_RT_FORMAT_ZETA_Z24S8 | fmt->card_fmt); PUSH_DATA (push, exaGetPixmapPitch(pPix)); PUSH_MTHDl(push, NV30_3D(COLOR0_OFFSET), bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR); return TRUE; }
static void nv30_draw_elements_inline_u16(struct nouveau_pushbuf *push, const uint16_t *map, unsigned start, unsigned count) { map += start; if (count & 1) { BEGIN_NV04(push, NV30_3D(VB_ELEMENT_U32), 1); PUSH_DATA (push, *map++); } count >>= 1; while (count) { unsigned npush = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN); count -= npush; BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U16), npush); while (npush--) { PUSH_DATA (push, (map[1] << 16) | map[0]); map += 2; } } }
static void nv30_update_user_vbufs(struct nv30_context *nv30) { struct nouveau_pushbuf *push = nv30->base.pushbuf; uint32_t base, offset, size; int i; uint32_t written = 0; for (i = 0; i < nv30->vertex->num_elements; i++) { struct pipe_vertex_element *ve = &nv30->vertex->pipe[i]; const int b = ve->vertex_buffer_index; struct pipe_vertex_buffer *vb = &nv30->vtxbuf[b]; struct nv04_resource *buf = nv04_resource(vb->buffer); if (!(nv30->vbo_user & (1 << b))) continue; if (!vb->stride) { nv30_emit_vtxattr(nv30, vb, ve, i); continue; } nv30_vbuf_range(nv30, b, &base, &size); if (!(written & (1 << b))) { written |= 1 << b; nouveau_user_buffer_upload(&nv30->base, buf, base, size); } offset = vb->buffer_offset + ve->src_offset; BEGIN_NV04(push, NV30_3D(VTXBUF(i)), 1); PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP, buf, offset, NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, NV30_3D_VTXBUF_DMA1); } nv30->base.vbo_dirty = TRUE; }
static void emit_vertices_seq(struct push_context *ctx, unsigned start, unsigned count) { while (count) { unsigned push = MIN2(count, ctx->packet_vertex_limit); unsigned size = ctx->vertex_words * push; BEGIN_NI04(ctx->push, NV30_3D(VERTEX_DATA), size); ctx->translate->run(ctx->translate, start, push, 0, 0, ctx->push->cur); ctx->push->cur += size; count -= push; start += push; } }
static void nv30_render_draw_arrays(struct vbuf_render *render, unsigned start, uint nr) { struct nv30_render *r = nv30_render(render); struct nv30_context *nv30 = r->nv30; struct nouveau_pushbuf *push = nv30->base.pushbuf; unsigned fn = nr >> 8, pn = nr & 0xff; unsigned ps = fn + (pn ? 1 : 0); unsigned i; BEGIN_NV04(push, NV30_3D(VTXBUF(0)), r->vertex_info.num_attribs); for (i = 0; i < r->vertex_info.num_attribs; i++) { PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP, nv04_resource(r->buffer), r->offset + r->vtxptr[i], NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, NV30_3D_VTXBUF_DMA1); } if (!nv30_state_validate(nv30, FALSE)) return; BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, r->prim); BEGIN_NI04(push, NV30_3D(VB_VERTEX_BATCH), ps); while (fn--) { PUSH_DATA (push, 0xff000000 | start); start += 256; } if (pn) PUSH_DATA (push, ((pn - 1) << 24) | start); BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP); PUSH_RESET(push, BUFCTX_VTXTMP); }
static void nv30_draw_elements_inline_u32(struct nouveau_pushbuf *push, const uint32_t *map, unsigned start, unsigned count) { map += start; while (count) { const unsigned nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN); BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U32), nr); PUSH_DATAp(push, map, nr); map += nr; count -= nr; } }
static void nv30_query_end(struct pipe_context *pipe, struct pipe_query *pq) { struct nv30_context *nv30 = nv30_context(pipe); struct nv30_screen *screen = nv30->screen; struct nv30_query *q = nv30_query(pq); struct nouveau_pushbuf *push = nv30->base.pushbuf; q->qo[1] = nv30_query_object_new(screen); if (q->qo[1]) { BEGIN_NV04(push, NV30_3D(QUERY_GET), 1); PUSH_DATA (push, (q->report << 24) | q->qo[1]->hw->start); } if (q->enable) { BEGIN_NV04(push, SUBC_3D(q->enable), 1); PUSH_DATA (push, 0); } PUSH_KICK (push); }
static void nv30_render_draw_elements(struct vbuf_render *render, const ushort *indices, uint count) { struct nv30_render *r = nv30_render(render); struct nv30_context *nv30 = r->nv30; struct nouveau_pushbuf *push = nv30->screen->base.pushbuf; unsigned i; BEGIN_NV04(push, NV30_3D(VTXBUF(0)), r->vertex_info.num_attribs); for (i = 0; i < r->vertex_info.num_attribs; i++) { PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP, nv04_resource(r->buffer), r->offset + r->vtxptr[i], NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, NV30_3D_VTXBUF_DMA1); } if (!nv30_state_validate(nv30, FALSE)) return; BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, r->prim); if (count & 1) { BEGIN_NV04(push, NV30_3D(VB_ELEMENT_U32), 1); PUSH_DATA (push, *indices++); } count >>= 1; while (count) { unsigned npush = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN); count -= npush; BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U16), npush); while (npush--) { PUSH_DATA(push, (indices[1] << 16) | indices[0]); indices += 2; } } BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP); PUSH_RESET(push, BUFCTX_VTXTMP); }
void nv30_fragtex_validate(struct nv30_context *nv30) { struct pipe_screen *pscreen = &nv30->screen->base.base; struct nouveau_object *eng3d = nv30->screen->eng3d; struct nouveau_pushbuf *push = nv30->base.pushbuf; unsigned dirty = nv30->fragprog.dirty_samplers; while (dirty) { unsigned unit = ffs(dirty) - 1; struct nv30_sampler_view *sv = (void *)nv30->fragprog.textures[unit]; struct nv30_sampler_state *ss = nv30->fragprog.samplers[unit]; PUSH_RESET(push, BUFCTX_FRAGTEX(unit)); if (ss && sv) { const struct nv30_texfmt *fmt = nv30_texfmt(pscreen, sv->pipe.format); struct pipe_resource *pt = sv->pipe.texture; struct nv30_miptree *mt = nv30_miptree(pt); unsigned min_lod, max_lod; u32 filter = sv->filt | (ss->filt & sv->filt_mask); u32 format = sv->fmt | ss->fmt; u32 enable = ss->en; /* handle base_level when not using a mip filter, min/max level * is unfortunately ignored by the hardware otherwise */ if (ss->pipe.min_mip_filter == PIPE_TEX_MIPFILTER_NONE) { if (sv->base_lod) filter += 0x00020000; /* N/L -> NMN/LMN */ max_lod = sv->base_lod; min_lod = sv->base_lod; } else { max_lod = MIN2(ss->max_lod + sv->base_lod, sv->high_lod); min_lod = MIN2(ss->min_lod + sv->base_lod, max_lod); } if (eng3d->oclass >= NV40_3D_CLASS) { /* this is a tad stupid of the hardware, but there's no non-rcomp * z16/z24 texture formats to be had, we have to suffer and lose * some precision to handle this case. */ if (ss->pipe.compare_mode != PIPE_TEX_COMPARE_R_TO_TEXTURE) { if (fmt->nv40 == NV40_3D_TEX_FORMAT_FORMAT_Z16) format |= NV40_3D_TEX_FORMAT_FORMAT_A8L8; else if (fmt->nv40 == NV40_3D_TEX_FORMAT_FORMAT_Z24) format |= NV40_3D_TEX_FORMAT_FORMAT_A16L16; else format |= fmt->nv40; } else { format |= fmt->nv40; } enable |= (min_lod << 19) | (max_lod << 7); enable |= NV40_3D_TEX_ENABLE_ENABLE; BEGIN_NV04(push, NV40_3D(TEX_SIZE1(unit)), 1); PUSH_DATA (push, sv->npot_size1); } else { /* this is a tad stupid of the hardware, but there's no non-rcomp * z16/z24 texture formats to be had, we have to suffer and lose * some precision to handle this case. */ if (ss->pipe.compare_mode != PIPE_TEX_COMPARE_R_TO_TEXTURE) { if (fmt->nv30 == NV30_3D_TEX_FORMAT_FORMAT_Z16) { if (ss->pipe.normalized_coords) format |= NV30_3D_TEX_FORMAT_FORMAT_A8L8; else format |= NV30_3D_TEX_FORMAT_FORMAT_A8L8_RECT; } else if (fmt->nv30 == NV30_3D_TEX_FORMAT_FORMAT_Z24) { if (ss->pipe.normalized_coords) format |= NV30_3D_TEX_FORMAT_FORMAT_HILO16; else format |= NV30_3D_TEX_FORMAT_FORMAT_HILO16_RECT; } else { if (ss->pipe.normalized_coords) format |= fmt->nv30; else format |= fmt->nv30_rect; } } else { if (ss->pipe.normalized_coords) format |= fmt->nv30; else format |= fmt->nv30_rect; } enable |= NV30_3D_TEX_ENABLE_ENABLE; enable |= (min_lod << 18) | (max_lod << 6); } BEGIN_NV04(push, NV30_3D(TEX_OFFSET(unit)), 8); PUSH_MTHDl(push, NV30_3D(TEX_OFFSET(unit)), BUFCTX_FRAGTEX(unit), mt->base.bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); PUSH_MTHDs(push, NV30_3D(TEX_FORMAT(unit)), BUFCTX_FRAGTEX(unit), mt->base.bo, format, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD, NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1); PUSH_DATA (push, sv->wrap | (ss->wrap & sv->wrap_mask)); PUSH_DATA (push, enable); PUSH_DATA (push, sv->swz); PUSH_DATA (push, filter); PUSH_DATA (push, sv->npot_size0); PUSH_DATA (push, ss->bcol); BEGIN_NV04(push, NV30_3D(TEX_FILTER_OPTIMIZATION(unit)), 1); PUSH_DATA (push, nv30->config.filter); } else { BEGIN_NV04(push, NV30_3D(TEX_ENABLE(unit)), 1); PUSH_DATA (push, 0); } dirty &= ~(1 << unit); } nv30->fragprog.dirty_samplers = 0; }
static boolean nv30_render_validate(struct nv30_context *nv30) { struct nv30_render *r = nv30_render(nv30->draw->render); struct nv30_rasterizer_stateobj *rast = nv30->rast; struct pipe_screen *pscreen = &nv30->screen->base.base; struct nouveau_pushbuf *push = nv30->screen->base.pushbuf; struct nouveau_object *eng3d = nv30->screen->eng3d; struct nv30_vertprog *vp = nv30->vertprog.program; struct vertex_info *vinfo = &r->vertex_info; unsigned vp_attribs = 0; unsigned vp_results = 0; unsigned attrib = 0; unsigned pntc; int i; if (!r->vertprog) { struct nouveau_heap *heap = nv30_screen(pscreen)->vp_exec_heap; if (nouveau_heap_alloc(heap, 16, &r->vertprog, &r->vertprog)) { while (heap->next && heap->size < 16) { struct nouveau_heap **evict = heap->next->priv; nouveau_heap_free(evict); } if (nouveau_heap_alloc(heap, 16, &r->vertprog, &r->vertprog)) return FALSE; } } vinfo->num_attribs = 0; vinfo->size = 0; /* setup routing for all necessary vp outputs */ for (i = 0; i < vp->info.num_outputs && attrib < 16; i++) { uint semantic = vp->info.output_semantic_name[i]; uint index = vp->info.output_semantic_index[i]; if (vroute_add(r, attrib, semantic, &index)) { vp_attribs |= (1 << attrib++); vp_results |= index; } } /* setup routing for replaced point coords not written by vp */ if (rast && rast->pipe.point_quad_rasterization) pntc = rast->pipe.sprite_coord_enable & 0x000002ff; else pntc = 0; while (pntc && attrib < 16) { uint index = ffs(pntc) - 1; pntc &= ~(1 << index); if (vroute_add(r, attrib, TGSI_SEMANTIC_TEXCOORD, &index)) { vp_attribs |= (1 << attrib++); vp_results |= index; } } /* modify vertex format for correct stride, and stub out unused ones */ BEGIN_NV04(push, NV30_3D(VP_UPLOAD_FROM_ID), 1); PUSH_DATA (push, r->vertprog->start); r->vtxprog[attrib - 1][3] |= 1; for (i = 0; i < attrib; i++) { BEGIN_NV04(push, NV30_3D(VP_UPLOAD_INST(0)), 4); PUSH_DATAp(push, r->vtxprog[i], 4); r->vtxfmt[i] |= vinfo->size << 8; } for (; i < 16; i++) r->vtxfmt[i] = NV30_3D_VTXFMT_TYPE_V32_FLOAT; BEGIN_NV04(push, NV30_3D(VIEWPORT_TRANSLATE_X), 8); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 1.0); PUSH_DATAf(push, 1.0); PUSH_DATAf(push, 1.0); PUSH_DATAf(push, 1.0); BEGIN_NV04(push, NV30_3D(DEPTH_RANGE_NEAR), 2); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 1.0); BEGIN_NV04(push, NV30_3D(VTXFMT(0)), 16); PUSH_DATAp(push, r->vtxfmt, 16); BEGIN_NV04(push, NV30_3D(VP_START_FROM_ID), 1); PUSH_DATA (push, r->vertprog->start); BEGIN_NV04(push, NV30_3D(ENGINE), 1); PUSH_DATA (push, 0x00000103); if (eng3d->oclass >= NV40_3D_CLASS) { BEGIN_NV04(push, NV40_3D(VP_ATTRIB_EN), 2); PUSH_DATA (push, vp_attribs); PUSH_DATA (push, vp_results); } vinfo->size /= 4; return TRUE; }
static void nv30_clear_depth_stencil(struct pipe_context *pipe, struct pipe_surface *ps, unsigned buffers, double depth, unsigned stencil, unsigned x, unsigned y, unsigned w, unsigned h) { struct nv30_context *nv30 = nv30_context(pipe); struct nv30_surface *sf = nv30_surface(ps); struct nv30_miptree *mt = nv30_miptree(ps->texture); struct nouveau_pushbuf *push = nv30->base.pushbuf; struct nouveau_object *eng3d = nv30->screen->eng3d; struct nouveau_pushbuf_refn refn; uint32_t rt_format, mode = 0; rt_format = nv30_format(pipe->screen, ps->format)->hw; if (util_format_get_blocksize(ps->format) == 4) rt_format |= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8; else rt_format |= NV30_3D_RT_FORMAT_COLOR_R5G6B5; if (nv30_miptree(ps->texture)->swizzled) { rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED; rt_format |= util_logbase2(sf->width) << 16; rt_format |= util_logbase2(sf->height) << 24; } else { rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR; } if (buffers & PIPE_CLEAR_DEPTH) mode |= NV30_3D_CLEAR_BUFFERS_DEPTH; if (buffers & PIPE_CLEAR_STENCIL) mode |= NV30_3D_CLEAR_BUFFERS_STENCIL; refn.bo = mt->base.bo; refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR; if (nouveau_pushbuf_space(push, 32, 1, 0) || nouveau_pushbuf_refn (push, &refn, 1)) return; BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1); PUSH_DATA (push, 0); BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3); PUSH_DATA (push, sf->width << 16); PUSH_DATA (push, sf->height << 16); PUSH_DATA (push, rt_format); if (eng3d->oclass < NV40_3D_CLASS) { BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 1); PUSH_DATA (push, (sf->pitch << 16) | sf->pitch); } else { BEGIN_NV04(push, NV40_3D(ZETA_PITCH), 1); PUSH_DATA (push, sf->pitch); } BEGIN_NV04(push, NV30_3D(ZETA_OFFSET), 1); PUSH_RELOC(push, mt->base.bo, sf->offset, NOUVEAU_BO_LOW, 0, 0); BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2); PUSH_DATA (push, (w << 16) | x); PUSH_DATA (push, (h << 16) | y); BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 1); PUSH_DATA (push, pack_zeta(ps->format, depth, stencil)); BEGIN_NV04(push, NV30_3D(CLEAR_BUFFERS), 1); PUSH_DATA (push, mode); nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR; }
Bool NV30EXAPrepareComposite(int op, PicturePtr psPict, PicturePtr pmPict, PicturePtr pdPict, PixmapPtr psPix, PixmapPtr pmPix, PixmapPtr pdPix) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pdPix->drawable.pScreen); NVPtr pNv = NVPTR(pScrn); nv_pict_op_t *blend = NV30_GetPictOpRec(op); struct nouveau_pushbuf *push = pNv->pushbuf; uint32_t sc, sa, mc, ma, solid[2]; if (!PUSH_SPACE(push, 128)) return FALSE; PUSH_RESET(push); /* setup render target and blending */ if (!NV30_SetupSurface(pScrn, pdPix, pdPict)) return FALSE; NV30_SetupBlend(pScrn, blend, pdPict->format, (pmPict && pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format))); /* select picture sources */ if (!NV30EXAPicture(pScrn, psPix, psPict, 0, &sc, &sa, &solid[0])) return FALSE; if (!NV30EXAPicture(pScrn, pmPix, pmPict, 1, &mc, &ma, &solid[1])) return FALSE; /* configure register combiners */ BEGIN_NV04(push, NV30_3D(RC_IN_ALPHA(0)), 6); PUSH_DATA (push, sa | ma); if (pmPict && pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format)) { if (blend->src_alpha) PUSH_DATA(push, sa | mc); else PUSH_DATA(push, sc | mc); } else { PUSH_DATA(push, sc | ma); } PUSH_DATA (push, solid[0]); PUSH_DATA (push, solid[1]); PUSH_DATA (push, 0x00000c00); PUSH_DATA (push, 0x00000c00); BEGIN_NV04(push, NV30_3D(RC_FINAL0), 3); if (pdPict->format != PICT_a8) PUSH_DATA (push, 0x0000000c); else PUSH_DATA (push, 0x0000001c); PUSH_DATA (push, 0x00001c00); PUSH_DATA (push, 0x01000101); /* select fragprog which just sources textures for combiners */ BEGIN_NV04(push, NV30_3D(FP_ACTIVE_PROGRAM), 1); PUSH_MTHD (push, NV30_3D(FP_ACTIVE_PROGRAM), pNv->scratch, PFP_PASS, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, NV30_3D_FP_ACTIVE_PROGRAM_DMA0, NV30_3D_FP_ACTIVE_PROGRAM_DMA1); BEGIN_NV04(push, NV30_3D(FP_REG_CONTROL), 1); PUSH_DATA (push, 0x0001000f); BEGIN_NV04(push, NV30_3D(FP_CONTROL), 1); PUSH_DATA (push, 0x00000000); BEGIN_NV04(push, NV30_3D(TEX_UNITS_ENABLE), 1); PUSH_DATA (push, 3); nouveau_pushbuf_bufctx(push, pNv->bufctx); if (nouveau_pushbuf_validate(push)) { nouveau_pushbuf_bufctx(push, NULL); return FALSE; } return TRUE; }
void nv30_push_vbo(struct nv30_context *nv30, const struct pipe_draw_info *info) { struct push_context ctx; unsigned i, index_size; boolean apply_bias = info->indexed && info->index_bias; ctx.push = nv30->base.pushbuf; ctx.translate = nv30->vertex->translate; ctx.packet_vertex_limit = nv30->vertex->vtx_per_packet_max; ctx.vertex_words = nv30->vertex->vtx_size; for (i = 0; i < nv30->num_vtxbufs; ++i) { uint8_t *data; struct pipe_vertex_buffer *vb = &nv30->vtxbuf[i]; struct nv04_resource *res = nv04_resource(vb->buffer); if (!vb->buffer && !vb->user_buffer) { continue; } data = nouveau_resource_map_offset(&nv30->base, res, vb->buffer_offset, NOUVEAU_BO_RD); if (apply_bias) data += info->index_bias * vb->stride; ctx.translate->set_buffer(ctx.translate, i, data, vb->stride, ~0); } if (info->indexed) { if (nv30->idxbuf.buffer) ctx.idxbuf = nouveau_resource_map_offset(&nv30->base, nv04_resource(nv30->idxbuf.buffer), nv30->idxbuf.offset, NOUVEAU_BO_RD); else ctx.idxbuf = nv30->idxbuf.user_buffer; if (!ctx.idxbuf) { nv30_state_release(nv30); return; } index_size = nv30->idxbuf.index_size; ctx.primitive_restart = info->primitive_restart; ctx.restart_index = info->restart_index; } else { ctx.idxbuf = NULL; index_size = 0; ctx.primitive_restart = FALSE; ctx.restart_index = 0; } if (nv30->screen->eng3d->oclass >= NV40_3D_CLASS) { BEGIN_NV04(ctx.push, NV40_3D(PRIM_RESTART_ENABLE), 2); PUSH_DATA (ctx.push, info->primitive_restart); PUSH_DATA (ctx.push, info->restart_index); nv30->state.prim_restart = info->primitive_restart; } ctx.prim = nv30_prim_gl(info->mode); PUSH_RESET(ctx.push, BUFCTX_IDXBUF); BEGIN_NV04(ctx.push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (ctx.push, ctx.prim); switch (index_size) { case 0: emit_vertices_seq(&ctx, info->start, info->count); break; case 1: emit_vertices_i08(&ctx, info->start, info->count); break; case 2: emit_vertices_i16(&ctx, info->start, info->count); break; case 4: emit_vertices_i32(&ctx, info->start, info->count); break; default: assert(0); break; } BEGIN_NV04(ctx.push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (ctx.push, NV30_3D_VERTEX_BEGIN_END_STOP); if (info->indexed) nouveau_resource_unmap(nv04_resource(nv30->idxbuf.buffer)); for (i = 0; i < nv30->num_vtxbufs; ++i) { if (nv30->vtxbuf[i].buffer) { nouveau_resource_unmap(nv04_resource(nv30->vtxbuf[i].buffer)); } } nv30_state_release(nv30); }
Bool NV40EXAPrepareComposite(int op, PicturePtr psPict, PicturePtr pmPict, PicturePtr pdPict, PixmapPtr psPix, PixmapPtr pmPix, PixmapPtr pdPix) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pdPix->drawable.pScreen); NVPtr pNv = NVPTR(pScrn); nv_pict_op_t *blend = NV40_GetPictOpRec(op); struct nouveau_pushbuf *push = pNv->pushbuf; uint32_t fragprog; if (!PUSH_SPACE(push, 128)) NOUVEAU_FALLBACK("space\n"); PUSH_RESET(push); NV40_SetupBlend(pScrn, blend, pdPict->format, (pmPict && pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format))); if (!NV40_SetupSurface(pScrn, pdPix, pdPict->format) || !NV40EXAPicture(pNv, psPix, psPict, 0)) return FALSE; if (pmPict) { if (!NV40EXAPicture(pNv, pmPix, pmPict, 1)) return FALSE; if (pdPict->format == PICT_a8) { fragprog = PFP_C_A8; } else if (pmPict->componentAlpha && PICT_FORMAT_RGB(pmPict->format)) { if (blend->src_alpha) fragprog = PFP_CCASA; else fragprog = PFP_CCA; } else { fragprog = PFP_C; } } else { if (pdPict->format == PICT_a8) fragprog = PFP_S_A8; else fragprog = PFP_S; } BEGIN_NV04(push, NV30_3D(FP_ACTIVE_PROGRAM), 1); PUSH_MTHD (push, NV30_3D(FP_ACTIVE_PROGRAM), pNv->scratch, fragprog, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, NV30_3D_FP_ACTIVE_PROGRAM_DMA0, NV30_3D_FP_ACTIVE_PROGRAM_DMA1); BEGIN_NV04(push, NV30_3D(FP_CONTROL), 1); PUSH_DATA (push, 0x02000000); /* Appears to be some kind of cache flush, needed here at least * sometimes.. funky text rendering otherwise :) */ BEGIN_NV04(push, NV40_3D(TEX_CACHE_CTL), 1); PUSH_DATA (push, 2); BEGIN_NV04(push, NV40_3D(TEX_CACHE_CTL), 1); PUSH_DATA (push, 1); nouveau_pushbuf_bufctx(push, pNv->bufctx); if (nouveau_pushbuf_validate(push)) { nouveau_pushbuf_bufctx(push, NULL); return FALSE; } return TRUE; }
static Bool NV40EXAPictTexture(NVPtr pNv, PixmapPtr pPix, PicturePtr pPict, int unit) { unsigned reloc = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_WR; struct nouveau_pushbuf *push = pNv->pushbuf; struct nouveau_bo *bo = nouveau_pixmap_bo(pPix); nv_pict_texture_format_t *fmt; fmt = NV40_GetPictTextureFormat(pPict->format); if (!fmt) return FALSE; BEGIN_NV04(push, NV30_3D(TEX_OFFSET(unit)), 8); PUSH_MTHDl(push, NV30_3D(TEX_OFFSET(unit)), bo, 0, reloc); PUSH_MTHDs(push, NV30_3D(TEX_FORMAT(unit)), bo, fmt->card_fmt | NV40_3D_TEX_FORMAT_LINEAR | NV30_3D_TEX_FORMAT_DIMS_2D | 0x8000 | NV30_3D_TEX_FORMAT_NO_BORDER | (1 << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT), reloc | NOUVEAU_BO_OR, NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1); if (pPict->repeat) { switch(pPict->repeatType) { case RepeatPad: PUSH_DATA (push, NV30_3D_TEX_WRAP_S_CLAMP | NV30_3D_TEX_WRAP_T_CLAMP | NV30_3D_TEX_WRAP_R_CLAMP); break; case RepeatReflect: PUSH_DATA (push, NV30_3D_TEX_WRAP_S_MIRRORED_REPEAT | NV30_3D_TEX_WRAP_T_MIRRORED_REPEAT | NV30_3D_TEX_WRAP_R_MIRRORED_REPEAT); break; case RepeatNormal: default: PUSH_DATA (push, NV30_3D_TEX_WRAP_S_REPEAT | NV30_3D_TEX_WRAP_T_REPEAT | NV30_3D_TEX_WRAP_R_REPEAT); break; } } else { PUSH_DATA (push, NV30_3D_TEX_WRAP_S_CLAMP_TO_BORDER | NV30_3D_TEX_WRAP_T_CLAMP_TO_BORDER | NV30_3D_TEX_WRAP_R_CLAMP_TO_BORDER); } PUSH_DATA (push, NV40_3D_TEX_ENABLE_ENABLE); PUSH_DATA (push, fmt->card_swz); if (pPict->filter == PictFilterBilinear) { PUSH_DATA (push, NV30_3D_TEX_FILTER_MIN_LINEAR | NV30_3D_TEX_FILTER_MAG_LINEAR | 0x3fd6); } else { PUSH_DATA (push, NV30_3D_TEX_FILTER_MIN_NEAREST | NV30_3D_TEX_FILTER_MAG_NEAREST | 0x3fd6); } PUSH_DATA (push, (pPix->drawable.width << 16) | pPix->drawable.height); PUSH_DATA (push, 0); /* border ARGB */ BEGIN_NV04(push, NV40_3D(TEX_SIZE1(unit)), 1); PUSH_DATA (push, (1 << NV40_3D_TEX_SIZE1_DEPTH__SHIFT) | (uint32_t)exaGetPixmapPitch(pPix)); BEGIN_NV04(push, NV30_3D(VP_UPLOAD_CONST_ID), 17); PUSH_DATA (push, unit * 4); if (pPict->transform) { PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[0][0])); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[0][1])); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[0][2])); PUSH_DATAf(push, 0); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[1][0])); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[1][1])); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[1][2])); PUSH_DATAf(push, 0); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[2][0])); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[2][1])); PUSH_DATAf(push, xFixedToFloat(pPict->transform->matrix[2][2])); PUSH_DATAf(push, 0); } else { PUSH_DATAf(push, 1.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 1.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 1.0); PUSH_DATAf(push, 0.0); } PUSH_DATAf(push, 1.0 / pPix->drawable.width); PUSH_DATAf(push, 1.0 / pPix->drawable.height); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 1.0); return TRUE; }