OSDN Git Service

i965/fs: Exit the compile if spilling would overwrite in-use MRFs.
[android-x86/external-mesa.git] / src / mesa / drivers / dri / i965 / brw_wm_sampler_state.c
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 <keith@tungstengraphics.com>
30   */
31                    
32
33 #include "brw_context.h"
34 #include "brw_state.h"
35 #include "brw_defines.h"
36 #include "intel_mipmap_tree.h"
37
38 #include "main/macros.h"
39 #include "main/samplerobj.h"
40
41
42 /* Samplers aren't strictly wm state from the hardware's perspective,
43  * but that is the only situation in which we use them in this driver.
44  */
45
46
47
48 uint32_t
49 translate_wrap_mode(GLenum wrap, bool using_nearest)
50 {
51    switch( wrap ) {
52    case GL_REPEAT: 
53       return BRW_TEXCOORDMODE_WRAP;
54    case GL_CLAMP:
55       /* GL_CLAMP is the weird mode where coordinates are clamped to
56        * [0.0, 1.0], so linear filtering of coordinates outside of
57        * [0.0, 1.0] give you half edge texel value and half border
58        * color.  The fragment shader will clamp the coordinates, and
59        * we set clamp_border here, which gets the result desired.  We
60        * just use clamp(_to_edge) for nearest, because for nearest
61        * clamping to 1.0 gives border color instead of the desired
62        * edge texels.
63        */
64       if (using_nearest)
65          return BRW_TEXCOORDMODE_CLAMP;
66       else
67          return BRW_TEXCOORDMODE_CLAMP_BORDER;
68    case GL_CLAMP_TO_EDGE: 
69       return BRW_TEXCOORDMODE_CLAMP;
70    case GL_CLAMP_TO_BORDER: 
71       return BRW_TEXCOORDMODE_CLAMP_BORDER;
72    case GL_MIRRORED_REPEAT: 
73       return BRW_TEXCOORDMODE_MIRROR;
74    case GL_MIRROR_CLAMP_TO_EDGE:
75       return BRW_TEXCOORDMODE_MIRROR_ONCE;
76    default: 
77       return BRW_TEXCOORDMODE_WRAP;
78    }
79 }
80
81 /**
82  * Upload SAMPLER_BORDER_COLOR_STATE.
83  */
84 void
85 upload_default_color(struct brw_context *brw,
86                      struct gl_sampler_object *sampler,
87                      int unit,
88                      uint32_t *sdc_offset)
89 {
90    struct gl_context *ctx = &brw->ctx;
91    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
92    struct gl_texture_object *texObj = texUnit->_Current;
93    struct gl_texture_image *firstImage = texObj->Image[0][texObj->BaseLevel];
94    float color[4];
95
96    switch (firstImage->_BaseFormat) {
97    case GL_DEPTH_COMPONENT:
98       /* GL specs that border color for depth textures is taken from the
99        * R channel, while the hardware uses A.  Spam R into all the
100        * channels for safety.
101        */
102       color[0] = sampler->BorderColor.f[0];
103       color[1] = sampler->BorderColor.f[0];
104       color[2] = sampler->BorderColor.f[0];
105       color[3] = sampler->BorderColor.f[0];
106       break;
107    case GL_ALPHA:
108       color[0] = 0.0;
109       color[1] = 0.0;
110       color[2] = 0.0;
111       color[3] = sampler->BorderColor.f[3];
112       break;
113    case GL_INTENSITY:
114       color[0] = sampler->BorderColor.f[0];
115       color[1] = sampler->BorderColor.f[0];
116       color[2] = sampler->BorderColor.f[0];
117       color[3] = sampler->BorderColor.f[0];
118       break;
119    case GL_LUMINANCE:
120       color[0] = sampler->BorderColor.f[0];
121       color[1] = sampler->BorderColor.f[0];
122       color[2] = sampler->BorderColor.f[0];
123       color[3] = 1.0;
124       break;
125    case GL_LUMINANCE_ALPHA:
126       color[0] = sampler->BorderColor.f[0];
127       color[1] = sampler->BorderColor.f[0];
128       color[2] = sampler->BorderColor.f[0];
129       color[3] = sampler->BorderColor.f[3];
130       break;
131    default:
132       color[0] = sampler->BorderColor.f[0];
133       color[1] = sampler->BorderColor.f[1];
134       color[2] = sampler->BorderColor.f[2];
135       color[3] = sampler->BorderColor.f[3];
136       break;
137    }
138
139    /* In some cases we use an RGBA surface format for GL RGB textures,
140     * where we've initialized the A channel to 1.0.  We also have to set
141     * the border color alpha to 1.0 in that case.
142     */
143    if (firstImage->_BaseFormat == GL_RGB)
144       color[3] = 1.0;
145
146    if (brw->gen == 5 || brw->gen == 6) {
147       struct gen5_sampler_default_color *sdc;
148
149       sdc = brw_state_batch(brw, AUB_TRACE_SAMPLER_DEFAULT_COLOR,
150                             sizeof(*sdc), 32, sdc_offset);
151
152       memset(sdc, 0, sizeof(*sdc));
153
154       UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[0], color[0]);
155       UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[1], color[1]);
156       UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[2], color[2]);
157       UNCLAMPED_FLOAT_TO_UBYTE(sdc->ub[3], color[3]);
158
159       UNCLAMPED_FLOAT_TO_USHORT(sdc->us[0], color[0]);
160       UNCLAMPED_FLOAT_TO_USHORT(sdc->us[1], color[1]);
161       UNCLAMPED_FLOAT_TO_USHORT(sdc->us[2], color[2]);
162       UNCLAMPED_FLOAT_TO_USHORT(sdc->us[3], color[3]);
163
164       UNCLAMPED_FLOAT_TO_SHORT(sdc->s[0], color[0]);
165       UNCLAMPED_FLOAT_TO_SHORT(sdc->s[1], color[1]);
166       UNCLAMPED_FLOAT_TO_SHORT(sdc->s[2], color[2]);
167       UNCLAMPED_FLOAT_TO_SHORT(sdc->s[3], color[3]);
168
169       sdc->hf[0] = _mesa_float_to_half(color[0]);
170       sdc->hf[1] = _mesa_float_to_half(color[1]);
171       sdc->hf[2] = _mesa_float_to_half(color[2]);
172       sdc->hf[3] = _mesa_float_to_half(color[3]);
173
174       sdc->b[0] = sdc->s[0] >> 8;
175       sdc->b[1] = sdc->s[1] >> 8;
176       sdc->b[2] = sdc->s[2] >> 8;
177       sdc->b[3] = sdc->s[3] >> 8;
178
179       sdc->f[0] = color[0];
180       sdc->f[1] = color[1];
181       sdc->f[2] = color[2];
182       sdc->f[3] = color[3];
183    } else {
184       struct brw_sampler_default_color *sdc;
185
186       sdc = brw_state_batch(brw, AUB_TRACE_SAMPLER_DEFAULT_COLOR,
187                             sizeof(*sdc), 32, sdc_offset);
188
189       COPY_4V(sdc->color, color);
190    }
191 }
192
193 /**
194  * Sets the sampler state for a single unit based off of the sampler key
195  * entry.
196  */
197 static void brw_update_sampler_state(struct brw_context *brw,
198                                      int unit,
199                                      int ss_index,
200                                      struct brw_sampler_state *sampler,
201                                      uint32_t sampler_state_table_offset,
202                                      uint32_t *sdc_offset)
203 {
204    struct gl_context *ctx = &brw->ctx;
205    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
206    struct gl_texture_object *texObj = texUnit->_Current;
207    struct gl_sampler_object *gl_sampler = _mesa_get_samplerobj(ctx, unit);
208    bool using_nearest = false;
209
210    /* These don't use samplers at all. */
211    if (texObj->Target == GL_TEXTURE_BUFFER)
212       return;
213
214    switch (gl_sampler->MinFilter) {
215    case GL_NEAREST:
216       sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
217       sampler->ss0.mip_filter = BRW_MIPFILTER_NONE;
218       using_nearest = true;
219       break;
220    case GL_LINEAR:
221       sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
222       sampler->ss0.mip_filter = BRW_MIPFILTER_NONE;
223       break;
224    case GL_NEAREST_MIPMAP_NEAREST:
225       sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
226       sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST;
227       break;
228    case GL_LINEAR_MIPMAP_NEAREST:
229       sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
230       sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST;
231       break;
232    case GL_NEAREST_MIPMAP_LINEAR:
233       sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
234       sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR;
235       break;
236    case GL_LINEAR_MIPMAP_LINEAR:
237       sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
238       sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR;
239       break;
240    default:
241       break;
242    }
243
244    /* Set Anisotropy: 
245     */
246    if (gl_sampler->MaxAnisotropy > 1.0) {
247       sampler->ss0.min_filter = BRW_MAPFILTER_ANISOTROPIC; 
248       sampler->ss0.mag_filter = BRW_MAPFILTER_ANISOTROPIC;
249
250       if (gl_sampler->MaxAnisotropy > 2.0) {
251          sampler->ss3.max_aniso = MIN2((gl_sampler->MaxAnisotropy - 2) / 2,
252                                        BRW_ANISORATIO_16);
253       }
254    }
255    else {
256       switch (gl_sampler->MagFilter) {
257       case GL_NEAREST:
258          sampler->ss0.mag_filter = BRW_MAPFILTER_NEAREST;
259          using_nearest = true;
260          break;
261       case GL_LINEAR:
262          sampler->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
263          break;
264       default:
265          break;
266       }  
267    }
268
269    sampler->ss1.r_wrap_mode = translate_wrap_mode(gl_sampler->WrapR,
270                                                   using_nearest);
271    sampler->ss1.s_wrap_mode = translate_wrap_mode(gl_sampler->WrapS,
272                                                   using_nearest);
273    sampler->ss1.t_wrap_mode = translate_wrap_mode(gl_sampler->WrapT,
274                                                   using_nearest);
275
276    if (brw->gen >= 6 &&
277        sampler->ss0.min_filter != sampler->ss0.mag_filter)
278         sampler->ss0.min_mag_neq = 1;
279
280    /* Cube-maps on 965 and later must use the same wrap mode for all 3
281     * coordinate dimensions.  Futher, only CUBE and CLAMP are valid.
282     */
283    if (texObj->Target == GL_TEXTURE_CUBE_MAP ||
284        texObj->Target == GL_TEXTURE_CUBE_MAP_ARRAY) {
285       if ((ctx->Texture.CubeMapSeamless || gl_sampler->CubeMapSeamless) &&
286           (gl_sampler->MinFilter != GL_NEAREST ||
287            gl_sampler->MagFilter != GL_NEAREST)) {
288          sampler->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CUBE;
289          sampler->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CUBE;
290          sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CUBE;
291       } else {
292          sampler->ss1.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
293          sampler->ss1.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
294          sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
295       }
296    } else if (texObj->Target == GL_TEXTURE_1D) {
297       /* There's a bug in 1D texture sampling - it actually pays
298        * attention to the wrap_t value, though it should not.
299        * Override the wrap_t value here to GL_REPEAT to keep
300        * any nonexistent border pixels from floating in.
301        */
302       sampler->ss1.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
303    }
304
305
306    /* Set shadow function: 
307     */
308    if (gl_sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) {
309       /* Shadowing is "enabled" by emitting a particular sampler
310        * message (sample_c).  So need to recompile WM program when
311        * shadow comparison is enabled on each/any texture unit.
312        */
313       sampler->ss0.shadow_function =
314          intel_translate_shadow_compare_func(gl_sampler->CompareFunc);
315    }
316
317    /* Set LOD bias: 
318     */
319    sampler->ss0.lod_bias = S_FIXED(CLAMP(texUnit->LodBias +
320                                          gl_sampler->LodBias, -16, 15), 6);
321
322    sampler->ss0.lod_preclamp = 1; /* OpenGL mode */
323    sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */
324
325    sampler->ss0.base_level = U_FIXED(0, 1);
326
327    sampler->ss1.max_lod = U_FIXED(CLAMP(gl_sampler->MaxLod, 0, 13), 6);
328    sampler->ss1.min_lod = U_FIXED(CLAMP(gl_sampler->MinLod, 0, 13), 6);
329
330    /* On Gen6+, the sampler can handle non-normalized texture
331     * rectangle coordinates natively
332     */
333    if (brw->gen >= 6 && texObj->Target == GL_TEXTURE_RECTANGLE) {
334       sampler->ss3.non_normalized_coord = 1;
335    }
336
337    upload_default_color(brw, gl_sampler, unit, sdc_offset);
338
339    if (brw->gen >= 6) {
340       sampler->ss2.default_color_pointer = *sdc_offset >> 5;
341    } else {
342       /* reloc */
343       sampler->ss2.default_color_pointer = (brw->batch.bo->offset +
344                                             *sdc_offset) >> 5;
345
346       drm_intel_bo_emit_reloc(brw->batch.bo,
347                               sampler_state_table_offset +
348                               ss_index * sizeof(struct brw_sampler_state) +
349                               offsetof(struct brw_sampler_state, ss2),
350                               brw->batch.bo, *sdc_offset,
351                               I915_GEM_DOMAIN_SAMPLER, 0);
352    }
353
354    if (sampler->ss0.min_filter != BRW_MAPFILTER_NEAREST)
355       sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MIN |
356                                     BRW_ADDRESS_ROUNDING_ENABLE_V_MIN |
357                                     BRW_ADDRESS_ROUNDING_ENABLE_R_MIN;
358    if (sampler->ss0.mag_filter != BRW_MAPFILTER_NEAREST)
359       sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MAG |
360                                     BRW_ADDRESS_ROUNDING_ENABLE_V_MAG |
361                                     BRW_ADDRESS_ROUNDING_ENABLE_R_MAG;
362 }
363
364
365 static void
366 brw_upload_sampler_state_table(struct brw_context *brw,
367                                struct gl_program *prog,
368                                uint32_t sampler_count,
369                                uint32_t *sst_offset,
370                                uint32_t *sdc_offset)
371 {
372    struct gl_context *ctx = &brw->ctx;
373    struct brw_sampler_state *samplers;
374
375    GLbitfield SamplersUsed = prog->SamplersUsed;
376
377    if (sampler_count == 0)
378       return;
379
380    samplers = brw_state_batch(brw, AUB_TRACE_SAMPLER_STATE,
381                               sampler_count * sizeof(*samplers),
382                               32, sst_offset);
383    memset(samplers, 0, sampler_count * sizeof(*samplers));
384
385    for (unsigned s = 0; s < sampler_count; s++) {
386       if (SamplersUsed & (1 << s)) {
387          const unsigned unit = prog->SamplerUnits[s];
388          if (ctx->Texture.Unit[unit]._ReallyEnabled)
389             brw_update_sampler_state(brw, unit, s, &samplers[s],
390                                      *sst_offset, &sdc_offset[s]);
391       }
392    }
393
394    brw->state.dirty.cache |= CACHE_NEW_SAMPLER;
395 }
396
397 static void
398 brw_upload_fs_samplers(struct brw_context *brw)
399 {
400    /* BRW_NEW_FRAGMENT_PROGRAM */
401    struct gl_program *fs = (struct gl_program *) brw->fragment_program;
402    brw->vtbl.upload_sampler_state_table(brw, fs,
403                                         brw->wm.base.sampler_count,
404                                         &brw->wm.base.sampler_offset,
405                                         brw->wm.base.sdc_offset);
406 }
407
408 const struct brw_tracked_state brw_fs_samplers = {
409    .dirty = {
410       .mesa = _NEW_TEXTURE,
411       .brw = BRW_NEW_BATCH |
412              BRW_NEW_FRAGMENT_PROGRAM,
413       .cache = 0
414    },
415    .emit = brw_upload_fs_samplers,
416 };
417
418 static void
419 brw_upload_vs_samplers(struct brw_context *brw)
420 {
421    struct brw_stage_state *stage_state = &brw->vs.base;
422
423    /* BRW_NEW_VERTEX_PROGRAM */
424    struct gl_program *vs = (struct gl_program *) brw->vertex_program;
425    brw->vtbl.upload_sampler_state_table(brw, vs,
426                                         stage_state->sampler_count,
427                                         &stage_state->sampler_offset,
428                                         stage_state->sdc_offset);
429 }
430
431
432 const struct brw_tracked_state brw_vs_samplers = {
433    .dirty = {
434       .mesa = _NEW_TEXTURE,
435       .brw = BRW_NEW_BATCH |
436              BRW_NEW_VERTEX_PROGRAM,
437       .cache = 0
438    },
439    .emit = brw_upload_vs_samplers,
440 };
441
442
443 static void
444 brw_upload_gs_samplers(struct brw_context *brw)
445 {
446    struct brw_stage_state *stage_state = &brw->gs.base;
447
448    /* BRW_NEW_GEOMETRY_PROGRAM */
449    struct gl_program *gs = (struct gl_program *) brw->geometry_program;
450    if (!gs)
451       return;
452
453    brw->vtbl.upload_sampler_state_table(brw, gs,
454                                         stage_state->sampler_count,
455                                         &stage_state->sampler_offset,
456                                         stage_state->sdc_offset);
457 }
458
459
460 const struct brw_tracked_state brw_gs_samplers = {
461    .dirty = {
462       .mesa = _NEW_TEXTURE,
463       .brw = BRW_NEW_BATCH |
464              BRW_NEW_GEOMETRY_PROGRAM,
465       .cache = 0
466    },
467    .emit = brw_upload_gs_samplers,
468 };
469
470
471 void
472 gen4_init_vtable_sampler_functions(struct brw_context *brw)
473 {
474    brw->vtbl.upload_sampler_state_table = brw_upload_sampler_state_table;
475 }