Subversion Repositories Kolibri OS

Rev

Rev 4358 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/**************************************************************************
2
 *
3
 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
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 TUNGSTEN GRAPHICS 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
#include "main/mtypes.h"
29
#include "main/enums.h"
30
#include "main/macros.h"
31
#include "main/colormac.h"
32
#include "main/samplerobj.h"
33
 
34
#include "intel_mipmap_tree.h"
35
#include "intel_tex.h"
36
 
37
#include "i915_context.h"
38
#include "i915_reg.h"
39
 
40
 
41
static GLuint
42
translate_texture_format(gl_format mesa_format, GLenum DepthMode)
43
{
44
   switch (mesa_format) {
45
   case MESA_FORMAT_L8:
46
      return MAPSURF_8BIT | MT_8BIT_L8;
47
   case MESA_FORMAT_I8:
48
      return MAPSURF_8BIT | MT_8BIT_I8;
49
   case MESA_FORMAT_A8:
4633 Serge 50
   case MESA_FORMAT_R8:
4358 Serge 51
      return MAPSURF_8BIT | MT_8BIT_A8;
52
   case MESA_FORMAT_AL88:
53
      return MAPSURF_16BIT | MT_16BIT_AY88;
54
   case MESA_FORMAT_RGB565:
55
      return MAPSURF_16BIT | MT_16BIT_RGB565;
56
   case MESA_FORMAT_ARGB1555:
57
      return MAPSURF_16BIT | MT_16BIT_ARGB1555;
58
   case MESA_FORMAT_ARGB4444:
59
      return MAPSURF_16BIT | MT_16BIT_ARGB4444;
60
   case MESA_FORMAT_SARGB8:
61
   case MESA_FORMAT_ARGB8888:
62
      return MAPSURF_32BIT | MT_32BIT_ARGB8888;
63
   case MESA_FORMAT_XRGB8888:
64
      return MAPSURF_32BIT | MT_32BIT_XRGB8888;
65
   case MESA_FORMAT_RGBA8888_REV:
66
      return MAPSURF_32BIT | MT_32BIT_ABGR8888;
67
   case MESA_FORMAT_YCBCR_REV:
68
      return (MAPSURF_422 | MT_422_YCRCB_NORMAL);
69
   case MESA_FORMAT_YCBCR:
70
      return (MAPSURF_422 | MT_422_YCRCB_SWAPY);
71
   case MESA_FORMAT_RGB_FXT1:
72
   case MESA_FORMAT_RGBA_FXT1:
73
      return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1);
74
   case MESA_FORMAT_Z16:
75
      if (DepthMode == GL_ALPHA)
76
          return (MAPSURF_16BIT | MT_16BIT_A16);
77
      else if (DepthMode == GL_INTENSITY)
78
          return (MAPSURF_16BIT | MT_16BIT_I16);
79
      else
80
          return (MAPSURF_16BIT | MT_16BIT_L16);
81
   case MESA_FORMAT_RGBA_DXT1:
82
   case MESA_FORMAT_RGB_DXT1:
83
   case MESA_FORMAT_SRGB_DXT1:
84
   case MESA_FORMAT_SRGBA_DXT1:
85
      return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
86
   case MESA_FORMAT_RGBA_DXT3:
87
   case MESA_FORMAT_SRGBA_DXT3:
88
      return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
89
   case MESA_FORMAT_RGBA_DXT5:
90
   case MESA_FORMAT_SRGBA_DXT5:
91
      return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
92
   case MESA_FORMAT_S8_Z24:
93
   case MESA_FORMAT_X8_Z24:
94
      if (DepthMode == GL_ALPHA)
95
	 return (MAPSURF_32BIT | MT_32BIT_x8A24);
96
      else if (DepthMode == GL_INTENSITY)
97
	 return (MAPSURF_32BIT | MT_32BIT_x8I24);
98
      else
99
	 return (MAPSURF_32BIT | MT_32BIT_x8L24);
100
   default:
101
      fprintf(stderr, "%s: bad image format %s\n", __FUNCTION__,
102
	      _mesa_get_format_name(mesa_format));
103
      abort();
104
      return 0;
105
   }
106
}
107
 
108
 
109
 
110
 
111
/* The i915 (and related graphics cores) do not support GL_CLAMP.  The
112
 * Intel drivers for "other operating systems" implement GL_CLAMP as
113
 * GL_CLAMP_TO_EDGE, so the same is done here.
114
 */
