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/context.h"
36#include "main/macros.h"
37#include "main/mtypes.h"
38#include "main/samplerobj.h"
39#include "main/teximage.h"
40#include "main/texobj.h"
41#include "program/prog_instruction.h"
42
43#include "st_context.h"
44#include "st_atom.h"
45#include "st_sampler_view.h"
46#include "st_texture.h"
47#include "st_format.h"
48#include "st_cb_texture.h"
49#include "pipe/p_context.h"
50#include "util/u_format.h"
51#include "util/u_inlines.h"
52#include "cso_cache/cso_context.h"
53
54
55/**
56 * Get a pipe_sampler_view object from a texture unit.
57 */
58void
59st_update_single_texture(struct st_context *st,
60                         struct pipe_sampler_view **sampler_view,
61                         GLuint texUnit, bool glsl130_or_later,
62                         bool ignore_srgb_decode)
63{
64   struct gl_context *ctx = st->ctx;
65   const struct gl_sampler_object *samp;
66   struct gl_texture_object *texObj;
67   struct st_texture_object *stObj;
68
69   samp = _mesa_get_samplerobj(ctx, texUnit);
70
71   texObj = ctx->Texture.Unit[texUnit]._Current;
72   assert(texObj);
73
74   stObj = st_texture_object(texObj);
75
76   if (unlikely(texObj->Target == GL_TEXTURE_BUFFER)) {
77      *sampler_view = st_get_buffer_sampler_view_from_stobj(st, stObj);
78      return;
79   }
80
81   if (!st_finalize_texture(ctx, st->pipe, texObj, 0) ||
82       !stObj->pt) {
83      /* out of mem */
84      *sampler_view = NULL;
85      return;
86   }
87
88   if (texObj->TargetIndex == TEXTURE_EXTERNAL_INDEX &&
89       stObj->pt->screen->resource_changed)
90         stObj->pt->screen->resource_changed(stObj->pt->screen, stObj->pt);
91
92   *sampler_view =
93      st_get_texture_sampler_view_from_stobj(st, stObj, samp,
94                                             glsl130_or_later,
95                                             ignore_srgb_decode);
96}
97
98
99
100static void
101update_textures(struct st_context *st,
102                enum pipe_shader_type shader_stage,
103                const struct gl_program *prog,
104                struct pipe_sampler_view **sampler_views)
105{
106   const GLuint old_max = st->state.num_sampler_views[shader_stage];
107   GLbitfield samplers_used = prog->SamplersUsed;
108   GLbitfield texel_fetch_samplers = prog->info.textures_used_by_txf;
109   GLbitfield free_slots = ~prog->SamplersUsed;
110   GLbitfield external_samplers_used = prog->ExternalSamplersUsed;
111   GLuint unit;
112
113   if (samplers_used == 0x0 && old_max == 0)
114      return;
115
116   unsigned num_textures = 0;
117
118   /* prog->sh.data is NULL if it's ARB_fragment_program */
119   bool glsl130 = (prog->sh.data ? prog->sh.data->Version : 0) >= 130;
120
121   /* loop over sampler units (aka tex image units) */
122   for (unit = 0; samplers_used || unit < old_max;
123        unit++, samplers_used >>= 1, texel_fetch_samplers >>= 1) {
124      struct pipe_sampler_view *sampler_view = NULL;
125
126      if (samplers_used & 1) {
127         const GLuint texUnit = prog->SamplerUnits[unit];
128
129         /* The EXT_texture_sRGB_decode extension says:
130          *
131          *    "The conversion of sRGB color space components to linear color
132          *     space is always performed if the texel lookup function is one
133          *     of the texelFetch builtin functions.
134          *
135          *     Otherwise, if the texel lookup function is one of the texture
136          *     builtin functions or one of the texture gather functions, the
137          *     conversion of sRGB color space components to linear color space
138          *     is controlled by the TEXTURE_SRGB_DECODE_EXT parameter.
139          *
140          *     If the TEXTURE_SRGB_DECODE_EXT parameter is DECODE_EXT, the
141          *     conversion of sRGB color space components to linear color space
142          *     is performed.
143          *
144          *     If the TEXTURE_SRGB_DECODE_EXT parameter is SKIP_DECODE_EXT,
145          *     the value is returned without decoding. However, if the texture
146          *     is also [statically] accessed with a texelFetch function, then
147          *     the result of texture builtin functions and/or texture gather
148          *     functions may be returned with decoding or without decoding."
149          *
150          * Note: the "statically" will be added to the language per
151          *       https://cvs.khronos.org/bugzilla/show_bug.cgi?id=14934
152          *
153          * So we simply ignore the setting entirely for samplers that are
154          * (statically) accessed with a texelFetch function.
155          */
156         st_update_single_texture(st, &sampler_view, texUnit, glsl130,
157                                  texel_fetch_samplers & 1);
158         num_textures = unit + 1;
159      }
160
161      pipe_sampler_view_reference(&(sampler_views[unit]), sampler_view);
162   }
163
164   /* For any external samplers with multiplaner YUV, stuff the additional
165    * sampler views we need at the end.
166    *
167    * Trying to cache the sampler view in the stObj looks painful, so just
168    * re-create the sampler view for the extra planes each time.  Main use
169    * case is video playback (ie. fps games wouldn't be using this) so I
170    * guess no point to try to optimize this feature.
171    */
172   while (unlikely(external_samplers_used)) {
173      GLuint unit = u_bit_scan(&external_samplers_used);
174      GLuint extra = 0;
175      struct st_texture_object *stObj =
176            st_get_texture_object(st->ctx, prog, unit);
177      struct pipe_sampler_view tmpl;
178
179      if (!stObj)
180         continue;
181
182      /* use original view as template: */
183      tmpl = *sampler_views[unit];
184
185      switch (st_get_view_format(stObj)) {
186      case PIPE_FORMAT_NV12:
187         /* we need one additional R8G8 view: */
188         tmpl.format = PIPE_FORMAT_RG88_UNORM;
189         tmpl.swizzle_g = PIPE_SWIZZLE_Y;   /* tmpl from Y plane is R8 */
190         extra = u_bit_scan(&free_slots);
191         sampler_views[extra] =
192               st->pipe->create_sampler_view(st->pipe, stObj->pt->next, &tmpl);
193         break;
194      case PIPE_FORMAT_IYUV:
195         /* we need two additional R8 views: */
196         tmpl.format = PIPE_FORMAT_R8_UNORM;
197         extra = u_bit_scan(&free_slots);
198         sampler_views[extra] =
199               st->pipe->create_sampler_view(st->pipe, stObj->pt->next, &tmpl);
200         extra = u_bit_scan(&free_slots);
201         sampler_views[extra] =
202               st->pipe->create_sampler_view(st->pipe, stObj->pt->next->next, &tmpl);
203         break;
204      default:
205         break;
206      }
207
208      num_textures = MAX2(num_textures, extra + 1);
209   }
210
211   cso_set_sampler_views(st->cso_context,
212                         shader_stage,
213                         num_textures,
214                         sampler_views);
215   st->state.num_sampler_views[shader_stage] = num_textures;
216}
217
218/* Same as update_textures, but don't store the views in st_context. */
219static void
220update_textures_local(struct st_context *st,
221                      enum pipe_shader_type shader_stage,
222                      const struct gl_program *prog)
223{
224   struct pipe_sampler_view *local_views[PIPE_MAX_SAMPLERS] = {0};
225
226   update_textures(st, shader_stage, prog, local_views);
227
228   unsigned num = st->state.num_sampler_views[shader_stage];
229   for (unsigned i = 0; i < num; i++)
230      pipe_sampler_view_reference(&local_views[i], NULL);
231}
232
233void
234st_update_vertex_textures(struct st_context *st)
235{
236   const struct gl_context *ctx = st->ctx;
237
238   if (ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits > 0) {
239      update_textures_local(st, PIPE_SHADER_VERTEX,
240                            ctx->VertexProgram._Current);
241   }
242}
243
244
245void
246st_update_fragment_textures(struct st_context *st)
247{
248   const struct gl_context *ctx = st->ctx;
249
250   update_textures(st,
251                   PIPE_SHADER_FRAGMENT,
252                   ctx->FragmentProgram._Current,
253                   st->state.frag_sampler_views);
254}
255
256
257void
258st_update_geometry_textures(struct st_context *st)
259{
260   const struct gl_context *ctx = st->ctx;
261
262   if (ctx->GeometryProgram._Current) {
263      update_textures_local(st, PIPE_SHADER_GEOMETRY,
264                            ctx->GeometryProgram._Current);
265   }
266}
267
268
269void
270st_update_tessctrl_textures(struct st_context *st)
271{
272   const struct gl_context *ctx = st->ctx;
273
274   if (ctx->TessCtrlProgram._Current) {
275      update_textures_local(st, PIPE_SHADER_TESS_CTRL,
276                            ctx->TessCtrlProgram._Current);
277   }
278}
279
280
281void
282st_update_tesseval_textures(struct st_context *st)
283{
284   const struct gl_context *ctx = st->ctx;
285
286   if (ctx->TessEvalProgram._Current) {
287      update_textures_local(st, PIPE_SHADER_TESS_EVAL,
288                            ctx->TessEvalProgram._Current);
289   }
290}
291
292
293void
294st_update_compute_textures(struct st_context *st)
295{
296   const struct gl_context *ctx = st->ctx;
297
298   if (ctx->ComputeProgram._Current) {
299      update_textures_local(st, PIPE_SHADER_COMPUTE,
300                            ctx->ComputeProgram._Current);
301   }
302}
303