Home | History | Annotate | Download | only in i915
      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/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_L8:
     47       return MAPSURF_8BIT | MT_8BIT_L8;
     48    case MESA_FORMAT_I8:
     49       return MAPSURF_8BIT | MT_8BIT_I8;
     50    case MESA_FORMAT_A8:
     51       return MAPSURF_8BIT | MT_8BIT_I8; /* Kludge! */
     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_ARGB8888:
     61       return MAPSURF_32BIT | MT_32BIT_ARGB8888;
     62    case MESA_FORMAT_XRGB8888:
     63       return MAPSURF_32BIT | MT_32BIT_XRGB8888;
     64    case MESA_FORMAT_YCBCR_REV:
     65       return (MAPSURF_422 | MT_422_YCRCB_NORMAL);
     66    case MESA_FORMAT_YCBCR:
     67       return (MAPSURF_422 | MT_422_YCRCB_SWAPY);
     68    case MESA_FORMAT_RGB_FXT1:
     69    case MESA_FORMAT_RGBA_FXT1:
     70       return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1);
     71    case MESA_FORMAT_RGBA_DXT1:
     72    case MESA_FORMAT_RGB_DXT1:
     73       return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
     74    case MESA_FORMAT_RGBA_DXT3:
     75       return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
     76    case MESA_FORMAT_RGBA_DXT5:
     77       return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
     78    default:
     79       fprintf(stderr, "%s: bad image format %s\n", __FUNCTION__,
     80 	      _mesa_get_format_name(mesa_format));
     81       abort();
     82       return 0;
     83    }
     84 }
     85 
     86 
     87 
     88 
     89 /* The i915 (and related graphics cores) do not support GL_CLAMP.  The
     90  * Intel drivers for "other operating systems" implement GL_CLAMP as
     91  * GL_CLAMP_TO_EDGE, so the same is done here.
     92  */
     93 static GLuint
     94 translate_wrap_mode(GLenum wrap)
     95 {
     96    switch (wrap) {
     97    case GL_REPEAT:
     98       return TEXCOORDMODE_WRAP;
     99    case GL_CLAMP:
    100    case GL_CLAMP_TO_EDGE:
    101       return TEXCOORDMODE_CLAMP;        /* not really correct */
    102    case GL_CLAMP_TO_BORDER:
    103       return TEXCOORDMODE_CLAMP_BORDER;
    104    case GL_MIRRORED_REPEAT:
    105       return TEXCOORDMODE_MIRROR;
    106    default:
    107       return TEXCOORDMODE_WRAP;
    108    }
    109 }
    110 
    111 
    112 /* Recalculate all state from scratch.  Perhaps not the most
    113  * efficient, but this has gotten complex enough that we need
    114  * something which is understandable and reliable.
    115  */
    116 static bool
    117 i830_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
    118 {
    119    struct gl_context *ctx = &intel->ctx;
    120    struct i830_context *i830 = i830_context(ctx);
    121    struct gl_texture_unit *tUnit = &ctx->Texture.Unit[unit];
    122    struct gl_texture_object *tObj = tUnit->_Current;
    123    struct intel_texture_object *intelObj = intel_texture_object(tObj);
    124    struct gl_texture_image *firstImage;
    125    struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit);
    126    GLuint *state = i830->state.Tex[unit], format, pitch;
    127    GLint lodbias;
    128    GLubyte border[4];
    129    GLuint dst_x, dst_y;
    130 
    131    memset(state, 0, sizeof(*state));
    132 
    133    /*We need to refcount these. */
    134 
    135    if (i830->state.tex_buffer[unit] != NULL) {
    136        drm_intel_bo_unreference(i830->state.tex_buffer[unit]);
    137        i830->state.tex_buffer[unit] = NULL;
    138    }
    139 
    140    if (!intel_finalize_mipmap_tree(intel, unit))
    141       return false;
    142 
    143    /* Get first image here, since intelObj->firstLevel will get set in
    144     * the intel_finalize_mipmap_tree() call above.
    145     */
    146    firstImage = tObj->Image[0][tObj->BaseLevel];
    147 
    148    intel_miptree_get_image_offset(intelObj->mt, tObj->BaseLevel, 0, 0,
    149 				  &dst_x, &dst_y);
    150 
    151    drm_intel_bo_reference(intelObj->mt->region->bo);
    152    i830->state.tex_buffer[unit] = intelObj->mt->region->bo;
    153    pitch = intelObj->mt->region->pitch * intelObj->mt->cpp;
    154 
    155    /* XXX: This calculation is probably broken for tiled images with
    156     * a non-page-aligned offset.
    157     */
    158    i830->state.tex_offset[unit] = dst_x * intelObj->mt->cpp + dst_y * pitch;
    159 
    160    format = translate_texture_format(firstImage->TexFormat);
    161 
    162    state[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
    163                                (LOAD_TEXTURE_MAP0 << unit) | 4);
    164 
    165    state[I830_TEXREG_TM0S1] =
    166       (((firstImage->Height - 1) << TM0S1_HEIGHT_SHIFT) |
    167        ((firstImage->Width - 1) << TM0S1_WIDTH_SHIFT) | format);
    168 
    169    if (intelObj->mt->region->tiling != I915_TILING_NONE) {
    170       state[I830_TEXREG_TM0S1] |= TM0S1_TILED_SURFACE;
    171       if (intelObj->mt->region->tiling == I915_TILING_Y)
    172 	 state[I830_TEXREG_TM0S1] |= TM0S1_TILE_WALK;
    173    }
    174 
    175    state[I830_TEXREG_TM0S2] =
    176       ((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT) | TM0S2_CUBE_FACE_ENA_MASK);
    177 
    178    {
    179       if (tObj->Target == GL_TEXTURE_CUBE_MAP)
    180          state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit) |
    181                                     CUBE_NEGX_ENABLE |
    182                                     CUBE_POSX_ENABLE |
    183                                     CUBE_NEGY_ENABLE |
    184                                     CUBE_POSY_ENABLE |
    185                                     CUBE_NEGZ_ENABLE | CUBE_POSZ_ENABLE);
    186       else
    187          state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit));
    188    }
    189 
    190 
    191 
    192 
    193    {
    194       GLuint minFilt, mipFilt, magFilt;
    195       float maxlod;
    196       uint32_t minlod_fixed, maxlod_fixed;
    197 
    198       switch (sampler->MinFilter) {
    199       case GL_NEAREST:
    200          minFilt = FILTER_NEAREST;
    201          mipFilt = MIPFILTER_NONE;
    202          break;
    203       case GL_LINEAR:
    204          minFilt = FILTER_LINEAR;
    205          mipFilt = MIPFILTER_NONE;
    206          break;
    207       case GL_NEAREST_MIPMAP_NEAREST:
    208          minFilt = FILTER_NEAREST;
    209          mipFilt = MIPFILTER_NEAREST;
    210          break;
    211       case GL_LINEAR_MIPMAP_NEAREST:
    212          minFilt = FILTER_LINEAR;
    213          mipFilt = MIPFILTER_NEAREST;
    214          break;
    215       case GL_NEAREST_MIPMAP_LINEAR:
    216          minFilt = FILTER_NEAREST;
    217          mipFilt = MIPFILTER_LINEAR;
    218          break;
    219       case GL_LINEAR_MIPMAP_LINEAR:
    220          minFilt = FILTER_LINEAR;
    221          mipFilt = MIPFILTER_LINEAR;
    222          break;
    223       default:
    224          return false;
    225       }
    226 
    227       if (sampler->MaxAnisotropy > 1.0) {
    228          minFilt = FILTER_ANISOTROPIC;
    229          magFilt = FILTER_ANISOTROPIC;
    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       switch (intel->ctx.Texture.Unit[i]._ReallyEnabled) {
    335       case TEXTURE_1D_BIT:
    336       case TEXTURE_2D_BIT:
    337       case TEXTURE_CUBE_BIT:
    338          ok = i830_update_tex_unit(intel, i, TEXCOORDS_ARE_NORMAL);
    339          break;
    340       case TEXTURE_RECT_BIT:
    341          ok = i830_update_tex_unit(intel, i, TEXCOORDS_ARE_IN_TEXELUNITS);
    342          break;
    343       case 0:{
    344 	 struct i830_context *i830 = i830_context(&intel->ctx);
    345          if (i830->state.active & I830_UPLOAD_TEX(i))
    346             I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(i), false);
    347 
    348 	 if (i830->state.tex_buffer[i] != NULL) {
    349 	    drm_intel_bo_unreference(i830->state.tex_buffer[i]);
    350 	    i830->state.tex_buffer[i] = NULL;
    351 	 }
    352          break;
    353       }
    354       case TEXTURE_3D_BIT:
    355       default:
    356          ok = false;
    357          break;
    358       }
    359    }
    360 
    361    FALLBACK(intel, I830_FALLBACK_TEXTURE, !ok);
    362 
    363    if (ok)
    364       i830EmitTextureBlend(i830);
    365 }
    366