115
static GLuint
116
translate_wrap_mode(GLenum wrap)
117
{
118
   switch (wrap) {
119
   case GL_REPEAT:
120
      return TEXCOORDMODE_WRAP;
121
   case GL_CLAMP:
122
      return TEXCOORDMODE_CLAMP_EDGE;   /* not quite correct */
123
   case GL_CLAMP_TO_EDGE:
124
      return TEXCOORDMODE_CLAMP_EDGE;
125
   case GL_CLAMP_TO_BORDER:
126
      return TEXCOORDMODE_CLAMP_BORDER;
127
   case GL_MIRRORED_REPEAT:
128
      return TEXCOORDMODE_MIRROR;
129
   default:
130
      return TEXCOORDMODE_WRAP;
131
   }
132
}
133
 
134
 
135
 
136
/* Recalculate all state from scratch.  Perhaps not the most
137
 * efficient, but this has gotten complex enough that we need
138
 * something which is understandable and reliable.
139
 */
140
static bool
141
i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
142
{
143
   struct gl_context *ctx = &intel->ctx;
144
   struct i915_context *i915 = i915_context(ctx);
145
   struct gl_texture_unit *tUnit = &ctx->Texture.Unit[unit];
146
   struct gl_texture_object *tObj = tUnit->_Current;
147
   struct intel_texture_object *intelObj = intel_texture_object(tObj);
148
   struct gl_texture_image *firstImage;
149
   struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit);
150
   GLuint *state = i915->state.Tex[unit], format;
151
   GLint lodbias, aniso = 0;
152
   GLubyte border[4];
153
   GLfloat maxlod;
154
 
155
   memset(state, 0, sizeof(*state));
156
 
157
   /*We need to refcount these. */
158
 
159
   if (i915->state.tex_buffer[unit] != NULL) {
160
       drm_intel_bo_unreference(i915->state.tex_buffer[unit]);
161
       i915->state.tex_buffer[unit] = NULL;
162
   }
163
 
164
   if (!intel_finalize_mipmap_tree(intel, unit))
165
      return false;
166
 
167
   /* Get first image here, since intelObj->firstLevel will get set in
168
    * the intel_finalize_mipmap_tree() call above.
169
    */
170
   firstImage = tObj->Image[0][tObj->BaseLevel];
171
 
172
   drm_intel_bo_reference(intelObj->mt->region->bo);
173
   i915->state.tex_buffer[unit] = intelObj->mt->region->bo;
174
   i915->state.tex_offset[unit] = intelObj->mt->offset;
175
 
176
   format = translate_texture_format(firstImage->TexFormat,
177
				     tObj->DepthMode);
178
 
179
   state[I915_TEXREG_MS3] =
180
      (((firstImage->Height - 1) << MS3_HEIGHT_SHIFT) |
181
       ((firstImage->Width - 1) << MS3_WIDTH_SHIFT) | format);
182
 
183
   if (intelObj->mt->region->tiling != I915_TILING_NONE) {
184
      state[I915_TEXREG_MS3] |= MS3_TILED_SURFACE;
185
      if (intelObj->mt->region->tiling == I915_TILING_Y)
186
	 state[I915_TEXREG_MS3] |= MS3_TILE_WALK;
187
   }
188
 
189
   /* We get one field with fraction bits for the maximum addressable
190
    * (lowest resolution) LOD.  Use it to cover both MAX_LEVEL and
191
    * MAX_LOD.
192
    */
