Merge remote branch 'origin/master' into nv50-compiler
[mesa.git] / src / gallium / drivers / nvfx / nv30_fragtex.c
1 #include "util/u_format.h"
2
3 #include "nvfx_context.h"
4 #include "nvfx_tex.h"
5 #include "nvfx_resource.h"
6
7 void
8 nv30_sampler_state_init(struct pipe_context *pipe,
9 struct nvfx_sampler_state *ps,
10 const struct pipe_sampler_state *cso)
11 {
12 float limit;
13
14 if (cso->max_anisotropy >= 2)
15 {
16 if (cso->max_anisotropy >= 8)
17 ps->en |= NV34TCL_TX_ENABLE_ANISO_8X;
18 else if (cso->max_anisotropy >= 4)
19 ps->en |= NV34TCL_TX_ENABLE_ANISO_4X;
20 else if (cso->max_anisotropy >= 2)
21 ps->en |= NV34TCL_TX_ENABLE_ANISO_2X;
22 }
23
24 limit = CLAMP(cso->lod_bias, -16.0, 15.0 + (255.0 / 256.0));
25 ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff;
26
27 ps->max_lod = (int)CLAMP(cso->max_lod, 0.0, 15.0);
28 ps->min_lod = (int)CLAMP(cso->min_lod, 0.0, 15.0);
29
30 ps->en |= NV34TCL_TX_ENABLE_ENABLE;
31 }
32
33 void
34 nv30_sampler_view_init(struct pipe_context *pipe,
35 struct nvfx_sampler_view *sv)
36 {
37 struct pipe_resource* pt = sv->base.texture;
38 struct nvfx_texture_format *tf = &nvfx_texture_formats[sv->base.format];
39 unsigned txf;
40 unsigned level = pt->target == PIPE_TEXTURE_CUBE ? 0 : sv->base.first_level;
41
42 assert(tf->fmt[0] >= 0);
43
44 txf = sv->u.init_fmt;
45 txf |= (level != sv->base.last_level ? NV34TCL_TX_FORMAT_MIPMAP : 0);
46 txf |= util_logbase2(u_minify(pt->width0, level)) << NV34TCL_TX_FORMAT_BASE_SIZE_U_SHIFT;
47 txf |= util_logbase2(u_minify(pt->height0, level)) << NV34TCL_TX_FORMAT_BASE_SIZE_V_SHIFT;
48 txf |= util_logbase2(u_minify(pt->depth0, level)) << NV34TCL_TX_FORMAT_BASE_SIZE_W_SHIFT;
49 txf |= 0x10000;
50
51 sv->u.nv30.fmt[0] = tf->fmt[0] | txf;
52 sv->u.nv30.fmt[1] = tf->fmt[1] | txf;
53 sv->u.nv30.fmt[2] = tf->fmt[2] | txf;
54 sv->u.nv30.fmt[3] = tf->fmt[3] | txf;
55
56 sv->swizzle |= (nvfx_subresource_pitch(pt, 0) << NV34TCL_TX_SWIZZLE_RECT_PITCH_SHIFT);
57
58 if(pt->height0 <= 1 || util_format_is_compressed(sv->base.format))
59 sv->u.nv30.rect = -1;
60 else
61 sv->u.nv30.rect = !!(pt->flags & NVFX_RESOURCE_FLAG_LINEAR);
62
63 sv->lod_offset = sv->base.first_level - level;
64 sv->max_lod_limit = sv->base.last_level - level;
65 }
66
67 void
68 nv30_fragtex_set(struct nvfx_context *nvfx, int unit)
69 {
70 struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit];
71 struct nvfx_sampler_view* sv = (struct nvfx_sampler_view*)nvfx->fragment_sampler_views[unit];
72 struct nouveau_bo *bo = ((struct nvfx_miptree *)sv->base.texture)->base.bo;
73 struct nouveau_channel* chan = nvfx->screen->base.channel;
74 unsigned txf;
75 unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
76 unsigned use_rect;
77 unsigned max_lod = MIN2(ps->max_lod + sv->lod_offset, sv->max_lod_limit);
78 unsigned min_lod = MIN2(ps->min_lod + sv->lod_offset, max_lod) ;
79
80 if(sv->u.nv30.rect < 0)
81 {
82 /* in the case of compressed or 1D textures, we can get away with this,
83 * since the layout is the same
84 */
85 use_rect = ps->fmt;
86 }
87 else
88 {
89 static boolean warned = FALSE;
90 if( !!ps->fmt != sv->u.nv30.rect && !warned) {
91 warned = TRUE;
92 fprintf(stderr,
93 "Unimplemented: coordinate normalization mismatch. Possible reasons:\n"
94 "1. ARB_texture_non_power_of_two is being used despite the fact it isn't supported\n"
95 "2. The state tracker is not using the appropriate coordinate normalization\n"
96 "3. The state tracker is not supported\n");
97 }
98
99 use_rect = sv->u.nv30.rect;
100 }
101
102 txf = sv->u.nv30.fmt[ps->compare + (use_rect ? 2 : 0)];
103
104 MARK_RING(chan, 9, 2);
105 OUT_RING(chan, RING_3D(NV34TCL_TX_OFFSET(unit), 8));
106 OUT_RELOC(chan, bo, sv->offset, tex_flags | NOUVEAU_BO_LOW, 0, 0);
107 OUT_RELOC(chan, bo, txf,
108 tex_flags | NOUVEAU_BO_OR,
109 NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1);
110 OUT_RING(chan, (ps->wrap & sv->wrap_mask) | sv->wrap);
111 OUT_RING(chan, ps->en | (min_lod << NV34TCL_TX_ENABLE_MIPMAP_MIN_LOD_SHIFT) | (max_lod << NV34TCL_TX_ENABLE_MIPMAP_MAX_LOD_SHIFT));
112 OUT_RING(chan, sv->swizzle);
113 OUT_RING(chan, ps->filt | sv->filt);
114 OUT_RING(chan, sv->npot_size);
115 OUT_RING(chan, ps->bcol);
116
117 nvfx->hw_txf[unit] = txf;
118 nvfx->hw_samplers |= (1 << unit);
119 }