Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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