Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 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 
31
  *   Brian Paul
32
  */
33
 
34
 
35
#include "main/macros.h"
36
#include "main/mtypes.h"
37
#include "main/samplerobj.h"
38
#include "main/teximage.h"
39
#include "main/texobj.h"
40
#include "program/prog_instruction.h"
41
 
42
#include "st_context.h"
43
#include "st_atom.h"
44
#include "st_texture.h"
45
#include "st_format.h"
46
#include "st_cb_texture.h"
47
#include "pipe/p_context.h"
48
#include "util/u_format.h"
49
#include "util/u_inlines.h"
50
#include "cso_cache/cso_context.h"
51
 
52
 
53
/**
54
 * Return swizzle1(swizzle2)
55
 */
56
static unsigned
57
swizzle_swizzle(unsigned swizzle1, unsigned swizzle2)
58
{
59
   unsigned i, swz[4];
60
 
61
   for (i = 0; i < 4; i++) {
62
      unsigned s = GET_SWZ(swizzle1, i);
63
      switch (s) {
64
      case SWIZZLE_X:
65
      case SWIZZLE_Y:
66
      case SWIZZLE_Z:
67
      case SWIZZLE_W:
68
         swz[i] = GET_SWZ(swizzle2, s);
69
         break;
70
      case SWIZZLE_ZERO:
71
         swz[i] = SWIZZLE_ZERO;
72
         break;
73
      case SWIZZLE_ONE:
74
         swz[i] = SWIZZLE_ONE;
75
         break;
76
      default:
77
         assert(!"Bad swizzle term");
78
         swz[i] = SWIZZLE_X;
79
      }
80
   }
81
 
82
   return MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]);
83
}
84
 
85
 
86
/**
87
 * Given a user-specified texture base format, the actual gallium texture
88
 * format and the current GL_DEPTH_MODE, return a texture swizzle.
89
 *
90
 * Consider the case where the user requests a GL_RGB internal texture
91
 * format the driver actually uses an RGBA format.  The A component should
92
 * be ignored and sampling from the texture should always return (r,g,b,1).
93
 * But if we rendered to the texture we might have written A values != 1.
94
 * By sampling the texture with a ".xyz1" swizzle we'll get the expected A=1.
95
 * This function computes the texture swizzle needed to get the expected
96
 * values.
97
 *
98
 * In the case of depth textures, the GL_DEPTH_MODE state determines the
99
 * texture swizzle.
100
 *
101
 * This result must be composed with the user-specified swizzle to get
102
 * the final swizzle.
103
 */
104
static unsigned
105
compute_texture_format_swizzle(GLenum baseFormat, GLenum depthMode,
106
                               enum pipe_format actualFormat)
107
{
108
   switch (baseFormat) {
109
   case GL_RGBA:
110
      return SWIZZLE_XYZW;
111
   case GL_RGB:
112
      if (util_format_has_alpha(actualFormat))
113
         return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ONE);
114
      else
115
         return SWIZZLE_XYZW;
116
   case GL_RG:
117
      if (util_format_get_nr_components(actualFormat) > 2)
118
         return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_ZERO, SWIZZLE_ONE);
119
      else
120
         return SWIZZLE_XYZW;
121
   case GL_RED:
122
      if (util_format_get_nr_components(actualFormat) > 1)
123
         return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO,
124
                              SWIZZLE_ZERO, SWIZZLE_ONE);
125
      else
126
         return SWIZZLE_XYZW;
127
   case GL_ALPHA:
128
      if (util_format_get_nr_components(actualFormat) > 1)
129
         return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO,
130
                              SWIZZLE_ZERO, SWIZZLE_W);
131
      else
132
         return SWIZZLE_XYZW;
133
   case GL_LUMINANCE:
134
      if (util_format_get_nr_components(actualFormat) > 1)
135
         return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE);
136
      else
137
         return SWIZZLE_XYZW;
138
   case GL_LUMINANCE_ALPHA:
