i965: Support CS in update_stage_texture_surfaces
[mesa.git] / src / mesa / drivers / dri / i915 / i915_texstate.c
index 742bb994adb6ca07eb8600aa9a82cf096ac63ccc..f653f441ad81ba8b5719658f5ac5497ff2e06830 100644 (file)
@@ -1,6 +1,6 @@
 /**************************************************************************
  * 
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2003 VMware, Inc.
  * All Rights Reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a
@@ -18,7 +18,7 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -29,6 +29,7 @@
 #include "main/enums.h"
 #include "main/macros.h"
 #include "main/colormac.h"
+#include "main/samplerobj.h"
 
 #include "intel_mipmap_tree.h"
 #include "intel_tex.h"
 
 
 static GLuint
-translate_texture_format(gl_format mesa_format, GLuint internal_format,
-                        GLenum DepthMode)
+translate_texture_format(mesa_format mesa_format, GLenum DepthMode)
 {
    switch (mesa_format) {
-   case MESA_FORMAT_L8:
+   case MESA_FORMAT_L_UNORM8:
       return MAPSURF_8BIT | MT_8BIT_L8;
-   case MESA_FORMAT_I8:
+   case MESA_FORMAT_I_UNORM8:
       return MAPSURF_8BIT | MT_8BIT_I8;
-   case MESA_FORMAT_A8:
+   case MESA_FORMAT_A_UNORM8:
       return MAPSURF_8BIT | MT_8BIT_A8;
-   case MESA_FORMAT_AL88:
+   case MESA_FORMAT_L8A8_UNORM:
       return MAPSURF_16BIT | MT_16BIT_AY88;
-   case MESA_FORMAT_RGB565:
+   case MESA_FORMAT_B5G6R5_UNORM:
       return MAPSURF_16BIT | MT_16BIT_RGB565;
-   case MESA_FORMAT_ARGB1555:
+   case MESA_FORMAT_B5G5R5A1_UNORM:
       return MAPSURF_16BIT | MT_16BIT_ARGB1555;
-   case MESA_FORMAT_ARGB4444:
+   case MESA_FORMAT_B4G4R4A4_UNORM:
       return MAPSURF_16BIT | MT_16BIT_ARGB4444;
-   case MESA_FORMAT_ARGB8888:
+   case MESA_FORMAT_B8G8R8A8_SRGB:
+   case MESA_FORMAT_B8G8R8A8_UNORM:
       return MAPSURF_32BIT | MT_32BIT_ARGB8888;
-   case MESA_FORMAT_XRGB8888:
+   case MESA_FORMAT_B8G8R8X8_UNORM:
       return MAPSURF_32BIT | MT_32BIT_XRGB8888;
+   case MESA_FORMAT_R8G8B8A8_UNORM:
+      return MAPSURF_32BIT | MT_32BIT_ABGR8888;
    case MESA_FORMAT_YCBCR_REV:
       return (MAPSURF_422 | MT_422_YCRCB_NORMAL);
    case MESA_FORMAT_YCBCR:
@@ -67,7 +70,7 @@ translate_texture_format(gl_format mesa_format, GLuint internal_format,
    case MESA_FORMAT_RGB_FXT1:
    case MESA_FORMAT_RGBA_FXT1:
       return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1);
-   case MESA_FORMAT_Z16:
+   case MESA_FORMAT_Z_UNORM16:
       if (DepthMode == GL_ALPHA)
           return (MAPSURF_16BIT | MT_16BIT_A16);
       else if (DepthMode == GL_INTENSITY)
@@ -76,12 +79,17 @@ translate_texture_format(gl_format mesa_format, GLuint internal_format,
           return (MAPSURF_16BIT | MT_16BIT_L16);
    case MESA_FORMAT_RGBA_DXT1:
    case MESA_FORMAT_RGB_DXT1:
+   case MESA_FORMAT_SRGB_DXT1:
+   case MESA_FORMAT_SRGBA_DXT1:
       return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1);
    case MESA_FORMAT_RGBA_DXT3:
+   case MESA_FORMAT_SRGBA_DXT3:
       return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3);
    case MESA_FORMAT_RGBA_DXT5:
+   case MESA_FORMAT_SRGBA_DXT5:
       return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5);
-   case MESA_FORMAT_S8_Z24:
+   case MESA_FORMAT_Z24_UNORM_S8_UINT:
+   case MESA_FORMAT_Z24_UNORM_X8_UINT:
       if (DepthMode == GL_ALPHA)
         return (MAPSURF_32BIT | MT_32BIT_x8A24);
       else if (DepthMode == GL_INTENSITY)
@@ -89,7 +97,8 @@ translate_texture_format(gl_format mesa_format, GLuint internal_format,
       else
         return (MAPSURF_32BIT | MT_32BIT_x8L24);
    default:
-      fprintf(stderr, "%s: bad image format %x\n", __FUNCTION__, mesa_format);
+      fprintf(stderr, "%s: bad image format %s\n", __func__,
+             _mesa_get_format_name(mesa_format));
       abort();
       return 0;
    }
@@ -127,7 +136,7 @@ translate_wrap_mode(GLenum wrap)
  * efficient, but this has gotten complex enough that we need
  * something which is understandable and reliable.
  */
