Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | /************************************************************************** |
2 | * |
||
3 | * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. |
||
4 | * All Rights Reserved. |
||
5 | * |
||
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
7 | * copy of this software and associated documentation files (the |
||
8 | * "Software"), to deal in the Software without restriction, including |
||
9 | * without limitation the rights to use, copy, modify, merge, publish, |
||
10 | * distribute, sub license, and/or sell copies of the Software, and to |
||
11 | * permit persons to whom the Software is furnished to do so, subject to |
||
12 | * the following conditions: |
||
13 | * |
||
14 | * The above copyright notice and this permission notice (including the |
||
15 | * next paragraph) shall be included in all copies or substantial portions |
||
16 | * of the Software. |
||
17 | * |
||
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
||
19 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||
20 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. |
||
21 | * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR |
||
22 | * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
||
23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
||
24 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||
25 | * |
||
26 | **************************************************************************/ |
||
27 | |||
28 | /* |
||
29 | * Authors: |
||
30 | * Keith Whitwell |
||
31 | * Brian Paul |
||
32 | */ |
||
33 | |||
34 | |||
35 | #include "main/macros.h" |
||
36 | #include "main/mtypes.h" |
||
37 | #include "main/glformats.h" |
||
38 | #include "main/samplerobj.h" |
||
39 | #include "main/texobj.h" |
||
40 | |||
41 | #include "st_context.h" |
||
42 | #include "st_cb_texture.h" |
||
43 | #include "st_format.h" |
||
44 | #include "st_atom.h" |
||
45 | #include "st_texture.h" |
||
46 | #include "pipe/p_context.h" |
||
47 | #include "pipe/p_defines.h" |
||
48 | |||
49 | #include "cso_cache/cso_context.h" |
||
50 | |||
51 | #include "util/u_format.h" |
||
52 | |||
53 | |||
54 | /** |
||
55 | * Convert GLenum texcoord wrap tokens to pipe tokens. |
||
56 | */ |
||
57 | static GLuint |
||
58 | gl_wrap_xlate(GLenum wrap) |
||
59 | { |
||
60 | switch (wrap) { |
||
61 | case GL_REPEAT: |
||
62 | return PIPE_TEX_WRAP_REPEAT; |
||
63 | case GL_CLAMP: |
||
64 | return PIPE_TEX_WRAP_CLAMP; |
||
65 | case GL_CLAMP_TO_EDGE: |
||
66 | return PIPE_TEX_WRAP_CLAMP_TO_EDGE; |
||
67 | case GL_CLAMP_TO_BORDER: |
||
68 | return PIPE_TEX_WRAP_CLAMP_TO_BORDER; |
||
69 | case GL_MIRRORED_REPEAT: |
||
70 | return PIPE_TEX_WRAP_MIRROR_REPEAT; |
||
71 | case GL_MIRROR_CLAMP_EXT: |
||
72 | return PIPE_TEX_WRAP_MIRROR_CLAMP; |
||
73 | case GL_MIRROR_CLAMP_TO_EDGE_EXT: |
||
74 | return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE; |
||
75 | case GL_MIRROR_CLAMP_TO_BORDER_EXT: |
||
76 | return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER; |
||
77 | default: |
||
78 | assert(0); |
||
79 | return 0; |
||
80 | } |
||
81 | } |
||
82 | |||
83 | |||
84 | static GLuint |
||
85 | gl_filter_to_mip_filter(GLenum filter) |
||
86 | { |
||
87 | switch (filter) { |
||
88 | case GL_NEAREST: |
||
89 | case GL_LINEAR: |
||
90 | return PIPE_TEX_MIPFILTER_NONE; |
||
91 | |||
92 | case GL_NEAREST_MIPMAP_NEAREST: |
||
93 | case GL_LINEAR_MIPMAP_NEAREST: |
||
94 | return PIPE_TEX_MIPFILTER_NEAREST; |
||
95 | |||
96 | case GL_NEAREST_MIPMAP_LINEAR: |
||
97 | case GL_LINEAR_MIPMAP_LINEAR: |
||
98 | return PIPE_TEX_MIPFILTER_LINEAR; |
||
99 | |||
100 | default: |
||
101 | assert(0); |
||
102 | return PIPE_TEX_MIPFILTER_NONE; |
||
103 | } |
||
104 | } |
||
105 | |||
106 | |||
107 | static GLuint |
||
108 | gl_filter_to_img_filter(GLenum filter) |
||
109 | { |
||
110 | switch (filter) { |
||
111 | case GL_NEAREST: |
||
112 | case GL_NEAREST_MIPMAP_NEAREST: |
||
113 | case GL_NEAREST_MIPMAP_LINEAR: |
||
114 | return PIPE_TEX_FILTER_NEAREST; |
||
115 | |||
116 | case GL_LINEAR: |
||
117 | case GL_LINEAR_MIPMAP_NEAREST: |
||
118 | case GL_LINEAR_MIPMAP_LINEAR: |
||
119 | return PIPE_TEX_FILTER_LINEAR; |
||
120 | |||
121 | default: |
||
122 | assert(0); |
||
123 | return PIPE_TEX_FILTER_NEAREST; |
||
124 | } |
||
125 | } |
||
126 | |||
127 | |||
128 | static void |
||
129 | convert_sampler(struct st_context *st, |
||
130 | struct pipe_sampler_state *sampler, |
||
131 | GLuint texUnit) |
||
132 | { |
||
133 | struct gl_texture_object *texobj; |
||
134 | struct gl_context *ctx = st->ctx; |
||
135 | struct gl_sampler_object *msamp; |
||
136 | |||
137 | texobj = ctx->Texture.Unit[texUnit]._Current; |
||
138 | if (!texobj) { |
||
139 | texobj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX); |
||
140 | } |
||
141 | |||
142 | msamp = _mesa_get_samplerobj(ctx, texUnit); |
||
143 | |||
144 | memset(sampler, 0, sizeof(*sampler)); |
||
145 | sampler->wrap_s = gl_wrap_xlate(msamp->WrapS); |
||
146 | sampler->wrap_t = gl_wrap_xlate(msamp->WrapT); |
||
147 | sampler->wrap_r = gl_wrap_xlate(msamp->WrapR); |
||
148 | |||
149 | sampler->min_img_filter = gl_filter_to_img_filter(msamp->MinFilter); |
||
150 | sampler->min_mip_filter = gl_filter_to_mip_filter(msamp->MinFilter); |
||
151 | sampler->mag_img_filter = gl_filter_to_img_filter(msamp->MagFilter); |
||
152 | |||
153 | if (texobj->Target != GL_TEXTURE_RECTANGLE_ARB) |
||
154 | sampler->normalized_coords = 1; |
||
155 | |||
156 | sampler->lod_bias = ctx->Texture.Unit[texUnit].LodBias + msamp->LodBias; |
||
157 | |||
158 | sampler->min_lod = CLAMP(msamp->MinLod, |
||
159 | 0.0f, |
||
160 | (GLfloat) texobj->MaxLevel - texobj->BaseLevel); |
||
161 | sampler->max_lod = MIN2((GLfloat) texobj->MaxLevel - texobj->BaseLevel, |
||
162 | msamp->MaxLod); |
||
163 | if (sampler->max_lod < sampler->min_lod) { |
||
164 | /* The GL spec doesn't seem to specify what to do in this case. |
||
165 | * Swap the values. |
||
166 | */ |
||
167 | float tmp = sampler->max_lod; |
||
168 | sampler->max_lod = sampler->min_lod; |
||
169 | sampler->min_lod = tmp; |
||
170 | assert(sampler->min_lod <= sampler->max_lod); |
||
171 | } |
||
172 | |||
173 | if (msamp->BorderColor.ui[0] || |
||
174 | msamp->BorderColor.ui[1] || |
||
175 | msamp->BorderColor.ui[2] || |
||
176 | msamp->BorderColor.ui[3]) { |
||
177 | struct st_texture_object *stobj = st_texture_object(texobj); |
||
178 | struct gl_texture_image *teximg; |
||
179 | GLboolean is_integer = GL_FALSE; |
||
180 | union pipe_color_union border_color; |
||
181 | |||
182 | teximg = texobj->Image[0][texobj->BaseLevel]; |
||
183 | |||
184 | if (teximg) { |
||
185 | is_integer = _mesa_is_enum_format_integer(teximg->InternalFormat); |
||
186 | } |
||
187 | |||
188 | if (st->apply_texture_swizzle_to_border_color && stobj->sampler_view) { |
||
189 | const unsigned char swz[4] = |
||
190 | { |
||
191 | stobj->sampler_view->swizzle_r, |
||
192 | stobj->sampler_view->swizzle_g, |
||
193 | stobj->sampler_view->swizzle_b, |
||
194 | stobj->sampler_view->swizzle_a, |
||
195 | }; |
||
196 | |||
197 | st_translate_color(&msamp->BorderColor, |
||
198 | &border_color, |
||
199 | teximg ? teximg->_BaseFormat : GL_RGBA, is_integer); |
||
200 | |||
201 | util_format_apply_color_swizzle(&sampler->border_color, |
||
202 | &border_color, swz, is_integer); |
||
203 | } else { |
||
204 | st_translate_color(&msamp->BorderColor, |
||
205 | &sampler->border_color, |
||
206 | teximg ? teximg->_BaseFormat : GL_RGBA, is_integer); |
||
207 | } |
||
208 | } |
||
209 | |||
210 | sampler->max_anisotropy = (msamp->MaxAnisotropy == 1.0 ? |
||
211 | |||
212 | |||
213 | /* only care about ARB_shadow, not SGI shadow */ |
||
214 | if (msamp->CompareMode == GL_COMPARE_R_TO_TEXTURE) { |
||
215 | sampler->compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE; |
||
216 | sampler->compare_func |
||
217 | = st_compare_func_to_pipe(msamp->CompareFunc); |
||
218 | } |
||
219 | |||
220 | sampler->seamless_cube_map = |
||
221 | ctx->Texture.CubeMapSeamless || msamp->CubeMapSeamless; |
||
222 | } |
||
223 | |||
224 | |||
225 | /** |
||
226 | * Update the gallium driver's sampler state for fragment, vertex or |
||
227 | * geometry shader stage. |
||
228 | */ |
||
229 | static void |
||
230 | update_shader_samplers(struct st_context *st, |
||
231 | unsigned shader_stage, |
||
232 | const struct gl_program *prog, |
||
233 | unsigned max_units, |
||
234 | struct pipe_sampler_state *samplers, |
||
235 | unsigned *num_samplers) |
||
236 | { |
||
237 | GLuint unit; |
||
238 | GLbitfield samplers_used; |
||
239 | const GLuint old_max = *num_samplers; |
||
240 | |||
241 | samplers_used = prog->SamplersUsed; |
||
242 | |||
243 | if (*num_samplers == 0 && samplers_used == 0x0) |
||
244 | return; |
||
245 | |||
246 | *num_samplers = 0; |
||
247 | |||
248 | /* loop over sampler units (aka tex image units) */ |
||
249 | for (unit = 0; unit < max_units; unit++, samplers_used >>= 1) { |
||
250 | struct pipe_sampler_state *sampler = samplers + unit; |
||
251 | |||
252 | if (samplers_used & 1) { |
||
253 | const GLuint texUnit = prog->SamplerUnits[unit]; |
||
254 | |||
255 | convert_sampler(st, sampler, texUnit); |
||
256 | |||
257 | *num_samplers = unit + 1; |
||
258 | |||
259 | cso_single_sampler(st->cso_context, shader_stage, unit, sampler); |
||
260 | } |
||
261 | else if (samplers_used != 0 || unit < old_max) { |
||
262 | cso_single_sampler(st->cso_context, shader_stage, unit, NULL); |
||
263 | } |
||
264 | else { |
||
265 | /* if we've reset all the old samplers and we have no more new ones */ |
||
266 | break; |
||
267 | } |
||
268 | } |
||
269 | |||
270 | cso_single_sampler_done(st->cso_context, shader_stage); |
||
271 | } |
||
272 | |||
273 | |||
274 | static void |
||
275 | update_samplers(struct st_context *st) |
||
276 | { |
||
277 | const struct gl_context *ctx = st->ctx; |
||
278 | |||
279 | update_shader_samplers(st, |
||
280 | PIPE_SHADER_FRAGMENT, |
||
281 | &ctx->FragmentProgram._Current->Base, |
||
282 | ctx->Const.FragmentProgram.MaxTextureImageUnits, |
||
283 | st->state.samplers[PIPE_SHADER_FRAGMENT], |
||
284 | &st->state.num_samplers[PIPE_SHADER_FRAGMENT]); |
||
285 | |||
286 | update_shader_samplers(st, |
||
287 | PIPE_SHADER_VERTEX, |
||
288 | &ctx->VertexProgram._Current->Base, |
||
289 | ctx->Const.VertexProgram.MaxTextureImageUnits, |
||
290 | st->state.samplers[PIPE_SHADER_VERTEX], |
||
291 | &st->state.num_samplers[PIPE_SHADER_VERTEX]); |
||
292 | |||
293 | if (ctx->GeometryProgram._Current) { |
||
294 | update_shader_samplers(st, |
||
295 | PIPE_SHADER_GEOMETRY, |
||
296 | &ctx->GeometryProgram._Current->Base, |
||
297 | ctx->Const.GeometryProgram.MaxTextureImageUnits, |
||
298 | st->state.samplers[PIPE_SHADER_GEOMETRY], |
||
299 | &st->state.num_samplers[PIPE_SHADER_GEOMETRY]); |
||
300 | } |
||
301 | } |
||
302 | |||
303 | |||
304 | const struct st_tracked_state st_update_sampler = { |
||
305 | "st_update_sampler", /* name */ |
||
306 | { /* dirty */ |
||
307 | _NEW_TEXTURE, /* mesa */ |
||
308 | 0, /* st */ |
||
309 | }, |
||
310 | update_samplers /* update */ |
||
311 | };>>=>> |