139
      if (util_format_get_nr_components(actualFormat) > 2)
140
         return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_W);
141
      else
142
         return SWIZZLE_XYZW;
143
   case GL_INTENSITY:
144
      if (util_format_get_nr_components(actualFormat) > 1)
145
         return SWIZZLE_XXXX;
146
      else
147
         return SWIZZLE_XYZW;
148
   case GL_STENCIL_INDEX:
149
      return SWIZZLE_XYZW;
150
   case GL_DEPTH_STENCIL:
151
      /* fall-through */
152
   case GL_DEPTH_COMPONENT:
153
      /* Now examine the depth mode */
154
      switch (depthMode) {
155
      case GL_LUMINANCE:
156
         return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE);
157
      case GL_INTENSITY:
158
         return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X);
159
      case GL_ALPHA:
160
         return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO,
161
                              SWIZZLE_ZERO, SWIZZLE_X);
162
      case GL_RED:
163
         return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO,
164
                              SWIZZLE_ZERO, SWIZZLE_ONE);
165
      default:
166
         assert(!"Unexpected depthMode");
167
         return SWIZZLE_XYZW;
168
      }
169
   default:
170
      assert(!"Unexpected baseFormat");
171
      return SWIZZLE_XYZW;
172
   }
173
}
174
 
175
 
176
static unsigned
177
get_texture_format_swizzle(const struct st_texture_object *stObj)
178
{
179
   GLenum baseFormat = _mesa_texture_base_format(&stObj->base);
180
   unsigned tex_swizzle;
181
 
182
   if (baseFormat != GL_NONE) {
183
      tex_swizzle = compute_texture_format_swizzle(baseFormat,
184
                                                   stObj->base.DepthMode,
185
                                                   stObj->pt->format);
186
   }
187
   else {
188
      tex_swizzle = SWIZZLE_XYZW;
189
   }
190
 
191
   /* Combine the texture format swizzle with user's swizzle */
192
   return swizzle_swizzle(stObj->base._Swizzle, tex_swizzle);
193
}
194
 
195
 
196
/**
197
 * Return TRUE if the texture's sampler view swizzle is not equal to
198
 * the texture's swizzle.
199
 *
200
 * \param stObj  the st texture object,
201
 */
202
static boolean
203
check_sampler_swizzle(const struct st_texture_object *stObj,
204
		      struct pipe_sampler_view *sv)
205
{
206
   unsigned swizzle = get_texture_format_swizzle(stObj);
207
 
208
   return ((sv->swizzle_r != GET_SWZ(swizzle, 0)) ||
209
           (sv->swizzle_g != GET_SWZ(swizzle, 1)) ||
210
           (sv->swizzle_b != GET_SWZ(swizzle, 2)) ||
211
           (sv->swizzle_a != GET_SWZ(swizzle, 3)));
212
}
213
 
214
 
215
static unsigned last_level(struct st_texture_object *stObj)
216
{
217
   unsigned ret = MIN2(stObj->base.MinLevel + stObj->base._MaxLevel,
218
                       stObj->pt->last_level);
219
   if (stObj->base.Immutable)
220
      ret = MIN2(ret, stObj->base.MinLevel + stObj->base.NumLevels - 1);
221
   return ret;
222
}
223
 
224
static unsigned last_layer(struct st_texture_object *stObj)
225
{
226
   if (stObj->base.Immutable && stObj->pt->array_size > 1)
227
      return MIN2(stObj->base.MinLayer + stObj->base.NumLayers - 1,
228
                  stObj->pt->array_size - 1);
229
   return stObj->pt->array_size - 1;
230
}
231
 
232
static struct pipe_sampler_view *
233
st_create_texture_sampler_view_from_stobj(struct pipe_context *pipe,
234
					  struct st_texture_object *stObj,
235
                                          const struct gl_sampler_object *samp,
236
					  enum pipe_format format)
