Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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.