Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / i965 / gen7_sampler_state.c
1 /*
2  * Copyright © 2011 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23
24 #include "brw_context.h"
25 #include "brw_state.h"
26 #include "brw_defines.h"
27 #include "intel_batchbuffer.h"
28
29 #include "main/macros.h"
30 #include "main/samplerobj.h"
31
32 /**
33  * Sets the sampler state for a single unit.
34  */
35 static void
36 gen7_update_sampler_state(struct brw_context *brw, int unit,
37                           struct gen7_sampler_state *sampler)
38 {
39    struct intel_context *intel = &brw->intel;
40    struct gl_context *ctx = &intel->ctx;
41    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
42    struct gl_texture_object *texObj = texUnit->_Current;
43    struct gl_sampler_object *gl_sampler = _mesa_get_samplerobj(ctx, unit);
44    bool using_nearest = false;
45
46    switch (gl_sampler->MinFilter) {
47    case GL_NEAREST:
48       sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
49       sampler->ss0.mip_filter = BRW_MIPFILTER_NONE;
50       using_nearest = true;
51       break;
52    case GL_LINEAR:
53       sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
54       sampler->ss0.mip_filter = BRW_MIPFILTER_NONE;
55       break;
56    case GL_NEAREST_MIPMAP_NEAREST:
57       sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
58       sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST;
59       break;
60    case GL_LINEAR_MIPMAP_NEAREST:
61       sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
62       sampler->ss0.mip_filter = BRW_MIPFILTER_NEAREST;
63       break;
64    case GL_NEAREST_MIPMAP_LINEAR:
65       sampler->ss0.min_filter = BRW_MAPFILTER_NEAREST;
66       sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR;
67       break;
68    case GL_LINEAR_MIPMAP_LINEAR:
69       sampler->ss0.min_filter = BRW_MAPFILTER_LINEAR;
70       sampler->ss0.mip_filter = BRW_MIPFILTER_LINEAR;
71       break;
72    default:
73       break;
74    }
75
76    /* Set Anisotropy: */
77    if (gl_sampler->MaxAnisotropy > 1.0) {
78       sampler->ss0.min_filter = BRW_MAPFILTER_ANISOTROPIC;
79       sampler->ss0.mag_filter = BRW_MAPFILTER_ANISOTROPIC;
80
81       if (gl_sampler->MaxAnisotropy > 2.0) {
82          sampler->ss3.max_aniso = MIN2((gl_sampler->MaxAnisotropy - 2) / 2,
83                                        BRW_ANISORATIO_16);
84       }
85    }
86    else {
87       switch (gl_sampler->MagFilter) {
88       case GL_NEAREST:
89          sampler->ss0.mag_filter = BRW_MAPFILTER_NEAREST;
90          using_nearest = true;
91          break;
92       case GL_LINEAR:
93          sampler->ss0.mag_filter = BRW_MAPFILTER_LINEAR;
94          break;
95       default:
96          break;
97       }
98    }
99
100    sampler->ss3.r_wrap_mode = translate_wrap_mode(gl_sampler->WrapR,
101                                                   using_nearest);
102    sampler->ss3.s_wrap_mode = translate_wrap_mode(gl_sampler->WrapS,
103                                                   using_nearest);
104    sampler->ss3.t_wrap_mode = translate_wrap_mode(gl_sampler->WrapT,
105                                                   using_nearest);
106
107    /* Cube-maps on 965 and later must use the same wrap mode for all 3
108     * coordinate dimensions.  Futher, only CUBE and CLAMP are valid.
109     */
110    if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
111       if (ctx->Texture.CubeMapSeamless &&
112           (gl_sampler->MinFilter != GL_NEAREST ||
113            gl_sampler->MagFilter != GL_NEAREST)) {
114          sampler->ss3.r_wrap_mode = BRW_TEXCOORDMODE_CUBE;
115          sampler->ss3.s_wrap_mode = BRW_TEXCOORDMODE_CUBE;
116          sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_CUBE;
117       } else {
118          sampler->ss3.r_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
119          sampler->ss3.s_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
120          sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_CLAMP;
121       }
122    } else if (texObj->Target == GL_TEXTURE_1D) {
123       /* There's a bug in 1D texture sampling - it actually pays
124        * attention to the wrap_t value, though it should not.
125        * Override the wrap_t value here to GL_REPEAT to keep
126        * any nonexistent border pixels from floating in.
127        */
128       sampler->ss3.t_wrap_mode = BRW_TEXCOORDMODE_WRAP;
129    }
130
131    /* Set shadow function: */
132    if (gl_sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB) {
133       /* Shadowing is "enabled" by emitting a particular sampler
134        * message (sample_c).  So need to recompile WM program when
135        * shadow comparison is enabled on each/any texture unit.
136        */
137       sampler->ss1.shadow_function =
138          intel_translate_shadow_compare_func(gl_sampler->CompareFunc);
139    }
140
141    /* Set LOD bias: */
142    sampler->ss0.lod_bias = S_FIXED(CLAMP(texUnit->LodBias +
143                                          gl_sampler->LodBias, -16, 15), 8);
144
145    sampler->ss0.lod_preclamp = 1; /* OpenGL mode */
146    sampler->ss0.default_color_mode = 0; /* OpenGL/DX10 mode */
147
148    /* Set BaseMipLevel, MaxLOD, MinLOD:
149     *
150     * XXX: I don't think that using firstLevel, lastLevel works,
151     * because we always setup the surface state as if firstLevel ==
152     * level zero.  Probably have to subtract firstLevel from each of
153     * these:
154     */
155    sampler->ss0.base_level = U_FIXED(0, 1);
156
157    sampler->ss1.max_lod = U_FIXED(CLAMP(gl_sampler->MaxLod, 0, 13), 8);
158    sampler->ss1.min_lod = U_FIXED(CLAMP(gl_sampler->MinLod, 0, 13), 8);
159
160    upload_default_color(brw, gl_sampler, unit);
161
162    sampler->ss2.default_color_pointer = brw->wm.sdc_offset[unit] >> 5;
163
164    if (sampler->ss0.min_filter != BRW_MAPFILTER_NEAREST)
165       sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MIN |
166                                     BRW_ADDRESS_ROUNDING_ENABLE_V_MIN |
167                                     BRW_ADDRESS_ROUNDING_ENABLE_R_MIN;
168    if (sampler->ss0.mag_filter != BRW_MAPFILTER_NEAREST)
169       sampler->ss3.address_round |= BRW_ADDRESS_ROUNDING_ENABLE_U_MAG |
170                                     BRW_ADDRESS_ROUNDING_ENABLE_V_MAG |
171                                     BRW_ADDRESS_ROUNDING_ENABLE_R_MAG;
172 }
173
174
175 /* All samplers must be uploaded in a single contiguous array, which
176  * complicates various things.  However, this is still too confusing -
177  * FIXME: simplify all the different new texture state flags.
178  */
179 static void
180 gen7_prepare_samplers(struct brw_context *brw)
181 {
182    struct gl_context *ctx = &brw->intel.ctx;
183    struct gen7_sampler_state *samplers;
184    int i;
185
186    brw->wm.sampler_count = 0;
187    for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
188       if (ctx->Texture.Unit[i]._ReallyEnabled)
189          brw->wm.sampler_count = i + 1;
190    }
191
192    if (brw->wm.sampler_count == 0)
193       return;
194
195    samplers = brw_state_batch(brw, brw->wm.sampler_count * sizeof(*samplers),
196                               32, &brw->wm.sampler_offset);
197    memset(samplers, 0, brw->wm.sampler_count * sizeof(*samplers));
198
199    for (i = 0; i < brw->wm.sampler_count; i++) {
200       if (ctx->Texture.Unit[i]._ReallyEnabled)
201          gen7_update_sampler_state(brw, i, &samplers[i]);
202    }
203
204    brw->state.dirty.cache |= CACHE_NEW_SAMPLER;
205 }
206
207 const struct brw_tracked_state gen7_samplers = {
208    .dirty = {
209       .mesa = _NEW_TEXTURE,
210       .brw = BRW_NEW_BATCH,
211       .cache = 0
212    },
213    .prepare = gen7_prepare_samplers,
214 };