237
{
238
   struct pipe_sampler_view templ;
239
   unsigned swizzle = get_texture_format_swizzle(stObj);
240
 
241
   u_sampler_view_default_template(&templ,
242
                                   stObj->pt,
243
                                   format);
244
 
245
   if (stObj->pt->target == PIPE_BUFFER) {
246
      unsigned base, size;
247
      unsigned f, n;
248
      const struct util_format_description *desc
249
         = util_format_description(templ.format);
250
 
251
      base = stObj->base.BufferOffset;
252
      if (base >= stObj->pt->width0)
253
         return NULL;
254
      size = MIN2(stObj->pt->width0 - base, (unsigned)stObj->base.BufferSize);
255
 
256
      f = ((base * 8) / desc->block.bits) * desc->block.width;
257
      n = ((size * 8) / desc->block.bits) * desc->block.width;
258
      if (!n)
259
         return NULL;
260
      templ.u.buf.first_element = f;
261
      templ.u.buf.last_element  = f + (n - 1);
262
   } else {
263
      templ.u.tex.first_level = stObj->base.MinLevel + stObj->base.BaseLevel;
264
      templ.u.tex.last_level = last_level(stObj);
265
      assert(templ.u.tex.first_level <= templ.u.tex.last_level);
266
      templ.u.tex.first_layer = stObj->base.MinLayer;
267
      templ.u.tex.last_layer = last_layer(stObj);
268
      assert(templ.u.tex.first_layer <= templ.u.tex.last_layer);
269
      templ.target = gl_target_to_pipe(stObj->base.Target);
270
   }
271
 
272
   if (swizzle != SWIZZLE_NOOP) {
273
      templ.swizzle_r = GET_SWZ(swizzle, 0);
274
      templ.swizzle_g = GET_SWZ(swizzle, 1);
275
      templ.swizzle_b = GET_SWZ(swizzle, 2);
276
      templ.swizzle_a = GET_SWZ(swizzle, 3);
277
   }
278
 
279
   return pipe->create_sampler_view(pipe, stObj->pt, &templ);
280
}
281
 
282
 
283
static struct pipe_sampler_view *
284
st_get_texture_sampler_view_from_stobj(struct st_context *st,
285
                                       struct st_texture_object *stObj,
286
                                       const struct gl_sampler_object *samp,
287
				       enum pipe_format format)
288
{
289
   struct pipe_sampler_view **sv;
290
   const struct st_texture_image *firstImage;
291
   if (!stObj || !stObj->pt) {
292
      return NULL;
293
   }
294
 
295
   sv = st_texture_get_sampler_view(st, stObj);
296
 
297
   if (util_format_is_depth_and_stencil(format)) {
298
      if (stObj->base.StencilSampling)
299
         format = util_format_stencil_only(format);
300
      else {
301
         firstImage = st_texture_image_const(_mesa_base_tex_image(&stObj->base));
302
         if (firstImage->base._BaseFormat == GL_STENCIL_INDEX)
303
            format = util_format_stencil_only(format);
304
      }
305
   }
306
 
307
   /* if sampler view has changed dereference it */
308
   if (*sv) {
309
      if (check_sampler_swizzle(stObj, *sv) ||
310
	  (format != (*sv)->format) ||
311
          gl_target_to_pipe(stObj->base.Target) != (*sv)->target ||
312
          stObj->base.MinLevel + stObj->base.BaseLevel != (*sv)->u.tex.first_level ||
313
          last_level(stObj) != (*sv)->u.tex.last_level ||
314
          stObj->base.MinLayer != (*sv)->u.tex.first_layer ||
315
          last_layer(stObj) != (*sv)->u.tex.last_layer) {
316
	 pipe_sampler_view_reference(sv, NULL);
317
      }
318
   }
319
 
320
   if (!*sv) {
321
      *sv = st_create_texture_sampler_view_from_stobj(st->pipe, stObj, samp, format);
322
 
323
   } else if ((*sv)->context != st->pipe) {
324
      /* Recreate view in correct context, use existing view as template */
325
      struct pipe_sampler_view *new_sv =
326
         st->pipe->create_sampler_view(st->pipe, stObj->pt, *sv);
327
      pipe_sampler_view_reference(sv, NULL);
328
      *sv = new_sv;
329
   }
330
 
331
   return *sv;
332
}
333
 
