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 <[email protected]>
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 #include "program/prog_instruction.h"
54
55
56 /**
57 * Convert a gl_sampler_object to a pipe_sampler_state object.
58 */
59 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,bool ignore_srgb_decode,bool glsl130_or_later)60 st_convert_sampler(const struct st_context *st,
61 const struct gl_texture_object *texobj,
62 const struct gl_sampler_object *msamp,
63 float tex_unit_lod_bias,
64 struct pipe_sampler_state *sampler,
65 bool seamless_cube_map,
66 bool ignore_srgb_decode,
67 bool glsl130_or_later)
68 {
69 memcpy(sampler, &msamp->Attrib.state, sizeof(*sampler));
70
71 sampler->seamless_cube_map |= seamless_cube_map;
72
73 if (texobj->_IsIntegerFormat ||
74 (texobj->_IsFloat && st->ctx->Const.ForceFloat32TexNearest)) {
75 sampler->min_img_filter = PIPE_TEX_FILTER_NEAREST;
76 sampler->min_mip_filter = PIPE_TEX_FILTER_NEAREST;
77 sampler->mag_img_filter = PIPE_TEX_FILTER_NEAREST;
78 }
79
80 if (texobj->Target == GL_TEXTURE_RECTANGLE_ARB && !st->lower_rect_tex)
81 sampler->unnormalized_coords = 1;
82
83 /*
84 * The spec says that "texture wrap modes are ignored" for seamless cube
85 * maps, so normalize the CSO. This works around Apple hardware which honours
86 * REPEAT modes even for seamless cube maps.
87 */
88 if ((texobj->Target == GL_TEXTURE_CUBE_MAP ||
89 texobj->Target == GL_TEXTURE_CUBE_MAP_ARRAY) &&
90 sampler->seamless_cube_map) {
91
92 sampler->wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
93 sampler->wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
94 sampler->wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
95 }
96
97 sampler->lod_bias += tex_unit_lod_bias;
98
99 /* Check that only wrap modes using the border color have the first bit
100 * set.
101 */
102 STATIC_ASSERT(PIPE_TEX_WRAP_CLAMP & 0x1);
103 STATIC_ASSERT(PIPE_TEX_WRAP_CLAMP_TO_BORDER & 0x1);
104 STATIC_ASSERT(PIPE_TEX_WRAP_MIRROR_CLAMP & 0x1);
105 STATIC_ASSERT(PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER & 0x1);
106 STATIC_ASSERT(((PIPE_TEX_WRAP_REPEAT |
107 PIPE_TEX_WRAP_CLAMP_TO_EDGE |
108 PIPE_TEX_WRAP_MIRROR_REPEAT |
109 PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE) & 0x1) == 0);
110
111 if (msamp->Attrib.IsBorderColorNonZero &&
112 /* This is true if wrap modes are using the border color: */
113 (sampler->wrap_s | sampler->wrap_t | sampler->wrap_r) & 0x1) {
114 GLenum texBaseFormat = _mesa_base_tex_image(texobj)->_BaseFormat;
115
116 /* From OpenGL 4.3 spec, "Combined Depth/Stencil Textures":
117 *
118 * "The DEPTH_STENCIL_TEXTURE_MODE is ignored for non
119 * depth/stencil textures.
120 */
121 const bool has_combined_ds = texBaseFormat == GL_DEPTH_STENCIL;
122
123 const GLboolean is_integer =
124 texobj->_IsIntegerFormat ||
125 (texobj->StencilSampling && has_combined_ds) ||
126 texBaseFormat == GL_STENCIL_INDEX;
127
128 if (texobj->StencilSampling && has_combined_ds)
129 texBaseFormat = GL_STENCIL_INDEX;
130
131 if (st->apply_texture_swizzle_to_border_color ||
132 st->alpha_border_color_is_not_w || st->use_format_with_border_color) {
133 if (st->apply_texture_swizzle_to_border_color) {
134 const unsigned swizzle = glsl130_or_later ? texobj->SwizzleGLSL130 : texobj->Swizzle;
135
136 union pipe_color_union tmp = sampler->border_color;
137 const unsigned char swz[4] =
138 {
139 GET_SWZ(swizzle, 0),
140 GET_SWZ(swizzle, 1),
141 GET_SWZ(swizzle, 2),
142 GET_SWZ(swizzle, 3),
143 };
144
145 st_translate_color(&tmp, texBaseFormat, is_integer);
146
147 util_format_apply_color_swizzle(&sampler->border_color,
148 &tmp, swz, is_integer);
149 } else {
150 bool srgb_skip_decode = false;
151
152 if (!ignore_srgb_decode && msamp->Attrib.sRGBDecode == GL_SKIP_DECODE_EXT)
153 srgb_skip_decode = true;
154 enum pipe_format format = st_get_sampler_view_format(st, texobj, srgb_skip_decode);
155 if (st->use_format_with_border_color)
156 sampler->border_color_format = format;
157 /* alpha is not w, so set it to the first available component: */
158 if (st->alpha_border_color_is_not_w && util_format_is_alpha(format)) {
159 /* use x component */
160 sampler->border_color.ui[0] = sampler->border_color.ui[3];
161 } else if (st->alpha_border_color_is_not_w && util_format_is_luminance_alpha(format)) {
162 /* use y component */
163 sampler->border_color.ui[1] = sampler->border_color.ui[3];
164 } else {
165 /* not an alpha format */
166 st_translate_color(&sampler->border_color,
167 texBaseFormat, is_integer);
168 }
169 }
170 } else {
171 st_translate_color(&sampler->border_color,
172 texBaseFormat, is_integer);
173 }
174 sampler->border_color_is_integer = is_integer;
175 }
176
177 /* If sampling a depth texture and using shadow comparison */
178 if (msamp->Attrib.CompareMode == GL_COMPARE_R_TO_TEXTURE) {
179 GLenum texBaseFormat = _mesa_base_tex_image(texobj)->_BaseFormat;
180
181 if (texBaseFormat == GL_DEPTH_COMPONENT ||
182 (texBaseFormat == GL_DEPTH_STENCIL && !texobj->StencilSampling))
183 sampler->compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE;
184 }
185 }
186
187 /**
188 * Get a pipe_sampler_state object from a texture unit.
189 */
190 void
st_convert_sampler_from_unit(const struct st_context * st,struct pipe_sampler_state * sampler,GLuint texUnit,bool glsl130_or_later)191 st_convert_sampler_from_unit(const struct st_context *st,
192 struct pipe_sampler_state *sampler,
193 GLuint texUnit,
194 bool glsl130_or_later)
195 {
196 const struct gl_texture_object *texobj;
197 struct gl_context *ctx = st->ctx;
198 const struct gl_sampler_object *msamp;
199
200 texobj = ctx->Texture.Unit[texUnit]._Current;
201 assert(texobj);
202
203 msamp = _mesa_get_samplerobj(ctx, texUnit);
204
205 st_convert_sampler(st, texobj, msamp, ctx->Texture.Unit[texUnit].LodBiasQuantized,
206 sampler, ctx->Texture.CubeMapSeamless, true, glsl130_or_later);
207 }
208
209
210 /**
211 * Update the gallium driver's sampler state for fragment, vertex or
212 * geometry shader stage.
213 */
214 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)215 update_shader_samplers(struct st_context *st,
216 enum pipe_shader_type shader_stage,
217 const struct gl_program *prog,
218 struct pipe_sampler_state *samplers,
219 unsigned *out_num_samplers)
220 {
221 struct gl_context *ctx = st->ctx;
222 GLbitfield samplers_used = prog->SamplersUsed;
223 GLbitfield free_slots = ~prog->SamplersUsed;
224 GLbitfield external_samplers_used = prog->ExternalSamplersUsed;
225 unsigned unit, num_samplers;
226 struct pipe_sampler_state local_samplers[PIPE_MAX_SAMPLERS];
227 const struct pipe_sampler_state *states[PIPE_MAX_SAMPLERS];
228
229 if (samplers_used == 0x0) {
230 if (out_num_samplers)
231 *out_num_samplers = 0;
232 return;
233 }
234
235 if (!samplers)
236 samplers = local_samplers;
237
238 num_samplers = util_last_bit(samplers_used);
239
240 /* loop over sampler units (aka tex image units) */
241 for (unit = 0; samplers_used; unit++, samplers_used >>= 1) {
242 struct pipe_sampler_state *sampler = samplers + unit;
243 unsigned tex_unit = prog->SamplerUnits[unit];
244
245 /* Don't update the sampler for TBOs. cso_context will not bind sampler
246 * states that are NULL.
247 */
248 if (samplers_used & 1 &&
249 (ctx->Texture.Unit[tex_unit]._Current->Target != GL_TEXTURE_BUFFER)) {
250 st_convert_sampler_from_unit(
251 st, sampler, tex_unit,
252 prog->shader_program && prog->shader_program->GLSL_Version >= 130);
253 states[unit] = sampler;
254 } else {
255 states[unit] = NULL;
256 }
257 }
258
259 /* For any external samplers with multiplaner YUV, stuff the additional
260 * sampler states we need at the end.
261 *
262 * Just re-use the existing sampler-state from the primary slot.
263 */
264 while (unlikely(external_samplers_used)) {
265 GLuint unit = u_bit_scan(&external_samplers_used);
266 GLuint extra = 0;
267 struct gl_texture_object *stObj =
268 st_get_texture_object(st->ctx, prog, unit);
269 struct pipe_sampler_state *sampler = samplers + unit;
270
271 /* if resource format matches then YUV wasn't lowered */
272 if (!stObj || st_get_view_format(stObj) == stObj->pt->format)
273 continue;
274
275 switch (st_get_view_format(stObj)) {
276 case PIPE_FORMAT_NV12:
277 if (stObj->pt->format == PIPE_FORMAT_R8_G8B8_420_UNORM)
278 /* no additional views needed */
279 break;
280 FALLTHROUGH;
281 case PIPE_FORMAT_NV21:
282 if (stObj->pt->format == PIPE_FORMAT_R8_B8G8_420_UNORM)
283 /* no additional views needed */
284 break;
285 FALLTHROUGH;
286 case PIPE_FORMAT_P010:
287 case PIPE_FORMAT_P012:
288 case PIPE_FORMAT_P016:
289 case PIPE_FORMAT_P030:
290 case PIPE_FORMAT_Y210:
291 case PIPE_FORMAT_Y212:
292 case PIPE_FORMAT_Y216:
293 case PIPE_FORMAT_YUYV:
294 case PIPE_FORMAT_YVYU:
295 case PIPE_FORMAT_UYVY:
296 case PIPE_FORMAT_VYUY:
297 if (stObj->pt->format == PIPE_FORMAT_R8G8_R8B8_UNORM ||
298 stObj->pt->format == PIPE_FORMAT_R8B8_R8G8_UNORM ||
299 stObj->pt->format == PIPE_FORMAT_B8R8_G8R8_UNORM ||
300 stObj->pt->format == PIPE_FORMAT_G8R8_B8R8_UNORM) {
301 /* no additional views needed */
302 break;
303 }
304
305 /* we need one additional sampler: */
306 extra = u_bit_scan(&free_slots);
307 states[extra] = sampler;
308 break;
309 case PIPE_FORMAT_IYUV:
310 if (stObj->pt->format == PIPE_FORMAT_R8_G8_B8_420_UNORM ||
311 stObj->pt->format == PIPE_FORMAT_R8_B8_G8_420_UNORM) {
312 /* no additional views needed */
313 break;
314 }
315 /* we need two additional samplers: */
316 extra = u_bit_scan(&free_slots);
317 states[extra] = sampler;
318 extra = u_bit_scan(&free_slots);
319 states[extra] = sampler;
320 break;
321 default:
322 break;
323 }
324
325 num_samplers = MAX2(num_samplers, extra + 1);
326 }
327
328 cso_set_samplers(st->cso_context, shader_stage, num_samplers, states);
329
330 if (out_num_samplers)
331 *out_num_samplers = num_samplers;
332 }
333
334
335 void
st_update_vertex_samplers(struct st_context * st)336 st_update_vertex_samplers(struct st_context *st)
337 {
338 const struct gl_context *ctx = st->ctx;
339
340 update_shader_samplers(st,
341 PIPE_SHADER_VERTEX,
342 ctx->VertexProgram._Current,
343 st->state.vert_samplers,
344 &st->state.num_vert_samplers);
345 }
346
347
348 void
st_update_tessctrl_samplers(struct st_context * st)349 st_update_tessctrl_samplers(struct st_context *st)
350 {
351 const struct gl_context *ctx = st->ctx;
352
353 if (ctx->TessCtrlProgram._Current) {
354 update_shader_samplers(st,
355 PIPE_SHADER_TESS_CTRL,
356 ctx->TessCtrlProgram._Current, NULL, NULL);
357 }
358 }
359
360
361 void
st_update_tesseval_samplers(struct st_context * st)362 st_update_tesseval_samplers(struct st_context *st)
363 {
364 const struct gl_context *ctx = st->ctx;
365
366 if (ctx->TessEvalProgram._Current) {
367 update_shader_samplers(st,
368 PIPE_SHADER_TESS_EVAL,
369 ctx->TessEvalProgram._Current, NULL, NULL);
370 }
371 }
372
373
374 void
st_update_geometry_samplers(struct st_context * st)375 st_update_geometry_samplers(struct st_context *st)
376 {
377 const struct gl_context *ctx = st->ctx;
378
379 if (ctx->GeometryProgram._Current) {
380 update_shader_samplers(st,
381 PIPE_SHADER_GEOMETRY,
382 ctx->GeometryProgram._Current, NULL, NULL);
383 }
384 }
385
386
387 void
st_update_fragment_samplers(struct st_context * st)388 st_update_fragment_samplers(struct st_context *st)
389 {
390 const struct gl_context *ctx = st->ctx;
391
392 update_shader_samplers(st,
393 PIPE_SHADER_FRAGMENT,
394 ctx->FragmentProgram._Current,
395 st->state.frag_samplers,
396 &st->state.num_frag_samplers);
397 }
398
399
400 void
st_update_compute_samplers(struct st_context * st)401 st_update_compute_samplers(struct st_context *st)
402 {
403 const struct gl_context *ctx = st->ctx;
404
405 if (ctx->ComputeProgram._Current) {
406 update_shader_samplers(st,
407 PIPE_SHADER_COMPUTE,
408 ctx->ComputeProgram._Current, NULL, NULL);
409 }
410 }
411