193
   maxlod = MIN2(sampler->MaxLod, tObj->_MaxLevel - tObj->BaseLevel);
194
   state[I915_TEXREG_MS4] =
195
      ((((intelObj->mt->region->pitch / 4) - 1) << MS4_PITCH_SHIFT) |
196
       MS4_CUBE_FACE_ENA_MASK |
197
       (U_FIXED(CLAMP(maxlod, 0.0, 11.0), 2) << MS4_MAX_LOD_SHIFT) |
198
       ((firstImage->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT));
199
 
200
 
201
   {
202
      GLuint minFilt, mipFilt, magFilt;
203
 
204
      switch (sampler->MinFilter) {
205
      case GL_NEAREST:
206
         minFilt = FILTER_NEAREST;
207
         mipFilt = MIPFILTER_NONE;
208
         break;
209
      case GL_LINEAR:
210
         minFilt = FILTER_LINEAR;
211
         mipFilt = MIPFILTER_NONE;
212
         break;
213
      case GL_NEAREST_MIPMAP_NEAREST:
214
         minFilt = FILTER_NEAREST;
215
         mipFilt = MIPFILTER_NEAREST;
216
         break;
217
      case GL_LINEAR_MIPMAP_NEAREST:
218
         minFilt = FILTER_LINEAR;
219
         mipFilt = MIPFILTER_NEAREST;
220
         break;
221
      case GL_NEAREST_MIPMAP_LINEAR:
222
         minFilt = FILTER_NEAREST;
223
         mipFilt = MIPFILTER_LINEAR;
224
         break;
225
      case GL_LINEAR_MIPMAP_LINEAR:
226
         minFilt = FILTER_LINEAR;
227
         mipFilt = MIPFILTER_LINEAR;
228
         break;
229
      default:
230
         return false;
231
      }
232
 
233
      if (sampler->MaxAnisotropy > 1.0) {
234
         minFilt = FILTER_ANISOTROPIC;
235
         magFilt = FILTER_ANISOTROPIC;
236
         if (sampler->MaxAnisotropy > 2.0)
237
            aniso = SS2_MAX_ANISO_4;
238
         else
239
            aniso = SS2_MAX_ANISO_2;
240
      }
241
      else {
242
         switch (sampler->MagFilter) {
243
         case GL_NEAREST:
244
            magFilt = FILTER_NEAREST;
245
            break;
246
         case GL_LINEAR:
247
            magFilt = FILTER_LINEAR;
248
            break;
249
         default:
250
            return false;
251
         }
252
      }
253
 
254
      lodbias = (int) ((tUnit->LodBias + sampler->LodBias) * 16.0);
255
      if (lodbias < -256)
256
          lodbias = -256;
257
      if (lodbias > 255)
258
          lodbias = 255;
259
      state[I915_TEXREG_SS2] = ((lodbias << SS2_LOD_BIAS_SHIFT) &
260
                                SS2_LOD_BIAS_MASK);
261
 
262
      /* YUV conversion:
263
       */
264
      if (firstImage->TexFormat == MESA_FORMAT_YCBCR ||
265
          firstImage->TexFormat == MESA_FORMAT_YCBCR_REV)
266
         state[I915_TEXREG_SS2] |= SS2_COLORSPACE_CONVERSION;
267
 
268
      /* Shadow:
269
       */
270
      if (sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB &&
271
          tObj->Target != GL_TEXTURE_3D) {
272
         if (tObj->Target == GL_TEXTURE_1D)
273
            return false;
274
 
275
         state[I915_TEXREG_SS2] |=
276
            (SS2_SHADOW_ENABLE |
277
             intel_translate_shadow_compare_func(sampler->CompareFunc));
278
 
279
         minFilt = FILTER_4X4_FLAT;
280
         magFilt = FILTER_4X4_FLAT;
281
      }
282
 
283
      state[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) |
284
                                 (mipFilt << SS2_MIP_FILTER_SHIFT) |
285
                                 (magFilt << SS2_MAG_FILTER_SHIFT) |
286
                                 aniso);
287
   }