334
static GLboolean
335
update_single_texture(struct st_context *st,
336
                      struct pipe_sampler_view **sampler_view,
337
		      GLuint texUnit)
338
{
339
   struct gl_context *ctx = st->ctx;
340
   const struct gl_sampler_object *samp;
341
   struct gl_texture_object *texObj;
342
   struct st_texture_object *stObj;
343
   enum pipe_format view_format;
344
   GLboolean retval;
345
 
346
   samp = _mesa_get_samplerobj(ctx, texUnit);
347
 
348
   texObj = ctx->Texture.Unit[texUnit]._Current;
349
 
350
   if (!texObj) {
351
      texObj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX);
352
      samp = &texObj->Sampler;
353
   }
354
   stObj = st_texture_object(texObj);
355
 
356
   retval = st_finalize_texture(ctx, st->pipe, texObj);
357
   if (!retval) {
358
      /* out of mem */
359
      return GL_FALSE;
360
   }
361
 
362
   /* Determine the format of the texture sampler view */
363
   if (texObj->Target == GL_TEXTURE_BUFFER) {
364
      view_format =
365
         st_mesa_format_to_pipe_format(st, stObj->base._BufferObjectFormat);
366
   }
367
   else {
368
      view_format =
369
         stObj->surface_based ? stObj->surface_format : stObj->pt->format;
370
 
371
      /* If sRGB decoding is off, use the linear format */
372
      if (samp->sRGBDecode == GL_SKIP_DECODE_EXT) {
373
         view_format = util_format_linear(view_format);
374
      }
375
   }
376
 
377
   *sampler_view = st_get_texture_sampler_view_from_stobj(st, stObj, samp,
378
							  view_format);
379
   return GL_TRUE;
380
}
381
 
382
 
383
 
384
static void
385
update_textures(struct st_context *st,
386
                unsigned shader_stage,
387
                const struct gl_program *prog,
388
                unsigned max_units,
389
                struct pipe_sampler_view **sampler_views,
390
                unsigned *num_textures)
391
{
392
   const GLuint old_max = *num_textures;
393
   GLbitfield samplers_used = prog->SamplersUsed;
394
   GLuint unit;
395
 
396
   if (samplers_used == 0x0 && old_max == 0)
397
      return;
398
 
399
   *num_textures = 0;
400
 
401
   /* loop over sampler units (aka tex image units) */
402
   for (unit = 0; unit < max_units; unit++, samplers_used >>= 1) {
403
      struct pipe_sampler_view *sampler_view = NULL;
404
 
405
      if (samplers_used & 1) {
406
         const GLuint texUnit = prog->SamplerUnits[unit];
407
         GLboolean retval;
408
 
409
         retval = update_single_texture(st, &sampler_view, texUnit);
410
         if (retval == GL_FALSE)
411
            continue;
412
 
413
         *num_textures = unit + 1;
414
      }
415
      else if (samplers_used == 0 && unit >= old_max) {
416
         /* if we've reset all the old views and we have no more new ones */
417
         break;
418
      }
419
 
420
      pipe_sampler_view_reference(&(sampler_views[unit]), sampler_view);
421
   }
422
 
423
   cso_set_sampler_views(st->cso_context,
424
                         shader_stage,
425
                         *num_textures,
426
                         sampler_views);
427
}
428
 
429
 
430
 
