fe87cebbb68ca7e3ef89b8577920fa9ba33b13ef
[profile/ivi/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
5 void
6 nv40_sampler_state_init(struct pipe_context *pipe,
7                           struct nvfx_sampler_state *ps,
8                           const struct pipe_sampler_state *cso)
9 {
10         if (cso->max_anisotropy >= 2) {
11                 /* no idea, binary driver sets it, works without it.. meh.. */
12                 ps->wrap |= (1 << 5);
13
14                 if (cso->max_anisotropy >= 16) {
15                         ps->en |= NV40TCL_TEX_ENABLE_ANISO_16X;
16                 } else
17                 if (cso->max_anisotropy >= 12) {
18                         ps->en |= NV40TCL_TEX_ENABLE_ANISO_12X;
19                 } else
20                 if (cso->max_anisotropy >= 10) {
21                         ps->en |= NV40TCL_TEX_ENABLE_ANISO_10X;
22                 } else
23                 if (cso->max_anisotropy >= 8) {
24                         ps->en |= NV40TCL_TEX_ENABLE_ANISO_8X;
25                 } else
26                 if (cso->max_anisotropy >= 6) {
27                         ps->en |= NV40TCL_TEX_ENABLE_ANISO_6X;
28                 } else
29                 if (cso->max_anisotropy >= 4) {
30                         ps->en |= NV40TCL_TEX_ENABLE_ANISO_4X;
31                 } else {
32                         ps->en |= NV40TCL_TEX_ENABLE_ANISO_2X;
33                 }
34         }
35
36         {
37                 float limit;
38
39                 limit = CLAMP(cso->lod_bias, -16.0, 15.0);
40                 ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff;
41
42                 limit = CLAMP(cso->max_lod, 0.0, 15.0);
43                 ps->en |= (int)(limit * 256.0) << 7;
44
45                 limit = CLAMP(cso->min_lod, 0.0, 15.0);
46                 ps->en |= (int)(limit * 256.0) << 19;
47         }
48 }
49
50 #define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,sx,sy,sz,sw)            \
51 {                                                                              \
52   TRUE,                                                                        \
53   PIPE_FORMAT_##m,                                                             \
54   NV40TCL_TEX_FORMAT_FORMAT_##tf,                                              \
55   (NV34TCL_TX_SWIZZLE_S0_X_##ts0x | NV34TCL_TX_SWIZZLE_S0_Y_##ts0y |         \
56    NV34TCL_TX_SWIZZLE_S0_Z_##ts0z | NV34TCL_TX_SWIZZLE_S0_W_##ts0w |         \
57    NV34TCL_TX_SWIZZLE_S1_X_##ts1x | NV34TCL_TX_SWIZZLE_S1_Y_##ts1y |         \
58    NV34TCL_TX_SWIZZLE_S1_Z_##ts1z | NV34TCL_TX_SWIZZLE_S1_W_##ts1w),         \
59   ((NV34TCL_TX_FILTER_SIGNED_RED*sx) | (NV34TCL_TX_FILTER_SIGNED_GREEN*sy) |       \
60    (NV34TCL_TX_FILTER_SIGNED_BLUE*sz) | (NV34TCL_TX_FILTER_SIGNED_ALPHA*sw))       \
61 }
62
63 struct nv40_texture_format {
64         boolean defined;
65         uint    pipe;
66         int     format;
67         int     swizzle;
68         int     sign;
69 };
70
71 static struct nv40_texture_format
72 nv40_texture_formats[] = {
73         _(B8G8R8X8_UNORM, A8R8G8B8,   S1,   S1,   S1,  ONE, X, Y, Z, W, 0, 0, 0, 0),
74         _(B8G8R8A8_UNORM, A8R8G8B8,   S1,   S1,   S1,   S1, X, Y, Z, W, 0, 0, 0, 0),
75         _(B5G5R5A1_UNORM, A1R5G5B5,   S1,   S1,   S1,   S1, X, Y, Z, W, 0, 0, 0, 0),
76         _(B4G4R4A4_UNORM, A4R4G4B4,   S1,   S1,   S1,   S1, X, Y, Z, W, 0, 0, 0, 0),
77         _(B5G6R5_UNORM  , R5G6B5  ,   S1,   S1,   S1,  ONE, X, Y, Z, W, 0, 0, 0, 0),
78         _(L8_UNORM      , L8      ,   S1,   S1,   S1,  ONE, X, X, X, X, 0, 0, 0, 0),
79         _(A8_UNORM      , L8      , ZERO, ZERO, ZERO,   S1, X, X, X, X, 0, 0, 0, 0),
80         _(R16_SNORM     , A16     , ZERO, ZERO,   S1,  ONE, X, X, X, Y, 1, 1, 1, 1),
81         _(I8_UNORM      , L8      ,   S1,   S1,   S1,   S1, X, X, X, X, 0, 0, 0, 0),
82         _(L8A8_UNORM    , A8L8    ,   S1,   S1,   S1,   S1, X, X, X, Y, 0, 0, 0, 0),
83         _(Z16_UNORM     , Z16     ,   S1,   S1,   S1,  ONE, X, X, X, X, 0, 0, 0, 0),
84         _(S8_USCALED_Z24_UNORM   , Z24     ,   S1,   S1,   S1,  ONE, X, X, X, X, 0, 0, 0, 0),
85         _(DXT1_RGB      , DXT1    ,   S1,   S1,   S1,  ONE, X, Y, Z, W, 0, 0, 0, 0),
86         _(DXT1_RGBA     , DXT1    ,   S1,   S1,   S1,   S1, X, Y, Z, W, 0, 0, 0, 0),
87         _(DXT3_RGBA     , DXT3    ,   S1,   S1,   S1,   S1, X, Y, Z, W, 0, 0, 0, 0),
88         _(DXT5_RGBA     , DXT5    ,   S1,   S1,   S1,   S1, X, Y, Z, W, 0, 0, 0, 0),
89         {},
90 };
91
92 static struct nv40_texture_format *
93 nv40_fragtex_format(uint pipe_format)
94 {
95         struct nv40_texture_format *tf = nv40_texture_formats;
96
97         while (tf->defined) {
98                 if (tf->pipe == pipe_format)
99                         return tf;
100                 tf++;
101         }
102
103         NOUVEAU_ERR("unknown texture format %s\n", util_format_name(pipe_format));
104         return NULL;
105 }
106
107
108 struct nouveau_stateobj *
109 nv40_fragtex_build(struct nvfx_context *nvfx, int unit)
110 {
111         struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit];
112         struct nvfx_miptree *nv40mt = (struct nvfx_miptree *)nvfx->fragment_sampler_views[unit]->texture;
113         struct nouveau_bo *bo = nouveau_bo(nv40mt->buffer);
114         struct pipe_texture *pt = &nv40mt->base;
115         struct nv40_texture_format *tf;
116         struct nouveau_stateobj *so;
117         uint32_t txf, txs, txp;
118         unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
119
120         tf = nv40_fragtex_format(pt->format);
121         if (!tf)
122                 assert(0);
123
124         txf  = ps->fmt;
125         txf |= tf->format | 0x8000;
126         txf |= ((pt->last_level + 1) << NV40TCL_TEX_FORMAT_MIPMAP_COUNT_SHIFT);
127
128         if (1) /* XXX */
129                 txf |= NV34TCL_TX_FORMAT_NO_BORDER;
130
131         switch (pt->target) {
132         case PIPE_TEXTURE_CUBE:
133                 txf |= NV34TCL_TX_FORMAT_CUBIC;
134                 /* fall-through */
135         case PIPE_TEXTURE_2D:
136                 txf |= NV34TCL_TX_FORMAT_DIMS_2D;
137                 break;
138         case PIPE_TEXTURE_3D:
139                 txf |= NV34TCL_TX_FORMAT_DIMS_3D;
140                 break;
141         case PIPE_TEXTURE_1D:
142                 txf |= NV34TCL_TX_FORMAT_DIMS_1D;
143                 break;
144         default:
145                 NOUVEAU_ERR("Unknown target %d\n", pt->target);
146                 return NULL;
147         }
148
149         if (!(pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) {
150                 txp = 0;
151         } else {
152                 txp  = nv40mt->level[0].pitch;
153                 txf |= NV40TCL_TEX_FORMAT_LINEAR;
154         }
155
156         txs = tf->swizzle;
157
158         so = so_new(2, 9, 2);
159         so_method(so, nvfx->screen->eng3d, NV34TCL_TX_OFFSET(unit), 8);
160         so_reloc (so, bo, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0);
161         so_reloc (so, bo, txf, tex_flags | NOUVEAU_BO_OR,
162                       NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1);
163         so_data  (so, ps->wrap);
164         so_data  (so, NV40TCL_TEX_ENABLE_ENABLE | ps->en);
165         so_data  (so, txs);
166         so_data  (so, ps->filt | tf->sign | 0x2000 /*voodoo*/);
167         so_data  (so, (pt->width0 << NV34TCL_TX_NPOT_SIZE_W_SHIFT) |
168                        pt->height0);
169         so_data  (so, ps->bcol);
170         so_method(so, nvfx->screen->eng3d, NV40TCL_TEX_SIZE1(unit), 1);
171         so_data  (so, (pt->depth0 << NV40TCL_TEX_SIZE1_DEPTH_SHIFT) | txp);
172
173         return so;
174 }