Home | History | Annotate | Download | only in i915
      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/colormac.h"
     31 #include "main/macros.h"
     32 #include "main/samplerobj.h"
     33 
     34 #include "intel_mipmap_tree.h"
     35 #include "intel_tex.h"
     36 
     37 #include "i830_context.h"
     38 #include "i830_reg.h"
     39 #include "intel_chipset.h"
     40 
     41 
     42 static GLuint
     43 translate_texture_format(GLuint mesa_format)
     44 {
     45    switch (mesa_format) {
     46    case MESA_FORMAT_L_UNORM8:
     47       return MAPSURF_8BIT | MT_8BIT_L8;
     48    case MESA_FORMAT_I_UNORM8:
     49       return MAPSURF_8BIT | MT_8BIT_I8;
     50    case MESA_FORMAT_L8A8_UNORM:
     51       return MAPSURF_16BIT | MT_16BIT_AY88;
     52    case MESA_FORMAT_B5G6R5_UNORM:
     53       return MAPSURF_16BIT | MT_16BIT_RGB565;
     54    case MESA_FORMAT_B5G5R5A1_UNORM:
     55       return MAPSURF_16BIT | MT_16BIT_ARGB1555;
     56    case MESA_FORMAT_B4G4R4A4_UNORM:
     57       return MAPSURF_16BIT | MT_16BIT_ARGB4444;
     58    case MESA_FORMAT_B8G8R8A8_UNORM:
     59       return MAPSURF_32BIT | MT_32BIT_ARGB8888;
     60    case MESA_FORMAT_B8G8R8X8_UNORM:
     61       return MAPSURF_32BIT | MT_32BIT_XRGB8888;
     62    case MESA_FORMAT_YCBCR_REV:
     63       return (MAPSURF_422 | MT_422_YCRCB_NORMAL);
     64    case MESA_FORMAT_YCBCR:
     65       return (MAPSURF_422 | MT_422_YCRCB_SWAPY);
     66    case MESA_FORMAT_RGB_FXT1:
     67    case MESA_FORMAT_RGBA_FXT1:
     68       return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1);
     69    case MESA_FORMAT_RGBA_DXT1:
     70    case MESA_FORMAT_RGB_DXT1:
     71       return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
     72    case MESA_FORMAT_RGBA_DXT3:
     73       return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
     74    case MESA_FORMAT_RGBA_DXT5:
     75       return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
     76    default:
     77       fprintf(stderr, "%s: bad image format %s\n", __func__,
     78 	      _mesa_get_format_name(mesa_format));
     79       abort();
     80       return 0;
     81    }
     82 }
     83 
     84 
     85 
     86 
     87 /* The i915 (and related graphics cores) do not support GL_CLAMP.  The
     88  * Intel drivers for "other operating systems" implement GL_CLAMP as
     89  * GL_CLAMP_TO_EDGE, so the same is done here.
     90  */
     91 static GLuint
     92 translate_wrap_mode(GLenum wrap)
     93 {
     94    switch (wrap) {
     95    case GL_REPEAT:
     96       return TEXCOORDMODE_WRAP;
     97    case GL_CLAMP:
     98    case GL_CLAMP_TO_EDGE:
     99       return TEXCOORDMODE_CLAMP;        /* not really correct */
    100    case GL_CLAMP_TO_BORDER:
    101       return TEXCOORDMODE_CLAMP_BORDER;
    102    case GL_MIRRORED_REPEAT:
    103       return TEXCOORDMODE_MIRROR;
    104    default:
    105       return TEXCOORDMODE_WRAP;
    106    }
    107 }
    108 
    109 
    110 /* Recalculate all state from scratch.  Perhaps not the most
    111  * efficient, but this has gotten complex enough that we need
    112  * something which is understandable and reliable.
    113  */
    114 static bool
    115 i830_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
    116 {
    117    struct gl_context *ctx = &intel->ctx;
    118    struct i830_context *i830 = i830_context(ctx);
    119    struct gl_texture_unit *tUnit = &ctx->Texture.Unit[unit];
    120    struct gl_texture_object *tObj = tUnit->_Current;
    121    struct intel_texture_object *intelObj = intel_texture_object(tObj);
    122    struct gl_texture_image *firstImage;
    123    struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit);
    124    GLuint *state = i830->state.Tex[unit], format, pitch;
    125    GLint lodbias;
    126    GLubyte border[4];
    127    GLuint dst_x, dst_y;
    128 
    129    memset(state, 0, sizeof(*state));
    130 
    131    /*We need to refcount these. */
    132 
    133    if (i830->state.tex_buffer[unit] != NULL) {
    134        drm_intel_bo_unreference(i830->state.tex_buffer[unit]);
    135        i830->state.tex_buffer[unit] = NULL;
    136    }
    137 
    138    if (!intel_finalize_mipmap_tree(intel, unit))
    139       return false;
    140 
    141    /* Get first image here, since intelObj->firstLevel will get set in
    142     * the intel_finalize_mipmap_tree() call above.
    143     */
    144    firstImage = tObj->Image[0][tObj->BaseLevel];
    145 
    146    intel_miptree_get_image_offset(intelObj->mt, tObj->BaseLevel, 0,
    147 				  &dst_x, &dst_y);
    148 
    149    drm_intel_bo_reference(intelObj->mt->region->bo);
    150    i830->state.tex_buffer[unit] = intelObj->mt->region->bo;
    151    pitch = intelObj->mt->region->pitch;
    152 
    153    /* XXX: This calculation is probably broken for tiled images with
    154     * a non-page-aligned offset.
    155     */
    156    i830->state.tex_offset[unit] = dst_x * intelObj->mt->cpp + dst_y * pitch;
    157 
    158    format = translate_texture_format(firstImage->TexFormat);
    159 
    160    state[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
    161                                (LOAD_TEXTURE_MAP0 << unit) | 4);
    162 
    163    state[I830_TEXREG_TM0S1] =
    164       (((firstImage->Height - 1) << TM0S1_HEIGHT_SHIFT) |
    165        ((firstImage->Width - 1) << TM0S1_WIDTH_SHIFT) | format);
    166 
    167    if (intelObj->mt->region->tiling != I915_TILING_NONE) {
    168       state[I830_TEXREG_TM0S1] |= TM0S1_TILED_SURFACE;
    169       if (intelObj->mt->region->tiling == I915_TILING_Y)
    170 	 state[I830_TEXREG_TM0S1] |= TM0S1_TILE_WALK;
    171    }
    172 
    173    state[I830_TEXREG_TM0S2] =
    174       ((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT) | TM0S2_CUBE_FACE_ENA_MASK);
    175 
    176    {
    177       if (tObj->Target == GL_TEXTURE_CUBE_MAP)
    178          state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit) |
    179                                     CUBE_NEGX_ENABLE |
    180                                     CUBE_POSX_ENABLE |
    181                                     CUBE_NEGY_ENABLE |
    182                                     CUBE_POSY_ENABLE |
    183                                     CUBE_NEGZ_ENABLE | CUBE_POSZ_ENABLE);
    184       else
    185          state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit));
    186    }
    187 
    188 
    189 
    190 
    191    {
    192       GLuint minFilt, mipFilt, magFilt;
    193       float maxlod;
    194       uint32_t minlod_fixed, maxlod_fixed;
    195 
    196       switch (sampler->MinFilter) {
    197       case GL_NEAREST:
    198          minFilt = FILTER_NEAREST;
    199          mipFilt = MIPFILTER_NONE;
    200          break;
    201       case GL_LINEAR:
    202          minFilt = FILTER_LINEAR;
    203          mipFilt = MIPFILTER_NONE;
    204          break;
    205       case GL_NEAREST_MIPMAP_NEAREST:
    206          minFilt = FILTER_NEAREST;
    207          mipFilt = MIPFILTER_NEAREST;
    208          break;
    209       case GL_LINEAR_MIPMAP_NEAREST:
    210          minFilt = FILTER_LINEAR;
    211          mipFilt = MIPFILTER_NEAREST;
    212          break;
    213       case GL_NEAREST_MIPMAP_LINEAR:
    214          minFilt = FILTER_NEAREST;
    215          mipFilt = MIPFILTER_LINEAR;
    216          break;
    217       case GL_LINEAR_MIPMAP_LINEAR:
    218          minFilt = FILTER_LINEAR;
    219          mipFilt = MIPFILTER_LINEAR;
    220          break;
    221       default:
    222          return false;
    223       }
    224 
    225       if (sampler->MaxAnisotropy > 1.0) {
    226          minFilt = FILTER_ANISOTROPIC;
    227          magFilt = FILTER_ANISOTROPIC;
    228          /* no trilinear + anisotropic */
    229          mipFilt = MIPFILTER_NEAREST;
    230       }
    231       else {
    232          switch (sampler->MagFilter) {
    233          case GL_NEAREST:
    234             magFilt = FILTER_NEAREST;
    235             break;
    236          case GL_LINEAR:
    237             magFilt = FILTER_LINEAR;
    238             break;
    239          default:
    240             return false;
    241          }
    242       }
    243 
    244       lodbias = (int) ((tUnit->LodBias + sampler->LodBias) * 16.0);
    245       if (lodbias < -64)
    246           lodbias = -64;
    247       if (lodbias > 63)
    248           lodbias = 63;
    249 
    250       state[I830_TEXREG_TM0S3] = ((lodbias << TM0S3_LOD_BIAS_SHIFT) &
    251                                   TM0S3_LOD_BIAS_MASK);
    252 #if 0
    253       /* YUV conversion:
    254        */
    255       if (firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR ||
    256           firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV)
    257          state[I830_TEXREG_TM0S3] |= SS2_COLORSPACE_CONVERSION;
    258 #endif
    259 
    260       /* We get one field with fraction bits for the maximum
    261        * addressable (smallest resolution) LOD.  Use it to cover both
    262        * MAX_LEVEL and MAX_LOD.
    263        */
    264       minlod_fixed = U_FIXED(CLAMP(sampler->MinLod, 0.0, 11), 4);
    265       maxlod = MIN2(sampler->MaxLod, tObj->_MaxLevel - tObj->BaseLevel);
    266       if (intel->intelScreen->deviceID == PCI_CHIP_I855_GM ||
    267 	  intel->intelScreen->deviceID == PCI_CHIP_I865_G) {
    268 	 maxlod_fixed = U_FIXED(CLAMP(maxlod, 0.0, 11.75), 2);
    269 	 maxlod_fixed = MAX2(maxlod_fixed, (minlod_fixed + 3) >> 2);
    270 	 state[I830_TEXREG_TM0S3] |= maxlod_fixed << TM0S3_MIN_MIP_SHIFT;
    271 	 state[I830_TEXREG_TM0S2] |= TM0S2_LOD_PRECLAMP;
    272       } else {
    273 	 maxlod_fixed = U_FIXED(CLAMP(maxlod, 0.0, 11), 0);
    274 	 maxlod_fixed = MAX2(maxlod_fixed, (minlod_fixed + 15) >> 4);
    275 	 state[I830_TEXREG_TM0S3] |= maxlod_fixed << TM0S3_MIN_MIP_SHIFT_830;
    276       }
    277       state[I830_TEXREG_TM0S3] |= minlod_fixed << TM0S3_MAX_MIP_SHIFT;
    278       state[I830_TEXREG_TM0S3] |= ((minFilt << TM0S3_MIN_FILTER_SHIFT) |
    279                                    (mipFilt << TM0S3_MIP_FILTER_SHIFT) |
    280                                    (magFilt << TM0S3_MAG_FILTER_SHIFT));
    281    }
    282 
    283    {
    284       GLenum ws = sampler->WrapS;
    285       GLenum wt = sampler->WrapT;
    286 
    287 
    288       /* 3D textures not available on i830
    289        */
    290       if (tObj->Target == GL_TEXTURE_3D)
    291          return false;
    292 
    293       state[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
    294                                 MAP_UNIT(unit) |
    295                                 ENABLE_TEXCOORD_PARAMS |
    296                                 ss3 |
    297                                 ENABLE_ADDR_V_CNTL |
    298                                 TEXCOORD_ADDR_V_MODE(translate_wrap_mode(wt))
    299                                 | ENABLE_ADDR_U_CNTL |
    300                                 TEXCOORD_ADDR_U_MODE(translate_wrap_mode
    301                                                      (ws)));
    302    }
    303 
    304    /* convert border color from float to ubyte */
    305    CLAMPED_FLOAT_TO_UBYTE(border[0], sampler->BorderColor.f[0]);
    306    CLAMPED_FLOAT_TO_UBYTE(border[1], sampler->BorderColor.f[1]);
    307    CLAMPED_FLOAT_TO_UBYTE(border[2], sampler->BorderColor.f[2]);
    308    CLAMPED_FLOAT_TO_UBYTE(border[3], sampler->BorderColor.f[3]);
    309 
    310    state[I830_TEXREG_TM0S4] = PACK_COLOR_8888(border[3],
    311 					      border[0],
    312 					      border[1],
    313 					      border[2]);
    314 
    315    I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(unit), true);
    316    /* memcmp was already disabled, but definitely won't work as the
    317     * region might now change and that wouldn't be detected:
    318     */
    319    I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
    320    return true;
    321 }
    322 
    323 
    324 
    325 
    326 void
    327 i830UpdateTextureState(struct intel_context *intel)
    328 {
    329    struct i830_context *i830 = i830_context(&intel->ctx);
    330    bool ok = true;
    331    GLuint i;
    332 
    333    for (i = 0; i < I830_TEX_UNITS && ok; i++) {
    334       if (intel->ctx.Texture.Unit[i]._Current) {
    335          switch (intel->ctx.Texture.Unit[i]._Current->Target) {
    336          case GL_TEXTURE_1D:
    337          case GL_TEXTURE_2D:
    338          case GL_TEXTURE_CUBE_MAP:
    339             ok = i830_update_tex_unit(intel, i, TEXCOORDS_ARE_NORMAL);
    340             break;
    341          case GL_TEXTURE_RECTANGLE:
    342             ok = i830_update_tex_unit(intel, i, TEXCOORDS_ARE_IN_TEXELUNITS);
    343             break;
    344          case GL_TEXTURE_3D:
    345          default:
    346             ok = false;
    347             break;
    348          }
    349       } else {
    350          struct i830_context *i830 = i830_context(&intel->ctx);
    351          if (i830->state.active & I830_UPLOAD_TEX(i))
    352             I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(i), false);
    353 
    354          if (i830->state.tex_buffer[i] != NULL) {
    355             drm_intel_bo_unreference(i830->state.tex_buffer[i]);
    356             i830->state.tex_buffer[i] = NULL;
    357          }
    358       }
    359    }
    360 
    361    FALLBACK(intel, I830_FALLBACK_TEXTURE, !ok);
    362 
    363    if (ok)
    364       i830EmitTextureBlend(i830);
    365 }
    366