Merge remote branch 'origin/7.8'
[mesa.git] / src / gallium / drivers / i965 / brw_pipe_sampler.c
1
2 #include "util/u_memory.h"
3 #include "util/u_math.h"
4
5 #include "pipe/p_context.h"
6 #include "pipe/p_state.h"
7 #include "util/u_inlines.h"
8
9 #include "brw_context.h"
10 #include "brw_defines.h"
11
12
13
14 /* The brw (and related graphics cores) do not support GL_CLAMP. The
15 * Intel drivers for "other operating systems" implement GL_CLAMP as
16 * GL_CLAMP_TO_EDGE, so the same is done here.
17 */
18 static GLuint translate_wrap_mode( unsigned wrap )
19 {
20 switch( wrap ) {
21 case PIPE_TEX_WRAP_REPEAT:
22 return BRW_TEXCOORDMODE_WRAP;
23
24 case PIPE_TEX_WRAP_CLAMP:
25 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
26 return BRW_TEXCOORDMODE_CLAMP;
27
28 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
29 return BRW_TEXCOORDMODE_CLAMP_BORDER;
30
31 case PIPE_TEX_WRAP_MIRROR_REPEAT:
32 return BRW_TEXCOORDMODE_MIRROR;
33
34 case PIPE_TEX_WRAP_MIRROR_CLAMP:
35 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
36 case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
37 return BRW_TEXCOORDMODE_MIRROR_ONCE;
38
39 default:
40 return BRW_TEXCOORDMODE_WRAP;
41 }
42 }
43
44 static GLuint translate_img_filter( unsigned filter )
45 {
46 switch (filter) {
47 case PIPE_TEX_FILTER_NEAREST:
48 return BRW_MAPFILTER_NEAREST;
49 case PIPE_TEX_FILTER_LINEAR:
50 return BRW_MAPFILTER_LINEAR;
51 default:
52 assert(0);
53 return BRW_MAPFILTER_NEAREST;
54 }
55 }
56
57 static GLuint translate_mip_filter( unsigned filter )
58 {
59 switch (filter) {
60 case PIPE_TEX_MIPFILTER_NONE:
61 return BRW_MIPFILTER_NONE;
62 case PIPE_TEX_MIPFILTER_NEAREST:
63 return BRW_MIPFILTER_NEAREST;
64 case PIPE_TEX_MIPFILTER_LINEAR:
65 return BRW_MIPFILTER_LINEAR;
66 default:
67 assert(0);
68 return BRW_MIPFILTER_NONE;
69 }
70 }
71
72 /* XXX: not sure why there are special translations for the shadow tex
73 * compare functions. In particular ALWAYS is translated to NEVER.
74 * Is this a hardware issue? Does i965 really suffer from this?
75 */
76 static GLuint translate_shadow_compare_func( unsigned func )
77 {
78 switch (func) {
79 case PIPE_FUNC_NEVER:
80 return BRW_COMPAREFUNCTION_ALWAYS;
81 case PIPE_FUNC_LESS:
82 return BRW_COMPAREFUNCTION_LEQUAL;
83 case PIPE_FUNC_LEQUAL:
84 return BRW_COMPAREFUNCTION_LESS;
85 case PIPE_FUNC_GREATER:
86 return BRW_COMPAREFUNCTION_GEQUAL;
87 case PIPE_FUNC_GEQUAL:
88 return BRW_COMPAREFUNCTION_GREATER;
89 case PIPE_FUNC_NOTEQUAL:
90 return BRW_COMPAREFUNCTION_EQUAL;
91 case PIPE_FUNC_EQUAL:
92 return BRW_COMPAREFUNCTION_NOTEQUAL;
93 case PIPE_FUNC_ALWAYS:
94 return BRW_COMPAREFUNCTION_NEVER;
95 default:
96 assert(0);
97 return BRW_COMPAREFUNCTION_NEVER;
98 }
99 }
100
101
102
103
104 static void *
105 brw_create_sampler_state( struct pipe_context *pipe,
106 const struct pipe_sampler_state *template )
107 {
108 struct brw_sampler *sampler = CALLOC_STRUCT(brw_sampler);
109
110 sampler->ss0.min_filter = translate_img_filter( template->min_img_filter );
111 sampler->ss0.mag_filter = translate_img_filter( template->mag_img_filter );
112 sampler->ss0.mip_filter = translate_mip_filter( template->min_mip_filter );
113
114
115 /* XXX: anisotropy logic slightly changed:
116 */
117 if (template->max_anisotropy > 1) {
118 sampler->ss0.min_filter = BRW_MAPFILTER_ANISOTROPIC;
119 sampler->ss0.mag_filter = BRW_MAPFILTER_ANISOTROPIC;
120
121 sampler->ss3.max_aniso = MIN2((template->max_anisotropy - 2) / 2,
122 BRW_ANISORATIO_16);
123 }
124
125 sampler->ss1.r_wrap_mode = translate_wrap_mode(template->wrap_r);
126 sampler->ss1.s_wrap_mode = translate_wrap_mode(template->wrap_s);
127 sampler->ss1.t_wrap_mode = translate_wrap_mode(template->wrap_t);
128
129 /* Set LOD bias:
130 */
131 sampler->ss0.lod_bias =
132 util_signed_fixed(CLAMP(template->lod_bias, -16, 15), 6);
133
134
135 sampler->ss0.lod_preclamp = 1; /* OpenGL mode */
136 sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */
137
138 /* Set shadow function:
139 */
140 if (template->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {
141
142 /* Shadowing is "enabled" by emitting a particular sampler
143 * message (sample_c). So need to recompile WM program when
144 * shadow comparison is enabled on each/any texture unit.
145 */
146 sampler->ss0.shadow_function =
147 translate_shadow_compare_func(template->compare_func);
148 }
149
150 /* Set BaseMipLevel, MaxLOD, MinLOD:
151 */
152 sampler->ss0.base_level =
153 util_unsigned_fixed(0, 1);
154
155 sampler->ss1.max_lod =
156 util_unsigned_fixed(CLAMP(template->max_lod, 0, 13), 6);
157
158 sampler->ss1.min_lod =
159 util_unsigned_fixed(CLAMP(template->min_lod, 0, 13), 6);
160
161 return (void *)sampler;
162 }
163
164 static void brw_bind_sampler_state(struct pipe_context *pipe,
165 unsigned num, void **sampler)
166 {
167 struct brw_context *brw = brw_context(pipe);
168 int i;
169
170 for (i = 0; i < num; i++)
171 brw->curr.sampler[i] = sampler[i];
172
173 for (i = num; i < brw->curr.num_samplers; i++)
174 brw->curr.sampler[i] = NULL;
175
176 brw->curr.num_samplers = num;
177 brw->state.dirty.mesa |= PIPE_NEW_SAMPLERS;
178 }
179
180 static void brw_delete_sampler_state(struct pipe_context *pipe,
181 void *cso)
182 {
183 FREE(cso);
184 }
185
186 static void brw_set_fragment_sampler_views(struct pipe_context *pipe,
187 unsigned num,
188 struct pipe_sampler_view **views)
189 {
190 struct brw_context *brw = brw_context(pipe);
191 int i;
192
193 for (i = 0; i < num; i++)
194 pipe_sampler_view_reference(&brw->curr.fragment_sampler_views[i], views[i]);
195
196 for (i = num; i < brw->curr.num_fragment_sampler_views; i++)
197 pipe_sampler_view_reference(&brw->curr.fragment_sampler_views[i], NULL);
198
199 brw->curr.num_fragment_sampler_views = num;
200 brw->state.dirty.mesa |= PIPE_NEW_BOUND_TEXTURES;
201 }
202
203 static void brw_set_vertex_sampler_views(struct pipe_context *pipe,
204 unsigned num,
205 struct pipe_sampler_view **views)
206 {
207 }
208
209 static void brw_bind_vertex_sampler_state(struct pipe_context *pipe,
210 unsigned num, void **sampler)
211 {
212 }
213
214
215 static struct pipe_sampler_view *
216 brw_create_sampler_view(struct pipe_context *pipe,
217 struct pipe_texture *texture,
218 const struct pipe_sampler_view *templ)
219 {
220 struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);
221
222 if (view) {
223 *view = *templ;
224 view->reference.count = 1;
225 view->texture = NULL;
226 pipe_texture_reference(&view->texture, texture);
227 view->context = pipe;
228 }
229
230 return view;
231 }
232
233
234 static void
235 brw_sampler_view_destroy(struct pipe_context *pipe,
236 struct pipe_sampler_view *view)
237 {
238 pipe_texture_reference(&view->texture, NULL);
239 FREE(view);
240 }
241
242
243 void brw_pipe_sampler_init( struct brw_context *brw )
244 {
245 brw->base.create_sampler_state = brw_create_sampler_state;
246 brw->base.delete_sampler_state = brw_delete_sampler_state;
247
248 brw->base.set_fragment_sampler_views = brw_set_fragment_sampler_views;
249 brw->base.bind_fragment_sampler_states = brw_bind_sampler_state;
250
251 brw->base.set_vertex_sampler_views = brw_set_vertex_sampler_views;
252 brw->base.bind_vertex_sampler_states = brw_bind_vertex_sampler_state;
253
254 brw->base.create_sampler_view = brw_create_sampler_view;
255 brw->base.sampler_view_destroy = brw_sampler_view_destroy;
256 }
257 void brw_pipe_sampler_cleanup( struct brw_context *brw )
258 {
259 }