Rev 4358 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | /* |
2 | Copyright (C) Intel Corp. 2006. All Rights Reserved. |
||
3 | Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to |
||
4 | develop this 3D driver. |
||
5 | |||
6 | Permission is hereby granted, free of charge, to any person obtaining |
||
7 | a 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, sublicense, 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 |
||
16 | portions of the Software. |
||
17 | |||
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||
19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||
20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
||
21 | IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE |
||
22 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
||
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
||
24 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||
25 | |||
26 | **********************************************************************/ |
||
27 | /* |
||
28 | * Authors: |
||
29 | * Keith Whitwell |
||
30 | */ |
||
31 | |||
32 | #include "brw_context.h" |
||
33 | #include "brw_wm.h" |
||
34 | #include "brw_state.h" |
||
35 | #include "main/formats.h" |
||
36 | #include "main/fbobject.h" |
||
37 | #include "main/samplerobj.h" |
||
38 | #include "program/prog_parameter.h" |
||
39 | |||
40 | #include "glsl/ralloc.h" |
||
41 | |||
42 | /** |
||
43 | * Return a bitfield where bit n is set if barycentric interpolation mode n |
||
44 | * (see enum brw_wm_barycentric_interp_mode) is needed by the fragment shader. |
||
45 | */ |
||
46 | static unsigned |
||
47 | brw_compute_barycentric_interp_modes(struct brw_context *brw, |
||
48 | bool shade_model_flat, |
||
49 | const struct gl_fragment_program *fprog) |
||
50 | { |
||
51 | unsigned barycentric_interp_modes = 0; |
||
52 | int attr; |
||
53 | |||
54 | /* Loop through all fragment shader inputs to figure out what interpolation |
||
55 | * modes are in use, and set the appropriate bits in |
||
56 | * barycentric_interp_modes. |
||
57 | */ |
||
58 | for (attr = 0; attr < VARYING_SLOT_MAX; ++attr) { |
||
59 | enum glsl_interp_qualifier interp_qualifier = |
||
60 | fprog->InterpQualifier[attr]; |
||
61 | bool is_centroid = fprog->IsCentroid & BITFIELD64_BIT(attr); |
||
62 | bool is_gl_Color = attr == VARYING_SLOT_COL0 || attr == VARYING_SLOT_COL1; |
||
63 | |||
64 | /* Ignore unused inputs. */ |
||
65 | if (!(fprog->Base.InputsRead & BITFIELD64_BIT(attr))) |
||
66 | continue; |
||
67 | |||
68 | /* Ignore WPOS and FACE, because they don't require interpolation. */ |
||
69 | if (attr == VARYING_SLOT_POS || attr == VARYING_SLOT_FACE) |
||
70 | continue; |
||
71 | |||
72 | /* Determine the set (or sets) of barycentric coordinates needed to |
||
73 | * interpolate this variable. Note that when |
||
74 | * brw->needs_unlit_centroid_workaround is set, centroid interpolation |
||
75 | * uses PIXEL interpolation for unlit pixels and CENTROID interpolation |
||
76 | * for lit pixels, so we need both sets of barycentric coordinates. |
||
77 | */ |
||
78 | if (interp_qualifier == INTERP_QUALIFIER_NOPERSPECTIVE) { |
||
79 | if (is_centroid) { |
||
80 | barycentric_interp_modes |= |
||
81 | 1 << BRW_WM_NONPERSPECTIVE_CENTROID_BARYCENTRIC; |
||
82 | } |
||
83 | if (!is_centroid || brw->needs_unlit_centroid_workaround) { |
||
84 | barycentric_interp_modes |= |
||
85 | 1 << BRW_WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC; |
||
86 | } |
||
87 | } else if (interp_qualifier == INTERP_QUALIFIER_SMOOTH || |
||
88 | (!(shade_model_flat && is_gl_Color) && |
||
89 | interp_qualifier == INTERP_QUALIFIER_NONE)) { |
||
90 | if (is_centroid) { |
||
91 | barycentric_interp_modes |= |
||
92 | 1 << BRW_WM_PERSPECTIVE_CENTROID_BARYCENTRIC; |
||
93 | } |
||
94 | if (!is_centroid || brw->needs_unlit_centroid_workaround) { |
||
95 | barycentric_interp_modes |= |
||
96 | 1 << BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC; |
||
97 | } |
||
98 | } |
||
99 | } |
||
100 | |||
101 | return barycentric_interp_modes; |
||
102 | } |
||
103 | |||
104 | bool |
||
105 | brw_wm_prog_data_compare(const void *in_a, const void *in_b, |
||
106 | int aux_size, const void *in_key) |
||
107 | { |
||
108 | const struct brw_wm_prog_data *a = in_a; |
||
109 | const struct brw_wm_prog_data *b = in_b; |
||
110 | |||
111 | /* Compare all the struct up to the pointers. */ |
||
112 | if (memcmp(a, b, offsetof(struct brw_wm_prog_data, param))) |
||
113 | return false; |
||
114 | |||
115 | if (memcmp(a->param, b->param, a->nr_params * sizeof(void *))) |
||
116 | return false; |
||
117 | |||
118 | if (memcmp(a->pull_param, b->pull_param, a->nr_pull_params * sizeof(void *))) |
||
119 | return false; |
||
120 | |||
121 | return true; |
||
122 | } |
||
123 | |||
124 | void |
||
125 | brw_wm_prog_data_free(const void *in_prog_data) |
||
126 | { |
||
127 | const struct brw_wm_prog_data *prog_data = in_prog_data; |
||
128 | |||
129 | ralloc_free((void *)prog_data->param); |
||
130 | ralloc_free((void *)prog_data->pull_param); |
||
131 | } |
||
132 | |||
133 | /** |
||
134 | * All Mesa program -> GPU code generation goes through this function. |
||
135 | * Depending on the instructions used (i.e. flow control instructions) |
||
136 | * we'll use one of two code generators. |
||
137 | */ |
||
138 | bool do_wm_prog(struct brw_context *brw, |
||
139 | struct gl_shader_program *prog, |
||
140 | struct brw_fragment_program *fp, |
||
141 | struct brw_wm_prog_key *key) |
||
142 | { |
||
143 | struct brw_wm_compile *c; |
||
144 | const GLuint *program; |
||
145 | struct gl_shader *fs = NULL; |
||
146 | GLuint program_size; |
||
147 | |||
148 | if (prog) |
||
149 | fs = prog->_LinkedShaders[MESA_SHADER_FRAGMENT]; |
||
150 | |||
151 | c = rzalloc(NULL, struct brw_wm_compile); |
||
152 | |||
153 | /* Allocate the references to the uniforms that will end up in the |
||
154 | * prog_data associated with the compiled program, and which will be freed |
||
155 | * by the state cache. |
||
156 | */ |
||
157 | int param_count; |
||
158 | if (fs) { |
||
159 | param_count = fs->num_uniform_components; |
||
160 | } else { |
||
161 | param_count = fp->program.Base.Parameters->NumParameters * 4; |
||
162 | } |
||
163 | /* The backend also sometimes adds params for texture size. */ |
||
164 | param_count += 2 * BRW_MAX_TEX_UNIT; |
||
165 | c->prog_data.param = rzalloc_array(NULL, const float *, param_count); |
||
166 | c->prog_data.pull_param = rzalloc_array(NULL, const float *, param_count); |
||
167 | |||
168 | memcpy(&c->key, key, sizeof(*key)); |
||
169 | |||
170 | c->prog_data.barycentric_interp_modes = |
||
171 | brw_compute_barycentric_interp_modes(brw, c->key.flat_shade, |
||
172 | &fp->program); |
||
173 | |||
174 | program = brw_wm_fs_emit(brw, c, &fp->program, prog, &program_size); |
||
175 | if (program == NULL) |
||
176 | return false; |
||
177 | |||
178 | /* Scratch space is used for register spilling */ |
||
179 | if (c->last_scratch) { |
||
180 | perf_debug("Fragment shader triggered register spilling. " |
||
181 | "Try reducing the number of live scalar values to " |
||
182 | "improve performance.\n"); |
||
183 | |||
184 | c->prog_data.total_scratch = brw_get_scratch_size(c->last_scratch); |
||
185 | |||
186 | brw_get_scratch_bo(brw, &brw->wm.scratch_bo, |
||
187 | c->prog_data.total_scratch * brw->max_wm_threads); |
||
188 | } |
||
189 | |||
190 | if (unlikely(INTEL_DEBUG & DEBUG_WM)) |
||
191 | fprintf(stderr, "\n"); |
||
192 | |||
193 | brw_upload_cache(&brw->cache, BRW_WM_PROG, |
||
194 | &c->key, sizeof(c->key), |
||
195 | program, program_size, |
||
196 | &c->prog_data, sizeof(c->prog_data), |
||
197 | &brw->wm.prog_offset, &brw->wm.prog_data); |
||
198 | |||
199 | ralloc_free(c); |
||
200 | |||
201 | return true; |
||
202 | } |
||
203 | |||
204 | static bool |
||
205 | key_debug(struct brw_context *brw, const char *name, int a, int b) |
||
206 | { |
||
207 | if (a != b) { |
||
208 | perf_debug(" %s %d->%d\n", name, a, b); |
||
209 | return true; |
||
210 | } else { |
||
211 | return false; |
||
212 | } |
||
213 | } |
||
214 | |||
215 | bool |
||
216 | brw_debug_recompile_sampler_key(struct brw_context *brw, |
||
217 | const struct brw_sampler_prog_key_data *old_key, |
||
218 | const struct brw_sampler_prog_key_data *key) |
||
219 | { |
||
220 | bool found = false; |
||
221 | |||
222 | for (unsigned int i = 0; i < MAX_SAMPLERS; i++) { |
||
223 | found |= key_debug(brw, "EXT_texture_swizzle or DEPTH_TEXTURE_MODE", |
||
224 | old_key->swizzles[i], key->swizzles[i]); |
||
225 | } |
||
226 | found |= key_debug(brw, "GL_CLAMP enabled on any texture unit's 1st coordinate", |
||
227 | old_key->gl_clamp_mask[0], key->gl_clamp_mask[0]); |
||
228 | found |= key_debug(brw, "GL_CLAMP enabled on any texture unit's 2nd coordinate", |
||
229 | old_key->gl_clamp_mask[1], key->gl_clamp_mask[1]); |
||
230 | found |= key_debug(brw, "GL_CLAMP enabled on any texture unit's 3rd coordinate", |
||
231 | old_key->gl_clamp_mask[2], key->gl_clamp_mask[2]); |
||
232 | found |= key_debug(brw, "GL_MESA_ycbcr texturing\n", |
||
233 | old_key->yuvtex_mask, key->yuvtex_mask); |
||
234 | found |= key_debug(brw, "GL_MESA_ycbcr UV swapping\n", |
||
235 | old_key->yuvtex_swap_mask, key->yuvtex_swap_mask); |
||
236 | |||
237 | return found; |
||
238 | } |
||
239 | |||
240 | void |
||
241 | brw_wm_debug_recompile(struct brw_context *brw, |
||
242 | struct gl_shader_program *prog, |
||
243 | const struct brw_wm_prog_key *key) |
||
244 | { |
||
245 | struct brw_cache_item *c = NULL; |
||
246 | const struct brw_wm_prog_key *old_key = NULL; |
||
247 | bool found = false; |
||
248 | |||
249 | perf_debug("Recompiling fragment shader for program %d\n", prog->Name); |
||
250 | |||
251 | for (unsigned int i = 0; i < brw->cache.size; i++) { |
||
252 | for (c = brw->cache.items[i]; c; c = c->next) { |
||
253 | if (c->cache_id == BRW_WM_PROG) { |
||
254 | old_key = c->key; |
||
255 | |||
256 | if (old_key->program_string_id == key->program_string_id) |
||
257 | break; |
||
258 | } |
||
259 | } |
||
260 | if (c) |
||
261 | break; |
||
262 | } |
||
263 | |||
264 | if (!c) { |
||
265 | perf_debug(" Didn't find previous compile in the shader cache for debug\n"); |
||
266 | return; |
||
267 | } |
||
268 | |||
269 | found |= key_debug(brw, "alphatest, computed depth, depth test, or " |
||
270 | "depth write", |
||
271 | old_key->iz_lookup, key->iz_lookup); |
||
272 | found |= key_debug(brw, "depth statistics", |
||
273 | old_key->stats_wm, key->stats_wm); |
||
274 | found |= key_debug(brw, "flat shading", |
||
275 | old_key->flat_shade, key->flat_shade); |
||
276 | found |= key_debug(brw, "number of color buffers", |
||
277 | old_key->nr_color_regions, key->nr_color_regions); |
||
278 | found |= key_debug(brw, "MRT alpha test or alpha-to-coverage", |
||
279 | old_key->replicate_alpha, key->replicate_alpha); |
||
280 | found |= key_debug(brw, "rendering to FBO", |
||
281 | old_key->render_to_fbo, key->render_to_fbo); |
||
282 | found |= key_debug(brw, "fragment color clamping", |
||
283 | old_key->clamp_fragment_color, key->clamp_fragment_color); |
||
284 | found |= key_debug(brw, "line smoothing", |
||
285 | old_key->line_aa, key->line_aa); |
||
286 | found |= key_debug(brw, "renderbuffer height", |
||
287 | old_key->drawable_height, key->drawable_height); |
||
288 | found |= key_debug(brw, "input slots valid", |
||
289 | old_key->input_slots_valid, key->input_slots_valid); |
||
4401 | Serge | 290 | found |= key_debug(brw, "mrt alpha test function", |
291 | old_key->alpha_test_func, key->alpha_test_func); |
||
292 | found |= key_debug(brw, "mrt alpha test reference value", |
||
293 | old_key->alpha_test_ref, key->alpha_test_ref); |
||
4358 | Serge | 294 | |
295 | found |= brw_debug_recompile_sampler_key(brw, &old_key->tex, &key->tex); |
||
296 | |||
297 | if (!found) { |
||
298 | perf_debug(" Something else\n"); |
||
299 | } |
||
300 | } |
||
301 | |||
302 | void |
||
303 | brw_populate_sampler_prog_key_data(struct gl_context *ctx, |
||
304 | const struct gl_program *prog, |
||
305 | struct brw_sampler_prog_key_data *key) |
||
306 | { |
||
307 | struct brw_context *brw = brw_context(ctx); |
||
308 | |||
309 | for (int s = 0; s < MAX_SAMPLERS; s++) { |
||
310 | key->swizzles[s] = SWIZZLE_NOOP; |
||
311 | |||
312 | if (!(prog->SamplersUsed & (1 << s))) |
||
313 | continue; |
||
314 | |||
315 | int unit_id = prog->SamplerUnits[s]; |
||
316 | const struct gl_texture_unit *unit = &ctx->Texture.Unit[unit_id]; |
||
317 | |||
318 | if (unit->_ReallyEnabled && unit->_Current->Target != GL_TEXTURE_BUFFER) { |
||
319 | const struct gl_texture_object *t = unit->_Current; |
||
320 | const struct gl_texture_image *img = t->Image[0][t->BaseLevel]; |
||
321 | struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit_id); |
||
322 | |||
323 | const bool alpha_depth = t->DepthMode == GL_ALPHA && |
||
324 | (img->_BaseFormat == GL_DEPTH_COMPONENT || |
||
325 | img->_BaseFormat == GL_DEPTH_STENCIL); |
||
326 | |||
327 | /* Haswell handles texture swizzling as surface format overrides |
||
328 | * (except for GL_ALPHA); all other platforms need MOVs in the shader. |
||
329 | */ |
||
330 | if (!brw->is_haswell || alpha_depth) |
||
331 | key->swizzles[s] = brw_get_texture_swizzle(ctx, t); |
||
332 | |||
333 | if (img->InternalFormat == GL_YCBCR_MESA) { |
||
334 | key->yuvtex_mask |= 1 << s; |
||
335 | if (img->TexFormat == MESA_FORMAT_YCBCR) |
||
336 | key->yuvtex_swap_mask |= 1 << s; |
||
337 | } |
||
338 | |||
339 | if (sampler->MinFilter != GL_NEAREST && |
||
340 | sampler->MagFilter != GL_NEAREST) { |
||
341 | if (sampler->WrapS == GL_CLAMP) |
||
342 | key->gl_clamp_mask[0] |= 1 << s; |
||
343 | if (sampler->WrapT == GL_CLAMP) |
||
344 | key->gl_clamp_mask[1] |= 1 << s; |
||
345 | if (sampler->WrapR == GL_CLAMP) |
||
346 | key->gl_clamp_mask[2] |= 1 << s; |
||
347 | } |
||
348 | } |
||
349 | } |
||
350 | } |
||
351 | |||
352 | static void brw_wm_populate_key( struct brw_context *brw, |
||
353 | struct brw_wm_prog_key *key ) |
||
354 | { |
||
355 | struct gl_context *ctx = &brw->ctx; |
||
356 | /* BRW_NEW_FRAGMENT_PROGRAM */ |
||
357 | const struct brw_fragment_program *fp = |
||
358 | (struct brw_fragment_program *)brw->fragment_program; |
||
359 | const struct gl_program *prog = (struct gl_program *) brw->fragment_program; |
||
360 | GLuint lookup = 0; |
||
361 | GLuint line_aa; |
||
362 | bool program_uses_dfdy = fp->program.UsesDFdy; |
||
363 | |||
364 | memset(key, 0, sizeof(*key)); |
||
365 | |||
366 | /* Build the index for table lookup |
||
367 | */ |
||
368 | if (brw->gen < 6) { |
||
369 | /* _NEW_COLOR */ |
||
370 | if (fp->program.UsesKill || ctx->Color.AlphaEnabled) |
||
371 | lookup |= IZ_PS_KILL_ALPHATEST_BIT; |
||
372 | |||
373 | if (fp->program.Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) |
||
374 | lookup |= IZ_PS_COMPUTES_DEPTH_BIT; |
||
375 | |||
376 | /* _NEW_DEPTH */ |
||
377 | if (ctx->Depth.Test) |
||
378 | lookup |= IZ_DEPTH_TEST_ENABLE_BIT; |
||
379 | |||
380 | if (ctx->Depth.Test && ctx->Depth.Mask) /* ?? */ |
||
381 | lookup |= IZ_DEPTH_WRITE_ENABLE_BIT; |
||
382 | |||
383 | /* _NEW_STENCIL | _NEW_BUFFERS */ |
||
384 | if (ctx->Stencil._Enabled) { |
||
385 | lookup |= IZ_STENCIL_TEST_ENABLE_BIT; |
||
386 | |||
387 | if (ctx->Stencil.WriteMask[0] || |
||
388 | ctx->Stencil.WriteMask[ctx->Stencil._BackFace]) |
||
389 | lookup |= IZ_STENCIL_WRITE_ENABLE_BIT; |
||
390 | } |
||
391 | key->iz_lookup = lookup; |
||
392 | } |
||
393 | |||
394 | line_aa = AA_NEVER; |
||
395 | |||
396 | /* _NEW_LINE, _NEW_POLYGON, BRW_NEW_REDUCED_PRIMITIVE */ |
||
397 | if (ctx->Line.SmoothFlag) { |
||
398 | if (brw->reduced_primitive == GL_LINES) { |
||
399 | line_aa = AA_ALWAYS; |
||
400 | } |
||
401 | else if (brw->reduced_primitive == GL_TRIANGLES) { |
||
402 | if (ctx->Polygon.FrontMode == GL_LINE) { |
||
403 | line_aa = AA_SOMETIMES; |
||
404 | |||
405 | if (ctx->Polygon.BackMode == GL_LINE || |
||
406 | (ctx->Polygon.CullFlag && |
||
407 | ctx->Polygon.CullFaceMode == GL_BACK)) |
||
408 | line_aa = AA_ALWAYS; |
||
409 | } |
||
410 | else if (ctx->Polygon.BackMode == GL_LINE) { |
||
411 | line_aa = AA_SOMETIMES; |
||
412 | |||
413 | if ((ctx->Polygon.CullFlag && |
||
414 | ctx->Polygon.CullFaceMode == GL_FRONT)) |
||
415 | line_aa = AA_ALWAYS; |
||
416 | } |
||
417 | } |
||
418 | } |
||
419 | |||
420 | key->line_aa = line_aa; |
||
421 | |||
422 | if (brw->gen < 6) |
||
423 | key->stats_wm = brw->stats_wm; |
||
424 | |||
425 | /* _NEW_LIGHT */ |
||
426 | key->flat_shade = (ctx->Light.ShadeModel == GL_FLAT); |
||
427 | |||
428 | /* _NEW_FRAG_CLAMP | _NEW_BUFFERS */ |
||
429 | key->clamp_fragment_color = ctx->Color._ClampFragmentColor; |
||
430 | |||
431 | /* _NEW_TEXTURE */ |
||
432 | brw_populate_sampler_prog_key_data(ctx, prog, &key->tex); |
||
433 | |||
434 | /* _NEW_BUFFERS */ |
||
435 | /* |
||
436 | * Include the draw buffer origin and height so that we can calculate |
||
437 | * fragment position values relative to the bottom left of the drawable, |
||
438 | * from the incoming screen origin relative position we get as part of our |
||
439 | * payload. |
||
440 | * |
||
441 | * This is only needed for the WM_WPOSXY opcode when the fragment program |
||
442 | * uses the gl_FragCoord input. |
||
443 | * |
||
444 | * We could avoid recompiling by including this as a constant referenced by |
||
445 | * our program, but if we were to do that it would also be nice to handle |
||
446 | * getting that constant updated at batchbuffer submit time (when we |
||
447 | * hold the lock and know where the buffer really is) rather than at emit |
||
448 | * time when we don't hold the lock and are just guessing. We could also |
||
449 | * just avoid using this as key data if the program doesn't use |
||
450 | * fragment.position. |
||
451 | * |
||
452 | * For DRI2 the origin_x/y will always be (0,0) but we still need the |
||
453 | * drawable height in order to invert the Y axis. |
||
454 | */ |
||
455 | if (fp->program.Base.InputsRead & VARYING_BIT_POS) { |
||
456 | key->drawable_height = ctx->DrawBuffer->Height; |
||
457 | } |
||
458 | |||
459 | if ((fp->program.Base.InputsRead & VARYING_BIT_POS) || program_uses_dfdy) { |
||
460 | key->render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); |
||
461 | } |
||
462 | |||
463 | /* _NEW_BUFFERS */ |
||
464 | key->nr_color_regions = ctx->DrawBuffer->_NumColorDrawBuffers; |
||
465 | |||
466 | /* _NEW_MULTISAMPLE, _NEW_COLOR, _NEW_BUFFERS */ |
||
467 | key->replicate_alpha = ctx->DrawBuffer->_NumColorDrawBuffers > 1 && |
||
468 | (ctx->Multisample.SampleAlphaToCoverage || ctx->Color.AlphaEnabled); |
||
469 | |||
470 | /* BRW_NEW_VUE_MAP_GEOM_OUT */ |
||
471 | if (brw->gen < 6) |
||
472 | key->input_slots_valid = brw->vue_map_geom_out.slots_valid; |
||
473 | |||
4401 | Serge | 474 | |
475 | /* _NEW_COLOR | _NEW_BUFFERS */ |
||
476 | /* Pre-gen6, the hardware alpha test always used each render |
||
477 | * target's alpha to do alpha test, as opposed to render target 0's alpha |
||
478 | * like GL requires. Fix that by building the alpha test into the |
||
479 | * shader, and we'll skip enabling the fixed function alpha test. |
||
480 | */ |
||
481 | if (brw->gen < 6 && ctx->DrawBuffer->_NumColorDrawBuffers > 1 && ctx->Color.AlphaEnabled) { |
||
482 | key->alpha_test_func = ctx->Color.AlphaFunc; |
||
483 | key->alpha_test_ref = ctx->Color.AlphaRef; |
||
484 | } |
||
485 | |||
4358 | Serge | 486 | /* The unique fragment program ID */ |
487 | key->program_string_id = fp->id; |
||
488 | } |
||
489 | |||
490 | |||
491 | static void |
||
492 | brw_upload_wm_prog(struct brw_context *brw) |
||
493 | { |
||
494 | struct gl_context *ctx = &brw->ctx; |
||
495 | struct brw_wm_prog_key key; |
||
496 | struct brw_fragment_program *fp = (struct brw_fragment_program *) |
||
497 | brw->fragment_program; |
||
498 | |||
499 | brw_wm_populate_key(brw, &key); |
||
500 | |||
501 | if (!brw_search_cache(&brw->cache, BRW_WM_PROG, |
||
502 | &key, sizeof(key), |
||
503 | &brw->wm.prog_offset, &brw->wm.prog_data)) { |
||
504 | bool success = do_wm_prog(brw, ctx->Shader._CurrentFragmentProgram, fp, |
||
505 | &key); |
||
506 | (void) success; |
||
507 | assert(success); |
||
508 | } |
||
509 | } |
||
510 | |||
511 | |||
512 | const struct brw_tracked_state brw_wm_prog = { |
||
513 | .dirty = { |
||
514 | .mesa = (_NEW_COLOR | |
||
515 | _NEW_DEPTH | |
||
516 | _NEW_STENCIL | |
||
517 | _NEW_POLYGON | |
||
518 | _NEW_LINE | |
||
519 | _NEW_LIGHT | |
||
520 | _NEW_FRAG_CLAMP | |
||
521 | _NEW_BUFFERS | |
||
522 | _NEW_TEXTURE | |
||
523 | _NEW_MULTISAMPLE), |
||
524 | .brw = (BRW_NEW_FRAGMENT_PROGRAM | |
||
525 | BRW_NEW_REDUCED_PRIMITIVE | |
||
526 | BRW_NEW_VUE_MAP_GEOM_OUT | |
||
527 | BRW_NEW_STATS_WM) |
||
528 | }, |
||
529 | .emit = brw_upload_wm_prog |
||
530 | };>>>>><>><>><>><>><>><>>>>><>><>><>><>> |
||
531 |