[Mesa-dev] [PATCH 02/12] intel: Create intel_miptree_get_region() to prepare for fast color clear.

Paul Berry stereotype441 at gmail.com
Tue May 21 16:52:06 PDT 2013


With the advent of fast color clears, it will no longer be safe for
the driver to access the data stored in a miptree with impunity.  For
example, sometimes a resolve will need to be performed first (to
ensure that deferred writes due to a fast clear are performed before
the buffer is accessed).  Other times, fast clear will need to be
disabled for the miptree, so that its contents can be safely shared
with an entity that Mesa can't synchronize with easily.

To prepare for that, this patch renames intel_mipmap_tree::region to
intel_mipmap_tree::region_private and creates an accessor function,
intel_miptree_get_region().  At the moment, the accessor function
simply returns region_private.  Later in the patch series, this
function will be expanded to take appropriate actions to maintain the
proper fast color clear state.

As much as possible, I've tried to restrict the functions which
directly access region_private to low-level miptree functions
(e.g. miptree initialization functions), so that it will be easy to
verify that those functions access the miptree contents safely.
---
 src/mesa/drivers/dri/i915/i830_texstate.c         |  12 +-
 src/mesa/drivers/dri/i915/i830_vtbl.c             |  28 ++++-
 src/mesa/drivers/dri/i915/i915_texstate.c         |  12 +-
 src/mesa/drivers/dri/i915/i915_vtbl.c             |  13 +-
 src/mesa/drivers/dri/i915/intel_clear.c           |   8 +-
 src/mesa/drivers/dri/i965/brw_blorp.cpp           |   6 +-
 src/mesa/drivers/dri/i965/brw_blorp.h             |   3 +-
 src/mesa/drivers/dri/i965/brw_blorp_clear.cpp     |   4 +-
 src/mesa/drivers/dri/i965/brw_context.h           |   3 +-
 src/mesa/drivers/dri/i965/brw_misc_state.c        |  57 ++++++---
 src/mesa/drivers/dri/i965/brw_state.h             |   2 +-
 src/mesa/drivers/dri/i965/brw_wm_surface_state.c  |  17 +--
 src/mesa/drivers/dri/i965/gen6_blorp.cpp          |  29 +++--
 src/mesa/drivers/dri/i965/gen7_blorp.cpp          |  30 +++--
 src/mesa/drivers/dri/i965/gen7_misc_state.c       |  21 +++-
 src/mesa/drivers/dri/i965/gen7_wm_surface_state.c |  31 +++--
 src/mesa/drivers/dri/intel/intel_blit.c           |   9 +-
 src/mesa/drivers/dri/intel/intel_buffer_objects.c |  34 +++--
 src/mesa/drivers/dri/intel/intel_buffers.c        |  10 +-
 src/mesa/drivers/dri/intel/intel_buffers.h        |   9 +-
 src/mesa/drivers/dri/intel/intel_context.c        |   8 +-
 src/mesa/drivers/dri/intel/intel_fbo.c            |  16 ++-
 src/mesa/drivers/dri/intel/intel_fbo.h            |   8 +-
 src/mesa/drivers/dri/intel/intel_mipmap_tree.c    | 145 ++++++++++++++--------
 src/mesa/drivers/dri/intel/intel_mipmap_tree.h    |  72 ++++++++++-
 src/mesa/drivers/dri/intel/intel_pixel_bitmap.c   |   3 +-
 src/mesa/drivers/dri/intel/intel_pixel_copy.c     |  14 ++-
 src/mesa/drivers/dri/intel/intel_pixel_read.c     |   3 +-
 src/mesa/drivers/dri/intel/intel_screen.c         |  21 ++--
 src/mesa/drivers/dri/intel/intel_tex_copy.c       |  14 ++-
 src/mesa/drivers/dri/intel/intel_tex_image.c      |  21 ++--
 src/mesa/drivers/dri/intel/intel_tex_subimage.c   |  27 ++--
 32 files changed, 480 insertions(+), 210 deletions(-)

diff --git a/src/mesa/drivers/dri/i915/i830_texstate.c b/src/mesa/drivers/dri/i915/i830_texstate.c
index f186fac..b2eb724 100644
--- a/src/mesa/drivers/dri/i915/i830_texstate.c
+++ b/src/mesa/drivers/dri/i915/i830_texstate.c
@@ -148,9 +148,11 @@ i830_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
    intel_miptree_get_image_offset(intelObj->mt, tObj->BaseLevel, 0,
 				  &dst_x, &dst_y);
 
-   drm_intel_bo_reference(intelObj->mt->region->bo);
-   i830->state.tex_buffer[unit] = intelObj->mt->region->bo;
-   pitch = intelObj->mt->region->pitch;
+   struct intel_region *region =
+      intel_miptree_get_region(intel, intelObj->mt, INTEL_MIPTREE_ACCESS_TEX);
+   drm_intel_bo_reference(region->bo);
+   i830->state.tex_buffer[unit] = region->bo;
+   pitch = region->pitch;
 
    /* XXX: This calculation is probably broken for tiled images with
     * a non-page-aligned offset.
@@ -166,9 +168,9 @@ i830_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
       (((firstImage->Height - 1) << TM0S1_HEIGHT_SHIFT) |
        ((firstImage->Width - 1) << TM0S1_WIDTH_SHIFT) | format);
 
-   if (intelObj->mt->region->tiling != I915_TILING_NONE) {
+   if (region->tiling != I915_TILING_NONE) {
       state[I830_TEXREG_TM0S1] |= TM0S1_TILED_SURFACE;
-      if (intelObj->mt->region->tiling == I915_TILING_Y)
+      if (region->tiling == I915_TILING_Y)
 	 state[I830_TEXREG_TM0S1] |= TM0S1_TILE_WALK;
    }
 
diff --git a/src/mesa/drivers/dri/i915/i830_vtbl.c b/src/mesa/drivers/dri/i915/i830_vtbl.c
index b30f45e..a35f58b 100644
--- a/src/mesa/drivers/dri/i915/i830_vtbl.c
+++ b/src/mesa/drivers/dri/i915/i830_vtbl.c
@@ -760,7 +760,13 @@ i830_update_draw_buffer(struct intel_context *intel)
 
        for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
            irb = intel_renderbuffer(fb->_ColorDrawBuffers[i]);
-           colorRegions[i] = (irb && irb->mt) ? irb->mt->region : NULL;
+           if (irb && irb->mt) {
+              colorRegions[i] =
+                 intel_miptree_get_region(intel, irb->mt,
+                                          INTEL_MIPTREE_ACCESS_RENDER);
+           } else {
+              colorRegions[i] = NULL;
+           }
        }
    }
    else {
@@ -770,15 +776,23 @@ i830_update_draw_buffer(struct intel_context *intel)
       if (_mesa_is_winsys_fbo(fb)) {
 	 /* drawing to window system buffer */
 	 if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT)
-	    colorRegions[0] = intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
+	    colorRegions[0] = intel_get_rb_region(intel, fb, BUFFER_FRONT_LEFT,
+                                                  INTEL_MIPTREE_ACCESS_RENDER);
 	 else
-	    colorRegions[0] = intel_get_rb_region(fb, BUFFER_BACK_LEFT);
+	    colorRegions[0] = intel_get_rb_region(intel, fb, BUFFER_BACK_LEFT,
+                                                  INTEL_MIPTREE_ACCESS_RENDER);
       }
       else {
 	 /* drawing to user-created FBO */
 	 struct intel_renderbuffer *irb;
 	 irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]);
-	 colorRegions[0] = (irb && irb->mt->region) ? irb->mt->region : NULL;
+         if (irb && irb->mt) {
+            colorRegions[0] =
+               intel_miptree_get_region(intel, irb->mt,
+                                        INTEL_MIPTREE_ACCESS_RENDER);
+         } else {
+            colorRegions[0] = NULL;
+         }
       }
    }
 
@@ -792,7 +806,8 @@ i830_update_draw_buffer(struct intel_context *intel)
    /* Check for depth fallback. */
    if (irbDepth && irbDepth->mt) {
       FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, false);
-      depthRegion = irbDepth->mt->region;
+      depthRegion = intel_miptree_get_region(intel, irbDepth->mt,
+                                             INTEL_MIPTREE_ACCESS_RENDER);
    } else if (irbDepth && !irbDepth->mt) {
       FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, true);
       depthRegion = NULL;
@@ -818,7 +833,8 @@ i830_update_draw_buffer(struct intel_context *intel)
     */
    if (depthRegion == NULL && irbStencil && irbStencil->mt
        && intel_rb_format(irbStencil) == MESA_FORMAT_S8_Z24) {
-      depthRegion = irbStencil->mt->region;
+      depthRegion = intel_miptree_get_region(intel, irbStencil->mt,
+                                             INTEL_MIPTREE_ACCESS_RENDER);
    }
 
    /*
diff --git a/src/mesa/drivers/dri/i915/i915_texstate.c b/src/mesa/drivers/dri/i915/i915_texstate.c
index 43c802b..d186e77 100644
--- a/src/mesa/drivers/dri/i915/i915_texstate.c
+++ b/src/mesa/drivers/dri/i915/i915_texstate.c
@@ -168,8 +168,10 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
     */
    firstImage = tObj->Image[0][tObj->BaseLevel];
 
-   drm_intel_bo_reference(intelObj->mt->region->bo);
-   i915->state.tex_buffer[unit] = intelObj->mt->region->bo;
+   struct intel_region *region =
+      intel_miptree_get_region(intel, intelObj->mt, INTEL_MIPTREE_ACCESS_TEX);
+   drm_intel_bo_reference(region->bo);
+   i915->state.tex_buffer[unit] = region->bo;
    i915->state.tex_offset[unit] = intelObj->mt->offset;
 
    format = translate_texture_format(firstImage->TexFormat,
@@ -179,9 +181,9 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
       (((firstImage->Height - 1) << MS3_HEIGHT_SHIFT) |
        ((firstImage->Width - 1) << MS3_WIDTH_SHIFT) | format);
 
-   if (intelObj->mt->region->tiling != I915_TILING_NONE) {
+   if (region->tiling != I915_TILING_NONE) {
       state[I915_TEXREG_MS3] |= MS3_TILED_SURFACE;
-      if (intelObj->mt->region->tiling == I915_TILING_Y)
+      if (region->tiling == I915_TILING_Y)
 	 state[I915_TEXREG_MS3] |= MS3_TILE_WALK;
    }
 
@@ -191,7 +193,7 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
     */
    maxlod = MIN2(sampler->MaxLod, tObj->_MaxLevel - tObj->BaseLevel);
    state[I915_TEXREG_MS4] =
-      ((((intelObj->mt->region->pitch / 4) - 1) << MS4_PITCH_SHIFT) |
+      ((((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));
diff --git a/src/mesa/drivers/dri/i915/i915_vtbl.c b/src/mesa/drivers/dri/i915/i915_vtbl.c
index 91fde55..94939e6 100644
--- a/src/mesa/drivers/dri/i915/i915_vtbl.c
+++ b/src/mesa/drivers/dri/i915/i915_vtbl.c
@@ -758,14 +758,20 @@ i915_update_draw_buffer(struct intel_context *intel)
    } else {
       struct intel_renderbuffer *irb;
       irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]);
-      colorRegion = (irb && irb->mt) ? irb->mt->region : NULL;
+      if (irb && irb->mt) {
+         colorRegion = intel_miptree_get_region(intel, irb->mt,
+                                                INTEL_MIPTREE_ACCESS_RENDER);
+      } else {
+         colorRegion = NULL;
+      }
       FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, false);
    }
 
    /* Check for depth fallback. */
    if (irbDepth && irbDepth->mt) {
       FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, false);
-      depthRegion = irbDepth->mt->region;
+      depthRegion = intel_miptree_get_region(intel, irbDepth->mt,
+                                             INTEL_MIPTREE_ACCESS_RENDER);
    } else if (irbDepth && !irbDepth->mt) {
       FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, true);
       depthRegion = NULL;
