Merge remote branch 'origin/master' into nv50-compiler
[mesa.git] / src / gallium / drivers / nvfx / nv40_fragtex.c
1 #include "util/u_format.h"
2 #include "nvfx_context.h"
3 #include "nvfx_tex.h"
4 #include "nvfx_resource.h"
5
6 void
7 nv40_sampler_state_init(struct pipe_context *pipe,
8 struct nvfx_sampler_state *ps,
9 const struct pipe_sampler_state *cso)
10 {
11 float limit;
12 if (cso->max_anisotropy >= 2) {
13 /* no idea, binary driver sets it, works without it.. meh.. */
14 ps->wrap |= (1 << 5);
15
16 if (cso->max_anisotropy >= 16)
17 ps->en |= NV40TCL_TEX_ENABLE_ANISO_16X;
18 else if (cso->max_anisotropy >= 12)
19 ps->en |= NV40TCL_TEX_ENABLE_ANISO_12X;
20 else if (cso->max_anisotropy >= 10)
21 ps->en |= NV40TCL_TEX_ENABLE_ANISO_10X;
22 else if (cso->max_anisotropy >= 8)
23 ps->en |= NV40TCL_TEX_ENABLE_ANISO_8X;
24 else if (cso->max_anisotropy >= 6)
25 ps->en |= NV40TCL_TEX_ENABLE_ANISO_6X;
26 else if (cso->max_anisotropy >= 4)
27 ps->en |= NV40TCL_TEX_ENABLE_ANISO_4X;
28 else
29 ps->en |= NV40TCL_TEX_ENABLE_ANISO_2X;
30 }
31
32 limit = CLAMP(cso->lod_bias, -16.0, 15.0 + (255.0 / 256.0));
33 ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff;
34
35 ps->max_lod = (int)(CLAMP(cso->max_lod, 0.0, 15.0 + (255.0 / 256.0)) * 256.0);
36 ps->min_lod = (int)(CLAMP(cso->min_lod, 0.0, 15.0 + (255.0 / 256.0)) * 256.0);
37
38 ps->en |= NV40TCL_TEX_ENABLE_ENABLE;
39 }
40
41 void
42 nv40_sampler_view_init(struct pipe_context *pipe,
43 struct nvfx_sampler_view *sv)
44 {
45 struct pipe_resource* pt = sv->base.texture;
46 struct nvfx_miptree* mt = (struct nvfx_miptree*)pt;
47 struct nvfx_texture_format *tf = &nvfx_texture_formats[sv->base.format];
48 unsigned txf;
49 unsigned level = pt->target == PIPE_TEXTURE_CUBE ? 0 : sv->base.first_level;
50 assert(tf->fmt[4] >= 0);
51
52 txf = sv->u.init_fmt;
53 txf |= 0x8000;
54 if(pt->target == PIPE_TEXTURE_CUBE)
55 txf |= ((pt->last_level + 1) << NV40TCL_TEX_FORMAT_MIPMAP_COUNT_SHIFT);
56 else
57 txf |= (((sv->base.last_level - sv->base.first_level) + 1) << NV40TCL_TEX_FORMAT_MIPMAP_COUNT_SHIFT);
58
59 if (!mt->linear_pitch)
60 sv->u.nv40.npot_size2 = 0;
61 else {
62 sv->u.nv40.npot_size2 = mt->linear_pitch;
63 txf |= NV40TCL_TEX_FORMAT_LINEAR;
64 }
65
66 sv->u.nv40.fmt[0] = tf->fmt[4] | txf;
67 sv->u.nv40.fmt[1] = tf->fmt[5] | txf;
68
69 sv->u.nv40.npot_size2 |= (u_minify(pt->depth0, level) << NV40TCL_TEX_SIZE1_DEPTH_SHIFT);
70
71 sv->lod_offset = (sv->base.first_level - level) * 256;
72 sv->max_lod_limit = (sv->base.last_level - level) * 256;
73 }
74
75 void
76 nv40_fragtex_set(struct nvfx_context *nvfx, int unit)
77 {
78 struct nouveau_channel* chan = nvfx->screen->base.channel;
79 struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit];
80 struct nvfx_sampler_view* sv = (struct nvfx_sampler_view*)nvfx->fragment_sampler_views[unit];
81 struct nouveau_bo *bo = ((struct nvfx_miptree *)sv->base.texture)->base.bo;
82 unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
83 unsigned txf;
84 unsigned max_lod = MIN2(ps->max_lod + sv->lod_offset, sv->max_lod_limit);
85 unsigned min_lod = MIN2(ps->min_lod + sv->lod_offset, max_lod);
86
87 txf = sv->u.nv40.fmt[ps->compare] | ps->fmt;
88
89 MARK_RING(chan, 11, 2);
90 OUT_RING(chan, RING_3D(NV34TCL_TX_OFFSET(unit), 8));
91 OUT_RELOC(chan, bo, sv->offset, tex_flags | NOUVEAU_BO_LOW, 0, 0);
92 OUT_RELOC(chan, bo, txf, tex_flags | NOUVEAU_BO_OR,
93 NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1);
94 OUT_RING(chan, (ps->wrap & sv->wrap_mask) | sv->wrap);
95 OUT_RING(chan, ps->en | (min_lod << 19) | (max_lod << 7));
96 OUT_RING(chan, sv->swizzle);
97 OUT_RING(chan, ps->filt | sv->filt);
98 OUT_RING(chan, sv->npot_size);
99 OUT_RING(chan, ps->bcol);
100 OUT_RING(chan, RING_3D(NV40TCL_TEX_SIZE1(unit), 1));
101 OUT_RING(chan, sv->u.nv40.npot_size2);
102
103 nvfx->hw_txf[unit] = txf;
104 nvfx->hw_samplers |= (1 << unit);
105 }