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; }
void nv40_verttex_validate(struct nv30_context *nv30) { struct nouveau_pushbuf *push = nv30->base.pushbuf; unsigned dirty = nv30->vertprog.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]; if (ss && sv) { } else { BEGIN_NV04(push, NV40_3D(VTXTEX_ENABLE(unit)), 1); PUSH_DATA (push, 0); } } nv30->vertprog.dirty_samplers = 0; }
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 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; }
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); }
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; }
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 void nv30_transfer_rect_blit(XFER_ARGS) { struct nv04_resource *fp = nv30_transfer_rect_fragprog(nv30); struct nouveau_heap *vp = nv30_transfer_rect_vertprog(nv30); struct nouveau_pushbuf *push = nv30->base.pushbuf; struct nouveau_pushbuf_refn refs[] = { { fp->bo, fp->domain | NOUVEAU_BO_RD }, { src->bo, src->domain | NOUVEAU_BO_RD }, { dst->bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR }, }; u32 texfmt, texswz; u32 format, stride; if (nouveau_pushbuf_space(push, 512, 8, 0) || nouveau_pushbuf_refn (push, refs, sizeof(refs) / sizeof(refs[0]))) return; /* various switches depending on cpp of the transfer */ switch (dst->cpp) { case 4: format = NV30_3D_RT_FORMAT_COLOR_A8R8G8B8 | NV30_3D_RT_FORMAT_ZETA_Z24S8; texfmt = NV40_3D_TEX_FORMAT_FORMAT_A8R8G8B8; texswz = 0x0000aae4; break; case 2: format = NV30_3D_RT_FORMAT_COLOR_R5G6B5 | NV30_3D_RT_FORMAT_ZETA_Z16; texfmt = NV40_3D_TEX_FORMAT_FORMAT_R5G6B5; texswz = 0x0000a9e4; break; case 1: format = NV30_3D_RT_FORMAT_COLOR_B8 | NV30_3D_RT_FORMAT_ZETA_Z16; texfmt = NV40_3D_TEX_FORMAT_FORMAT_L8; texswz = 0x0000aaff; break; default: assert(0); return; } /* render target */ if (!dst->pitch) { format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED; format |= util_logbase2(dst->w) << 16; format |= util_logbase2(dst->h) << 24; stride = 64; } else { format |= NV30_3D_RT_FORMAT_TYPE_LINEAR; stride = dst->pitch; } BEGIN_NV04(push, NV30_3D(VIEWPORT_HORIZ), 2); PUSH_DATA (push, dst->w << 16); PUSH_DATA (push, dst->h << 16); BEGIN_NV04(push, NV30_3D(RT_HORIZ), 5); PUSH_DATA (push, dst->w << 16); PUSH_DATA (push, dst->h << 16); PUSH_DATA (push, format); PUSH_DATA (push, stride); PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0); BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1); PUSH_DATA (push, NV30_3D_RT_ENABLE_COLOR0); nv30->dirty |= NV30_NEW_FRAMEBUFFER; /* viewport state */ 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); nv30->dirty |= NV30_NEW_VIEWPORT; /* blend state */ BEGIN_NV04(push, NV30_3D(COLOR_LOGIC_OP_ENABLE), 1); PUSH_DATA (push, 0); BEGIN_NV04(push, NV30_3D(DITHER_ENABLE), 1); PUSH_DATA (push, 0); BEGIN_NV04(push, NV30_3D(BLEND_FUNC_ENABLE), 1); PUSH_DATA (push, 0); BEGIN_NV04(push, NV30_3D(COLOR_MASK), 1); PUSH_DATA (push, 0x01010101); nv30->dirty |= NV30_NEW_BLEND; /* depth-stencil-alpha state */ BEGIN_NV04(push, NV30_3D(DEPTH_WRITE_ENABLE), 2); PUSH_DATA (push, 0); PUSH_DATA (push, 0); BEGIN_NV04(push, NV30_3D(STENCIL_ENABLE(0)), 1); PUSH_DATA (push, 0); BEGIN_NV04(push, NV30_3D(STENCIL_ENABLE(1)), 1); PUSH_DATA (push, 0); BEGIN_NV04(push, NV30_3D(ALPHA_FUNC_ENABLE), 1); PUSH_DATA (push, 0); nv30->dirty |= NV30_NEW_ZSA; /* rasterizer state */ BEGIN_NV04(push, NV30_3D(SHADE_MODEL), 1); PUSH_DATA (push, NV30_3D_SHADE_MODEL_FLAT); BEGIN_NV04(push, NV30_3D(CULL_FACE_ENABLE), 1); PUSH_DATA (push, 0); BEGIN_NV04(push, NV30_3D(POLYGON_MODE_FRONT), 2); PUSH_DATA (push, NV30_3D_POLYGON_MODE_FRONT_FILL); PUSH_DATA (push, NV30_3D_POLYGON_MODE_BACK_FILL); BEGIN_NV04(push, NV30_3D(POLYGON_OFFSET_FILL_ENABLE), 1); PUSH_DATA (push, 0); BEGIN_NV04(push, NV30_3D(POLYGON_STIPPLE_ENABLE), 1); PUSH_DATA (push, 0); nv30->state.scissor_off = 0; nv30->dirty |= NV30_NEW_RASTERIZER; /* vertex program */ BEGIN_NV04(push, NV30_3D(VP_START_FROM_ID), 1); PUSH_DATA (push, vp->start); BEGIN_NV04(push, NV40_3D(VP_ATTRIB_EN), 2); PUSH_DATA (push, 0x00000101); /* attrib: 0, 8 */ PUSH_DATA (push, 0x00004000); /* result: hpos, tex0 */ BEGIN_NV04(push, NV30_3D(ENGINE), 1); PUSH_DATA (push, 0x00000103); BEGIN_NV04(push, NV30_3D(VP_CLIP_PLANES_ENABLE), 1); PUSH_DATA (push, 0x00000000); nv30->dirty |= NV30_NEW_VERTPROG; nv30->dirty |= NV30_NEW_CLIP; /* fragment program */ BEGIN_NV04(push, NV30_3D(FP_ACTIVE_PROGRAM), 1); PUSH_RELOC(push, fp->bo, fp->offset, fp->domain | 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); nv30->state.fragprog = NULL; nv30->dirty |= NV30_NEW_FRAGPROG; /* texture */ texfmt |= 1 << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT; texfmt |= NV30_3D_TEX_FORMAT_NO_BORDER; texfmt |= NV40_3D_TEX_FORMAT_RECT; texfmt |= 0x00008000; if (src->d < 2) texfmt |= NV30_3D_TEX_FORMAT_DIMS_2D; else texfmt |= NV30_3D_TEX_FORMAT_DIMS_3D; if (src->pitch) texfmt |= NV40_3D_TEX_FORMAT_LINEAR; BEGIN_NV04(push, NV30_3D(TEX_OFFSET(0)), 8); PUSH_RELOC(push, src->bo, src->offset, NOUVEAU_BO_LOW, 0, 0); PUSH_RELOC(push, src->bo, texfmt, NOUVEAU_BO_OR, NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1); PUSH_DATA (push, NV30_3D_TEX_WRAP_S_CLAMP_TO_EDGE | NV30_3D_TEX_WRAP_T_CLAMP_TO_EDGE | NV30_3D_TEX_WRAP_R_CLAMP_TO_EDGE); PUSH_DATA (push, NV40_3D_TEX_ENABLE_ENABLE); PUSH_DATA (push, texswz); switch (filter) { case BILINEAR: PUSH_DATA (push, NV30_3D_TEX_FILTER_MIN_LINEAR | NV30_3D_TEX_FILTER_MAG_LINEAR | 0x00002000); break; default: PUSH_DATA (push, NV30_3D_TEX_FILTER_MIN_NEAREST | NV30_3D_TEX_FILTER_MAG_NEAREST | 0x00002000); break; } PUSH_DATA (push, (src->w << 16) | src->h); PUSH_DATA (push, 0x00000000); BEGIN_NV04(push, NV40_3D(TEX_SIZE1(0)), 1); PUSH_DATA (push, 0x00100000 | src->pitch); BEGIN_NV04(push, SUBC_3D(0x0b40), 1); PUSH_DATA (push, src->d < 2 ? 0x00000001 : 0x00000000); BEGIN_NV04(push, NV40_3D(TEX_CACHE_CTL), 1); PUSH_DATA (push, 1); nv30->fragprog.dirty_samplers |= 1; nv30->dirty |= NV30_NEW_FRAGTEX; /* blit! */ BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2); PUSH_DATA (push, (dst->x1 - dst->x0) << 16 | dst->x0); PUSH_DATA (push, (dst->y1 - dst->y0) << 16 | dst->y0); BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_QUADS); BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3); PUSH_DATAf(push, src->x0); PUSH_DATAf(push, src->y0); PUSH_DATAf(push, src->z); BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1); PUSH_DATA (push, (dst->y0 << 16) | dst->x0); BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3); PUSH_DATAf(push, src->x1); PUSH_DATAf(push, src->y0); PUSH_DATAf(push, src->z); BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1); PUSH_DATA (push, (dst->y0 << 16) | dst->x1); BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3); PUSH_DATAf(push, src->x1); PUSH_DATAf(push, src->y1); PUSH_DATAf(push, src->z); BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1); PUSH_DATA (push, (dst->y1 << 16) | dst->x1); BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3); PUSH_DATAf(push, src->x0); PUSH_DATAf(push, src->y1); PUSH_DATAf(push, src->z); BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1); PUSH_DATA (push, (dst->y1 << 16) | dst->x0); BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP); }
void nv30_vertprog_validate(struct nv30_context *nv30) { struct nouveau_pushbuf *push = nv30->base.pushbuf; struct nouveau_object *eng3d = nv30->screen->eng3d; struct nv30_vertprog *vp = nv30->vertprog.program; struct nv30_fragprog *fp = nv30->fragprog.program; boolean upload_code = FALSE; boolean upload_data = FALSE; unsigned i; if (nv30->dirty & NV30_NEW_FRAGPROG) { if (memcmp(vp->texcoord, fp->texcoord, sizeof(vp->texcoord))) { if (vp->translated) nv30_vertprog_destroy(vp); memcpy(vp->texcoord, fp->texcoord, sizeof(vp->texcoord)); } } if (nv30->rast && nv30->rast->pipe.clip_plane_enable != vp->enabled_ucps) { vp->enabled_ucps = nv30->rast->pipe.clip_plane_enable; if (vp->translated) nv30_vertprog_destroy(vp); } if (!vp->translated) { vp->translated = _nvfx_vertprog_translate(eng3d->oclass, vp); if (!vp->translated) { nv30->draw_flags |= NV30_NEW_VERTPROG; return; } nv30->dirty |= NV30_NEW_VERTPROG; } if (!vp->exec) { struct nouveau_heap *heap = nv30->screen->vp_exec_heap; struct nv30_shader_reloc *reloc = vp->branch_relocs.data; unsigned nr_reloc = vp->branch_relocs.size / sizeof(*reloc); uint32_t *inst, target; if (nouveau_heap_alloc(heap, vp->nr_insns, &vp->exec, &vp->exec)) { while (heap->next && heap->size < vp->nr_insns) { struct nouveau_heap **evict = heap->next->priv; nouveau_heap_free(evict); } if (nouveau_heap_alloc(heap, vp->nr_insns, &vp->exec, &vp->exec)) { nv30->draw_flags |= NV30_NEW_VERTPROG; return; } } if (eng3d->oclass < NV40_3D_CLASS) { while (nr_reloc--) { inst = vp->insns[reloc->location].data; target = vp->exec->start + reloc->target; inst[2] &= ~0x000007fc; inst[2] |= target << 2; reloc++; } } else { while (nr_reloc--) { inst = vp->insns[reloc->location].data; target = vp->exec->start + reloc->target; inst[2] &= ~0x0000003f; inst[2] |= target >> 3; inst[3] &= ~0xe0000000; inst[3] |= target << 29; reloc++; } } upload_code = TRUE; } if (vp->nr_consts && !vp->data) { struct nouveau_heap *heap = nv30->screen->vp_data_heap; struct nv30_shader_reloc *reloc = vp->const_relocs.data; unsigned nr_reloc = vp->const_relocs.size / sizeof(*reloc); uint32_t *inst, target; if (nouveau_heap_alloc(heap, vp->nr_consts, vp, &vp->data)) { while (heap->next && heap->size < vp->nr_consts) { struct nv30_vertprog *evp = heap->next->priv; nouveau_heap_free(&evp->data); } if (nouveau_heap_alloc(heap, vp->nr_consts, vp, &vp->data)) { nv30->draw_flags |= NV30_NEW_VERTPROG; return; } } if (eng3d->oclass < NV40_3D_CLASS) { while (nr_reloc--) { inst = vp->insns[reloc->location].data; target = vp->data->start + reloc->target; inst[1] &= ~0x0007fc000; inst[1] |= (target & 0x1ff) << 14; reloc++; } } else { while (nr_reloc--) { inst = vp->insns[reloc->location].data; target = vp->data->start + reloc->target; inst[1] &= ~0x0001ff000; inst[1] |= (target & 0x1ff) << 12; reloc++; } } upload_code = TRUE; upload_data = TRUE; } if (vp->nr_consts) { struct nv04_resource *res = nv04_resource(nv30->vertprog.constbuf); for (i = 0; i < vp->nr_consts; i++) { struct nv30_vertprog_data *data = &vp->consts[i]; if (data->index < 0) { if (!upload_data) continue; } else { float *constbuf = (float *)res->data; if (!upload_data && !memcmp(data->value, &constbuf[data->index * 4], 16)) continue; memcpy(data->value, &constbuf[data->index * 4], 16); } BEGIN_NV04(push, NV30_3D(VP_UPLOAD_CONST_ID), 5); PUSH_DATA (push, vp->data->start + i); PUSH_DATAp(push, data->value, 4); } } if (upload_code) { BEGIN_NV04(push, NV30_3D(VP_UPLOAD_FROM_ID), 1); PUSH_DATA (push, vp->exec->start); for (i = 0; i < vp->nr_insns; i++) { BEGIN_NV04(push, NV30_3D(VP_UPLOAD_INST(0)), 4); PUSH_DATAp(push, vp->insns[i].data, 4); } } if (nv30->dirty & (NV30_NEW_VERTPROG | NV30_NEW_FRAGPROG)) { BEGIN_NV04(push, NV30_3D(VP_START_FROM_ID), 1); PUSH_DATA (push, vp->exec->start); if (eng3d->oclass < NV40_3D_CLASS) { BEGIN_NV04(push, NV30_3D(ENGINE), 1); PUSH_DATA (push, 0x00000013); /* vp instead of ff, somehow */ } else { BEGIN_NV04(push, NV40_3D(VP_ATTRIB_EN), 2); PUSH_DATA (push, vp->ir); PUSH_DATA (push, vp->or | fp->vp_or); BEGIN_NV04(push, NV30_3D(ENGINE), 1); PUSH_DATA (push, 0x00000011); } } }