@@ -791,7 +797,8 @@ i915_update_draw_buffer(struct intel_context *intel)
     */
    if (depthRegion == NULL && irbStencil && irbStencil->mt
        && intel_rb_format(irbStencil) == MESA_FORMAT_S8_Z24) {
-      depthRegion = irbStencil->mt->region;
+      depthRegion = intel_miptree_get_region(intel, irbStencil->mt,
+                                             INTEL_MIPTREE_ACCESS_RENDER);
    }
 
    /*
diff --git a/src/mesa/drivers/dri/i915/intel_clear.c b/src/mesa/drivers/dri/i915/intel_clear.c
index ebac0f5..b397241 100644
--- a/src/mesa/drivers/dri/i915/intel_clear.c
+++ b/src/mesa/drivers/dri/i915/intel_clear.c
@@ -37,6 +37,7 @@
 #include "intel_clear.h"
 #include "intel_fbo.h"
 #include "intel_regions.h"
+#include "intel_mipmap_tree.h"
 
 #define FILE_DEBUG_FLAG DEBUG_BLIT
 
@@ -129,7 +130,8 @@ intelClear(struct gl_context *ctx, GLbitfield mask)
    /* HW stencil */
    if (mask & BUFFER_BIT_STENCIL) {
       const struct intel_region *stencilRegion
-         = intel_get_rb_region(fb, BUFFER_STENCIL);
+         = intel_get_rb_region(intel, fb, BUFFER_STENCIL,
+                               INTEL_MIPTREE_ACCESS_NONE);
       if (stencilRegion) {
          /* have hw stencil */
          if (stencilRegion->tiling == I915_TILING_Y ||
@@ -149,7 +151,9 @@ intelClear(struct gl_context *ctx, GLbitfield mask)
 
    /* HW depth */
    if (mask & BUFFER_BIT_DEPTH) {
-      const struct intel_region *irb = intel_get_rb_region(fb, BUFFER_DEPTH);
+      const struct intel_region *irb =
+         intel_get_rb_region(intel, fb, BUFFER_DEPTH,
+                             INTEL_MIPTREE_ACCESS_NONE);
 
       /* clear depth with whatever method is used for stencil (see above) */
       if (irb->tiling == I915_TILING_Y || tri_mask & BUFFER_BIT_STENCIL)
diff --git a/src/mesa/drivers/dri/i965/brw_blorp.cpp b/src/mesa/drivers/dri/i965/brw_blorp.cpp
index a2d02bf..20f7153 100644
--- a/src/mesa/drivers/dri/i965/brw_blorp.cpp
+++ b/src/mesa/drivers/dri/i965/brw_blorp.cpp
@@ -120,10 +120,12 @@ brw_blorp_surface_info::set(struct brw_context *brw,
  * directly from the adjusted offsets.
  */
 uint32_t
-brw_blorp_surface_info::compute_tile_offsets(uint32_t *tile_x,
+brw_blorp_surface_info::compute_tile_offsets(struct intel_context *intel,
+                                             uint32_t *tile_x,
                                              uint32_t *tile_y) const
 {
-   struct intel_region *region = mt->region;
+   struct intel_region *region =
+      intel_miptree_get_region(intel, mt, INTEL_MIPTREE_ACCESS_NONE);
    uint32_t mask_x, mask_y;
 
    intel_region_get_tile_masks(region, &mask_x, &mask_y,
diff --git a/src/mesa/drivers/dri/i965/brw_blorp.h b/src/mesa/drivers/dri/i965/brw_blorp.h
index 8915080..6360a62 100644
--- a/src/mesa/drivers/dri/i965/brw_blorp.h
+++ b/src/mesa/drivers/dri/i965/brw_blorp.h
@@ -118,7 +118,8 @@ public:
             struct intel_mipmap_tree *mt,
             unsigned int level, unsigned int layer);
 
-   uint32_t compute_tile_offsets(uint32_t *tile_x, uint32_t *tile_y) const;
+   uint32_t compute_tile_offsets(struct intel_context *intel,
+                                 uint32_t *tile_x, uint32_t *tile_y) const;
 
    /* Setting this flag indicates that the buffer's contents are W-tiled
     * stencil data, but the surface state should be set up for Y tiled
diff --git a/src/mesa/drivers/dri/i965/brw_blorp_clear.cpp b/src/mesa/drivers/dri/i965/brw_blorp_clear.cpp
index b626659..28d7ad0 100644
--- a/src/mesa/drivers/dri/i965/brw_blorp_clear.cpp
+++ b/src/mesa/drivers/dri/i965/brw_blorp_clear.cpp
@@ -149,7 +149,9 @@ brw_blorp_clear_params::brw_blorp_clear_params(struct brw_context *brw,
     *      accessing tiled memory.  Using this Message Type to access linear
     *      (untiled) memory is UNDEFINED."
     */
-   if (irb->mt->region->tiling == I915_TILING_NONE)
+   struct intel_region *region =
+      intel_miptree_get_region(intel, irb->mt, INTEL_MIPTREE_ACCESS_NONE);
+   if (region->tiling == I915_TILING_NONE)
       wm_prog_key.use_simd16_replicated_data = false;
 
    /* Constant color writes ignore everyting in blend and color calculator
diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
index fbff10b..a25eca8 100644
--- a/src/mesa/drivers/dri/i965/brw_context.h
+++ b/src/mesa/drivers/dri/i965/brw_context.h
@@ -1153,7 +1153,8 @@ bool brwCreateContext(int api,
 /*======================================================================
  * brw_misc_state.c
  */
-void brw_get_depthstencil_tile_masks(struct intel_mipmap_tree *depth_mt,
+void brw_get_depthstencil_tile_masks(struct intel_context *intel,
+                                     struct intel_mipmap_tree *depth_mt,
                                      uint32_t depth_level,
                                      uint32_t depth_layer,
                                      struct intel_mipmap_tree *stencil_mt,
diff --git a/src/mesa/drivers/dri/i965/brw_misc_state.c b/src/mesa/drivers/dri/i965/brw_misc_state.c
index 6b61929..d78d445 100644
--- a/src/mesa/drivers/dri/i965/brw_misc_state.c
+++ b/src/mesa/drivers/dri/i965/brw_misc_state.c
@@ -270,7 +270,8 @@ brw_depthbuffer_format(struct brw_context *brw)
  * mask, then we're in trouble.
  */
 void
-brw_get_depthstencil_tile_masks(struct intel_mipmap_tree *depth_mt,
+brw_get_depthstencil_tile_masks(struct intel_context *intel,
+                                struct intel_mipmap_tree *depth_mt,
                                 uint32_t depth_level,
                                 uint32_t depth_layer,
                                 struct intel_mipmap_tree *stencil_mt,
@@ -280,12 +281,17 @@ brw_get_depthstencil_tile_masks(struct intel_mipmap_tree *depth_mt,
    uint32_t tile_mask_x = 0, tile_mask_y = 0;
 
    if (depth_mt) {
-      intel_region_get_tile_masks(depth_mt->region,
+      struct intel_region *depth_region =
+         intel_miptree_get_region(intel, depth_mt, INTEL_MIPTREE_ACCESS_NONE);
+      struct intel_region *hiz_region =
+         intel_miptree_get_region(intel, depth_mt->hiz_mt,
+                                  INTEL_MIPTREE_ACCESS_NONE);
+      intel_region_get_tile_masks(depth_region,
                                   &tile_mask_x, &tile_mask_y, false);
 
       if (intel_miptree_slice_has_hiz(depth_mt, depth_level, depth_layer)) {
          uint32_t hiz_tile_mask_x, hiz_tile_mask_y;
-         intel_region_get_tile_masks(depth_mt->hiz_mt->region,
+         intel_region_get_tile_masks(hiz_region,
                                      &hiz_tile_mask_x, &hiz_tile_mask_y, false);
 
          /* Each HiZ row represents 2 rows of pixels */
@@ -305,8 +311,11 @@ brw_get_depthstencil_tile_masks(struct intel_mipmap_tree *depth_mt,
          tile_mask_x |= 63;
          tile_mask_y |= 63;
       } else {
+         struct intel_region *stencil_region =
+            intel_miptree_get_region(intel, stencil_mt,
+                                     INTEL_MIPTREE_ACCESS_NONE);
          uint32_t stencil_tile_mask_x, stencil_tile_mask_y;
-         intel_region_get_tile_masks(stencil_mt->region,
+         intel_region_get_tile_masks(stencil_region,
                                      &stencil_tile_mask_x,
                                      &stencil_tile_mask_y, false);
 
@@ -368,7 +377,7 @@ brw_workaround_depthstencil_alignment(struct brw_context *brw,
    }
 
    uint32_t tile_mask_x, tile_mask_y;
-   brw_get_depthstencil_tile_masks(depth_mt,
+   brw_get_depthstencil_tile_masks(intel, depth_mt,
                                    depth_mt ? depth_irb->mt_level : 0,
                                    depth_mt ? depth_irb->mt_layer : 0,
                                    stencil_mt,
@@ -532,15 +541,17 @@ brw_workaround_depthstencil_alignment(struct brw_context *brw,
    brw->depthstencil.stencil_mt = NULL;
    if (depth_irb) {
       depth_mt = depth_irb->mt;
+      struct intel_region *depth_region =
+         intel_miptree_get_region(intel, depth_mt, INTEL_MIPTREE_ACCESS_NONE);
       brw->depthstencil.depth_mt = depth_mt;
       brw->depthstencil.depth_offset =
-         intel_region_get_aligned_offset(depth_mt->region,
+         intel_region_get_aligned_offset(depth_region,
                                          depth_irb->draw_x & ~tile_mask_x,
                                          depth_irb->draw_y & ~tile_mask_y,
                                          false);
       if (intel_renderbuffer_has_hiz(depth_irb)) {
          brw->depthstencil.hiz_offset =
-            intel_region_get_aligned_offset(depth_mt->region,
+            intel_region_get_aligned_offset(depth_region,
                                             depth_irb->draw_x & ~tile_mask_x,
                                             (depth_irb->draw_y & ~tile_mask_y) /
                                             2,
@@ -556,8 +567,11 @@ brw_workaround_depthstencil_alignment(struct brw_context *brw,
           * intel_region_get_aligned_offset(), because stencil_region claims
           * that the region is untiled even though it's W tiled.
           */
+         struct intel_region *stencil_region =
+            intel_miptree_get_region(intel, stencil_mt,
+                                     INTEL_MIPTREE_ACCESS_NONE);
          brw->depthstencil.stencil_offset =
-            (stencil_draw_y & ~tile_mask_y) * stencil_mt->region->pitch +
+            (stencil_draw_y & ~tile_mask_y) * stencil_region->pitch +
             (stencil_draw_x & ~tile_mask_x) * 64;
       }
    }
@@ -614,8 +628,10 @@ brw_emit_depthbuffer(struct brw_context *brw)
       /* Prior to Gen7, if using separate stencil, hiz must be enabled. */
       assert(intel->gen >= 7 || !separate_stencil || hiz);
 
-      assert(intel->gen < 6 || depth_mt->region->tiling == I915_TILING_Y);
-      assert(!hiz || depth_mt->region->tiling == I915_TILING_Y);
+      struct intel_region *depth_region =
+         intel_miptree_get_region(intel, depth_mt, INTEL_MIPTREE_ACCESS_NONE);
+      assert(intel->gen < 6 || depth_region->tiling == I915_TILING_Y);
+      assert(!hiz || depth_region->tiling == I915_TILING_Y);
 
       depthbuffer_format = brw_depthbuffer_format(brw);
       depth_surface_type = BRW_SURFACE_2D;
@@ -670,6 +686,10 @@ brw_emit_depth_stencil_hiz(struct brw_context *brw,
     */
    bool enable_hiz_ss = hiz || separate_stencil;
 
+   struct intel_region *depth_region = depth_mt ?
+      intel_miptree_get_region(intel, depth_mt, INTEL_MIPTREE_ACCESS_RENDER) :
+      NULL;
+
 
    /* 3DSTATE_DEPTH_BUFFER, 3DSTATE_STENCIL_BUFFER are both
     * non-pipelined state that will need the PIPE_CONTROL workaround.
@@ -689,17 +709,17 @@ brw_emit_depth_stencil_hiz(struct brw_context *brw,
 
    BEGIN_BATCH(len);
    OUT_BATCH(_3DSTATE_DEPTH_BUFFER << 16 | (len - 2));
-   OUT_BATCH((depth_mt ? depth_mt->region->pitch - 1 : 0) |
+   OUT_BATCH((depth_mt ? depth_region->pitch - 1 : 0) |
              (depthbuffer_format << 18) |
              ((enable_hiz_ss ? 1 : 0) << 21) | /* separate stencil enable */
              ((enable_hiz_ss ? 1 : 0) << 22) | /* hiz enable */
              (BRW_TILEWALK_YMAJOR << 26) |
-             ((depth_mt ? depth_mt->region->tiling != I915_TILING_NONE : 1)
+             ((depth_mt ? depth_region->tiling != I915_TILING_NONE : 1)
               << 27) |
              (depth_surface_type << 29));
 
    if (depth_mt) {
-      OUT_RELOC(depth_mt->region->bo,
+      OUT_RELOC(depth_region->bo,
 		I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
 		depth_offset);
    } else {
@@ -732,10 +752,13 @@ brw_emit_depth_stencil_hiz(struct brw_context *brw,
       /* Emit hiz buffer. */
       if (hiz) {
          struct intel_mipmap_tree *hiz_mt = depth_mt->hiz_mt;
+         struct intel_region *hiz_region =
+            intel_miptree_get_region(intel, hiz_mt,
+                                     INTEL_MIPTREE_ACCESS_RENDER);
 	 BEGIN_BATCH(3);
 	 OUT_BATCH((_3DSTATE_HIER_DEPTH_BUFFER << 16) | (3 - 2));
-	 OUT_BATCH(hiz_mt->region->pitch - 1);
-	 OUT_RELOC(hiz_mt->region->bo,
+	 OUT_BATCH(hiz_region->pitch - 1);
+	 OUT_RELOC(hiz_region->bo,
 		   I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
 		   brw->depthstencil.hiz_offset);
 	 ADVANCE_BATCH();
@@ -749,7 +772,9 @@ brw_emit_depth_stencil_hiz(struct brw_context *brw,
 
       /* Emit stencil buffer. */
       if (separate_stencil) {
-	 struct intel_region *region = stencil_mt->region;
+	 struct intel_region *region =
+            intel_miptree_get_region(intel, stencil_mt,
+                                     INTEL_MIPTREE_ACCESS_RENDER);
 
 	 BEGIN_BATCH(3);
 	 OUT_BATCH((_3DSTATE_STENCIL_BUFFER << 16) | (3 - 2));
diff --git a/src/mesa/drivers/dri/i965/brw_state.h b/src/mesa/drivers/dri/i965/brw_state.h
index 9c956f8..ff17b39 100644
--- a/src/mesa/drivers/dri/i965/brw_state.h
+++ b/src/mesa/drivers/dri/i965/brw_state.h
@@ -206,7 +206,7 @@ uint32_t gen7_surface_msaa_bits(unsigned num_samples, enum intel_msaa_layout l);
 void gen7_set_surface_mcs_info(struct brw_context *brw,
                                uint32_t *surf,
                                uint32_t surf_offset,
-                               const struct intel_mipmap_tree *mcs_mt,
+                               struct intel_mipmap_tree *mcs_mt,
                                bool is_render_target);
 void gen7_check_surface_setup(uint32_t *surf, bool is_render_target);
 void gen7_init_vtable_surface_functions(struct brw_context *brw);
diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
index bbe8579..0173ba6 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -985,15 +985,17 @@ brw_update_texture_surface(struct gl_context *ctx,
 				    sampler->sRGBDecode) <<
 	       BRW_SURFACE_FORMAT_SHIFT));
 
-   surf[1] = intelObj->mt->region->bo->offset + intelObj->mt->offset; /* reloc */
+   struct intel_region *region =
+      intel_miptree_get_region(intel, intelObj->mt, INTEL_MIPTREE_ACCESS_TEX);
+   surf[1] = region->bo->offset + intelObj->mt->offset; /* reloc */
 
    surf[2] = ((intelObj->_MaxLevel - tObj->BaseLevel) << BRW_SURFACE_LOD_SHIFT |
 	      (width - 1) << BRW_SURFACE_WIDTH_SHIFT |
 	      (height - 1) << BRW_SURFACE_HEIGHT_SHIFT);
 
-   surf[3] = (brw_get_surface_tiling_bits(intelObj->mt->region->tiling) |
+   surf[3] = (brw_get_surface_tiling_bits(region->tiling) |
 	      (depth - 1) << BRW_SURFACE_DEPTH_SHIFT |
-	      (intelObj->mt->region->pitch - 1) <<
+	      (region->pitch - 1) <<
 	      BRW_SURFACE_PITCH_SHIFT);
 
    surf[4] = brw_get_surface_num_multisamples(intelObj->mt->num_samples);
@@ -1013,7 +1015,7 @@ brw_update_texture_surface(struct gl_context *ctx,
    /* Emit relocation to surface contents */
    drm_intel_bo_emit_reloc(brw->intel.batch.bo,
 			   binding_table[surf_index] + 4,
-			   intelObj->mt->region->bo,
+			   region->bo,
                            intelObj->mt->offset,
 			   I915_GEM_DOMAIN_SAMPLER, 0);
 }
@@ -1329,7 +1331,7 @@ brw_update_renderbuffer_surface(struct brw_context *brw,
    gl_format rb_format = _mesa_get_render_format(ctx, intel_rb_format(irb));
 
    if (rb->TexImage && !brw->has_surface_tile_offset) {
-      intel_renderbuffer_tile_offsets(irb, &tile_x, &tile_y);
+      intel_renderbuffer_tile_offsets(intel, irb, &tile_x, &tile_y);
 
       if (tile_x != 0 || tile_y != 0) {
 	 /* Original gen4 hardware couldn't draw to a non-tile-aligned
@@ -1343,7 +1345,8 @@ brw_update_renderbuffer_surface(struct brw_context *brw,
       }
    }
 
-   region = irb->mt->region;
+   region = intel_miptree_get_region(intel, irb->mt,
+                                     INTEL_MIPTREE_ACCESS_RENDER);
 
    surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE,
 			  6 * 4, 32, &brw->wm.surf_offset[unit]);
@@ -1358,7 +1361,7 @@ brw_update_renderbuffer_surface(struct brw_context *brw,
 	      format << BRW_SURFACE_FORMAT_SHIFT);
 
    /* reloc */
-   surf[1] = (intel_renderbuffer_tile_offsets(irb, &tile_x, &tile_y) +
+   surf[1] = (intel_renderbuffer_tile_offsets(intel, irb, &tile_x, &tile_y) +
 	      region->bo->offset);
 
    surf[2] = ((rb->Width - 1) << BRW_SURFACE_WIDTH_SHIFT |
diff --git a/src/mesa/drivers/dri/i965/gen6_blorp.cpp b/src/mesa/drivers/dri/i965/gen6_blorp.cpp
index c7bb815..7217212 100644
--- a/src/mesa/drivers/dri/i965/gen6_blorp.cpp
+++ b/src/mesa/drivers/dri/i965/gen6_blorp.cpp
@@ -405,7 +405,8 @@ static uint32_t
 gen6_blorp_emit_surface_state(struct brw_context *brw,
                               const brw_blorp_params *params,
                               const brw_blorp_surface_info *surface,
-                              uint32_t read_domains, uint32_t write_domain)
+                              uint32_t read_domains, uint32_t write_domain,
+                              enum intel_miptree_access_type access_type)
 {
    uint32_t wm_surf_offset;
    uint32_t width = surface->width;
@@ -418,7 +419,8 @@ gen6_blorp_emit_surface_state(struct brw_context *brw,
       width /= 2;
       height /= 2;
    }
-   struct intel_region *region = surface->mt->region;
+   struct intel_region *region =
+      intel_miptree_get_region(&brw->intel, surface->mt, access_type);
    uint32_t tile_x, tile_y;
 
    uint32_t *surf = (uint32_t *)
@@ -431,7 +433,7 @@ gen6_blorp_emit_surface_state(struct brw_context *brw,
               surface->brw_surfaceformat << BRW_SURFACE_FORMAT_SHIFT);
 
    /* reloc */
-   surf[1] = (surface->compute_tile_offsets(&tile_x, &tile_y) +
+   surf[1] = (surface->compute_tile_offsets(&brw->intel, &tile_x, &tile_y) +
               region->bo->offset);
 
    surf[2] = (0 << BRW_SURFACE_LOD_SHIFT |
@@ -862,7 +864,7 @@ gen6_blorp_emit_depth_stencil_config(struct brw_context *brw,
    uint32_t draw_y = params->depth.y_offset;
    uint32_t tile_mask_x, tile_mask_y;
 
-   brw_get_depthstencil_tile_masks(params->depth.mt,
+   brw_get_depthstencil_tile_masks(intel, params->depth.mt,
                                    params->depth.level,
                                    params->depth.layer,
                                    NULL,
@@ -870,10 +872,13 @@ gen6_blorp_emit_depth_stencil_config(struct brw_context *brw,
 
    /* 3DSTATE_DEPTH_BUFFER */
    {
+      struct intel_region *depth_region =
+         intel_miptree_get_region(intel, params->depth.mt,
+                                  INTEL_MIPTREE_ACCESS_RENDER);
       uint32_t tile_x = draw_x & tile_mask_x;
       uint32_t tile_y = draw_y & tile_mask_y;
       uint32_t offset =
-         intel_region_get_aligned_offset(params->depth.mt->region,
+         intel_region_get_aligned_offset(depth_region,
                                          draw_x & ~tile_mask_x,
                                          draw_y & ~tile_mask_y, false);
 
@@ -903,14 +908,14 @@ gen6_blorp_emit_depth_stencil_config(struct brw_context *brw,
 
       BEGIN_BATCH(7);
       OUT_BATCH(_3DSTATE_DEPTH_BUFFER << 16 | (7 - 2));
-      OUT_BATCH((params->depth.mt->region->pitch - 1) |
+      OUT_BATCH((depth_region->pitch - 1) |
                 params->depth_format << 18 |
                 1 << 21 | /* separate stencil enable */
                 1 << 22 | /* hiz enable */
                 BRW_TILEWALK_YMAJOR << 26 |
                 1 << 27 | /* y-tiled */
                 BRW_SURFACE_2D << 29);
-      OUT_RELOC(params->depth.mt->region->bo,
+      OUT_RELOC(depth_region->bo,
                 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
                 offset);
       OUT_BATCH(BRW_SURFACE_MIPMAPLAYOUT_BELOW << 1 |
@@ -925,7 +930,9 @@ gen6_blorp_emit_depth_stencil_config(struct brw_context *brw,
 
    /* 3DSTATE_HIER_DEPTH_BUFFER */
    {
-      struct intel_region *hiz_region = params->depth.mt->hiz_mt->region;
+      struct intel_region *hiz_region =
+         intel_miptree_get_region(intel, params->depth.mt->hiz_mt,
+                                  INTEL_MIPTREE_ACCESS_RENDER);
       uint32_t hiz_offset =
          intel_region_get_aligned_offset(hiz_region,
                                          draw_x & ~tile_mask_x,
@@ -1097,11 +1104,13 @@ gen6_blorp_exec(struct intel_context *intel,
       wm_surf_offset_renderbuffer =
          gen6_blorp_emit_surface_state(brw, params, &params->dst,
                                        I915_GEM_DOMAIN_RENDER,
-                                       I915_GEM_DOMAIN_RENDER);
+                                       I915_GEM_DOMAIN_RENDER,
+                                       INTEL_MIPTREE_ACCESS_RENDER);
       if (params->src.mt) {
          wm_surf_offset_texture =
             gen6_blorp_emit_surface_state(brw, params, &params->src,
-                                          I915_GEM_DOMAIN_SAMPLER, 0);
+                                          I915_GEM_DOMAIN_SAMPLER, 0,
+                                          INTEL_MIPTREE_ACCESS_TEX);
       }
       wm_bind_bo_offset =
          gen6_blorp_emit_binding_table(brw, params,
diff --git a/src/mesa/drivers/dri/i965/gen7_blorp.cpp b/src/mesa/drivers/dri/i965/gen7_blorp.cpp
index f83c7f2..f9eda63 100644
--- a/src/mesa/drivers/dri/i965/gen7_blorp.cpp
+++ b/src/mesa/drivers/dri/i965/gen7_blorp.cpp
@@ -137,7 +137,8 @@ gen7_blorp_emit_surface_state(struct brw_context *brw,
                               const brw_blorp_params *params,
                               const brw_blorp_surface_info *surface,
                               uint32_t read_domains, uint32_t write_domain,
-                              bool is_render_target)
+                              bool is_render_target,
+                              enum intel_miptree_access_type access_type)
 {
    struct intel_context *intel = &brw->intel;
 
@@ -149,7 +150,8 @@ gen7_blorp_emit_surface_state(struct brw_context *brw,
     * to divide them by 2 as we do for Gen6 (see
     * gen6_blorp_emit_surface_state).
     */
-   struct intel_region *region = surface->mt->region;
+   struct intel_region *region =
+      intel_miptree_get_region(intel, surface->mt, access_type);
    uint32_t tile_x, tile_y;
 
    uint32_t tiling = surface->map_stencil_as_y_tiled
@@ -175,7 +177,8 @@ gen7_blorp_emit_surface_state(struct brw_context *brw,
 
    /* reloc */
    surf[1] =
-      surface->compute_tile_offsets(&tile_x, &tile_y) + region->bo->offset;
+      surface->compute_tile_offsets(intel, &tile_x, &tile_y) +
+      region->bo->offset;
 
    /* Note that the low bits of these fields are missing, so
     * there's the possibility of getting in trouble.
@@ -680,7 +683,7 @@ gen7_blorp_emit_depth_stencil_config(struct brw_context *brw,
    uint32_t draw_y = params->depth.y_offset;
    uint32_t tile_mask_x, tile_mask_y;
 
-   brw_get_depthstencil_tile_masks(params->depth.mt,
+   brw_get_depthstencil_tile_masks(intel, params->depth.mt,
                                    params->depth.level,
                                    params->depth.layer,
                                    NULL,
@@ -688,10 +691,13 @@ gen7_blorp_emit_depth_stencil_config(struct brw_context *brw,
 
    /* 3DSTATE_DEPTH_BUFFER */
    {
+      struct intel_region *depth_region =
+         intel_miptree_get_region(intel, params->depth.mt,
+                                  INTEL_MIPTREE_ACCESS_RENDER);
       uint32_t tile_x = draw_x & tile_mask_x;
       uint32_t tile_y = draw_y & tile_mask_y;
       uint32_t offset =
-         intel_region_get_aligned_offset(params->depth.mt->region,
+         intel_region_get_aligned_offset(depth_region,
                                          draw_x & ~tile_mask_x,
                                          draw_y & ~tile_mask_y, false);
 
@@ -720,12 +726,12 @@ gen7_blorp_emit_depth_stencil_config(struct brw_context *brw,
 
       BEGIN_BATCH(7);
       OUT_BATCH(GEN7_3DSTATE_DEPTH_BUFFER << 16 | (7 - 2));
-      OUT_BATCH((params->depth.mt->region->pitch - 1) |
+      OUT_BATCH((depth_region->pitch - 1) |
                 params->depth_format << 18 |
                 1 << 22 | /* hiz enable */
                 1 << 28 | /* depth write */
                 BRW_SURFACE_2D << 29);
-      OUT_RELOC(params->depth.mt->region->bo,
+      OUT_RELOC(depth_region->bo,
                 I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
                 offset);
       OUT_BATCH((params->depth.width + tile_x - 1) << 4 |
@@ -739,7 +745,9 @@ gen7_blorp_emit_depth_stencil_config(struct brw_context *brw,
 
    /* 3DSTATE_HIER_DEPTH_BUFFER */
    {
-      struct intel_region *hiz_region = params->depth.mt->hiz_mt->region;
+      struct intel_region *hiz_region =
+         intel_miptree_get_region(intel, params->depth.mt->hiz_mt,
+                                  INTEL_MIPTREE_ACCESS_RENDER);
       uint32_t hiz_offset =
          intel_region_get_aligned_offset(hiz_region,
                                          draw_x & ~tile_mask_x,
@@ -867,12 +875,14 @@ gen7_blorp_exec(struct intel_context *intel,
          gen7_blorp_emit_surface_state(brw, params, &params->dst,
                                        I915_GEM_DOMAIN_RENDER,
                                        I915_GEM_DOMAIN_RENDER,
-                                       true /* is_render_target */);
+                                       true /* is_render_target */,
+                                       INTEL_MIPTREE_ACCESS_RENDER);
       if (params->src.mt) {
          wm_surf_offset_texture =
             gen7_blorp_emit_surface_state(brw, params, &params->src,
                                           I915_GEM_DOMAIN_SAMPLER, 0,
-                                          false /* is_render_target */);
+                                          false /* is_render_target */,
+                                          INTEL_MIPTREE_ACCESS_TEX);
       }
       wm_bind_bo_offset =
          gen6_blorp_emit_binding_table(brw, params,
diff --git a/src/mesa/drivers/dri/i965/gen7_misc_state.c b/src/mesa/drivers/dri/i965/gen7_misc_state.c
index 12b752c..11fbe18 100644
--- a/src/mesa/drivers/dri/i965/gen7_misc_state.c
+++ b/src/mesa/drivers/dri/i965/gen7_misc_state.c
@@ -42,12 +42,16 @@ gen7_emit_depth_stencil_hiz(struct brw_context *brw,
    struct intel_context *intel = &brw->intel;
    struct gl_context *ctx = &intel->ctx;
 
+   struct intel_region *depth_region = depth_mt ?
+      intel_miptree_get_region(intel, depth_mt, INTEL_MIPTREE_ACCESS_RENDER) :
+      NULL;
+
    intel_emit_depth_stall_flushes(intel);
 
    /* _NEW_DEPTH, _NEW_STENCIL */
    BEGIN_BATCH(7);
    OUT_BATCH(GEN7_3DSTATE_DEPTH_BUFFER << 16 | (7 - 2));
-   OUT_BATCH((depth_mt ? depth_mt->region->pitch - 1 : 0) |
+   OUT_BATCH((depth_mt ? depth_region->pitch - 1 : 0) |
              (depthbuffer_format << 18) |
              ((hiz ? 1 : 0) << 22) |
              ((stencil_mt != NULL && ctx->Stencil._WriteEnabled) << 27) |
@@ -55,7 +59,7 @@ gen7_emit_depth_stencil_hiz(struct brw_context *brw,
              (depth_surface_type << 29));
 
    if (depth_mt) {
-      OUT_RELOC(depth_mt->region->bo,
+      OUT_RELOC(depth_region->bo,
 	        I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
 		depth_offset);
    } else {
@@ -77,10 +81,12 @@ gen7_emit_depth_stencil_hiz(struct brw_context *brw,
       ADVANCE_BATCH();
    } else {
       struct intel_mipmap_tree *hiz_mt = depth_mt->hiz_mt;
+      struct intel_region *hiz_region =
+         intel_miptree_get_region(intel, hiz_mt, INTEL_MIPTREE_ACCESS_RENDER);
       BEGIN_BATCH(3);
       OUT_BATCH(GEN7_3DSTATE_HIER_DEPTH_BUFFER << 16 | (3 - 2));
-      OUT_BATCH(hiz_mt->region->pitch - 1);
-      OUT_RELOC(hiz_mt->region->bo,
+      OUT_BATCH(hiz_region->pitch - 1);
+      OUT_RELOC(hiz_region->bo,
                 I915_GEM_DOMAIN_RENDER,
                 I915_GEM_DOMAIN_RENDER,
                 brw->depthstencil.hiz_offset);
@@ -94,6 +100,9 @@ gen7_emit_depth_stencil_hiz(struct brw_context *brw,
       OUT_BATCH(0);
       ADVANCE_BATCH();
    } else {
+      struct intel_region *stencil_region =
+         intel_miptree_get_region(intel, stencil_mt,
+                                  INTEL_MIPTREE_ACCESS_RENDER);
       const int enabled = intel->is_haswell ? HSW_STENCIL_ENABLED : 0;
 
       BEGIN_BATCH(3);
@@ -113,8 +122,8 @@ gen7_emit_depth_stencil_hiz(struct brw_context *brw,
        * indicate that it does.
        */
       OUT_BATCH(enabled |
-	        (2 * stencil_mt->region->pitch - 1));
-      OUT_RELOC(stencil_mt->region->bo,
+	        (2 * stencil_region->pitch - 1));
+      OUT_RELOC(stencil_region->bo,
 	        I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
 		brw->depthstencil.stencil_offset);
       ADVANCE_BATCH();
diff --git a/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c b/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c
index 435f9dc..ea818f4 100644
--- a/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c
@@ -101,19 +101,22 @@ void
 gen7_set_surface_mcs_info(struct brw_context *brw,
                           uint32_t *surf,
                           uint32_t surf_offset,
-                          const struct intel_mipmap_tree *mcs_mt,
+                          struct intel_mipmap_tree *mcs_mt,
                           bool is_render_target)
 {
+   struct intel_region *region =
+      intel_miptree_get_region(&brw->intel, mcs_mt, INTEL_MIPTREE_ACCESS_MCS);
+
    /* From the Ivy Bridge PRM, Vol4 Part1 p76, "MCS Base Address":
     *
     *     "The MCS surface must be stored as Tile Y."
     */
-   assert(mcs_mt->region->tiling == I915_TILING_Y);
+   assert(region->tiling == I915_TILING_Y);
 
    /* Compute the pitch in units of tiles.  To do this we need to divide the
     * pitch in bytes by 128, since a single Y-tile is 128 bytes wide.
     */
-   unsigned pitch_tiles = mcs_mt->region->pitch / 128;
+   unsigned pitch_tiles = region->pitch / 128;
 
    /* The upper 20 bits of surface state DWORD 6 are the upper 20 bits of the
     * GPU address of the MCS buffer; the lower 12 bits contain other control
@@ -121,15 +124,15 @@ gen7_set_surface_mcs_info(struct brw_context *brw,
     * thus have their lower 12 bits zero), we can use an ordinary reloc to do
     * the necessary address translation.
     */
-   assert ((mcs_mt->region->bo->offset & 0xfff) == 0);
+   assert ((region->bo->offset & 0xfff) == 0);
 
    surf[6] = GEN7_SURFACE_MCS_ENABLE |
              SET_FIELD(pitch_tiles - 1, GEN7_SURFACE_MCS_PITCH) |
-             mcs_mt->region->bo->offset;
+             region->bo->offset;
 
    drm_intel_bo_emit_reloc(brw->intel.batch.bo,
                            surf_offset + 6 * 4,
-                           mcs_mt->region->bo,
+                           region->bo,
                            surf[6] & 0xfff,
                            is_render_target ? I915_GEM_DOMAIN_RENDER
                            : I915_GEM_DOMAIN_SAMPLER,
@@ -302,6 +305,9 @@ gen7_update_texture_surface(struct gl_context *ctx,
       return;
    }
 
+   struct intel_region *region =
+      intel_miptree_get_region(intel, mt, INTEL_MIPTREE_ACCESS_TEX);
+
    intel_miptree_get_dimensions_for_image(firstImage, &width, &height, &depth);
 
    uint32_t *surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE,
@@ -316,7 +322,7 @@ gen7_update_texture_surface(struct gl_context *ctx,
 
    surf[0] = translate_tex_target(tObj->Target) << BRW_SURFACE_TYPE_SHIFT |
              tex_format << BRW_SURFACE_FORMAT_SHIFT |
-             gen7_surface_tiling_mode(mt->region->tiling) |
+             gen7_surface_tiling_mode(region->tiling) |
              BRW_SURFACE_CUBEFACE_ENABLES;
 
    if (mt->align_h == 4)
@@ -330,12 +336,12 @@ gen7_update_texture_surface(struct gl_context *ctx,
    if (mt->array_spacing_lod0)
       surf[0] |= GEN7_SURFACE_ARYSPC_LOD0;
 
-   surf[1] = mt->region->bo->offset + mt->offset; /* reloc */
+   surf[1] = region->bo->offset + mt->offset; /* reloc */
 
    surf[2] = SET_FIELD(width - 1, GEN7_SURFACE_WIDTH) |
              SET_FIELD(height - 1, GEN7_SURFACE_HEIGHT);
    surf[3] = SET_FIELD(depth - 1, BRW_SURFACE_DEPTH) |
-             ((intelObj->mt->region->pitch) - 1);
+             ((region->pitch) - 1);
 
    surf[4] = gen7_surface_msaa_bits(mt->num_samples, mt->msaa_layout);
 
@@ -372,7 +378,7 @@ gen7_update_texture_surface(struct gl_context *ctx,
    /* Emit relocation to surface contents */
    drm_intel_bo_emit_reloc(brw->intel.batch.bo,
 			   binding_table[surf_index] + 4,
-			   intelObj->mt->region->bo, intelObj->mt->offset,
+			   region->bo, intelObj->mt->offset,
 			   I915_GEM_DOMAIN_SAMPLER, 0);
 
    gen7_check_surface_setup(surf, false /* is_render_target */);
@@ -527,7 +533,8 @@ gen7_update_renderbuffer_surface(struct brw_context *brw,
    struct intel_context *intel = &brw->intel;
    struct gl_context *ctx = &intel->ctx;
    struct intel_renderbuffer *irb = intel_renderbuffer(rb);
-   struct intel_region *region = irb->mt->region;
+   struct intel_region *region =
+      intel_miptree_get_region(intel, irb->mt, INTEL_MIPTREE_ACCESS_RENDER);
    uint32_t tile_x, tile_y;
    uint32_t format;
    /* _NEW_BUFFERS */
@@ -559,7 +566,7 @@ gen7_update_renderbuffer_surface(struct brw_context *brw,
       surf[0] |= GEN7_SURFACE_HALIGN_8;
 
    /* reloc */
-   surf[1] = intel_renderbuffer_tile_offsets(irb, &tile_x, &tile_y) +
+   surf[1] = intel_renderbuffer_tile_offsets(intel, irb, &tile_x, &tile_y) +
              region->bo->offset; /* reloc */
 
    assert(brw->has_surface_tile_offset);
diff --git a/src/mesa/drivers/dri/intel/intel_blit.c b/src/mesa/drivers/dri/intel/intel_blit.c
index f9cba85..39c69c9 100644
--- a/src/mesa/drivers/dri/intel/intel_blit.c
+++ b/src/mesa/drivers/dri/intel/intel_blit.c
@@ -313,7 +313,8 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask)
 
       irb = intel_get_renderbuffer(fb, buf);
       if (irb && irb->mt) {
-	 region = irb->mt->region;
+	 region = intel_miptree_get_region(intel, irb->mt,
+                                           INTEL_MIPTREE_ACCESS_BLIT);
 	 assert(region);
 	 assert(region->bo);
       } else {
@@ -574,7 +575,9 @@ intel_set_teximage_alpha_to_one(struct gl_context *ctx,
    uint32_t BR13, CMD;
    int pitch, cpp;
    drm_intel_bo *aper_array[2];
-   struct intel_region *region = intel_image->mt->region;
+   struct intel_region *region =
+      intel_miptree_get_region(intel, intel_image->mt,
+                               INTEL_MIPTREE_ACCESS_BLIT);
    int width, height, depth;
    BATCH_LOCALS;
 
@@ -603,7 +606,7 @@ intel_set_teximage_alpha_to_one(struct gl_context *ctx,
 
    DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n",
        __FUNCTION__,
-       intel_image->mt->region->bo, pitch,
+       region->bo, pitch,
        x1, y1, x2 - x1, y2 - y1);
 
    BR13 = br13_for_cpp(cpp) | 0xf0 << 16;
diff --git a/src/mesa/drivers/dri/intel/intel_buffer_objects.c b/src/mesa/drivers/dri/intel/intel_buffer_objects.c
index f568864..c48520c 100644
--- a/src/mesa/drivers/dri/intel/intel_buffer_objects.c
+++ b/src/mesa/drivers/dri/intel/intel_buffer_objects.c
@@ -746,14 +746,19 @@ intel_texture_object_purgeable(struct gl_context * ctx,
 {
    struct intel_texture_object *intel;
 
-   (void) ctx;
    (void) option;
 
    intel = intel_texture_object(obj);
-   if (intel->mt == NULL || intel->mt->region == NULL)
+   if (intel->mt == NULL)
       return GL_RELEASED_APPLE;
 
-   return intel_buffer_purgeable(intel->mt->region->bo);
+   struct intel_region *region =
+      intel_miptree_get_region(intel_context(ctx), intel->mt,
+                               INTEL_MIPTREE_ACCESS_NONE);
+   if (region == NULL)
+      return GL_RELEASED_APPLE;
+
+   return intel_buffer_purgeable(region->bo);
 }
 
 static GLenum
@@ -763,14 +768,16 @@ intel_render_object_purgeable(struct gl_context * ctx,
 {
    struct intel_renderbuffer *intel;
 
-   (void) ctx;
    (void) option;
 
    intel = intel_renderbuffer(obj);
    if (intel->mt == NULL)
       return GL_RELEASED_APPLE;
 
-   return intel_buffer_purgeable(intel->mt->region->bo);
+   struct intel_region *region =
+      intel_miptree_get_region(intel_context(ctx), intel->mt,
+                               INTEL_MIPTREE_ACCESS_NONE);
+   return intel_buffer_purgeable(region->bo);
 }
 
 static GLenum
@@ -803,14 +810,19 @@ intel_texture_object_unpurgeable(struct gl_context * ctx,
 {
    struct intel_texture_object *intel;
 
-   (void) ctx;
    (void) option;
 
    intel = intel_texture_object(obj);
-   if (intel->mt == NULL || intel->mt->region == NULL)
+   if (intel->mt == NULL)
       return GL_UNDEFINED_APPLE;
 
-   return intel_buffer_unpurgeable(intel->mt->region->bo);
+   struct intel_region *region =
+      intel_miptree_get_region(intel_context(ctx), intel->mt,
+                               INTEL_MIPTREE_ACCESS_NONE);
+   if (region == NULL)
+      return GL_UNDEFINED_APPLE;
+
+   return intel_buffer_unpurgeable(region->bo);
 }
 
 static GLenum
@@ -820,14 +832,16 @@ intel_render_object_unpurgeable(struct gl_context * ctx,
 {
    struct intel_renderbuffer *intel;
 
-   (void) ctx;
    (void) option;
 
    intel = intel_renderbuffer(obj);
    if (intel->mt == NULL)
       return GL_UNDEFINED_APPLE;
+   struct intel_region *region =
+      intel_miptree_get_region(intel_context(ctx), intel->mt,
+                               INTEL_MIPTREE_ACCESS_NONE);
 
-   return intel_buffer_unpurgeable(intel->mt->region->bo);
+   return intel_buffer_unpurgeable(region->bo);
 }
 
 void
diff --git a/src/mesa/drivers/dri/intel/intel_buffers.c b/src/mesa/drivers/dri/intel/intel_buffers.c
index 9a9a259..b7cd840 100644
--- a/src/mesa/drivers/dri/intel/intel_buffers.c
+++ b/src/mesa/drivers/dri/intel/intel_buffers.c
@@ -38,12 +38,13 @@
  * Return pointer to current color drawing region, or NULL.
  */
 struct intel_region *
-intel_drawbuf_region(struct intel_context *intel)
+intel_drawbuf_region(struct intel_context *intel,
+                     enum intel_miptree_access_type access_type)
 {
    struct intel_renderbuffer *irbColor =
       intel_renderbuffer(intel->ctx.DrawBuffer->_ColorDrawBuffers[0]);
    if (irbColor && irbColor->mt)
-      return irbColor->mt->region;
+      return intel_miptree_get_region(intel, irbColor->mt, access_type);
    else
       return NULL;
 }
@@ -52,12 +53,13 @@ intel_drawbuf_region(struct intel_context *intel)
  * Return pointer to current color reading region, or NULL.
  */
 struct intel_region *
-intel_readbuf_region(struct intel_context *intel)
+intel_readbuf_region(struct intel_context *intel,
+                     enum intel_miptree_access_type access_type)
 {
    struct intel_renderbuffer *irb
       = intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer);
    if (irb && irb->mt)
-      return irb->mt->region;
+      return intel_miptree_get_region(intel, irb->mt, access_type);
    else
       return NULL;
 }
diff --git a/src/mesa/drivers/dri/intel/intel_buffers.h b/src/mesa/drivers/dri/intel/intel_buffers.h
index e68cc67..5ae546d 100644
--- a/src/mesa/drivers/dri/intel/intel_buffers.h
+++ b/src/mesa/drivers/dri/intel/intel_buffers.h
@@ -35,10 +35,15 @@
 
 struct intel_context;
 struct intel_framebuffer;
+enum intel_miptree_access_type;
 
-extern struct intel_region *intel_readbuf_region(struct intel_context *intel);
+extern struct intel_region *
+intel_readbuf_region(struct intel_context *intel,
+                     enum intel_miptree_access_type access_type);
 
-extern struct intel_region *intel_drawbuf_region(struct intel_context *intel);
+extern struct intel_region *
+intel_drawbuf_region(struct intel_context *intel,
+                     enum intel_miptree_access_type access_type);
 
 extern void intel_check_front_buffer_rendering(struct intel_context *intel);
 
diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c
index 88cc247..fab99c1 100644
--- a/src/mesa/drivers/dri/intel/intel_context.c
+++ b/src/mesa/drivers/dri/intel/intel_context.c
@@ -1133,14 +1133,14 @@ intel_process_dri2_buffer(struct intel_context *intel,
     */
    if (num_samples == 0) {
        if (rb->mt &&
-           rb->mt->region &&
-           rb->mt->region->name == buffer->name)
+           rb->mt->region_private &&
+           rb->mt->region_private->name == buffer->name)
           return;
    } else {
        if (rb->mt &&
            rb->mt->singlesample_mt &&
-           rb->mt->singlesample_mt->region &&
-           rb->mt->singlesample_mt->region->name == buffer->name)
+           rb->mt->singlesample_mt->region_private &&
+           rb->mt->singlesample_mt->region_private->name == buffer->name)
           return;
    }
 
diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c
index 69f8629..1492d69 100644
--- a/src/mesa/drivers/dri/intel/intel_fbo.c
+++ b/src/mesa/drivers/dri/intel/intel_fbo.c
@@ -58,14 +58,18 @@ static struct gl_renderbuffer *
 intel_new_renderbuffer(struct gl_context * ctx, GLuint name);
 
 struct intel_region*
-intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex)
+intel_get_rb_region(struct intel_context *intel, struct gl_framebuffer *fb,
+                    GLuint attIndex,
+                    enum intel_miptree_access_type access_type)
 {
    struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex);
    if (irb && irb->mt) {
+      struct intel_mipmap_tree *mt;
       if (attIndex == BUFFER_STENCIL && irb->mt->stencil_mt)
-	 return irb->mt->stencil_mt->region;
+         mt = irb->mt->stencil_mt;
       else
-	 return irb->mt->region;
+	 mt = irb->mt;
+      return intel_miptree_get_region(intel, mt, access_type);
    } else
       return NULL;
 }
@@ -545,11 +549,13 @@ intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb)
  * from there.
  */
 uint32_t
-intel_renderbuffer_tile_offsets(struct intel_renderbuffer *irb,
+intel_renderbuffer_tile_offsets(struct intel_context *intel,
+                                struct intel_renderbuffer *irb,
 				uint32_t *tile_x,
 				uint32_t *tile_y)
 {
-   struct intel_region *region = irb->mt->region;
+   struct intel_region *region =
+      intel_miptree_get_region(intel, irb->mt, INTEL_MIPTREE_ACCESS_NONE);
    uint32_t mask_x, mask_y;
 
    intel_region_get_tile_masks(region, &mask_x, &mask_y, false);
diff --git a/src/mesa/drivers/dri/intel/intel_fbo.h b/src/mesa/drivers/dri/intel/intel_fbo.h
index aa52b97..da40574 100644
--- a/src/mesa/drivers/dri/intel/intel_fbo.h
+++ b/src/mesa/drivers/dri/intel/intel_fbo.h
@@ -34,6 +34,7 @@
 #include "main/macros.h"
 #include "intel_context.h"
 #include "intel_screen.h"
+#include "intel_mipmap_tree.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -149,12 +150,15 @@ void
 intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb);
 
 uint32_t
-intel_renderbuffer_tile_offsets(struct intel_renderbuffer *irb,
+intel_renderbuffer_tile_offsets(struct intel_context *intel,
+                                struct intel_renderbuffer *irb,
 				uint32_t *tile_x,
 				uint32_t *tile_y);
 
 struct intel_region*
-intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex);
+intel_get_rb_region(struct intel_context *intel, struct gl_framebuffer *fb,
+                    GLuint attIndex,
+                    enum intel_miptree_access_type access_type);
 
 void
 intel_renderbuffer_set_needs_downsample(struct intel_renderbuffer *irb);
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
index ad9e2b3..4440885 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c
@@ -444,33 +444,34 @@ intel_miptree_create(struct intel_context *intel,
    bool y_or_x = tiling == (I915_TILING_Y | I915_TILING_X);
 
    mt->etc_format = etc_format;
-   mt->region = intel_region_alloc(intel->intelScreen,
-				   y_or_x ? I915_TILING_Y : tiling,
-				   mt->cpp,
-				   total_width,
-				   total_height,
-				   expect_accelerated_upload);
+   mt->region_private = intel_region_alloc(intel->intelScreen,
+                                           y_or_x ? I915_TILING_Y : tiling,
+                                           mt->cpp,
+                                           total_width,
+                                           total_height,
+                                           expect_accelerated_upload);
 
    /* If the region is too large to fit in the aperture, we need to use the
     * BLT engine to support it.  The BLT paths can't currently handle Y-tiling,
     * so we need to fall back to X.
     */
-   if (y_or_x && mt->region->bo->size >= intel->max_gtt_map_object_size) {
+   if (y_or_x &&
+       mt->region_private->bo->size >= intel->max_gtt_map_object_size) {
       perf_debug("%dx%d miptree larger than aperture; falling back to X-tiled\n",
                  mt->total_width, mt->total_height);
-      intel_region_release(&mt->region);
-
-      mt->region = intel_region_alloc(intel->intelScreen,
-                                      I915_TILING_X,
-                                      mt->cpp,
-                                      total_width,
-                                      total_height,
-                                      expect_accelerated_upload);
+      intel_region_release(&mt->region_private);
+
+      mt->region_private = intel_region_alloc(intel->intelScreen,
+                                              I915_TILING_X,
+                                              mt->cpp,
+                                              total_width,
+                                              total_height,
+                                              expect_accelerated_upload);
    }
 
    mt->offset = 0;
 
-   if (!mt->region) {
+   if (!mt->region_private) {
        intel_miptree_release(&mt);
        return NULL;
    }
@@ -493,7 +494,7 @@ intel_miptree_create_for_region(struct intel_context *intel,
    if (!mt)
       return mt;
 
-   intel_region_reference(&mt->region, region);
+   intel_region_reference(&mt->region_private, region);
 
    return mt;
 }
@@ -621,7 +622,7 @@ intel_miptree_release(struct intel_mipmap_tree **mt)
 
       DBG("%s deleting %p\n", __FUNCTION__, *mt);
 
-      intel_region_release(&((*mt)->region));
+      intel_region_release(&((*mt)->region_private));
       intel_miptree_release(&(*mt)->stencil_mt);
       intel_miptree_release(&(*mt)->hiz_mt);
 #ifndef I915
@@ -783,7 +784,7 @@ intel_miptree_get_tile_offsets(struct intel_mipmap_tree *mt,
                                uint32_t *tile_x,
                                uint32_t *tile_y)
 {
-   struct intel_region *region = mt->region;
+   struct intel_region *region = mt->region_private;
    uint32_t mask_x, mask_y;
 
    intel_region_get_tile_masks(region, &mask_x, &mask_y, false);
@@ -896,12 +897,16 @@ intel_miptree_copy_slice(struct intel_context *intel,
    uint32_t dst_x, dst_y, src_x, src_y;
    intel_miptree_get_image_offset(dst_mt, level, slice, &dst_x, &dst_y);
    intel_miptree_get_image_offset(src_mt, level, slice, &src_x, &src_y);
+   struct intel_region *src_region =
+      intel_miptree_get_region(intel, src_mt, INTEL_MIPTREE_ACCESS_BLIT);
+   struct intel_region *dst_region =
+      intel_miptree_get_region(intel, dst_mt, INTEL_MIPTREE_ACCESS_BLIT);
 
    DBG("validate blit mt %s %p %d,%d/%d -> mt %s %p %d,%d/%d (%dx%d)\n",
        _mesa_get_format_name(src_mt->format),
-       src_mt, src_x, src_y, src_mt->region->pitch,
+       src_mt, src_x, src_y, src_region->pitch,
        _mesa_get_format_name(dst_mt->format),
-       dst_mt, dst_x, dst_y, dst_mt->region->pitch,
+       dst_mt, dst_x, dst_y, dst_region->pitch,
        width, height);
 
    /* Since we are about to copy depth data using either the blitter or swrast
@@ -911,11 +916,11 @@ intel_miptree_copy_slice(struct intel_context *intel,
    intel_miptree_slice_resolve_depth(intel, dst_mt, level, slice);
 
    if (!intelEmitCopyBlit(intel,
-			  dst_mt->region->cpp,
-			  src_mt->region->pitch, src_mt->region->bo,
-			  0, src_mt->region->tiling,
-			  dst_mt->region->pitch, dst_mt->region->bo,
-			  0, dst_mt->region->tiling,
+			  dst_region->cpp,
+			  src_region->pitch, src_region->bo,
+			  0, src_region->tiling,
+			  dst_region->pitch, dst_region->bo,
+			  0, dst_region->tiling,
 			  src_x, src_y,
 			  dst_x, dst_y,
 			  width, height,
@@ -1022,7 +1027,9 @@ intel_miptree_alloc_mcs(struct intel_context *intel,
     * Note: the clear value for MCS buffers is all 1's, so we memset to 0xff.
     */
    void *data = intel_miptree_map_raw(intel, mt->mcs_mt);
-   memset(data, 0xff, mt->mcs_mt->region->bo->size);
+   struct intel_region *region =
+      intel_miptree_get_region(intel, mt->mcs_mt, INTEL_MIPTREE_ACCESS_NONE);
+   memset(data, 0xff, region->bo->size);
    intel_miptree_unmap_raw(intel, mt->mcs_mt);
 
    return mt->mcs_mt;
@@ -1371,7 +1378,9 @@ intel_miptree_upsample(struct intel_context *intel,
 void *
 intel_miptree_map_raw(struct intel_context *intel, struct intel_mipmap_tree *mt)
 {
-   drm_intel_bo *bo = mt->region->bo;
+   struct intel_region *region =
+      intel_miptree_get_region(intel, mt, INTEL_MIPTREE_ACCESS_MAP);
+   drm_intel_bo *bo = region->bo;
 
    if (unlikely(INTEL_DEBUG & DEBUG_PERF)) {
       if (drm_intel_bo_busy(bo)) {
@@ -1381,7 +1390,7 @@ intel_miptree_map_raw(struct intel_context *intel, struct intel_mipmap_tree *mt)
 
    intel_flush(&intel->ctx);
 
-   if (mt->region->tiling != I915_TILING_NONE)
+   if (region->tiling != I915_TILING_NONE)
       drm_intel_gem_bo_map_gtt(bo);
    else
       drm_intel_bo_map(bo, true);
@@ -1393,7 +1402,9 @@ void
 intel_miptree_unmap_raw(struct intel_context *intel,
                         struct intel_mipmap_tree *mt)
 {
-   drm_intel_bo_unmap(mt->region->bo);
+   struct intel_region *region =
+      intel_miptree_get_region(intel, mt, INTEL_MIPTREE_ACCESS_NONE);
+   drm_intel_bo_unmap(region->bo);
 }
 
 static void
@@ -1428,7 +1439,9 @@ intel_miptree_map_gtt(struct intel_context *intel,
       x += image_x;
       y += image_y;
 
-      map->stride = mt->region->pitch;
+      struct intel_region *region =
+         intel_miptree_get_region(intel, mt, INTEL_MIPTREE_ACCESS_NONE);
+      map->stride = region->pitch;
       map->ptr = base + y * map->stride + x * mt->cpp;
    }
 
@@ -1458,9 +1471,11 @@ intel_miptree_map_blit(struct intel_context *intel,
    int x = map->x;
    int y = map->y;
    int ret;
+   struct intel_region *region =
+      intel_miptree_get_region(intel, mt, INTEL_MIPTREE_ACCESS_BLIT);
 
    /* The blitter requires the pitch to be aligned to 4. */
-   map->stride = ALIGN(map->w * mt->region->cpp, 4);
+   map->stride = ALIGN(map->w * region->cpp, 4);
 
    map->bo = drm_intel_bo_alloc(intel->bufmgr, "intel_miptree_map_blit() temp",
 				map->stride * map->h, 4096);
@@ -1474,9 +1489,9 @@ intel_miptree_map_blit(struct intel_context *intel,
    y += image_y;
 
    if (!intelEmitCopyBlit(intel,
-			  mt->region->cpp,
-			  mt->region->pitch, mt->region->bo,
-			  mt->offset, mt->region->tiling,
+			  region->cpp,
+			  region->pitch, region->bo,
+			  mt->offset, region->tiling,
 			  map->stride, map->bo,
 			  0, I915_TILING_NONE,
 			  x, y,
@@ -1520,6 +1535,8 @@ intel_miptree_unmap_blit(struct intel_context *intel,
    drm_intel_bo_unmap(map->bo);
 
    if (map->mode & GL_MAP_WRITE_BIT) {
+      struct intel_region *region =
+         intel_miptree_get_region(intel, mt, INTEL_MIPTREE_ACCESS_BLIT);
       unsigned int image_x, image_y;
       int x = map->x;
       int y = map->y;
@@ -1528,11 +1545,11 @@ intel_miptree_unmap_blit(struct intel_context *intel,
       y += image_y;
 
       bool ok = intelEmitCopyBlit(intel,
-                                  mt->region->cpp,
+                                  region->cpp,
                                   map->stride, map->bo,
                                   0, I915_TILING_NONE,
-                                  mt->region->pitch, mt->region->bo,
-                                  mt->offset, mt->region->tiling,
+                                  region->pitch, region->bo,
+                                  mt->offset, region->tiling,
                                   0, 0,
                                   x, y,
                                   map->w, map->h,
@@ -1568,7 +1585,9 @@ intel_miptree_map_s8(struct intel_context *intel,
 
       for (uint32_t y = 0; y < map->h; y++) {
 	 for (uint32_t x = 0; x < map->w; x++) {
-	    ptrdiff_t offset = intel_offset_S8(mt->region->pitch,
+            struct intel_region *region =
+               intel_miptree_get_region(intel, mt, INTEL_MIPTREE_ACCESS_NONE);
+	    ptrdiff_t offset = intel_offset_S8(region->pitch,
 	                                       x + image_x + map->x,
 	                                       y + image_y + map->y,
 					       intel->has_swizzling);
@@ -1604,7 +1623,9 @@ intel_miptree_unmap_s8(struct intel_context *intel,
 
       for (uint32_t y = 0; y < map->h; y++) {
 	 for (uint32_t x = 0; x < map->w; x++) {
-	    ptrdiff_t offset = intel_offset_S8(mt->region->pitch,
+            struct intel_region *region =
+               intel_miptree_get_region(intel, mt, INTEL_MIPTREE_ACCESS_NONE);
+	    ptrdiff_t offset = intel_offset_S8(region->pitch,
 	                                       x + map->x,
 	                                       y + map->y,
 					       intel->has_swizzling);
@@ -1646,6 +1667,8 @@ intel_miptree_unmap_etc(struct intel_context *intel,
                         unsigned int level,
                         unsigned int slice)
 {
+   struct intel_region *region =
+      intel_miptree_get_region(intel, mt, INTEL_MIPTREE_ACCESS_NONE);
    uint32_t image_x;
    uint32_t image_y;
    intel_miptree_get_image_offset(mt, level, slice, &image_x, &image_y);
@@ -1654,15 +1677,15 @@ intel_miptree_unmap_etc(struct intel_context *intel,
    image_y += map->y;
 
    uint8_t *dst = intel_miptree_map_raw(intel, mt)
-                + image_y * mt->region->pitch
-                + image_x * mt->region->cpp;
+                + image_y * region->pitch
+                + image_x * region->cpp;
 
    if (mt->etc_format == MESA_FORMAT_ETC1_RGB8)
-      _mesa_etc1_unpack_rgba8888(dst, mt->region->pitch,
+      _mesa_etc1_unpack_rgba8888(dst, region->pitch,
                                  map->ptr, map->stride,
                                  map->w, map->h);
    else
-      _mesa_unpack_etc2_format(dst, mt->region->pitch,
+      _mesa_unpack_etc2_format(dst, region->pitch,
                                map->ptr, map->stride,
                                map->w, map->h, mt->etc_format);
 
@@ -1717,12 +1740,18 @@ intel_miptree_map_depthstencil(struct intel_context *intel,
       for (uint32_t y = 0; y < map->h; y++) {
 	 for (uint32_t x = 0; x < map->w; x++) {
 	    int map_x = map->x + x, map_y = map->y + y;
-	    ptrdiff_t s_offset = intel_offset_S8(s_mt->region->pitch,
+            struct intel_region *s_region =
+               intel_miptree_get_region(intel, s_mt,
+                                        INTEL_MIPTREE_ACCESS_NONE);
+	    ptrdiff_t s_offset = intel_offset_S8(s_region->pitch,
 						 map_x + s_image_x,
 						 map_y + s_image_y,
 						 intel->has_swizzling);
+            struct intel_region *z_region =
+               intel_miptree_get_region(intel, z_mt,
+                                        INTEL_MIPTREE_ACCESS_NONE);
 	    ptrdiff_t z_offset = ((map_y + z_image_y) *
-                                  (z_mt->region->pitch / 4) +
+                                  (z_region->pitch / 4) +
 				  (map_x + z_image_x));
 	    uint8_t s = s_map[s_offset];
 	    uint32_t z = z_map[z_offset];
@@ -1777,12 +1806,18 @@ intel_miptree_unmap_depthstencil(struct intel_context *intel,
 
       for (uint32_t y = 0; y < map->h; y++) {
 	 for (uint32_t x = 0; x < map->w; x++) {
-	    ptrdiff_t s_offset = intel_offset_S8(s_mt->region->pitch,
+            struct intel_region *s_region =
+               intel_miptree_get_region(intel, s_mt,
+                                        INTEL_MIPTREE_ACCESS_NONE);
+	    ptrdiff_t s_offset = intel_offset_S8(s_region->pitch,
 						 x + s_image_x + map->x,
 						 y + s_image_y + map->y,
 						 intel->has_swizzling);
+            struct intel_region *z_region =
+               intel_miptree_get_region(intel, z_mt,
+                                        INTEL_MIPTREE_ACCESS_NONE);
 	    ptrdiff_t z_offset = ((y + z_image_y) *
-                                  (z_mt->region->pitch / 4) +
+                                  (z_region->pitch / 4) +
 				  (x + z_image_x));
 
 	    if (map_z32f_x24s8) {
@@ -1885,6 +1920,8 @@ intel_miptree_map_singlesample(struct intel_context *intel,
    if (map->mode & GL_MAP_WRITE_BIT) {
       intel_miptree_slice_set_needs_hiz_resolve(mt, level, slice);
    }
+   struct intel_region *region =
+      intel_miptree_get_region(intel, mt, INTEL_MIPTREE_ACCESS_NONE);
 
    if (mt->format == MESA_FORMAT_S8) {
       intel_miptree_map_s8(intel, mt, map, level, slice);
@@ -1915,13 +1952,13 @@ intel_miptree_map_singlesample(struct intel_context *intel,
    else if (intel->has_llc &&
             !(mode & GL_MAP_WRITE_BIT) &&
             !mt->compressed &&
-            (mt->region->tiling == I915_TILING_X ||
-             (intel->gen >= 6 && mt->region->tiling == I915_TILING_Y)) &&
-            mt->region->pitch < 32768) {
+            (region->tiling == I915_TILING_X ||
+             (intel->gen >= 6 && region->tiling == I915_TILING_Y)) &&
+            region->pitch < 32768) {
       intel_miptree_map_blit(intel, mt, map, level, slice);
-   } else if (mt->region->tiling != I915_TILING_NONE &&
-              mt->region->bo->size >= intel->max_gtt_map_object_size) {
-      assert(mt->region->pitch < 32768);
+   } else if (region->tiling != I915_TILING_NONE &&
+              region->bo->size >= intel->max_gtt_map_object_size) {
+      assert(region->pitch < 32768);
       intel_miptree_map_blit(intel, mt, map, level, slice);
    } else {
       intel_miptree_map_gtt(intel, mt, map, level, slice);
diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
index 0ec3c5e..81a3b69 100644
--- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
+++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h
@@ -287,9 +287,13 @@ struct intel_mipmap_tree
     */
    struct intel_mipmap_level level[MAX_TEXTURE_LEVELS];
 
-   /* The data is held here:
+   /**
+    * The data is held here.  Please don't access this field directly except
+    * in low-level intel_mipmap_tree functions; instead, use
+    * intel_miptree_get_region(), which takes care of updating fast color
+    * clear state appropriately.
     */
-   struct intel_region *region;
+   struct intel_region *region_private;
 
    /* Offset into region bo where miptree starts:
     */
@@ -632,6 +636,70 @@ intel_miptree_unmap(struct intel_context *intel,
 		    unsigned int level,
 		    unsigned int slice);
 
+
+/**
+ * Enum describing possible ways in which a miptree's region can be accessed.
+ * This is used by intel_miptree_get_region() to update the fast color clear
+ * state appropriately for the type of access.
+ */
+enum intel_miptree_access_type {
+   /**
+    * The contents of the region won't need to be accessed, just the metadata
+    * (pitch, cpp, bo->size, etc.)
+    */
+   INTEL_MIPTREE_ACCESS_NONE,
+
+   /**
+    * The contents of the region will be accessed by the hardware blitter.
+    */
+   INTEL_MIPTREE_ACCESS_BLIT,
+
+   /**
+    * The contents of the region will be mapped into memory and accessed by
+    * the CPU.
+    */
+   INTEL_MIPTREE_ACCESS_MAP,
+
+   /**
+    * The contents of the region will be used as a source for texturing
+    * operations.
+    */
+   INTEL_MIPTREE_ACCESS_TEX,
+
+   /**
+    * The contents of the region will be shared between multiple miptrees, or
+    * with an entity outside of Mesa (other than the display server or
+    * compositor).
+    */
+   INTEL_MIPTREE_ACCESS_SHARED,
+
+   /**
+    * The contents of the region will be used as a destination color buffer,
+    * depth buffer, or stencil buffer for 3D rendering operations.
+    */
+   INTEL_MIPTREE_ACCESS_RENDER,
+
+   /**
+    * The contents of the region will be used as an MCS buffer for some other
+    * buffer.
+    */
+   INTEL_MIPTREE_ACCESS_MCS,
+};
+
+
+/**
+ * Obtain the intel_region corresponding to this miptree, updating fast color
+ * clear state as appropriate.
+ */
+static inline struct intel_region *
+intel_miptree_get_region(struct intel_context *intel,
+                         struct intel_mipmap_tree *mt,
+                         enum intel_miptree_access_type access_type)
+{
+   return mt->region_private;
+}
+
+
 #ifdef I915
 static inline void
 intel_hiz_exec(struct intel_context *intel, struct intel_mipmap_tree *mt,
diff --git a/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c b/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c
index 954dfc5..9580629 100644
--- a/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c
+++ b/src/mesa/drivers/dri/intel/intel_pixel_bitmap.c
@@ -49,6 +49,7 @@
 #include "intel_buffers.h"
 #include "intel_pixel.h"
 #include "intel_reg.h"
+#include "intel_mipmap_tree.h"
 
 
 #define FILE_DEBUG_FLAG DEBUG_PIXEL
@@ -200,7 +201,7 @@ do_blit_bitmap( struct gl_context *ctx,
    }
 
    intel_prepare_render(intel);
-   dst = intel_drawbuf_region(intel);
+   dst = intel_drawbuf_region(intel, INTEL_MIPTREE_ACCESS_BLIT);
 
    if (!dst)
        return false;
diff --git a/src/mesa/drivers/dri/intel/intel_pixel_copy.c b/src/mesa/drivers/dri/intel/intel_pixel_copy.c
index 34376ba..d470e74 100644
--- a/src/mesa/drivers/dri/intel/intel_pixel_copy.c
+++ b/src/mesa/drivers/dri/intel/intel_pixel_copy.c
@@ -194,16 +194,20 @@ do_blit_copypixels(struct gl_context * ctx,
    dstx += draw_irb->draw_x;
    dsty += draw_irb->draw_y;
 
-   uint32_t src_pitch = read_irb->mt->region->pitch;
+   struct intel_region *read_region =
+      intel_miptree_get_region(intel, read_irb->mt, INTEL_MIPTREE_ACCESS_BLIT);
+   struct intel_region *draw_region =
+      intel_miptree_get_region(intel, draw_irb->mt, INTEL_MIPTREE_ACCESS_BLIT);
+   uint32_t src_pitch = read_region->pitch;
    if (flip)
       src_pitch = -src_pitch;
 
    if (!intelEmitCopyBlit(intel,
                           draw_irb->mt->cpp,
-                          src_pitch, read_irb->mt->region->bo,
-                          0, read_irb->mt->region->tiling,
-                          draw_irb->mt->region->pitch, draw_irb->mt->region->bo,
-                          0, draw_irb->mt->region->tiling,
+                          src_pitch, read_region->bo,
+                          0, read_region->tiling,
+                          draw_region->pitch, draw_region->bo,
+                          0, draw_region->tiling,
                           srcx, srcy,
                           dstx, dsty,
                           width, height,
diff --git a/src/mesa/drivers/dri/intel/intel_pixel_read.c b/src/mesa/drivers/dri/intel/intel_pixel_read.c
index ebdc528..7334035 100644
--- a/src/mesa/drivers/dri/intel/intel_pixel_read.c
+++ b/src/mesa/drivers/dri/intel/intel_pixel_read.c
@@ -76,7 +76,8 @@ do_blit_readpixels(struct gl_context * ctx,
                    const struct gl_pixelstore_attrib *pack, GLvoid * pixels)
 {
    struct intel_context *intel = intel_context(ctx);
-   struct intel_region *src = intel_readbuf_region(intel);
+   struct intel_region *src =
+      intel_readbuf_region(intel, INTEL_MIPTREE_ACCESS_BLIT);
    struct intel_buffer_object *dst = intel_buffer_object(pack->BufferObj);
    GLuint dst_offset;
    drm_intel_bo *dst_buffer;
diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c
index 325304d..cf1044c 100644
--- a/src/mesa/drivers/dri/intel/intel_screen.c
+++ b/src/mesa/drivers/dri/intel/intel_screen.c
@@ -138,14 +138,17 @@ aub_dump_bmp(struct gl_context *ctx)
 	    continue;
 	 }
 
-         assert(irb->mt->region->pitch % irb->mt->region->cpp == 0);
-	 drm_intel_gem_bo_aub_dump_bmp(irb->mt->region->bo,
+         struct intel_region *region =
+            intel_miptree_get_region(intel_context(ctx), irb->mt,
+                                     INTEL_MIPTREE_ACCESS_NONE);
+         assert(region->pitch % region->cpp == 0);
+	 drm_intel_gem_bo_aub_dump_bmp(region->bo,
 				       irb->draw_x,
 				       irb->draw_y,
 				       irb->Base.Base.Width,
 				       irb->Base.Base.Height,
 				       format,
-				       irb->mt->region->pitch,
+				       region->pitch,
 				       0);
       }
    }
@@ -299,10 +302,12 @@ intel_setup_image_from_mipmap_tree(struct intel_context *intel, __DRIimage *imag
 {
    unsigned int draw_x, draw_y;
    uint32_t mask_x, mask_y;
+   struct intel_region *region =
+      intel_miptree_get_region(intel, mt, INTEL_MIPTREE_ACCESS_SHARED);
 
    intel_miptree_check_level_layer(mt, level, zoffset);
 
-   intel_region_get_tile_masks(mt->region, &mask_x, &mask_y, false);
+   intel_region_get_tile_masks(region, &mask_x, &mask_y, false);
    intel_miptree_get_image_offset(mt, level, zoffset, &draw_x, &draw_y);
 
    image->width = mt->level[level].width;
@@ -310,12 +315,12 @@ intel_setup_image_from_mipmap_tree(struct intel_context *intel, __DRIimage *imag
    image->tile_x = draw_x & mask_x;
    image->tile_y = draw_y & mask_y;
 
-   image->offset = intel_region_get_aligned_offset(mt->region,
+   image->offset = intel_region_get_aligned_offset(region,
                                                    draw_x & ~mask_x,
                                                    draw_y & ~mask_y,
                                                    false);
 
-   intel_region_reference(&image->region, mt->region);
+   intel_region_reference(&image->region, region);
 }
 
 static void
@@ -404,7 +409,9 @@ intel_create_image_from_renderbuffer(__DRIcontext *context,
    image->format = rb->Format;
    image->offset = 0;
    image->data = loaderPrivate;
-   intel_region_reference(&image->region, irb->mt->region);
+   struct intel_region *region =
+      intel_miptree_get_region(intel, irb->mt, INTEL_MIPTREE_ACCESS_SHARED);
+   intel_region_reference(&image->region, region);
    intel_setup_image_from_dimensions(image);
    image->dri_format = intel_dri_format(image->format);
    image->has_depthstencil = irb->mt->stencil_mt? true : false;
diff --git a/src/mesa/drivers/dri/intel/intel_tex_copy.c b/src/mesa/drivers/dri/intel/intel_tex_copy.c
index 6043ed2..1571db6 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_copy.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_copy.c
@@ -69,7 +69,8 @@ intel_copy_texsubimage(struct intel_context *intel,
 		 __FUNCTION__, intelImage->mt, irb, internalFormat);
       return false;
    } else {
-      region = irb->mt->region;
+      region = intel_miptree_get_region(intel, irb->mt,
+                                        INTEL_MIPTREE_ACCESS_BLIT);
       assert(region);
    }
 
@@ -124,6 +125,9 @@ intel_copy_texsubimage(struct intel_context *intel,
    {
       GLuint image_x, image_y;
       GLshort src_pitch;
+      struct intel_region *image_region =
+         intel_miptree_get_region(intel, intelImage->mt,
+                                  INTEL_MIPTREE_ACCESS_BLIT);
 
       /* get dest x/y in destination texture */
       intel_miptree_get_image_offset(intelImage->mt,
@@ -132,7 +136,7 @@ intel_copy_texsubimage(struct intel_context *intel,
 				     &image_x, &image_y);
 
       /* The blitter can't handle Y-tiled buffers. */
-      if (intelImage->mt->region->tiling == I915_TILING_Y) {
+      if (image_region->tiling == I915_TILING_Y) {
 	 return false;
       }
 
@@ -152,10 +156,10 @@ intel_copy_texsubimage(struct intel_context *intel,
 			     region->bo,
 			     0,
 			     region->tiling,
-			     intelImage->mt->region->pitch,
-			     intelImage->mt->region->bo,
+			     image_region->pitch,
+			     image_region->bo,
 			     0,
-			     intelImage->mt->region->tiling,
+			     image_region->tiling,
 			     irb->draw_x + x, irb->draw_y + y,
 			     image_x + dstx, image_y + dsty,
 			     width, height,
diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c
index 4e307f8..ba59092 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_image.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_image.c
@@ -153,7 +153,10 @@ try_pbo_upload(struct gl_context *ctx,
       return false;
    }
 
-   dst_buffer = intelImage->mt->region->bo;
+   struct intel_region *region =
+      intel_miptree_get_region(intel, intelImage->mt,
+                               INTEL_MIPTREE_ACCESS_BLIT);
+   dst_buffer = region->bo;
    src_buffer = intel_bufferobj_source(intel, pbo, 64, &src_offset);
    /* note: potential 64-bit ptr to 32-bit int cast */
    src_offset += (GLuint) (unsigned long) pixels;
@@ -162,7 +165,7 @@ try_pbo_upload(struct gl_context *ctx,
       src_stride = unpack->RowLength;
    else
       src_stride = image->Width;
-   src_stride *= intelImage->mt->region->cpp;
+   src_stride *= region->cpp;
 
    intel_miptree_get_image_offset(intelImage->mt, intelImage->base.Base.Level,
 				  intelImage->base.Base.Face,
@@ -172,8 +175,8 @@ try_pbo_upload(struct gl_context *ctx,
 			  intelImage->mt->cpp,
 			  src_stride, src_buffer,
 			  src_offset, false,
-			  intelImage->mt->region->pitch, dst_buffer, 0,
-			  intelImage->mt->region->tiling,
+			  region->pitch, dst_buffer, 0,
+			  region->tiling,
 			  0, 0, dst_x, dst_y, image->Width, image->Height,
 			  GL_COPY)) {
       DBG("%s: blit failed\n", __FUNCTION__);
@@ -260,7 +263,7 @@ intel_set_texture_image_region(struct gl_context *ctx,
                                                  true, 0 /* num_samples */);
    if (intel_image->mt == NULL)
        return;
-   intel_region_reference(&intel_image->mt->region, region);
+   intel_region_reference(&intel_image->mt->region_private, region);
    intel_image->mt->total_width = width;
    intel_image->mt->total_height = height;
    intel_image->mt->level[0].slice[0].x_offset = tile_x;
@@ -340,10 +343,12 @@ intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
 
    _mesa_lock_texture(&intel->ctx, texObj);
    texImage = _mesa_get_tex_image(ctx, texObj, target, level);
-   intel_set_texture_image_region(ctx, texImage, rb->mt->region, target,
+   struct intel_region *region =
+      intel_miptree_get_region(intel, rb->mt, INTEL_MIPTREE_ACCESS_SHARED);
+   intel_set_texture_image_region(ctx, texImage, region, target,
                                   internalFormat, texFormat, 0,
-                                  rb->mt->region->width,
-                                  rb->mt->region->height,
+                                  region->width,
+                                  region->height,
                                   0, 0);
    _mesa_unlock_texture(&intel->ctx, texObj);
 }
diff --git a/src/mesa/drivers/dri/intel/intel_tex_subimage.c b/src/mesa/drivers/dri/intel/intel_tex_subimage.c
index 42cc739..258b135 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_subimage.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_subimage.c
@@ -66,8 +66,12 @@ intel_blit_texsubimage(struct gl_context * ctx,
    if (!intelImage->mt)
       return false;
 
+   struct intel_region *region =
+      intel_miptree_get_region(intel, intelImage->mt,
+                               INTEL_MIPTREE_ACCESS_BLIT);
+
    /* The blitter can't handle Y tiling */
-   if (intelImage->mt->region->tiling == I915_TILING_Y)
+   if (region->tiling == I915_TILING_Y)
       return false;
 
    if (texImage->TexObject->Target != GL_TEXTURE_2D)
@@ -79,7 +83,7 @@ intel_blit_texsubimage(struct gl_context * ctx,
    if (intel->gen >= 6)
       return false;
 
-   if (!drm_intel_bo_busy(intelImage->mt->region->bo))
+   if (!drm_intel_bo_busy(region->bo))
       return false;
 
    DBG("BLT subimage %s target %s level %d offset %d,%d %dx%d\n",
@@ -136,9 +140,9 @@ intel_blit_texsubimage(struct gl_context * ctx,
 			   intelImage->mt->cpp,
 			   dstRowStride,
 			   temp_bo, 0, false,
-			   intelImage->mt->region->pitch,
-			   intelImage->mt->region->bo, 0,
-			   intelImage->mt->region->tiling,
+			   region->pitch,
+			   region->bo, 0,
+			   region->tiling,
 			   0, 0, blit_x, blit_y, width, height,
 			   GL_COPY);
    assert(ret);
@@ -217,13 +221,18 @@ intel_texsubimage_tiled_memcpy(struct gl_context * ctx,
    if (for_glTexImage)
       ctx->Driver.AllocTextureImageBuffer(ctx, texImage);
 
-   if (!image->mt ||
-       image->mt->region->tiling != I915_TILING_X) {
+   if (!image->mt)
+      return false;
+
+   struct intel_region *region =
+      intel_miptree_get_region(intel, image->mt, INTEL_MIPTREE_ACCESS_MAP);
+
+   if (region->tiling != I915_TILING_X) {
       /* The algorithm below is written only for X-tiled memory. */
       return false;
    }
 
-   bo = image->mt->region->bo;
+   bo = region->bo;
 
    if (drm_intel_bo_references(intel->batch.bo, bo)) {
       perf_debug("Flushing before mapping a referenced bo.\n");
@@ -266,7 +275,7 @@ intel_texsubimage_tiled_memcpy(struct gl_context * ctx,
    const uint32_t cpp = 4; /* chars per pixel of GL_BGRA */
    const uint32_t swizzle_width_pixels = 16;
 
-   const uint32_t stride_bytes = image->mt->region->pitch;
+   const uint32_t stride_bytes = region->pitch;
    const uint32_t width_tiles = stride_bytes / tile_width_bytes;
 
    for (uint32_t y_pixels = yoffset; y_pixels < y_max_pixels; ++y_pixels) {
-- 
1.8.2.3



More information about the mesa-dev mailing list