• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 VMware, Inc.
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sub license, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial portions
15  * of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
21  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25 
26 #include "pipe/p_context.h"
27 #include "util/u_format.h"
28 #include "util/u_inlines.h"
29 
30 #include "main/context.h"
31 #include "main/macros.h"
32 #include "main/mtypes.h"
33 #include "main/teximage.h"
34 #include "main/texobj.h"
35 #include "program/prog_instruction.h"
36 
37 #include "st_context.h"
38 #include "st_sampler_view.h"
39 #include "st_texture.h"
40 #include "st_format.h"
41 #include "st_cb_texture.h"
42 
43 
44 /**
45  * Try to find a matching sampler view for the given context.
46  * If none is found an empty slot is initialized with a
47  * template and returned instead.
48  */
49 struct pipe_sampler_view **
st_texture_get_sampler_view(struct st_context * st,struct st_texture_object * stObj)50 st_texture_get_sampler_view(struct st_context *st,
51                             struct st_texture_object *stObj)
52 {
53    struct pipe_sampler_view **free = NULL;
54    GLuint i;
55 
56    for (i = 0; i < stObj->num_sampler_views; ++i) {
57       struct pipe_sampler_view **sv = &stObj->sampler_views[i];
58       /* Is the array entry used ? */
59       if (*sv) {
60          /* check if the context matches */
61          if ((*sv)->context == st->pipe) {
62             return sv;
63          }
64       } else {
65          /* Found a free slot, remember that */
66          free = sv;
67       }
68    }
69 
70    /* Couldn't find a slot for our context, create a new one */
71 
72    if (!free) {
73       /* Haven't even found a free one, resize the array */
74       unsigned new_size = (stObj->num_sampler_views + 1) *
75          sizeof(struct pipe_sampler_view *);
76       stObj->sampler_views = realloc(stObj->sampler_views, new_size);
77       free = &stObj->sampler_views[stObj->num_sampler_views++];
78       *free = NULL;
79    }
80 
81    assert(*free == NULL);
82 
83    return free;
84 }
85 
86 
87 /**
88  * For the given texture object, release any sampler views which belong
89  * to the calling context.
90  */
91 void
st_texture_release_sampler_view(struct st_context * st,struct st_texture_object * stObj)92 st_texture_release_sampler_view(struct st_context *st,
93                                 struct st_texture_object *stObj)
94 {
95    GLuint i;
96 
97    for (i = 0; i < stObj->num_sampler_views; ++i) {
98       struct pipe_sampler_view **sv = &stObj->sampler_views[i];
99 
100       if (*sv && (*sv)->context == st->pipe) {
101          pipe_sampler_view_reference(sv, NULL);
102          break;
103       }
104    }
105 }
106 
107 
108 /**
109  * Release all sampler views attached to the given texture object, regardless
110  * of the context.
111  */
112 void
st_texture_release_all_sampler_views(struct st_context * st,struct st_texture_object * stObj)113 st_texture_release_all_sampler_views(struct st_context *st,
114                                      struct st_texture_object *stObj)
115 {
116    GLuint i;
117 
118    /* XXX This should use sampler_views[i]->pipe, not st->pipe */
119    for (i = 0; i < stObj->num_sampler_views; ++i)
120       pipe_sampler_view_release(st->pipe, &stObj->sampler_views[i]);
121 }
122 
123 
124 void
st_texture_free_sampler_views(struct st_texture_object * stObj)125 st_texture_free_sampler_views(struct st_texture_object *stObj)
126 {
127    free(stObj->sampler_views);
128    stObj->sampler_views = NULL;
129    stObj->num_sampler_views = 0;
130 }
131 
132 
133 /**
134  * Return swizzle1(swizzle2)
135  */
136 static unsigned
swizzle_swizzle(unsigned swizzle1,unsigned swizzle2)137 swizzle_swizzle(unsigned swizzle1, unsigned swizzle2)
138 {
139    unsigned i, swz[4];
140 
141    if (swizzle1 == SWIZZLE_XYZW) {
142       /* identity swizzle, no change to swizzle2 */
143       return swizzle2;
144    }
145 
146    for (i = 0; i < 4; i++) {
147       unsigned s = GET_SWZ(swizzle1, i);
148       switch (s) {
149       case SWIZZLE_X:
150       case SWIZZLE_Y:
151       case SWIZZLE_Z:
152       case SWIZZLE_W:
153          swz[i] = GET_SWZ(swizzle2, s);
154          break;
155       case SWIZZLE_ZERO:
156          swz[i] = SWIZZLE_ZERO;
157          break;
158       case SWIZZLE_ONE:
159          swz[i] = SWIZZLE_ONE;
160          break;
161       default:
162          assert(!"Bad swizzle term");
163          swz[i] = SWIZZLE_X;
164       }
165    }
166 
167    return MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
168 }
169 
170 
171 /**
172  * Given a user-specified texture base format, the actual gallium texture
173  * format and the current GL_DEPTH_MODE, return a texture swizzle.
174  *
175  * Consider the case where the user requests a GL_RGB internal texture
176  * format the driver actually uses an RGBA format.  The A component should
177  * be ignored and sampling from the texture should always return (r,g,b,1).
178  * But if we rendered to the texture we might have written A values != 1.
179  * By sampling the texture with a ".xyz1" swizzle we'll get the expected A=1.
180  * This function computes the texture swizzle needed to get the expected
181  * values.
182  *
183  * In the case of depth textures, the GL_DEPTH_MODE state determines the
184  * texture swizzle.
185  *
186  * This result must be composed with the user-specified swizzle to get
187  * the final swizzle.
188  */
189 static unsigned
compute_texture_format_swizzle(GLenum baseFormat,GLenum depthMode,enum pipe_format actualFormat,unsigned glsl_version)190 compute_texture_format_swizzle(GLenum baseFormat, GLenum depthMode,
191                                enum pipe_format actualFormat,
192                                unsigned glsl_version)
193 {
194    switch (baseFormat) {
195    case GL_RGBA:
196       return SWIZZLE_XYZW;
197    case GL_RGB:
198       if (util_format_has_alpha(actualFormat))
199          return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ONE);
200       else
201          return SWIZZLE_XYZW;
202    case GL_RG:
203       if (util_format_get_nr_components(actualFormat) > 2)
204          return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_ZERO, SWIZZLE_ONE);
205       else
206          return SWIZZLE_XYZW;
207    case GL_RED:
208       if (util_format_get_nr_components(actualFormat) > 1)
209          return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO,
210                               SWIZZLE_ZERO, SWIZZLE_ONE);
211       else
212          return SWIZZLE_XYZW;
213    case GL_ALPHA:
214       if (util_format_get_nr_components(actualFormat) > 1)
215          return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO,
216                               SWIZZLE_ZERO, SWIZZLE_W);
217       else
218          return SWIZZLE_XYZW;
219    case GL_LUMINANCE:
220       if (util_format_get_nr_components(actualFormat) > 1)
221          return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE);
222       else
223          return SWIZZLE_XYZW;
224    case GL_LUMINANCE_ALPHA:
225       if (util_format_get_nr_components(actualFormat) > 2)
226          return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_W);
227       else
228          return SWIZZLE_XYZW;
229    case GL_INTENSITY:
230       if (util_format_get_nr_components(actualFormat) > 1)
231          return SWIZZLE_XXXX;
232       else
233          return SWIZZLE_XYZW;
234    case GL_STENCIL_INDEX:
235    case GL_DEPTH_STENCIL:
236    case GL_DEPTH_COMPONENT:
237       /* Now examine the depth mode */
238       switch (depthMode) {
239       case GL_LUMINANCE:
240          return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE);
241       case GL_INTENSITY:
242          return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X);
243       case GL_ALPHA:
244          /* The texture(sampler*Shadow) functions from GLSL 1.30 ignore
245           * the depth mode and return float, while older shadow* functions
246           * and ARB_fp instructions return vec4 according to the depth mode.
247           *
248           * The problem with the GLSL 1.30 functions is that GL_ALPHA forces
249           * them to return 0, breaking them completely.
250           *
251           * A proper fix would increase code complexity and that's not worth
252           * it for a rarely used feature such as the GL_ALPHA depth mode
253           * in GL3. Therefore, change GL_ALPHA to GL_INTENSITY for all
254           * shaders that use GLSL 1.30 or later.
255           *
256           * BTW, it's required that sampler views are updated when
257           * shaders change (check_sampler_swizzle takes care of that).
258           */
259          if (glsl_version && glsl_version >= 130)
260             return SWIZZLE_XXXX;
261          else
262             return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO,
263                                  SWIZZLE_ZERO, SWIZZLE_X);
264       case GL_RED:
265          return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO,
266                               SWIZZLE_ZERO, SWIZZLE_ONE);
267       default:
268          assert(!"Unexpected depthMode");
269          return SWIZZLE_XYZW;
270       }
271    default:
272       assert(!"Unexpected baseFormat");
273       return SWIZZLE_XYZW;
274    }
275 }
276 
277 
278 static unsigned
get_texture_format_swizzle(const struct st_context * st,const struct st_texture_object * stObj,unsigned glsl_version)279 get_texture_format_swizzle(const struct st_context *st,
280                            const struct st_texture_object *stObj,
281                            unsigned glsl_version)
282 {
283    GLenum baseFormat = _mesa_texture_base_format(&stObj->base);
284    unsigned tex_swizzle;
285 
286    if (baseFormat != GL_NONE) {
287       GLenum depth_mode = stObj->base.DepthMode;
288       /* In ES 3.0, DEPTH_TEXTURE_MODE is expected to be GL_RED for textures
289        * with depth component data specified with a sized internal format.
290        */
291       if (_mesa_is_gles3(st->ctx) &&
292           util_format_is_depth_or_stencil(stObj->pt->format)) {
293          const struct gl_texture_image *firstImage =
294             _mesa_base_tex_image(&stObj->base);
295          if (firstImage->InternalFormat != GL_DEPTH_COMPONENT &&
296              firstImage->InternalFormat != GL_DEPTH_STENCIL &&
297              firstImage->InternalFormat != GL_STENCIL_INDEX)
298             depth_mode = GL_RED;
299       }
300       tex_swizzle = compute_texture_format_swizzle(baseFormat,
301                                                    depth_mode,
302                                                    stObj->pt->format,
303                                                    glsl_version);
304    }
305    else {
306       tex_swizzle = SWIZZLE_XYZW;
307    }
308 
309    /* Combine the texture format swizzle with user's swizzle */
310    return swizzle_swizzle(stObj->base._Swizzle, tex_swizzle);
311 }
312 
313 
314 /**
315  * Return TRUE if the texture's sampler view swizzle is not equal to
316  * the texture's swizzle.
317  *
318  * \param stObj  the st texture object,
319  */
320 MAYBE_UNUSED static boolean
check_sampler_swizzle(const struct st_context * st,const struct st_texture_object * stObj,const struct pipe_sampler_view * sv,unsigned glsl_version)321 check_sampler_swizzle(const struct st_context *st,
322                       const struct st_texture_object *stObj,
323 		      const struct pipe_sampler_view *sv, unsigned glsl_version)
324 {
325    unsigned swizzle = get_texture_format_swizzle(st, stObj, glsl_version);
326 
327    return ((sv->swizzle_r != GET_SWZ(swizzle, 0)) ||
328            (sv->swizzle_g != GET_SWZ(swizzle, 1)) ||
329            (sv->swizzle_b != GET_SWZ(swizzle, 2)) ||
330            (sv->swizzle_a != GET_SWZ(swizzle, 3)));
331 }
332 
333 
334 static unsigned
last_level(const struct st_texture_object * stObj)335 last_level(const struct st_texture_object *stObj)
336 {
337    unsigned ret = MIN2(stObj->base.MinLevel + stObj->base._MaxLevel,
338                        stObj->pt->last_level);
339    if (stObj->base.Immutable)
340       ret = MIN2(ret, stObj->base.MinLevel + stObj->base.NumLevels - 1);
341    return ret;
342 }
343 
344 
345 static unsigned
last_layer(const struct st_texture_object * stObj)346 last_layer(const struct st_texture_object *stObj)
347 {
348    if (stObj->base.Immutable && stObj->pt->array_size > 1)
349       return MIN2(stObj->base.MinLayer + stObj->base.NumLayers - 1,
350                   stObj->pt->array_size - 1);
351    return stObj->pt->array_size - 1;
352 }
353 
354 
355 /**
356  * Determine the format for the texture sampler view.
357  */
358 static enum pipe_format
get_sampler_view_format(struct st_context * st,const struct st_texture_object * stObj,const struct gl_sampler_object * samp)359 get_sampler_view_format(struct st_context *st,
360                         const struct st_texture_object *stObj,
361                         const struct gl_sampler_object *samp)
362 {
363    enum pipe_format format;
364 
365    if (stObj->base.Target == GL_TEXTURE_BUFFER) {
366       format =
367          st_mesa_format_to_pipe_format(st, stObj->base._BufferObjectFormat);
368    }
369    else {
370       format =
371          stObj->surface_based ? stObj->surface_format : stObj->pt->format;
372 
373       if (util_format_is_depth_and_stencil(format)) {
374          if (stObj->base.StencilSampling) {
375             format = util_format_stencil_only(format);
376          }
377          else {
378             GLenum baseFormat = _mesa_texture_base_format(&stObj->base);
379             if (baseFormat == GL_STENCIL_INDEX) {
380                format = util_format_stencil_only(format);
381             }
382          }
383       }
384       else {
385          /* If sRGB decoding is off, use the linear format */
386          if (samp->sRGBDecode == GL_SKIP_DECODE_EXT) {
387             format = util_format_linear(format);
388          }
389 
390          /* Use R8_UNORM for video formats */
391          switch (format) {
392          case PIPE_FORMAT_NV12:
393          case PIPE_FORMAT_IYUV:
394             format = PIPE_FORMAT_R8_UNORM;
395             break;
396          default:
397             break;
398          }
399       }
400    }
401 
402    return format;
403 }
404 
405 
406 static struct pipe_sampler_view *
st_create_texture_sampler_view_from_stobj(struct st_context * st,struct st_texture_object * stObj,enum pipe_format format,unsigned glsl_version)407 st_create_texture_sampler_view_from_stobj(struct st_context *st,
408 					  struct st_texture_object *stObj,
409 					  enum pipe_format format,
410                                           unsigned glsl_version)
411 {
412    struct pipe_sampler_view templ;
413    unsigned swizzle = get_texture_format_swizzle(st, stObj, glsl_version);
414 
415    u_sampler_view_default_template(&templ, stObj->pt, format);
416 
417    if (stObj->pt->target == PIPE_BUFFER) {
418       unsigned base, size;
419 
420       base = stObj->base.BufferOffset;
421       if (base >= stObj->pt->width0)
422          return NULL;
423       size = MIN2(stObj->pt->width0 - base, (unsigned)stObj->base.BufferSize);
424       if (!size)
425          return NULL;
426 
427       templ.u.buf.offset = base;
428       templ.u.buf.size = size;
429    } else {
430       templ.u.tex.first_level = stObj->base.MinLevel + stObj->base.BaseLevel;
431       templ.u.tex.last_level = last_level(stObj);
432       assert(templ.u.tex.first_level <= templ.u.tex.last_level);
433       if (stObj->layer_override) {
434          templ.u.tex.first_layer = templ.u.tex.last_layer = stObj->layer_override;
435       } else {
436          templ.u.tex.first_layer = stObj->base.MinLayer;
437          templ.u.tex.last_layer = last_layer(stObj);
438       }
439       assert(templ.u.tex.first_layer <= templ.u.tex.last_layer);
440       templ.target = gl_target_to_pipe(stObj->base.Target);
441    }
442 
443    templ.swizzle_r = GET_SWZ(swizzle, 0);
444    templ.swizzle_g = GET_SWZ(swizzle, 1);
445    templ.swizzle_b = GET_SWZ(swizzle, 2);
446    templ.swizzle_a = GET_SWZ(swizzle, 3);
447 
448    return st->pipe->create_sampler_view(st->pipe, stObj->pt, &templ);
449 }
450 
451 
452 struct pipe_sampler_view *
st_get_texture_sampler_view_from_stobj(struct st_context * st,struct st_texture_object * stObj,const struct gl_sampler_object * samp,unsigned glsl_version)453 st_get_texture_sampler_view_from_stobj(struct st_context *st,
454                                        struct st_texture_object *stObj,
455                                        const struct gl_sampler_object *samp,
456                                        unsigned glsl_version)
457 {
458    struct pipe_sampler_view **sv;
459 
460    if (!stObj || !stObj->pt) {
461       return NULL;
462    }
463 
464    sv = st_texture_get_sampler_view(st, stObj);
465 
466    if (*sv) {
467       /* Debug check: make sure that the sampler view's parameters are
468        * what they're supposed to be.
469        */
470       MAYBE_UNUSED struct pipe_sampler_view *view = *sv;
471       assert(!check_sampler_swizzle(st, stObj, view, glsl_version));
472       assert(get_sampler_view_format(st, stObj, samp) == view->format);
473       assert(gl_target_to_pipe(stObj->base.Target) == view->target);
474       if (stObj->base.Target == GL_TEXTURE_BUFFER) {
475          unsigned base = stObj->base.BufferOffset;
476          MAYBE_UNUSED unsigned size = MIN2(stObj->pt->width0 - base,
477                               (unsigned) stObj->base.BufferSize);
478          assert(view->u.buf.offset == base);
479          assert(view->u.buf.size == size);
480       }
481       else {
482          assert(stObj->base.MinLevel + stObj->base.BaseLevel ==
483                 view->u.tex.first_level);
484          assert(last_level(stObj) == view->u.tex.last_level);
485          assert(stObj->layer_override || stObj->base.MinLayer == view->u.tex.first_layer);
486          assert(stObj->layer_override || last_layer(stObj) == view->u.tex.last_layer);
487          assert(!stObj->layer_override ||
488                 (stObj->layer_override == view->u.tex.first_layer &&
489                  stObj->layer_override == view->u.tex.last_layer));
490       }
491    }
492    else {
493       /* create new sampler view */
494       enum pipe_format format = get_sampler_view_format(st, stObj, samp);
495 
496       *sv = st_create_texture_sampler_view_from_stobj(st, stObj,
497                                                       format, glsl_version);
498 
499    }
500 
501    return *sv;
502 }
503