• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 || st->lower_rect_tex)
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       GLenum texBaseFormat = _mesa_base_tex_image(texobj)->_BaseFormat;
97       const GLboolean is_integer =
98          texobj->_IsIntegerFormat || texobj->StencilSampling ||
99          texBaseFormat == GL_STENCIL_INDEX;
100 
101       if (texobj->StencilSampling)
102          texBaseFormat = GL_STENCIL_INDEX;
103 
104       if (st->apply_texture_swizzle_to_border_color) {
105          const struct gl_texture_object *stobj = st_texture_object_const(texobj);
106          /* XXX: clean that up to not use the sampler view at all */
107          const struct st_sampler_view *sv = st_texture_get_current_sampler_view(st, stobj);
108 
109          if (sv) {
110             struct pipe_sampler_view *view = sv->view;
111             union pipe_color_union tmp = sampler->border_color;
112             const unsigned char swz[4] =
113             {
114                view->swizzle_r,
115                view->swizzle_g,
116                view->swizzle_b,
117                view->swizzle_a,
118             };
119 
120             st_translate_color(&tmp, texBaseFormat, is_integer);
121 
122             util_format_apply_color_swizzle(&sampler->border_color,
123                                             &tmp, swz, is_integer);
124          } else {
125             st_translate_color(&sampler->border_color,
126                                texBaseFormat, is_integer);
127          }
128       } else {
129          st_translate_color(&sampler->border_color,
130                             texBaseFormat, is_integer);
131          if (st->use_format_with_border_color)
132             sampler->border_color_format = st_get_sampler_view_format(st, texobj,
133                                                                       msamp->Attrib.sRGBDecode == GL_SKIP_DECODE_EXT);
134       }
135       sampler->border_color_is_integer = is_integer;
136    }
137 
138    /* If sampling a depth texture and using shadow comparison */
139    if (msamp->Attrib.CompareMode == GL_COMPARE_R_TO_TEXTURE) {
140       GLenum texBaseFormat = _mesa_base_tex_image(texobj)->_BaseFormat;
141 
142       if (texBaseFormat == GL_DEPTH_COMPONENT ||
143           (texBaseFormat == GL_DEPTH_STENCIL && !texobj->StencilSampling))
144          sampler->compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE;
145    }
146 }
147 
148 /**
149  * Get a pipe_sampler_state object from a texture unit.
150  */
151 void
st_convert_sampler_from_unit(const struct st_context * st,struct pipe_sampler_state * sampler,GLuint texUnit)152 st_convert_sampler_from_unit(const struct st_context *st,
153                              struct pipe_sampler_state *sampler,
154                              GLuint texUnit)
155 {
156    const struct gl_texture_object *texobj;
157    struct gl_context *ctx = st->ctx;
158    const struct gl_sampler_object *msamp;
159 
160    texobj = ctx->Texture.Unit[texUnit]._Current;
161    assert(texobj);
162 
163    msamp = _mesa_get_samplerobj(ctx, texUnit);
164 
165    st_convert_sampler(st, texobj, msamp, ctx->Texture.Unit[texUnit].LodBiasQuantized,
166                       sampler, ctx->Texture.CubeMapSeamless);
167 }
168 
169 
170 /**
171  * Update the gallium driver's sampler state for fragment, vertex or
172  * geometry shader stage.
173  */
174 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)175 update_shader_samplers(struct st_context *st,
176                        enum pipe_shader_type shader_stage,
177                        const struct gl_program *prog,
178                        struct pipe_sampler_state *samplers,
179                        unsigned *out_num_samplers)
180 {
181    struct gl_context *ctx = st->ctx;
182    GLbitfield samplers_used = prog->SamplersUsed;
183    GLbitfield free_slots = ~prog->SamplersUsed;
184    GLbitfield external_samplers_used = prog->ExternalSamplersUsed;
185    unsigned unit, num_samplers;
186    struct pipe_sampler_state local_samplers[PIPE_MAX_SAMPLERS];
187    const struct pipe_sampler_state *states[PIPE_MAX_SAMPLERS];
188 
189    if (samplers_used == 0x0) {
190       if (out_num_samplers)
191          *out_num_samplers = 0;
192       return;
193    }
194 
195    if (!samplers)
196       samplers = local_samplers;
197 
198    num_samplers = util_last_bit(samplers_used);
199 
200    /* loop over sampler units (aka tex image units) */
201    for (unit = 0; samplers_used; unit++, samplers_used >>= 1) {
202       struct pipe_sampler_state *sampler = samplers + unit;
203       unsigned tex_unit = prog->SamplerUnits[unit];
204 
205       /* Don't update the sampler for TBOs. cso_context will not bind sampler
206        * states that are NULL.
207        */
208       if (samplers_used & 1 &&
209           (ctx->Texture.Unit[tex_unit]._Current->Target != GL_TEXTURE_BUFFER ||
210            st->texture_buffer_sampler)) {
211          st_convert_sampler_from_unit(st, sampler, tex_unit);
212          states[unit] = sampler;
213       } else {
214          states[unit] = NULL;
215       }
216    }
217 
218    /* For any external samplers with multiplaner YUV, stuff the additional
219     * sampler states we need at the end.
220     *
221     * Just re-use the existing sampler-state from the primary slot.
222     */
223    while (unlikely(external_samplers_used)) {
224       GLuint unit = u_bit_scan(&external_samplers_used);
225       GLuint extra = 0;
226       struct gl_texture_object *stObj =
227             st_get_texture_object(st->ctx, prog, unit);
228       struct pipe_sampler_state *sampler = samplers + unit;
229 
230       /* if resource format matches then YUV wasn't lowered */
231       if (!stObj || st_get_view_format(stObj) == stObj->pt->format)
232          continue;
233 
234       switch (st_get_view_format(stObj)) {
235       case PIPE_FORMAT_NV12:
236          if (stObj->pt->format == PIPE_FORMAT_R8_G8B8_420_UNORM)
237             /* no additional views needed */
238             break;
239          FALLTHROUGH;
240       case PIPE_FORMAT_P010:
241       case PIPE_FORMAT_P012:
242       case PIPE_FORMAT_P016:
243       case PIPE_FORMAT_Y210:
244       case PIPE_FORMAT_Y212:
245       case PIPE_FORMAT_Y216:
246       case PIPE_FORMAT_YUYV:
247       case PIPE_FORMAT_UYVY:
248          if (stObj->pt->format == PIPE_FORMAT_R8G8_R8B8_UNORM ||
249              stObj->pt->format == PIPE_FORMAT_G8R8_B8R8_UNORM) {
250             /* no additional views needed */
251             break;
252          }
253 
254          /* we need one additional sampler: */
255          extra = u_bit_scan(&free_slots);
256          states[extra] = sampler;
257          break;
258       case PIPE_FORMAT_IYUV:
259          /* we need two additional samplers: */
260          extra = u_bit_scan(&free_slots);
261          states[extra] = sampler;
262          extra = u_bit_scan(&free_slots);
263          states[extra] = sampler;
264          break;
265       default:
266          break;
267       }
268 
269       num_samplers = MAX2(num_samplers, extra + 1);
270    }
271 
272    cso_set_samplers(st->cso_context, shader_stage, num_samplers, states);
273 
274    if (out_num_samplers)
275       *out_num_samplers = num_samplers;
276 }
277 
278 
279 void
st_update_vertex_samplers(struct st_context * st)280 st_update_vertex_samplers(struct st_context *st)
281 {
282    const struct gl_context *ctx = st->ctx;
283 
284    update_shader_samplers(st,
285                           PIPE_SHADER_VERTEX,
286                           ctx->VertexProgram._Current,
287                           st->state.vert_samplers,
288                           &st->state.num_vert_samplers);
289 }
290 
291 
292 void
st_update_tessctrl_samplers(struct st_context * st)293 st_update_tessctrl_samplers(struct st_context *st)
294 {
295    const struct gl_context *ctx = st->ctx;
296 
297    if (ctx->TessCtrlProgram._Current) {
298       update_shader_samplers(st,
299                              PIPE_SHADER_TESS_CTRL,
300                              ctx->TessCtrlProgram._Current, NULL, NULL);
301    }
302 }
303 
304 
305 void
st_update_tesseval_samplers(struct st_context * st)306 st_update_tesseval_samplers(struct st_context *st)
307 {
308    const struct gl_context *ctx = st->ctx;
309 
310    if (ctx->TessEvalProgram._Current) {
311       update_shader_samplers(st,
312                              PIPE_SHADER_TESS_EVAL,
313                              ctx->TessEvalProgram._Current, NULL, NULL);
314    }
315 }
316 
317 
318 void
st_update_geometry_samplers(struct st_context * st)319 st_update_geometry_samplers(struct st_context *st)
320 {
321    const struct gl_context *ctx = st->ctx;
322 
323    if (ctx->GeometryProgram._Current) {
324       update_shader_samplers(st,
325                              PIPE_SHADER_GEOMETRY,
326                              ctx->GeometryProgram._Current, NULL, NULL);
327    }
328 }
329 
330 
331 void
st_update_fragment_samplers(struct st_context * st)332 st_update_fragment_samplers(struct st_context *st)
333 {
334    const struct gl_context *ctx = st->ctx;
335 
336    update_shader_samplers(st,
337                           PIPE_SHADER_FRAGMENT,
338                           ctx->FragmentProgram._Current,
339                           st->state.frag_samplers,
340                           &st->state.num_frag_samplers);
341 }
342 
343 
344 void
st_update_compute_samplers(struct st_context * st)345 st_update_compute_samplers(struct st_context *st)
346 {
347    const struct gl_context *ctx = st->ctx;
348 
349    if (ctx->ComputeProgram._Current) {
350       update_shader_samplers(st,
351                              PIPE_SHADER_COMPUTE,
352                              ctx->ComputeProgram._Current, NULL, NULL);
353    }
354 }
355