-static GLboolean
+static bool
 i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
 {
    struct gl_context *ctx = &intel->ctx;
@@ -136,12 +145,13 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
    struct gl_texture_object *tObj = tUnit->_Current;
    struct intel_texture_object *intelObj = intel_texture_object(tObj);
    struct gl_texture_image *firstImage;
-   GLuint *state = i915->state.Tex[unit], format, pitch;
+   struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit);
+   GLuint *state = i915->state.Tex[unit], format;
    GLint lodbias, aniso = 0;
    GLubyte border[4];
    GLfloat maxlod;
 
-   memset(state, 0, sizeof(state));
+   memset(state, 0, sizeof(*state));
 
    /*We need to refcount these. */
 
@@ -151,21 +161,19 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
    }
 
    if (!intel_finalize_mipmap_tree(intel, unit))
-      return GL_FALSE;
+      return false;
 
    /* Get first image here, since intelObj->firstLevel will get set in
     * the intel_finalize_mipmap_tree() call above.
     */
    firstImage = tObj->Image[0][tObj->BaseLevel];
 
-   drm_intel_bo_reference(intelObj->mt->region->buffer);
-   i915->state.tex_buffer[unit] = intelObj->mt->region->buffer;
-   i915->state.tex_offset[unit] = 0; /* Always the origin of the miptree */
+   drm_intel_bo_reference(intelObj->mt->region->bo);
+   i915->state.tex_buffer[unit] = intelObj->mt->region->bo;
+   i915->state.tex_offset[unit] = intelObj->mt->offset;
 
    format = translate_texture_format(firstImage->TexFormat,
-                                    firstImage->InternalFormat,
-                                    tObj->Sampler.DepthMode);
-   pitch = intelObj->mt->region->pitch * intelObj->mt->cpp;
+                                    tObj->DepthMode);
 
    state[I915_TEXREG_MS3] =
       (((firstImage->Height - 1) << MS3_HEIGHT_SHIFT) |
@@ -181,9 +189,9 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
     * (lowest resolution) LOD.  Use it to cover both MAX_LEVEL and
     * MAX_LOD.
     */
-   maxlod = MIN2(tObj->Sampler.MaxLod, tObj->_MaxLevel - tObj->BaseLevel);
+   maxlod = MIN2(sampler->MaxLod, tObj->_MaxLevel - tObj->BaseLevel);
    state[I915_TEXREG_MS4] =
-      ((((pitch / 4) - 1) << MS4_PITCH_SHIFT) |
+      ((((intelObj->mt->region->pitch / 4) - 1) << MS4_PITCH_SHIFT) |
        MS4_CUBE_FACE_ENA_MASK |
        (U_FIXED(CLAMP(maxlod, 0.0, 11.0), 2) << MS4_MAX_LOD_SHIFT) |
        ((firstImage->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT));
@@ -192,7 +200,7 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
    {
       GLuint minFilt, mipFilt, magFilt;
 
-      switch (tObj->Sampler.MinFilter) {
+      switch (sampler->MinFilter) {
       case GL_NEAREST:
          minFilt = FILTER_NEAREST;
          mipFilt = MIPFILTER_NONE;
@@ -218,19 +226,19 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
          mipFilt = MIPFILTER_LINEAR;
          break;
       default:
-         return GL_FALSE;
+         return false;
       }
 
-      if (tObj->Sampler.MaxAnisotropy > 1.0) {
+      if (sampler->MaxAnisotropy > 1.0) {
          minFilt = FILTER_ANISOTROPIC;
          magFilt = FILTER_ANISOTROPIC;
-         if (tObj->Sampler.MaxAnisotropy > 2.0)
+         if (sampler->MaxAnisotropy > 2.0)
             aniso = SS2_MAX_ANISO_4;
          else
             aniso = SS2_MAX_ANISO_2;
       }
       else {
-         switch (tObj->Sampler.MagFilter) {
+         switch (sampler->MagFilter) {
          case GL_NEAREST:
             magFilt = FILTER_NEAREST;
             break;
@@ -238,11 +246,11 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
             magFilt = FILTER_LINEAR;
             break;
          default:
-            return GL_FALSE;
+            return false;
          }
       }
 
-      lodbias = (int) ((tUnit->LodBias + tObj->Sampler.LodBias) * 16.0);
+      lodbias = (int) ((tUnit->LodBias + sampler->LodBias) * 16.0);
       if (lodbias < -256)
           lodbias = -256;
       if (lodbias > 255)
@@ -258,14 +266,14 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
 
       /* Shadow:
        */
-      if (tObj->Sampler.CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB &&
+      if (sampler->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB &&
           tObj->Target != GL_TEXTURE_3D) {
          if (tObj->Target == GL_TEXTURE_1D) 
-            return GL_FALSE;
+            return false;
 
          state[I915_TEXREG_SS2] |=
             (SS2_SHADOW_ENABLE |
-             intel_translate_shadow_compare_func(tObj->Sampler.CompareFunc));
+             intel_translate_shadow_compare_func(sampler->CompareFunc));
 
          minFilt = FILTER_4X4_FLAT;
          magFilt = FILTER_4X4_FLAT;
@@ -278,9 +286,9 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
    }
 
    {
-      GLenum ws = tObj->Sampler.WrapS;
-      GLenum wt = tObj->Sampler.WrapT;
-      GLenum wr = tObj->Sampler.WrapR;
+      GLenum ws = sampler->WrapS;
+      GLenum wt = sampler->WrapT;
+      GLenum wr = sampler->WrapR;
       float minlod;
 
       /* We program 1D textures as 2D textures, so the 2D texcoord could
@@ -298,14 +306,14 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
        * clamp_to_border.
        */
       if (tObj->Target == GL_TEXTURE_3D &&
-          (tObj->Sampler.MinFilter != GL_NEAREST ||
-           tObj->Sampler.MagFilter != GL_NEAREST) &&
+          (sampler->MinFilter != GL_NEAREST ||
+           sampler->MagFilter != GL_NEAREST) &&
           (ws == GL_CLAMP ||
            wt == GL_CLAMP ||
            wr == GL_CLAMP ||
            ws == GL_CLAMP_TO_BORDER ||
            wt == GL_CLAMP_TO_BORDER || wr == GL_CLAMP_TO_BORDER))
-         return GL_FALSE;
+         return false;
 
       /* Only support TEXCOORDMODE_CLAMP_EDGE and TEXCOORDMODE_CUBE (not 
        * used) when using cube map texture coordinates
@@ -313,7 +321,29 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
       if (tObj->Target == GL_TEXTURE_CUBE_MAP_ARB &&
           (((ws != GL_CLAMP) && (ws != GL_CLAMP_TO_EDGE)) ||
            ((wt != GL_CLAMP) && (wt != GL_CLAMP_TO_EDGE))))
-          return GL_FALSE;
+          return false;
+
+      /*
+       * According to 3DSTATE_MAP_STATE at page of 104 in Bspec
+       * Vol3d 3D Instructions:
+       *   [DevGDG and DevAlv]: Must be a power of 2 for cube maps.
+       *   [DevLPT, DevCST and DevBLB]: If not a power of 2, cube maps
+       *      must have all faces enabled.
+       *
+       * But, as I tested on pineview(DevBLB derived), the rendering is
+       * bad(you will find the color isn't samplered right in some
+       * fragments). After checking, it seems that the texture layout is
+       * wrong: making the width and height align of 4(although this
+       * doesn't make much sense) will fix this issue and also broke some
+       * others. Well, Bspec mentioned nothing about the layout alignment
+       * and layout for NPOT cube map.  I guess the Bspec just assume it's
+       * a POT cube map.
+       *
+       * Thus, I guess we need do this for other platforms as well.
+       */
+      if (tObj->Target == GL_TEXTURE_CUBE_MAP_ARB &&
+          !_mesa_is_pow_two(firstImage->Height))
+         return false;
 
       state[I915_TEXREG_SS3] = ss3;     /* SS3_NORMALIZED_COORDS */
 
@@ -322,18 +352,24 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
           (translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT) |
           (translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT));
 
-      minlod = MIN2(tObj->Sampler.MinLod, tObj->_MaxLevel - tObj->BaseLevel);
+      minlod = MIN2(sampler->MinLod, tObj->_MaxLevel - tObj->BaseLevel);
       state[I915_TEXREG_SS3] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT);
       state[I915_TEXREG_SS3] |= (U_FIXED(CLAMP(minlod, 0.0, 11.0), 4) <<
                                 SS3_MIN_LOD_SHIFT);
 
    }
 
+   if (sampler->sRGBDecode == GL_DECODE_EXT &&
+       (_mesa_get_srgb_format_linear(firstImage->TexFormat) !=
+        firstImage->TexFormat)) {
+      state[I915_TEXREG_SS2] |= SS2_REVERSE_GAMMA_ENABLE;
+   }
+
    /* convert border color from float to ubyte */
-   CLAMPED_FLOAT_TO_UBYTE(border[0], tObj->Sampler.BorderColor.f[0]);
-   CLAMPED_FLOAT_TO_UBYTE(border[1], tObj->Sampler.BorderColor.f[1]);
-   CLAMPED_FLOAT_TO_UBYTE(border[2], tObj->Sampler.BorderColor.f[2]);
-   CLAMPED_FLOAT_TO_UBYTE(border[3], tObj->Sampler.BorderColor.f[3]);
+   CLAMPED_FLOAT_TO_UBYTE(border[0], sampler->BorderColor.f[0]);
+   CLAMPED_FLOAT_TO_UBYTE(border[1], sampler->BorderColor.f[1]);
+   CLAMPED_FLOAT_TO_UBYTE(border[2], sampler->BorderColor.f[2]);
+   CLAMPED_FLOAT_TO_UBYTE(border[3], sampler->BorderColor.f[3]);
 
    if (firstImage->_BaseFormat == GL_DEPTH_COMPONENT) {
       /* GL specs that border color for depth textures is taken from the
@@ -352,7 +388,7 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
    }
 
 
-   I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_TRUE);
+   I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), true);
    /* memcmp was already disabled, but definitely won't work as the
     * region might now change and that wouldn't be detected:
     */
@@ -368,7 +404,7 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
    DBG(TEXTURE, "state[I915_TEXREG_MS4] = 0x%x\n", state[I915_TEXREG_MS4]);
 #endif
 
-   return GL_TRUE;
+   return true;
 }
 
 
@@ -377,35 +413,34 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
 void
 i915UpdateTextureState(struct intel_context *intel)
 {
-   GLboolean ok = GL_TRUE;
+   bool ok = true;
    GLuint i;
 
    for (i = 0; i < I915_TEX_UNITS && ok; i++) {
-      switch (intel->ctx.Texture.Unit[i]._ReallyEnabled) {
-      case TEXTURE_1D_BIT:
-      case TEXTURE_2D_BIT:
-      case TEXTURE_CUBE_BIT:
-      case TEXTURE_3D_BIT:
-         ok = i915_update_tex_unit(intel, i, SS3_NORMALIZED_COORDS);
-         break;
-      case TEXTURE_RECT_BIT:
-         ok = i915_update_tex_unit(intel, i, 0);
-         break;
-      case 0:{
-            struct i915_context *i915 = i915_context(&intel->ctx);
-            if (i915->state.active & I915_UPLOAD_TEX(i))
-               I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(i), GL_FALSE);
-
-           if (i915->state.tex_buffer[i] != NULL) {
-              drm_intel_bo_unreference(i915->state.tex_buffer[i]);
-              i915->state.tex_buffer[i] = NULL;
-           }
-
+      if (intel->ctx.Texture.Unit[i]._Current) {
+         switch (intel->ctx.Texture.Unit[i]._Current->Target) {
+         case GL_TEXTURE_1D:
+         case GL_TEXTURE_2D:
+         case GL_TEXTURE_CUBE_MAP:
+         case GL_TEXTURE_3D:
+            ok = i915_update_tex_unit(intel, i, SS3_NORMALIZED_COORDS);
+            break;
+         case GL_TEXTURE_RECTANGLE:
+            ok = i915_update_tex_unit(intel, i, 0);
+            break;
+         default:
+            ok = false;
             break;
          }
-      default:
-         ok = GL_FALSE;
-         break;
+      } else {
+         struct i915_context *i915 = i915_context(&intel->ctx);
+         if (i915->state.active & I915_UPLOAD_TEX(i))
+            I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(i), false);
+
+         if (i915->state.tex_buffer[i] != NULL) {
+            drm_intel_bo_unreference(i915->state.tex_buffer[i]);
+            i915->state.tex_buffer[i] = NULL;
+         }
       }
    }