Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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,
  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;
  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.