Merge branch '7.8'
[mesa.git] / src / mesa / drivers / dri / intel / intel_mipmap_tree.c
index 01e9d4add341584d60ef1ca9179cfc7f34b35024..ef1966ea7e14c0136e87a1ec3bb59df08b38d7e0 100644 (file)
@@ -29,7 +29,6 @@
 #include "intel_mipmap_tree.h"
 #include "intel_regions.h"
 #include "intel_tex_layout.h"
-#include "intel_chipset.h"
 #ifndef I915
 #include "brw_state.h"
 #endif
@@ -84,10 +83,9 @@ intel_miptree_create_internal(struct intel_context *intel,
    mt->cpp = compress_byte ? compress_byte : cpp;
    mt->compressed = compress_byte ? 1 : 0;
    mt->refcount = 1; 
-   mt->pitch = 0;
 
 #ifdef I915
-   if (IS_945(intel->intelScreen->deviceID))
+   if (intel->is_945)
       ok = i945_miptree_layout(intel, mt, tiling);
    else
       ok = i915_miptree_layout(intel, mt, tiling);
@@ -120,9 +118,8 @@ intel_miptree_create(struct intel_context *intel,
    struct intel_mipmap_tree *mt;
    uint32_t tiling;
 
-   if (intel->use_texture_tiling && compress_byte == 0 &&
-       intel->intelScreen->kernel_exec_fencing) {
-      if (IS_965(intel->intelScreen->deviceID) &&
+   if (intel->use_texture_tiling && compress_byte == 0) {
+      if (intel->gen >= 4 &&
          (base_format == GL_DEPTH_COMPONENT ||
           base_format == GL_DEPTH_STENCIL_EXT))
         tiling = I915_TILING_Y;
@@ -138,15 +135,16 @@ intel_miptree_create(struct intel_context *intel,
    /*
     * pitch == 0 || height == 0  indicates the null texture
     */
-   if (!mt || !mt->pitch || !mt->total_height)
+   if (!mt || !mt->total_height) {
+      free(mt);
       return NULL;
+   }
 
    mt->region = intel_region_alloc(intel,
                                   tiling,
                                   mt->cpp,
-                                  mt->pitch,
+                                  mt->total_width,
                                   mt->total_height,
-                                  mt->pitch,
                                   expect_accelerated_upload);
 
    if (!mt->region) {
@@ -177,85 +175,12 @@ intel_miptree_create_for_region(struct intel_context *intel,
                                      I915_TILING_NONE);
    if (!mt)
       return mt;
-#if 0
-   if (mt->pitch != region->pitch) {
-      fprintf(stderr,
-             "region pitch (%d) doesn't match mipmap tree pitch (%d)\n",
-             region->pitch, mt->pitch);
-      free(mt);
-      return NULL;
-   }
-#else
-   /* The mipmap tree pitch is aligned to 64 bytes to make sure render
-    * to texture works, but we don't need that for texturing from a
-    * pixmap.  Just override it here. */
-   mt->pitch = region->pitch;
-#endif
 
    intel_region_reference(&mt->region, region);
 
    return mt;
 }
 
-
-/**
- * intel_miptree_pitch_align:
- *
- * @intel: intel context pointer
- *
- * @mt: the miptree to compute pitch alignment for
- *
- * @pitch: the natural pitch value
- *
- * Given @pitch, compute a larger value which accounts for
- * any necessary alignment required by the device
- */
-int intel_miptree_pitch_align (struct intel_context *intel,
-                              struct intel_mipmap_tree *mt,
-                              uint32_t tiling,
-                              int pitch)
-{
-#ifdef I915
-   GLcontext *ctx = &intel->ctx;
-#endif
-
-   if (!mt->compressed) {
-      int pitch_align;
-
-      if (intel->ttm) {
-        /* XXX: Align pitch to multiple of 64 bytes for now to allow
-         * render-to-texture to work in all cases. This should probably be
-         * replaced at some point by some scheme to only do this when really
-         * necessary.
-         */
-        pitch_align = 64;
-      } else {
-        pitch_align = 4;
-      }
-
-      if (tiling == I915_TILING_X)
-        pitch_align = 512;
-      else if (tiling == I915_TILING_Y)
-        pitch_align = 128;
-
-      pitch = ALIGN(pitch * mt->cpp, pitch_align);
-
-#ifdef I915
-      /* XXX: At least the i915 seems very upset when the pitch is a multiple
-       * of 1024 and sometimes 512 bytes - performance can drop by several
-       * times. Go to the next multiple of the required alignment for now.
-       */
-      if (!(pitch & 511) && 
-        (pitch + pitch_align) < (1 << ctx->Const.MaxTextureLevels))
-        pitch += pitch_align;
-#endif
-
-      pitch /= mt->cpp;
-   }
-   return pitch;
-}
-
-
 void
 intel_miptree_reference(struct intel_mipmap_tree **dst,
                         struct intel_mipmap_tree *src)
@@ -294,9 +219,10 @@ intel_miptree_release(struct intel_context *intel,
 
       intel_region_release(&((*mt)->region));
 
-      for (i = 0; i < MAX_TEXTURE_LEVELS; i++)
-         if ((*mt)->level[i].image_offset)
-            free((*mt)->level[i].image_offset);
+      for (i = 0; i < MAX_TEXTURE_LEVELS; i++) {
+        free((*mt)->level[i].x_offset);
+        free((*mt)->level[i].y_offset);
+      }
 
       free(*mt);
    }
@@ -312,24 +238,23 @@ intel_miptree_release(struct intel_context *intel,
  */
 GLboolean
 intel_miptree_match_image(struct intel_mipmap_tree *mt,
-                          struct gl_texture_image *image,
-                          GLuint face, GLuint level)
+                          struct gl_texture_image *image)
 {
-   /* Images with borders are never pulled into mipmap trees. 
-    */
-   if (image->Border ||
-       ((image->_BaseFormat == GL_DEPTH_COMPONENT) &&
-        ((image->TexObject->WrapS == GL_CLAMP_TO_BORDER) ||
-         (image->TexObject->WrapT == GL_CLAMP_TO_BORDER)))) 
+   GLboolean isCompressed = _mesa_is_format_compressed(image->TexFormat);
+   struct intel_texture_image *intelImage = intel_texture_image(image);
+   GLuint level = intelImage->level;
+
+   /* Images with borders are never pulled into mipmap trees. */
+   if (image->Border)
       return GL_FALSE;
 
    if (image->InternalFormat != mt->internal_format ||
-       image->IsCompressed != mt->compressed)
+       isCompressed != mt->compressed)
       return GL_FALSE;
 
-   if (!image->IsCompressed &&
+   if (!isCompressed &&
        !mt->compressed &&
-       image->TexFormat->TexelBytes != mt->cpp)
+       _mesa_get_format_bytes(image->TexFormat) != mt->cpp)
       return GL_FALSE;
 
    /* Test image dimensions against the base level image adjusted for
@@ -355,76 +280,59 @@ intel_miptree_set_level_info(struct intel_mipmap_tree *mt,
    mt->level[level].width = w;
    mt->level[level].height = h;
    mt->level[level].depth = d;
-   mt->level[level].level_offset = (x + y * mt->pitch) * mt->cpp;
+   mt->level[level].level_x = x;
+   mt->level[level].level_y = y;
    mt->level[level].nr_images = nr_images;
 
-   DBG("%s level %d size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
-       level, w, h, d, x, y, mt->level[level].level_offset);
-
-   /* Not sure when this would happen, but anyway: 
-    */
-   if (mt->level[level].image_offset) {
-      free(mt->level[level].image_offset);
-      mt->level[level].image_offset = NULL;
-   }
+   DBG("%s level %d size: %d,%d,%d offset %d,%d\n", __FUNCTION__,
+       level, w, h, d, x, y);
 
    assert(nr_images);
+   assert(!mt->level[level].x_offset);
 
-   mt->level[level].image_offset = malloc(nr_images * sizeof(GLuint));
-   mt->level[level].image_offset[0] = 0;
+   mt->level[level].x_offset = malloc(nr_images * sizeof(GLuint));
+   mt->level[level].x_offset[0] = mt->level[level].level_x;
+   mt->level[level].y_offset = malloc(nr_images * sizeof(GLuint));
+   mt->level[level].y_offset[0] = mt->level[level].level_y;
 }
 
 
 void
-intel_miptree_set_image_offset_ex(struct intel_mipmap_tree *mt,
-                                  GLuint level, GLuint img,
-                                  GLuint x, GLuint y, 
-                                  GLuint offset)
+intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
+                              GLuint level, GLuint img,
+                              GLuint x, GLuint y)
 {
    if (img == 0 && level == 0)
       assert(x == 0 && y == 0);
 
    assert(img < mt->level[level].nr_images);
 
-   mt->level[level].image_offset[img] = (x + y * mt->pitch) * mt->cpp + offset;
+   mt->level[level].x_offset[img] = mt->level[level].level_x + x;
+   mt->level[level].y_offset[img] = mt->level[level].level_y + y;
 
-   DBG("%s level %d img %d pos %d,%d image_offset %x\n",
-       __FUNCTION__, level, img, x, y, mt->level[level].image_offset[img]);
+   DBG("%s level %d img %d pos %d,%d\n",
+       __FUNCTION__, level, img,
+       mt->level[level].x_offset[img], mt->level[level].y_offset[img]);
 }
 
 
 void
-intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
-                              GLuint level, GLuint img,
-                              GLuint x, GLuint y)
-{
-    intel_miptree_set_image_offset_ex(mt, level, img, x, y, 0);
-}
-
-
-/**
- * Return offset to the start of a 2D slice of a texture (a mipmap level,
- * cube face, 3D Z slice).
- * \param mt  the texture object/miptree
- * \param face  cube map face in [0,5] or zero for non-cube textures
- * \param level  mipmap level
- * \param zslice  Z slice of a 3D texture, or zero for non-3D textures
- */
-GLuint
-intel_miptree_image_offset(const struct intel_mipmap_tree *mt,
-                           GLuint face, GLuint level, GLuint zslice)
+intel_miptree_get_image_offset(struct intel_mipmap_tree *mt,
+                              GLuint level, GLuint face, GLuint depth,
+                              GLuint *x, GLuint *y)
 {
-   GLuint offset = mt->level[level].level_offset;
-
-   if (mt->target == GL_TEXTURE_CUBE_MAP_ARB)
-      offset += mt->level[level].image_offset[face];
-   else if (mt->target == GL_TEXTURE_3D)
-      offset += mt->level[level].image_offset[zslice];
-
-   return offset;
+   if (mt->target == GL_TEXTURE_CUBE_MAP_ARB) {
+      *x = mt->level[level].x_offset[face];
+      *y = mt->level[level].y_offset[face];
+   } else if (mt->target == GL_TEXTURE_3D) {
+      *x = mt->level[level].x_offset[depth];
+      *y = mt->level[level].y_offset[depth];
+   } else {
+      *x = mt->level[level].x_offset[0];
+      *y = mt->level[level].y_offset[0];
+   }
 }
 
-
 /**
  * Map a teximage in a mipmap tree.
  * \param row_stride  returns row stride in bytes
@@ -440,25 +348,32 @@ intel_miptree_image_map(struct intel_context * intel,
                         GLuint level,
                         GLuint * row_stride, GLuint * image_offsets)
 {
+   GLuint x, y;
    DBG("%s \n", __FUNCTION__);
 
    if (row_stride)
-      *row_stride = mt->pitch * mt->cpp;
+      *row_stride = mt->region->pitch * mt->cpp;
 
    if (mt->target == GL_TEXTURE_3D) {
       int i;
 
-      for (i = 0; i < mt->level[level].depth; i++)
-        image_offsets[i] = mt->level[level].image_offset[i] / mt->cpp;
+      for (i = 0; i < mt->level[level].depth; i++) {
+
+        intel_miptree_get_image_offset(mt, level, face, i,
+                                       &x, &y);
+        image_offsets[i] = x + y * mt->region->pitch;
+      }
+
+      return intel_region_map(intel, mt->region);
    } else {
       assert(mt->level[level].depth == 1);
-      assert(mt->target == GL_TEXTURE_CUBE_MAP ||
-            mt->level[level].image_offset[0] == 0);
+      intel_miptree_get_image_offset(mt, level, face, 0,
+                                    &x, &y);
       image_offsets[0] = 0;
-   }
 
-   return (intel_region_map(intel, mt->region) +
-           intel_miptree_image_offset(mt, face, level, 0));
+      return intel_region_map(intel, mt->region) +
+        (x + y * mt->region->pitch) * mt->cpp;
+   }
 }
 
 
@@ -488,16 +403,16 @@ intel_miptree_image_data(struct intel_context *intel,
 
    DBG("%s: %d/%d\n", __FUNCTION__, face, level);
    for (i = 0; i < depth; i++) {
-      GLuint dst_offset = intel_miptree_image_offset(dst, face, level, i);
-      GLuint height = dst->level[level].height;
+      GLuint dst_x, dst_y, height;
 
-      if (dst->compressed)
+      intel_miptree_get_image_offset(dst, level, face, i, &dst_x, &dst_y);
+
+      height = dst->level[level].height;
+      if(dst->compressed)
         height = (height + 3) / 4;
 
       intel_region_data(intel,
-                       dst->region,
-                       dst_offset,
-                       0, 0,                             /* dstx, dsty */
+                       dst->region, 0, dst_x, dst_y,
                        src,
                        src_row_pitch,
                        0, 0,                             /* source x, y */
@@ -520,6 +435,7 @@ intel_miptree_image_copy(struct intel_context *intel,
    GLuint width = src->level[level].width;
    GLuint height = src->level[level].height;
    GLuint depth = src->level[level].depth;
+   GLuint src_x, src_y, dst_x, dst_y;
    GLuint i;
    GLboolean success;
 
@@ -532,28 +448,29 @@ intel_miptree_image_copy(struct intel_context *intel,
        width = ALIGN(width, align_w);
    }
 
-   for (i = 0; i < depth; i++) {
-      GLuint dst_offset = intel_miptree_image_offset(dst, face, level, i);
-      GLuint src_offset = intel_miptree_image_offset(src, face, level, i);
+   intel_prepare_render(intel);
 
+   for (i = 0; i < depth; i++) {
+      intel_miptree_get_image_offset(src, level, face, i, &src_x, &src_y);
+      intel_miptree_get_image_offset(dst, level, face, i, &dst_x, &dst_y);
       success = intel_region_copy(intel,
-                                 dst->region, dst_offset,
-                                 0, 0,
-                                 src->region, src_offset,
-                                 0, 0, width, height, GL_COPY);
+                                 dst->region, 0, dst_x, dst_y,
+                                 src->region, 0, src_x, src_y,
+                                 width, height, GL_FALSE,
+                                 GL_COPY);
       if (!success) {
         GLubyte *src_ptr, *dst_ptr;
 
         src_ptr = intel_region_map(intel, src->region);
         dst_ptr = intel_region_map(intel, dst->region);
 
-        _mesa_copy_rect(dst_ptr + dst_offset,
+        _mesa_copy_rect(dst_ptr,
                         dst->cpp,
-                        dst->pitch,
-                        0, 0, width, height,
-                        src_ptr + src_offset,
-                        src->pitch,
-                        0, 0);
+                        dst->region->pitch,
+                        dst_x, dst_y, width, height,
+                        src_ptr,
+                        src->region->pitch,
+                        src_x, src_y);
         intel_region_unmap(intel, src->region);
         intel_region_unmap(intel, dst->region);
       }