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