288
 
289
   {
290
      GLenum ws = sampler->WrapS;
291
      GLenum wt = sampler->WrapT;
292
      GLenum wr = sampler->WrapR;
293
      float minlod;
294
 
295
      /* We program 1D textures as 2D textures, so the 2D texcoord could
296
       * result in sampling border values if we don't set the T wrap to
297
       * repeat.
298
       */
299
      if (tObj->Target == GL_TEXTURE_1D)
300
	 wt = GL_REPEAT;
301
 
302
      /* 3D textures don't seem to respect the border color.
303
       * Fallback if there's ever a danger that they might refer to
304
       * it.
305
       *
306
       * Effectively this means fallback on 3D clamp or
307
       * clamp_to_border.
308
       */
309
      if (tObj->Target == GL_TEXTURE_3D &&
310
          (sampler->MinFilter != GL_NEAREST ||
311
           sampler->MagFilter != GL_NEAREST) &&
312
          (ws == GL_CLAMP ||
313
           wt == GL_CLAMP ||
314
           wr == GL_CLAMP ||
315
           ws == GL_CLAMP_TO_BORDER ||
316
           wt == GL_CLAMP_TO_BORDER || wr == GL_CLAMP_TO_BORDER))
317
         return false;
318
 
319
      /* Only support TEXCOORDMODE_CLAMP_EDGE and TEXCOORDMODE_CUBE (not
320
       * used) when using cube map texture coordinates
321
       */
322
      if (tObj->Target == GL_TEXTURE_CUBE_MAP_ARB &&
323
          (((ws != GL_CLAMP) && (ws != GL_CLAMP_TO_EDGE)) ||
324
           ((wt != GL_CLAMP) && (wt != GL_CLAMP_TO_EDGE))))
325
          return false;
326
 
327
      /*
328
       * According to 3DSTATE_MAP_STATE at page of 104 in Bspec
329
       * Vol3d 3D Instructions:
330
       *   [DevGDG and DevAlv]: Must be a power of 2 for cube maps.
331
       *   [DevLPT, DevCST and DevBLB]: If not a power of 2, cube maps
332
       *      must have all faces enabled.
333
       *
334
       * But, as I tested on pineview(DevBLB derived), the rendering is
335
       * bad(you will find the color isn't samplered right in some
336
       * fragments). After checking, it seems that the texture layout is
337
       * wrong: making the width and height align of 4(although this
338
       * doesn't make much sense) will fix this issue and also broke some
339
       * others. Well, Bspec mentioned nothing about the layout alignment
340
       * and layout for NPOT cube map.  I guess the Bspec just assume it's
341
       * a POT cube map.
342
       *
343
       * Thus, I guess we need do this for other platforms as well.
344
       */
345
      if (tObj->Target == GL_TEXTURE_CUBE_MAP_ARB &&
346
          !is_power_of_two(firstImage->Height))
347
         return false;
348
 
349
      state[I915_TEXREG_SS3] = ss3;     /* SS3_NORMALIZED_COORDS */
350
 
351
      state[I915_TEXREG_SS3] |=
352
         ((translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT) |
353
          (translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT) |
354
          (translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT));
355
 
356
      minlod = MIN2(sampler->MinLod, tObj->_MaxLevel - tObj->BaseLevel);
357
      state[I915_TEXREG_SS3] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT);
358
      state[I915_TEXREG_SS3] |= (U_FIXED(CLAMP(minlod, 0.0, 11.0), 4) <<
359
				 SS3_MIN_LOD_SHIFT);
360
 
361
   }
362
 