431
static void
432
update_vertex_textures(struct st_context *st)
433
{
434
   const struct gl_context *ctx = st->ctx;
435
 
436
   if (ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits > 0) {
437
      update_textures(st,
438
                      PIPE_SHADER_VERTEX,
439
                      &ctx->VertexProgram._Current->Base,
440
                      ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits,
441
                      st->state.sampler_views[PIPE_SHADER_VERTEX],
442
                      &st->state.num_sampler_views[PIPE_SHADER_VERTEX]);
443
   }
444
}
445
 
446
 
447
static void
448
update_fragment_textures(struct st_context *st)
449
{
450
   const struct gl_context *ctx = st->ctx;
451
 
452
   update_textures(st,
453
                   PIPE_SHADER_FRAGMENT,
454
                   &ctx->FragmentProgram._Current->Base,
455
                   ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits,
456
                   st->state.sampler_views[PIPE_SHADER_FRAGMENT],
457
                   &st->state.num_sampler_views[PIPE_SHADER_FRAGMENT]);
458
}
459
 
460
 
461
static void
462
update_geometry_textures(struct st_context *st)
463
{
464
   const struct gl_context *ctx = st->ctx;
465
 
466
   if (ctx->GeometryProgram._Current) {
467
      update_textures(st,
468
                      PIPE_SHADER_GEOMETRY,
469
                      &ctx->GeometryProgram._Current->Base,
470
                      ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits,
471
                      st->state.sampler_views[PIPE_SHADER_GEOMETRY],
472
                      &st->state.num_sampler_views[PIPE_SHADER_GEOMETRY]);
473
   }
474
}
475
 
476
 
477
const struct st_tracked_state st_update_fragment_texture = {
478
   "st_update_texture",					/* name */
479
   {							/* dirty */
480
      _NEW_TEXTURE,					/* mesa */
481
      ST_NEW_FRAGMENT_PROGRAM,				/* st */
482
   },
483
   update_fragment_textures				/* update */
484
};
485
 
486
 
487
const struct st_tracked_state st_update_vertex_texture = {
488
   "st_update_vertex_texture",				/* name */
489
   {							/* dirty */
490
      _NEW_TEXTURE,					/* mesa */
491
      ST_NEW_VERTEX_PROGRAM,				/* st */
492
   },
493
   update_vertex_textures				/* update */
494
};
495
 
496
 
497
const struct st_tracked_state st_update_geometry_texture = {
498
   "st_update_geometry_texture",			/* name */
499
   {							/* dirty */
500
      _NEW_TEXTURE,					/* mesa */
501
      ST_NEW_GEOMETRY_PROGRAM,				/* st */
502
   },
503
   update_geometry_textures				/* update */
504
};
505
 
506
 
507
 
508
static void
509
finalize_textures(struct st_context *st)
510
{
511
   struct gl_context *ctx = st->ctx;
512
   struct gl_fragment_program *fprog = ctx->FragmentProgram._Current;
513
   const GLboolean prev_missing_textures = st->missing_textures;
514
   GLuint su;
515
 
516
   st->missing_textures = GL_FALSE;
517
 
518
   for (su = 0; su < ctx->Const.MaxTextureCoordUnits; su++) {
519
      if (fprog->Base.SamplersUsed & (1 << su)) {
520
         const GLuint texUnit = fprog->Base.SamplerUnits[su];
521
         struct gl_texture_object *texObj
522
            = ctx->Texture.Unit[texUnit]._Current;
523
 
524
         if (texObj) {
525
            GLboolean retval;
526
 
527
            retval = st_finalize_texture(ctx, st->pipe, texObj);
528
            if (!retval) {
529
               /* out of mem */
530
               st->missing_textures = GL_TRUE;
531
               continue;
532
            }
533
         }
534
      }
535
   }
536
 
537
   if (prev_missing_textures != st->missing_textures)
538
      st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
539
}
540
 
541
 
542
const struct st_tracked_state st_finalize_textures = {
543
   "st_finalize_textures",		/* name */
544
   {					/* dirty */
545
      _NEW_TEXTURE,			/* mesa */
546
      0,				/* st */
547
   },
548
   finalize_textures			/* update */
549
};