Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1901 | 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 "program/prog_instruction.h" |
||
37 | |||
38 | #include "st_context.h" |
||
39 | #include "st_atom.h" |
||
40 | #include "st_texture.h" |
||
41 | #include "st_format.h" |
||
42 | #include "st_cb_texture.h" |
||
43 | #include "pipe/p_context.h" |
||
44 | #include "util/u_format.h" |
||
45 | #include "util/u_inlines.h" |
||
46 | #include "cso_cache/cso_context.h" |
||
47 | |||
48 | /** |
||
49 | * Combine depth texture mode with "swizzle" so that depth mode swizzling |
||
50 | * takes place before texture swizzling, and return the resulting swizzle. |
||
51 | * If the format is not a depth format, return "swizzle" unchanged. |
||
52 | * |
||
53 | * \param format PIPE_FORMAT_*. |
||
54 | * \param swizzle Texture swizzle, a bitmask computed using MAKE_SWIZZLE4. |
||
55 | * \param depthmode One of GL_LUMINANCE, GL_INTENSITY, GL_ALPHA, GL_RED. |
||
56 | */ |
||
57 | static GLuint apply_depthmode(enum pipe_format format, |
||
58 | GLuint swizzle, GLenum depthmode) |
||
59 | { |
||
60 | const struct util_format_description *desc = |
||
61 | util_format_description(format); |
||
62 | unsigned char swiz[4]; |
||
63 | unsigned i; |
||
64 | |||
65 | if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS || |
||
66 | desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_NONE) { |
||
67 | /* Not a depth format. */ |
||
68 | return swizzle; |
||
69 | } |
||
70 | |||
71 | for (i = 0; i < 4; i++) |
||
72 | swiz[i] = GET_SWZ(swizzle, i); |
||
73 | |||
74 | switch (depthmode) { |
||
75 | case GL_LUMINANCE: |
||
76 | /* Rewrite reads from W to ONE, and reads from XYZ to XXX. */ |
||
77 | for (i = 0; i < 4; i++) |
||
78 | if (swiz[i] == SWIZZLE_W) |
||
79 | swiz[i] = SWIZZLE_ONE; |
||
80 | else if (swiz[i] < SWIZZLE_W) |
||
81 | swiz[i] = SWIZZLE_X; |
||
82 | break; |
||
83 | |||
84 | case GL_INTENSITY: |
||
85 | /* Rewrite reads from XYZW to XXXX. */ |
||
86 | for (i = 0; i < 4; i++) |
||
87 | if (swiz[i] <= SWIZZLE_W) |
||
88 | swiz[i] = SWIZZLE_X; |
||
89 | break; |
||
90 | |||
91 | case GL_ALPHA: |
||
92 | /* Rewrite reads from W to X, and reads from XYZ to 000. */ |
||
93 | for (i = 0; i < 4; i++) |
||
94 | if (swiz[i] == SWIZZLE_W) |
||
95 | swiz[i] = SWIZZLE_X; |
||
96 | else if (swiz[i] < SWIZZLE_W) |
||
97 | swiz[i] = SWIZZLE_ZERO; |
||
98 | break; |
||
99 | case GL_RED: |
||
100 | /* Rewrite reads W to 1, XYZ to X00 */ |
||
101 | for (i = 0; i < 4; i++) |
||
102 | if (swiz[i] == SWIZZLE_W) |
||
103 | swiz[i] = SWIZZLE_ONE; |
||
104 | else if (swiz[i] == SWIZZLE_Y || swiz[i] == SWIZZLE_Z) |
||
105 | swiz[i] = SWIZZLE_ZERO; |
||
106 | break; |
||
107 | } |
||
108 | |||
109 | return MAKE_SWIZZLE4(swiz[0], swiz[1], swiz[2], swiz[3]); |
||
110 | } |
||
111 | |||
112 | /** |
||
113 | * Return TRUE if the swizzling described by "swizzle" and |
||
114 | * "depthmode" (for depth textures only) is different from the swizzling |
||
115 | * set in the given sampler view. |
||
116 | * |
||
117 | * \param sv A sampler view. |
||
118 | * \param swizzle Texture swizzle, a bitmask computed using MAKE_SWIZZLE4. |
||
119 | * \param depthmode One of GL_LUMINANCE, GL_INTENSITY, GL_ALPHA. |
||
120 | */ |
||
121 | static boolean check_sampler_swizzle(struct pipe_sampler_view *sv, |
||
122 | GLuint swizzle, GLenum depthmode) |
||
123 | { |
||
124 | swizzle = apply_depthmode(sv->texture->format, swizzle, depthmode); |
||
125 | |||
126 | if ((sv->swizzle_r != GET_SWZ(swizzle, 0)) || |
||
127 | (sv->swizzle_g != GET_SWZ(swizzle, 1)) || |
||
128 | (sv->swizzle_b != GET_SWZ(swizzle, 2)) || |
||
129 | (sv->swizzle_a != GET_SWZ(swizzle, 3))) |
||
130 | return true; |
||
131 | return false; |
||
132 | } |
||
133 | |||
134 | static INLINE struct pipe_sampler_view * |
||
135 | st_create_texture_sampler_view_from_stobj(struct pipe_context *pipe, |
||
136 | struct st_texture_object *stObj, |
||
137 | enum pipe_format format) |
||
138 | |||
139 | { |
||
140 | struct pipe_sampler_view templ; |
||
141 | GLuint swizzle = apply_depthmode(stObj->pt->format, |
||
142 | stObj->base._Swizzle, |
||
143 | stObj->base.DepthMode); |
||
144 | |||
145 | u_sampler_view_default_template(&templ, |
||
146 | stObj->pt, |
||
147 | format); |
||
148 | |||
149 | if (swizzle != SWIZZLE_NOOP) { |
||
150 | templ.swizzle_r = GET_SWZ(swizzle, 0); |
||
151 | templ.swizzle_g = GET_SWZ(swizzle, 1); |
||
152 | templ.swizzle_b = GET_SWZ(swizzle, 2); |
||
153 | templ.swizzle_a = GET_SWZ(swizzle, 3); |
||
154 | } |
||
155 | |||
156 | return pipe->create_sampler_view(pipe, stObj->pt, &templ); |
||
157 | } |
||
158 | |||
159 | |||
160 | static INLINE struct pipe_sampler_view * |
||
161 | st_get_texture_sampler_view_from_stobj(struct st_texture_object *stObj, |
||
162 | struct pipe_context *pipe, |
||
163 | enum pipe_format format) |
||
164 | |||
165 | { |
||
166 | if (!stObj || !stObj->pt) { |
||
167 | return NULL; |
||
168 | } |
||
169 | |||
170 | if (!stObj->sampler_view) { |
||
171 | stObj->sampler_view = st_create_texture_sampler_view_from_stobj(pipe, stObj, format); |
||
172 | } |
||
173 | |||
174 | return stObj->sampler_view; |
||
175 | } |
||
176 | |||
177 | static void |
||
178 | update_textures(struct st_context *st) |
||
179 | { |
||
180 | struct pipe_context *pipe = st->pipe; |
||
181 | struct gl_vertex_program *vprog = st->ctx->VertexProgram._Current; |
||
182 | struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current; |
||
183 | const GLbitfield samplersUsed = (vprog->Base.SamplersUsed | |
||
184 | fprog->Base.SamplersUsed); |
||
185 | GLuint su; |
||
186 | |||
187 | st->state.num_textures = 0; |
||
188 | |||
189 | /* loop over sampler units (aka tex image units) */ |
||
190 | for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) { |
||
191 | struct pipe_sampler_view *sampler_view = NULL; |
||
192 | enum pipe_format st_view_format; |
||
193 | if (samplersUsed & (1 << su)) { |
||
194 | struct gl_texture_object *texObj; |
||
195 | struct st_texture_object *stObj; |
||
196 | GLboolean retval; |
||
197 | GLuint texUnit; |
||
198 | |||
199 | if (fprog->Base.SamplersUsed & (1 << su)) |
||
200 | texUnit = fprog->Base.SamplerUnits[su]; |
||
201 | else |
||
202 | texUnit = vprog->Base.SamplerUnits[su]; |
||
203 | |||
204 | texObj = st->ctx->Texture.Unit[texUnit]._Current; |
||
205 | |||
206 | if (!texObj) { |
||
207 | texObj = st_get_default_texture(st); |
||
208 | } |
||
209 | stObj = st_texture_object(texObj); |
||
210 | |||
211 | retval = st_finalize_texture(st->ctx, st->pipe, texObj); |
||
212 | if (!retval) { |
||
213 | /* out of mem */ |
||
214 | continue; |
||
215 | } |
||
216 | |||
217 | st_view_format = stObj->pt->format; |
||
218 | { |
||
219 | struct st_texture_image *firstImage; |
||
220 | enum pipe_format firstImageFormat; |
||
221 | firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]); |
||
222 | |||
223 | firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat); |
||
224 | if (firstImageFormat != stObj->pt->format) |
||
225 | st_view_format = firstImageFormat; |
||
226 | |||
227 | } |
||
228 | st->state.num_textures = su + 1; |
||
229 | |||
230 | /* if sampler view has changed dereference it */ |
||
231 | if (stObj->sampler_view) |
||
232 | if (check_sampler_swizzle(stObj->sampler_view, |
||
233 | stObj->base._Swizzle, |
||
234 | stObj->base.DepthMode) || |
||
235 | (st_view_format != stObj->sampler_view->format)) |
||
236 | pipe_sampler_view_reference(&stObj->sampler_view, NULL); |
||
237 | |||
238 | sampler_view = st_get_texture_sampler_view_from_stobj(stObj, pipe, st_view_format); |
||
239 | } |
||
240 | pipe_sampler_view_reference(&st->state.sampler_views[su], sampler_view); |
||
241 | } |
||
242 | |||
243 | cso_set_fragment_sampler_views(st->cso_context, |
||
244 | st->state.num_textures, |
||
245 | st->state.sampler_views); |
||
246 | if (st->ctx->Const.MaxVertexTextureImageUnits > 0) { |
||
247 | cso_set_vertex_sampler_views(st->cso_context, |
||
248 | MIN2(st->state.num_textures, |
||
249 | st->ctx->Const.MaxVertexTextureImageUnits), |
||
250 | st->state.sampler_views); |
||
251 | } |
||
252 | } |
||
253 | |||
254 | |||
255 | const struct st_tracked_state st_update_texture = { |
||
256 | "st_update_texture", /* name */ |
||
257 | { /* dirty */ |
||
258 | _NEW_TEXTURE, /* mesa */ |
||
259 | ST_NEW_FRAGMENT_PROGRAM, /* st */ |
||
260 | }, |
||
261 | update_textures /* update */ |
||
262 | }; |
||
263 | |||
264 | |||
265 | |||
266 | |||
267 | static void |
||
268 | finalize_textures(struct st_context *st) |
||
269 | { |
||
270 | struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current; |
||
271 | const GLboolean prev_missing_textures = st->missing_textures; |
||
272 | GLuint su; |
||
273 | |||
274 | st->missing_textures = GL_FALSE; |
||
275 | |||
276 | for (su = 0; su < st->ctx->Const.MaxTextureCoordUnits; su++) { |
||
277 | if (fprog->Base.SamplersUsed & (1 << su)) { |
||
278 | const GLuint texUnit = fprog->Base.SamplerUnits[su]; |
||
279 | struct gl_texture_object *texObj |
||
280 | = st->ctx->Texture.Unit[texUnit]._Current; |
||
281 | |||
282 | if (texObj) { |
||
283 | GLboolean retval; |
||
284 | |||
285 | retval = st_finalize_texture(st->ctx, st->pipe, texObj); |
||
286 | if (!retval) { |
||
287 | /* out of mem */ |
||
288 | st->missing_textures = GL_TRUE; |
||
289 | continue; |
||
290 | } |
||
291 | } |
||
292 | } |
||
293 | } |
||
294 | |||
295 | if (prev_missing_textures != st->missing_textures) |
||
296 | st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; |
||
297 | } |
||
298 | |||
299 | |||
300 | |||
301 | const struct st_tracked_state st_finalize_textures = { |
||
302 | "st_finalize_textures", /* name */ |
||
303 | { /* dirty */ |
||
304 | _NEW_TEXTURE, /* mesa */ |
||
305 | 0, /* st */ |
||
306 | }, |
||
307 | finalize_textures /* update */ |
||
308 | };><>>><>><>>>>>=>>>>> |