363
   if (sampler->sRGBDecode == GL_DECODE_EXT &&
364
       (_mesa_get_srgb_format_linear(firstImage->TexFormat) !=
365
        firstImage->TexFormat)) {
366
      state[I915_TEXREG_SS2] |= SS2_REVERSE_GAMMA_ENABLE;
367
   }
368
 
369
   /* convert border color from float to ubyte */
370
   CLAMPED_FLOAT_TO_UBYTE(border[0], sampler->BorderColor.f[0]);
371
   CLAMPED_FLOAT_TO_UBYTE(border[1], sampler->BorderColor.f[1]);
372
   CLAMPED_FLOAT_TO_UBYTE(border[2], sampler->BorderColor.f[2]);
373
   CLAMPED_FLOAT_TO_UBYTE(border[3], sampler->BorderColor.f[3]);
374
 
375
   if (firstImage->_BaseFormat == GL_DEPTH_COMPONENT) {
376
      /* GL specs that border color for depth textures is taken from the
377
       * R channel, while the hardware uses A.  Spam R into all the channels
378
       * for safety.
379
       */
380
      state[I915_TEXREG_SS4] = PACK_COLOR_8888(border[0],
381
					       border[0],
382
					       border[0],
383
					       border[0]);
384
   } else {
385
      state[I915_TEXREG_SS4] = PACK_COLOR_8888(border[3],
386
					       border[0],
387
					       border[1],
388
					       border[2]);
389
   }
390
 
391
 
392
   I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), true);
393
   /* memcmp was already disabled, but definitely won't work as the
394
    * region might now change and that wouldn't be detected:
395
    */
396
   I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit));
397
 
398
 
399
#if 0
400
   DBG(TEXTURE, "state[I915_TEXREG_SS2] = 0x%x\n", state[I915_TEXREG_SS2]);
401
   DBG(TEXTURE, "state[I915_TEXREG_SS3] = 0x%x\n", state[I915_TEXREG_SS3]);
402
   DBG(TEXTURE, "state[I915_TEXREG_SS4] = 0x%x\n", state[I915_TEXREG_SS4]);
403
   DBG(TEXTURE, "state[I915_TEXREG_MS2] = 0x%x\n", state[I915_TEXREG_MS2]);
404
   DBG(TEXTURE, "state[I915_TEXREG_MS3] = 0x%x\n", state[I915_TEXREG_MS3]);
405
   DBG(TEXTURE, "state[I915_TEXREG_MS4] = 0x%x\n", state[I915_TEXREG_MS4]);
406
#endif
407
 
408
   return true;
409
}
410
 
411
 
412
 
413
 
414
void
415
i915UpdateTextureState(struct intel_context *intel)
416
{
417
   bool ok = true;
418
   GLuint i;
419
 
420
   for (i = 0; i < I915_TEX_UNITS && ok; i++) {
421
      switch (intel->ctx.Texture.Unit[i]._ReallyEnabled) {
422
      case TEXTURE_1D_BIT:
423
      case TEXTURE_2D_BIT:
424
      case TEXTURE_CUBE_BIT:
425
      case TEXTURE_3D_BIT:
426
         ok = i915_update_tex_unit(intel, i, SS3_NORMALIZED_COORDS);
427
         break;
428
      case TEXTURE_RECT_BIT:
429
         ok = i915_update_tex_unit(intel, i, 0);
430
         break;
431
      case 0:{
432
            struct i915_context *i915 = i915_context(&intel->ctx);
433
            if (i915->state.active & I915_UPLOAD_TEX(i))
434
               I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(i), false);
435
 
436
	    if (i915->state.tex_buffer[i] != NULL) {
437
	       drm_intel_bo_unreference(i915->state.tex_buffer[i]);
438
	       i915->state.tex_buffer[i] = NULL;
439
	    }
440
 
441
            break;
442
         }
443
      default:
444
         ok = false;
445
         break;
446
      }
447
   }
448
 
449
   FALLBACK(intel, I915_FALLBACK_TEXTURE, !ok);
450
}