1 /**************************************************************************
2  *
3  * Copyright 2007 VMware, Inc.
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 VMWARE 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 <keithw@vmware.com>
31   *   Brian Paul
32   */
33 
34 
35 #include "main/macros.h"
36 #include "main/glformats.h"
37 #include "main/samplerobj.h"
38 #include "main/teximage.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_sampler_view.h"
46 #include "st_texture.h"
47 #include "pipe/p_context.h"
48 #include "pipe/p_defines.h"
49 
50 #include "cso_cache/cso_context.h"
51 
52 #include "util/format/u_format.h"
53 
54 
55 /**
56  * Convert a gl_sampler_object to a pipe_sampler_state object.
57  */
58 void
st_convert_sampler(const struct st_context * st,const struct gl_texture_object * texobj,const struct gl_sampler_object * msamp,float tex_unit_lod_bias,struct pipe_sampler_state * sampler,bool seamless_cube_map)59 st_convert_sampler(const struct st_context *st,
60                    const struct gl_texture_object *texobj,
61                    const struct gl_sampler_object *msamp,
62                    float tex_unit_lod_bias,
63                    struct pipe_sampler_state *sampler,
64                    bool seamless_cube_map)
65 {
66    memcpy(sampler, &msamp->Attrib.state, sizeof(*sampler));
67 
68    sampler->seamless_cube_map |= seamless_cube_map;
69 
70    if (texobj->_IsIntegerFormat && st->ctx->Const.ForceIntegerTexNearest) {
71       sampler->min_img_filter = PIPE_TEX_FILTER_NEAREST;
72       sampler->mag_img_filter = PIPE_TEX_FILTER_NEAREST;
73    }
74 
75    if (texobj->Target != GL_TEXTURE_RECTANGLE_ARB)
76       sampler->normalized_coords = 1;
77 
78    sampler->lod_bias += tex_unit_lod_bias;
79 
80    /* Check that only wrap modes using the border color have the first bit
81     * set.
82     */
83    STATIC_ASSERT(PIPE_TEX_WRAP_CLAMP & 0x1);
84    STATIC_ASSERT(PIPE_TEX_WRAP_CLAMP_TO_BORDER & 0x1);
85    STATIC_ASSERT(PIPE_TEX_WRAP_MIRROR_CLAMP & 0x1);
86    STATIC_ASSERT(PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER & 0x1);
87    STATIC_ASSERT(((PIPE_TEX_WRAP_REPEAT |
88                    PIPE_TEX_WRAP_CLAMP_TO_EDGE |
89                    PIPE_TEX_WRAP_MIRROR_REPEAT |
90                    PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE) & 0x1) == 0);
91 
92    /* For non-black borders... */
93    if (msamp->Attrib.IsBorderColorNonZero &&
94        /* This is true if wrap modes are using the border color: */
95        (sampler->wrap_s | sampler->wrap_t | sampler->wrap_r) & 0x1) {
96       const GLboolean is_integer = texobj->_IsIntegerFormat;
97       GLenum texBaseFormat = _mesa_base_tex_image(texobj)->_BaseFormat;
98 
99       if (texobj->StencilSampling)
100          texBaseFormat = GL_STENCIL_INDEX;
101 
102       if (st->apply_texture_swizzle_to_border_color) {
103          const struct gl_texture_object *stobj = st_texture_object_const(texobj);
104          /* XXX: clean that up to not use the sampler view at all */
105          const struct st_sampler_view *sv = st_texture_get_current_sampler_view(st, stobj);
106 
107          if (sv) {
108             struct pipe_sampler_view *view = sv->view;
109             union pipe_color_union tmp = sampler->border_color;
110             const unsigned char swz[4] =
111             {
112                view->swizzle_r,
113                view->swizzle_g,
114                view->swizzle_b,
115                view->swizzle_a,
116             };
117 
118             st_translate_color(&tmp, texBaseFormat, is_integer);
119 
120             util_format_apply_color_swizzle(&sampler->border_color,
121                                             &tmp, swz, is_integer);
122          } else {
123             st_translate_color(&sampler->border_color,
124                                texBaseFormat, is_integer);
125          }
126       } else {
127          st_translate_color(&sampler->border_color,
128                             texBaseFormat, is_integer);
129       }
130       sampler->border_color_is_integer = is_integer;
131    }
132 
133    /* If sampling a depth texture and using shadow comparison */
134    if (msamp->Attrib.CompareMode == GL_COMPARE_R_TO_TEXTURE) {
135       GLenum texBaseFormat = _mesa_base_tex_image(texobj)->_BaseFormat;
136 
137       if (texBaseFormat == GL_DEPTH_COMPONENT ||
138           (texBaseFormat == GL_DEPTH_STENCIL && !texobj->StencilSampling))
139          sampler->compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE;
140    }
141 }
142 
143 /**
144  * Get a pipe_sampler_state object from a texture unit.
145  */
146 void
st_convert_sampler_from_unit(const struct st_context * st,struct pipe_sampler_state * sampler,GLuint texUnit)147 st_convert_sampler_from_unit(const struct st_context *st,
148                              struct pipe_sampler_state *sampler,
149                              GLuint texUnit)
150 {
151    const struct gl_texture_object *texobj;
152    struct gl_context *ctx = st->ctx;
153    const struct gl_sampler_object *msamp;
154 
155    texobj = ctx->Texture.Unit[texUnit]._Current;
156    assert(texobj);
157 
158    msamp = _mesa_get_samplerobj(ctx, texUnit);
159 
160    st_convert_sampler(st, texobj, msamp, ctx->Texture.Unit[texUnit].LodBiasQuantized,
161                       sampler, ctx->Texture.CubeMapSeamless);
162 }
163 
164 
165 /**
166  * Update the gallium driver's sampler state for fragment, vertex or
167  * geometry shader stage.
168  */
169 static void
update_shader_samplers(struct st_context * st,enum pipe_shader_type shader_stage,const struct gl_program * prog,struct pipe_sampler_state * samplers,unsigned * out_num_samplers)170 update_shader_samplers(struct st_context *st,
171                        enum pipe_shader_type shader_stage,
172                        const struct gl_program *prog,
173                        struct pipe_sampler_state *samplers,
174                        unsigned *out_num_samplers)
175 {
176    struct gl_context *ctx = st->ctx;
177    GLbitfield samplers_used = prog->SamplersUsed;
178    GLbitfield free_slots = ~prog->SamplersUsed;
179    GLbitfield external_samplers_used = prog->ExternalSamplersUsed;
180    unsigned unit, num_samplers;
181    struct pipe_sampler_state local_samplers[PIPE_MAX_SAMPLERS];
182    const struct pipe_sampler_state *states[PIPE_MAX_SAMPLERS];
183 
184    if (samplers_used == 0x0) {
185       if (out_num_samplers)
186          *out_num_samplers = 0;
187       return;
188    }
189 
190    if (!samplers)
191       samplers = local_samplers;
192 
193    num_samplers = util_last_bit(samplers_used);
194 
195    /* loop over sampler units (aka tex image units) */
196    for (unit = 0; samplers_used; unit++, samplers_used >>= 1) {
197       struct pipe_sampler_state *sampler = samplers + unit;
198       unsigned tex_unit = prog->SamplerUnits[unit];
199 
200       /* Don't update the sampler for TBOs. cso_context will not bind sampler
201        * states that are NULL.
202        */
203       if (samplers_used & 1 &&
204           (ctx->Texture.Unit[tex_unit]._Current->Target != GL_TEXTURE_BUFFER ||
205            st->texture_buffer_sampler)) {
206          st_convert_sampler_from_unit(st, sampler, tex_unit);
207          states[unit] = sampler;
208       } else {
209          states[unit] = NULL;
210       }
211    }
212 
213    /* For any external samplers with multiplaner YUV, stuff the additional
214     * sampler states we need at the end.
215     *
216     * Just re-use the existing sampler-state from the primary slot.
217     */
218    while (unlikely(external_samplers_used)) {
219       GLuint unit = u_bit_scan(&external_samplers_used);
220       GLuint extra = 0;
221       struct gl_texture_object *stObj =
222             st_get_texture_object(st->ctx, prog, unit);
223       struct pipe_sampler_state *sampler = samplers + unit;
224 
225       /* if resource format matches then YUV wasn't lowered */
226       if (!stObj || st_get_view_format(stObj) == stObj->pt->format)
227          continue;
228 
229       switch (st_get_view_format(stObj)) {
230       case PIPE_FORMAT_NV12:
231          if (stObj->pt->format == PIPE_FORMAT_R8_G8B8_420_UNORM)
232             /* no additional views needed */
233             break;
234          FALLTHROUGH;
235       case PIPE_FORMAT_P010:
236       case PIPE_FORMAT_P012:
237       case PIPE_FORMAT_P016:
238       case PIPE_FORMAT_Y210:
239       case PIPE_FORMAT_Y212:
240       case PIPE_FORMAT_Y216:
241       case PIPE_FORMAT_YUYV:
242       case PIPE_FORMAT_UYVY:
243          if (stObj->pt->format == PIPE_FORMAT_R8G8_R8B8_UNORM ||
244              stObj->pt->format == PIPE_FORMAT_G8R8_B8R8_UNORM) {
245             /* no additional views needed */
246             break;
247          }
248 
249          /* we need one additional sampler: */
250          extra = u_bit_scan(&free_slots);
251          states[extra] = sampler;
252          break;
253       case PIPE_FORMAT_IYUV:
254          /* we need two additional samplers: */
255          extra = u_bit_scan(&free_slots);
256          states[extra] = sampler;
257          extra = u_bit_scan(&free_slots);
258          states[extra] = sampler;
259          break;
260       default:
261          break;
262       }
263 
264       num_samplers = MAX2(num_samplers, extra + 1);
265    }
266 
267    cso_set_samplers(st->cso_context, shader_stage, num_samplers, states);
268 
269    if (out_num_samplers)
270       *out_num_samplers = num_samplers;
271 }
272 
273 
274 void
st_update_vertex_samplers(struct st_context * st)275 st_update_vertex_samplers(struct st_context *st)
276 {
277    const struct gl_context *ctx = st->ctx;
278 
279    update_shader_samplers(st,
280                           PIPE_SHADER_VERTEX,
281                           ctx->VertexProgram._Current,
282                           st->state.vert_samplers,
283                           &st->state.num_vert_samplers);
284 }
285 
286 
287 void
st_update_tessctrl_samplers(struct st_context * st)288 st_update_tessctrl_samplers(struct st_context *st)
289 {
290    const struct gl_context *ctx = st->ctx;
291 
292    if (ctx->TessCtrlProgram._Current) {
293       update_shader_samplers(st,
294                              PIPE_SHADER_TESS_CTRL,
295                              ctx->TessCtrlProgram._Current, NULL, NULL);
296    }
297 }
298 
299 
300 void
st_update_tesseval_samplers(struct st_context * st)301 st_update_tesseval_samplers(struct st_context *st)
302 {
303    const struct gl_context *ctx = st->ctx;
304 
305    if (ctx->TessEvalProgram._Current) {
306       update_shader_samplers(st,
307                              PIPE_SHADER_TESS_EVAL,
308                              ctx->TessEvalProgram._Current, NULL, NULL);
309    }
310 }
311 
312 
313 void
st_update_geometry_samplers(struct st_context * st)314 st_update_geometry_samplers(struct st_context *st)
315 {
316    const struct gl_context *ctx = st->ctx;
317 
318    if (ctx->GeometryProgram._Current) {
319       update_shader_samplers(st,
320                              PIPE_SHADER_GEOMETRY,
321                              ctx->GeometryProgram._Current, NULL, NULL);
322    }
323 }
324 
325 
326 void
st_update_fragment_samplers(struct st_context * st)327 st_update_fragment_samplers(struct st_context *st)
328 {
329    const struct gl_context *ctx = st->ctx;
330 
331    update_shader_samplers(st,
332                           PIPE_SHADER_FRAGMENT,
333                           ctx->FragmentProgram._Current,
334                           st->state.frag_samplers,
335                           &st->state.num_frag_samplers);
336 }
337 
338 
339 void
st_update_compute_samplers(struct st_context * st)340 st_update_compute_samplers(struct st_context *st)
341 {
342    const struct gl_context *ctx = st->ctx;
343 
344    if (ctx->ComputeProgram._Current) {
345       update_shader_samplers(st,
346                              PIPE_SHADER_COMPUTE,
347                              ctx->ComputeProgram._Current, NULL, NULL);
348    }
349 }
350