static Bool setup_texture(NVPtr pNv, int unit, PicturePtr pict, PixmapPtr pixmap) { struct nouveau_channel *chan = pNv->chan; struct nouveau_bo *bo = nouveau_pixmap_bo(pixmap); unsigned tex_reloc = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; long w = pict->pDrawable->width, h = pict->pDrawable->height; unsigned int txfmt = NV10_3D_TEX_FORMAT_WRAP_T_CLAMP_TO_EDGE | NV10_3D_TEX_FORMAT_WRAP_S_CLAMP_TO_EDGE | log2i(w) << 20 | log2i(h) << 16 | 1 << 12 | /* lod == 1 */ get_tex_format(pict) | 0x50 /* UNK */; BEGIN_NV04(chan, NV10_3D(TEX_OFFSET(unit)), 1); if (OUT_RELOCl(chan, bo, 0, tex_reloc)) return FALSE; if (pict->repeat == RepeatNone) { /* NPOT_SIZE expects an even number for width, we can * round up uneven numbers here because EXA always * gives 64 byte aligned pixmaps and for all formats * we support 64 bytes represents an even number of * pixels */ w = (w + 1) &~ 1; BEGIN_NV04(chan, NV10_3D(TEX_NPOT_PITCH(unit)), 1); OUT_RING (chan, exaGetPixmapPitch(pixmap) << 16); BEGIN_NV04(chan, NV10_3D(TEX_NPOT_SIZE(unit)), 1); OUT_RING (chan, w << 16 | h); } BEGIN_NV04(chan, NV10_3D(TEX_FORMAT(unit)), 1 ); if (OUT_RELOCd(chan, bo, txfmt, tex_reloc | NOUVEAU_BO_OR, NV10_3D_TEX_FORMAT_DMA0, NV10_3D_TEX_FORMAT_DMA1)) return FALSE; BEGIN_NV04(chan, NV10_3D(TEX_ENABLE(unit)), 1 ); OUT_RING (chan, NV10_3D_TEX_ENABLE_ENABLE); BEGIN_NV04(chan, NV10_3D(TEX_FILTER(unit)), 1); if (pict->filter == PictFilterNearest) OUT_RING(chan, (NV10_3D_TEX_FILTER_MAGNIFY_NEAREST | NV10_3D_TEX_FILTER_MINIFY_NEAREST)); else OUT_RING(chan, (NV10_3D_TEX_FILTER_MAGNIFY_LINEAR | NV10_3D_TEX_FILTER_MINIFY_LINEAR)); return TRUE; }
static Bool setup_texture(NVPtr pNv, int unit, PicturePtr pict, PixmapPtr pixmap) { struct nouveau_pushbuf *push = pNv->pushbuf; struct nouveau_bo *bo = nouveau_pixmap_bo(pixmap); unsigned reloc = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; unsigned h = pict->pDrawable->height; unsigned w = pict->pDrawable->width; unsigned format; format = NV10_3D_TEX_FORMAT_WRAP_T_CLAMP_TO_EDGE | NV10_3D_TEX_FORMAT_WRAP_S_CLAMP_TO_EDGE | log2i(w) << 20 | log2i(h) << 16 | 1 << 12 | /* lod == 1 */ get_tex_format(pNv, pict) | 0x50 /* UNK */; /* NPOT_SIZE expects an even number for width, we can round up uneven * numbers here because EXA always gives 64 byte aligned pixmaps and * for all formats we support 64 bytes represents an even number of * pixels */ w = (w + 1) & ~1; BEGIN_NV04(push, NV10_3D(TEX_OFFSET(unit)), 1); PUSH_MTHDl(push, NV10_3D(TEX_OFFSET(unit)), bo, 0, reloc); BEGIN_NV04(push, NV10_3D(TEX_FORMAT(unit)), 1); PUSH_MTHDs(push, NV10_3D(TEX_FORMAT(unit)), bo, format, reloc, NV10_3D_TEX_FORMAT_DMA0, NV10_3D_TEX_FORMAT_DMA1); BEGIN_NV04(push, NV10_3D(TEX_ENABLE(unit)), 1 ); PUSH_DATA (push, NV10_3D_TEX_ENABLE_ENABLE); BEGIN_NV04(push, NV10_3D(TEX_NPOT_PITCH(unit)), 1); PUSH_DATA (push, exaGetPixmapPitch(pixmap) << 16); BEGIN_NV04(push, NV10_3D(TEX_NPOT_SIZE(unit)), 1); PUSH_DATA (push, (w << 16) | h); BEGIN_NV04(push, NV10_3D(TEX_FILTER(unit)), 1); if (pict->filter == PictFilterNearest) PUSH_DATA(push, NV10_3D_TEX_FILTER_MAGNIFY_NEAREST | NV10_3D_TEX_FILTER_MINIFY_NEAREST); else PUSH_DATA(push, NV10_3D_TEX_FILTER_MAGNIFY_LINEAR | NV10_3D_TEX_FILTER_MINIFY_LINEAR); if (pict->transform) { BEGIN_NV04(push, NV10_3D(TEX_MATRIX_ENABLE(unit)), 1); PUSH_DATA (push, 1); BEGIN_NV04(push, NV10_3D(TEX_MATRIX(unit, 0)), 16); PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[0][0])); PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[0][1])); PUSH_DATAf(push, 0.f); PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[0][2])); PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[1][0])); PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[1][1])); PUSH_DATAf(push, 0.f); PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[1][2])); PUSH_DATAf(push, 0.0f); PUSH_DATAf(push, 0.0f); PUSH_DATAf(push, 0.0f); PUSH_DATAf(push, 0.0f); PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[2][0])); PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[2][1])); PUSH_DATAf(push, 0.0f); PUSH_DATAf(push, xFixedToFloat(pict->transform->matrix[2][2])); } else { BEGIN_NV04(push, NV10_3D(TEX_MATRIX_ENABLE(unit)), 1); PUSH_DATA (push, 0); } return TRUE; }
void nv20_emit_tex_obj(struct gl_context *ctx, int emit) { const int i = emit - NOUVEAU_STATE_TEX_OBJ0; struct nouveau_pushbuf *push = context_push(ctx); const int bo_flags = NOUVEAU_BO_RD | NOUVEAU_BO_GART | NOUVEAU_BO_VRAM; struct gl_texture_object *t; struct nouveau_surface *s; struct gl_texture_image *ti; const struct gl_sampler_object *sa; uint32_t tx_format, tx_filter, tx_wrap, tx_enable; PUSH_RESET(push, BUFCTX_TEX(i)); if (!ctx->Texture.Unit[i]._ReallyEnabled) { BEGIN_NV04(push, NV20_3D(TEX_ENABLE(i)), 1); PUSH_DATA (push, 0); context_dirty(ctx, TEX_SHADER); return; } t = ctx->Texture.Unit[i]._Current; s = &to_nouveau_texture(t)->surfaces[t->BaseLevel]; ti = t->Image[0][t->BaseLevel]; sa = _mesa_get_samplerobj(ctx, i); if (!nouveau_texture_validate(ctx, t)) return; /* Recompute the texturing registers. */ tx_format = ti->DepthLog2 << 28 | ti->HeightLog2 << 24 | ti->WidthLog2 << 20 | NV20_3D_TEX_FORMAT_DIMS_2D | NV20_3D_TEX_FORMAT_NO_BORDER | 1 << 16; tx_wrap = nvgl_wrap_mode(sa->WrapR) << 16 | nvgl_wrap_mode(sa->WrapT) << 8 | nvgl_wrap_mode(sa->WrapS) << 0; tx_filter = nvgl_filter_mode(sa->MagFilter) << 24 | nvgl_filter_mode(sa->MinFilter) << 16 | 2 << 12; tx_enable = NV20_3D_TEX_ENABLE_ENABLE | log2i(sa->MaxAnisotropy) << 4; if (t->Target == GL_TEXTURE_RECTANGLE) { BEGIN_NV04(push, NV20_3D(TEX_NPOT_PITCH(i)), 1); PUSH_DATA (push, s->pitch << 16); BEGIN_NV04(push, NV20_3D(TEX_NPOT_SIZE(i)), 1); PUSH_DATA (push, s->width << 16 | s->height); tx_format |= get_tex_format_rect(ti); } else { tx_format |= get_tex_format_pot(ti); } if (sa->MinFilter != GL_NEAREST && sa->MinFilter != GL_LINEAR) { int lod_min = sa->MinLod; int lod_max = MIN2(sa->MaxLod, t->_MaxLambda); int lod_bias = sa->LodBias + ctx->Texture.Unit[i].LodBias; lod_max = CLAMP(lod_max, 0, 15); lod_min = CLAMP(lod_min, 0, 15); lod_bias = CLAMP(lod_bias, 0, 15); tx_format |= NV20_3D_TEX_FORMAT_MIPMAP; tx_filter |= lod_bias << 8; tx_enable |= lod_min << 26 | lod_max << 14; } /* Write it to the hardware. */ BEGIN_NV04(push, NV20_3D(TEX_FORMAT(i)), 1); PUSH_MTHD (push, NV20_3D(TEX_FORMAT(i)), BUFCTX_TEX(i), s->bo, tx_format, bo_flags | NOUVEAU_BO_OR, NV20_3D_TEX_FORMAT_DMA0, NV20_3D_TEX_FORMAT_DMA1); BEGIN_NV04(push, NV20_3D(TEX_OFFSET(i)), 1); PUSH_MTHDl(push, NV20_3D(TEX_OFFSET(i)), BUFCTX_TEX(i), s->bo, s->offset, bo_flags); BEGIN_NV04(push, NV20_3D(TEX_WRAP(i)), 1); PUSH_DATA (push, tx_wrap); BEGIN_NV04(push, NV20_3D(TEX_FILTER(i)), 1); PUSH_DATA (push, tx_filter); BEGIN_NV04(push, NV20_3D(TEX_ENABLE(i)), 1); PUSH_DATA (push, tx_enable); context_dirty(ctx, TEX_SHADER); }