Mesa (master): nv50, nvc0: unify nvc0_miptree and nv50_miptree structs

Christoph Bumiller chrisbmr at kemper.freedesktop.org
Thu Jul 14 10:51:50 UTC 2011


Module: Mesa
Branch: master
Commit: cad17554c4b121c03e188dd0281718a52d603a15
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=cad17554c4b121c03e188dd0281718a52d603a15

Author: Christoph Bumiller <e0425955 at student.tuwien.ac.at>
Date:   Thu Jul 14 12:40:04 2011 +0200

nv50,nvc0: unify nvc0_miptree and nv50_miptree structs

Share some functions and restructure miptree creation a little.
Prepare for multi-sample resources.

---

 src/gallium/drivers/nv50/nv50_context.h        |   14 -
 src/gallium/drivers/nv50/nv50_miptree.c        |  350 +++++++++++++++--------
 src/gallium/drivers/nv50/nv50_resource.h       |   65 ++++-
 src/gallium/drivers/nvc0/nvc0_3d.xml.h         |   18 +-
 src/gallium/drivers/nvc0/nvc0_context.h        |   14 -
 src/gallium/drivers/nvc0/nvc0_miptree.c        |  368 ++++++++++++------------
 src/gallium/drivers/nvc0/nvc0_resource.c       |   12 +-
 src/gallium/drivers/nvc0/nvc0_resource.h       |   64 ++---
 src/gallium/drivers/nvc0/nvc0_screen.c         |    2 +-
 src/gallium/drivers/nvc0/nvc0_screen.h         |    1 +
 src/gallium/drivers/nvc0/nvc0_state_validate.c |   12 +-
 src/gallium/drivers/nvc0/nvc0_surface.c        |   30 +-
 src/gallium/drivers/nvc0/nvc0_tex.c            |    4 +-
 src/gallium/drivers/nvc0/nvc0_transfer.c       |    6 +-
 14 files changed, 535 insertions(+), 425 deletions(-)

diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h
index b4af24f..4e141a6 100644
--- a/src/gallium/drivers/nv50/nv50_context.h
+++ b/src/gallium/drivers/nv50/nv50_context.h
@@ -130,20 +130,6 @@ nv50_context(struct pipe_context *pipe)
    return (struct nv50_context *)pipe;
 }
 
-struct nv50_surface {
-   struct pipe_surface base;
-   uint32_t offset;
-   uint32_t width;
-   uint16_t height;
-   uint16_t depth;
-};
-
-static INLINE struct nv50_surface *
-nv50_surface(struct pipe_surface *ps)
-{
-   return (struct nv50_surface *)ps;
-}
-
 /* nv50_context.c */
 struct pipe_context *nv50_create(struct pipe_screen *, void *);
 
diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c
index 486b368..0a1fcbc 100644
--- a/src/gallium/drivers/nv50/nv50_miptree.c
+++ b/src/gallium/drivers/nv50/nv50_miptree.c
@@ -30,49 +30,85 @@
 #include "nv50_transfer.h"
 
 static INLINE uint32_t
-get_tile_dims(unsigned nx, unsigned ny, unsigned nz)
+nv50_tex_choose_tile_dims(unsigned nx, unsigned ny, unsigned nz)
 {
-   uint32_t tile_mode = 0x00;
-
-   if (ny > 32) tile_mode = 0x04; /* height 128 tiles */
-   else
-   if (ny > 16) tile_mode = 0x03; /* height 64 tiles */
-   else
-   if (ny >  8) tile_mode = 0x02; /* height 32 tiles */
-   else
-   if (ny >  4) tile_mode = 0x01; /* height 16 tiles */
-
-   if (nz == 1)
-      return tile_mode;
-   else
-   if (tile_mode > 0x02)
-      tile_mode = 0x02;
-
-   if (nz > 16 && tile_mode < 0x02)
-      return tile_mode | 0x50; /* depth 32 tiles */
-   if (nz > 8) return tile_mode | 0x40; /* depth 16 tiles */
-   if (nz > 4) return tile_mode | 0x30; /* depth 8 tiles */
-   if (nz > 2) return tile_mode | 0x20; /* depth 4 tiles */
-
-   return tile_mode | 0x10;
+   return nvc0_tex_choose_tile_dims(nx, ny * 2, nz) >> 4;
 }
 
-static INLINE unsigned
-calc_zslice_offset(uint32_t tile_mode, unsigned z, unsigned pitch, unsigned nbh)
+static uint32_t
+nv50_mt_choose_storage_type(struct nv50_miptree *mt, boolean compressed)
 {
-   unsigned tile_h = NV50_TILE_HEIGHT(tile_mode);
-   unsigned tile_d_shift = NV50_TILE_DIM_SHIFT(tile_mode, 1);
-   unsigned tile_d = 1 << tile_d_shift;
+   const unsigned ms = util_logbase2(mt->base.base.nr_samples);
 
-   /* stride_2d == to next slice within this volume tile */
-   /* stride_3d == size (in bytes) of a volume tile */
-   unsigned stride_2d = tile_h * NV50_TILE_PITCH(tile_mode);
-   unsigned stride_3d = tile_d * align(nbh, tile_h) * pitch;
+   uint32_t tile_flags;
+
+   if (mt->base.base.bind & PIPE_BIND_CURSOR)
+      return NOUVEAU_BO_TILE_SCANOUT;
 
-   return (z & (tile_d - 1)) * stride_2d + (z >> tile_d_shift) * stride_3d;
+   switch (mt->base.base.format) {
+   case PIPE_FORMAT_Z16_UNORM:
+      tile_flags = 0x6c00 + (ms << 8);
+      break;
+   case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
+      tile_flags = 0x1800 + (ms << 8);
+      break;
+   case PIPE_FORMAT_Z24X8_UNORM:
+   case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
+      tile_flags = 0x22800 + (ms << 8);
+      break;
+   case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED:
+      tile_flags = 0x6000 + (ms << 8);
+      break;
+   default:
+      switch (util_format_get_blocksizebits(mt->base.base.format)) {
+      case 128:
+         assert(ms < 3);
+         tile_flags = 0x7400;
+         break;
+      case 64:
+         switch (ms) {
+         case 2: tile_flags = 0x17c00; break;
+         case 3: tile_flags = 0x17d00; break;
+         default:
+            tile_flags = 0x7000;
+            break;
+         }
+         break;
+      case 32:
+         if (mt->base.base.bind & PIPE_BIND_SCANOUT) {
+            assert(ms == 0);
+            tile_flags = 0x7a00;
+         } else {
+            switch (ms) {
+            case 2: tile_flags = 0x17800; break;
+            case 3: tile_flags = 0x17900; break;
+            default:
+               tile_flags = 0x7000;
+               break;
+            }
+         }
+         break;
+      case 16:
+      case 8:
+         tile_flags = 0x7000;
+         break;
+      default:
+         return 0;
+      }
+      if (mt->base.base.bind & PIPE_BIND_CURSOR)
+         tile_flags = 0;
+   }
+
+   if (mt->base.base.bind & (PIPE_BIND_SCANOUT | PIPE_BIND_CURSOR))
+      tile_flags |= NOUVEAU_BO_TILE_SCANOUT;
+
+   if (!compressed)
+      tile_flags &= ~0x30000;
+
+   return tile_flags;
 }
 
-static void
+void
 nv50_miptree_destroy(struct pipe_screen *pscreen, struct pipe_resource *pt)
 {
    struct nv50_miptree *mt = nv50_miptree(pt);
@@ -82,7 +118,7 @@ nv50_miptree_destroy(struct pipe_screen *pscreen, struct pipe_resource *pt)
    FREE(mt);
 }
 
-static boolean
+boolean
 nv50_miptree_get_handle(struct pipe_screen *pscreen,
                         struct pipe_resource *pt,
                         struct winsys_handle *whandle)
@@ -108,88 +144,95 @@ const struct u_resource_vtbl nv50_miptree_vtbl =
    nv50_miptree_destroy,            /* resource_destroy */
    nv50_miptree_transfer_new,       /* get_transfer */
    nv50_miptree_transfer_del,       /* transfer_destroy */
-   nv50_miptree_transfer_map,	      /* transfer_map */
+   nv50_miptree_transfer_map,       /* transfer_map */
    u_default_transfer_flush_region, /* transfer_flush_region */
    nv50_miptree_transfer_unmap,     /* transfer_unmap */
    u_default_transfer_inline_write  /* transfer_inline_write */
 };
 
-struct pipe_resource *
-nv50_miptree_create(struct pipe_screen *pscreen,
-                    const struct pipe_resource *templ)
+static INLINE boolean
+nv50_miptree_init_ms_mode(struct nv50_miptree *mt)
 {
-   struct nouveau_device *dev = nouveau_screen(pscreen)->device;
-   struct nv50_miptree *mt = CALLOC_STRUCT(nv50_miptree);
-   struct pipe_resource *pt = &mt->base.base;
-   int ret;
-   unsigned w, h, d, l, alloc_size;
-   uint32_t tile_flags;
-
-   if (!mt)
-      return NULL;
-
-   mt->base.vtbl = &nv50_miptree_vtbl;
-   *pt = *templ;
-   pipe_reference_init(&pt->reference, 1);
-   pt->screen = pscreen;
-
-   mt->layout_3d = pt->target == PIPE_TEXTURE_3D;
-
-   w = pt->width0;
-   h = pt->height0;
-   d = mt->layout_3d ? pt->depth0 : 1;
-
-   switch (pt->format) {
-   case PIPE_FORMAT_Z16_UNORM:
-      tile_flags = 0x6c00;
-      break;
-   case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
-      tile_flags = 0x1800;
+   switch (mt->base.base.nr_samples) {
+   case 8:
+      mt->ms_mode = NV50_3D_MULTISAMPLE_MODE_MS8;
+      mt->ms_x = 2;
+      mt->ms_y = 1;
       break;
-   case PIPE_FORMAT_Z24X8_UNORM:
-   case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
-      tile_flags = 0x2800;
+   case 4:
+      mt->ms_mode = NV50_3D_MULTISAMPLE_MODE_MS4;
+      mt->ms_x = 1;
+      mt->ms_y = 1;
       break;
-   case PIPE_FORMAT_R32G32B32A32_FLOAT:
-   case PIPE_FORMAT_R32G32B32_FLOAT:
-      tile_flags = 0x7400;
+   case 2:
+      mt->ms_mode = NV50_3D_MULTISAMPLE_MODE_MS2;
+      mt->ms_x = 1;
       break;
-   case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED:
-      tile_flags = 0x6000;
+   case 1:
+   case 0:
+      mt->ms_mode = NV50_3D_MULTISAMPLE_MODE_MS1;
       break;
    default:
-      if (pt->bind & PIPE_BIND_CURSOR)
-         tile_flags = 0;
-      else
-      if ((pt->bind & PIPE_BIND_SCANOUT) &&
-          util_format_get_blocksizebits(pt->format) == 32)
-         tile_flags = 0x7a00;
-      else
-         tile_flags = 0x7000;
-      break;
+      NOUVEAU_ERR("invalid nr_samples: %u\n", mt->base.base.nr_samples);
+      return FALSE;
    }
-   if (pt->bind & (PIPE_BIND_SCANOUT | PIPE_BIND_CURSOR))
-      tile_flags |= NOUVEAU_BO_TILE_SCANOUT;
+   return TRUE;
+}
+
+boolean
+nv50_miptree_init_layout_linear(struct nv50_miptree *mt)
+{
+   struct pipe_resource *pt = &mt->base.base;
+
+   if (util_format_is_depth_or_stencil(pt->format))
+      return FALSE;
+
+   if ((pt->last_level > 0) || (pt->depth0 > 1) || (pt->array_size > 1))
+      return FALSE;
+   if (mt->ms_x | mt->ms_y)
+      return FALSE;
+
+   mt->level[0].pitch = align(pt->width0, 64);
+
+   mt->total_size = mt->level[0].pitch * pt->height0;
+
+   return TRUE;
+}
+
+static void
+nv50_miptree_init_layout_tiled(struct nv50_miptree *mt)
+{
+   struct pipe_resource *pt = &mt->base.base;
+   unsigned w, h, d, l;
+   const unsigned blocksize = util_format_get_blocksize(pt->format);
+
+   mt->layout_3d = pt->target == PIPE_TEXTURE_3D;
+
+   w = pt->width0 << mt->ms_x;
+   h = pt->height0 << mt->ms_y;
 
    /* For 3D textures, a mipmap is spanned by all the layers, for array
     * textures and cube maps, each layer contains its own mipmaps.
     */
+   d = mt->layout_3d ? pt->depth0 : 1;
+
    for (l = 0; l <= pt->last_level; ++l) {
       struct nv50_miptree_level *lvl = &mt->level[l];
+      unsigned tsx, tsy, tsz;
       unsigned nbx = util_format_get_nblocksx(pt->format, w);
       unsigned nby = util_format_get_nblocksy(pt->format, h);
-      unsigned blocksize = util_format_get_blocksize(pt->format);
 
       lvl->offset = mt->total_size;
 
-      if (tile_flags & NOUVEAU_BO_TILE_LAYOUT_MASK)
-         lvl->tile_mode = get_tile_dims(nbx, nby, d);
+      lvl->tile_mode = nv50_tex_choose_tile_dims(nbx, nby, d);
 
-      lvl->pitch = align(nbx * blocksize, NV50_TILE_PITCH(lvl->tile_mode));
+      tsx = NV50_TILE_SIZE_X(lvl->tile_mode); /* x is tile row pitch in bytes */
+      tsy = NV50_TILE_SIZE_Y(lvl->tile_mode);
+      tsz = NV50_TILE_SIZE_Z(lvl->tile_mode);
 
-      mt->total_size += lvl->pitch *
-         align(nby, NV50_TILE_HEIGHT(lvl->tile_mode)) *
-         align(d, NV50_TILE_DEPTH(lvl->tile_mode));
+      lvl->pitch = align(nbx * blocksize, tsx);
+
+      mt->total_size += lvl->pitch * align(nby, tsy) * align(d, tsz);
 
       w = u_minify(w, 1);
       h = u_minify(h, 1);
@@ -201,10 +244,43 @@ nv50_miptree_create(struct pipe_screen *pscreen,
                                NV50_TILE_SIZE(mt->level[0].tile_mode));
       mt->total_size = mt->layer_stride * pt->array_size;
    }
+}
+
+struct pipe_resource *
+nv50_miptree_create(struct pipe_screen *pscreen,
+                    const struct pipe_resource *templ)
+{
+   struct nouveau_device *dev = nouveau_screen(pscreen)->device;
+   struct nv50_miptree *mt = CALLOC_STRUCT(nv50_miptree);
+   struct pipe_resource *pt = &mt->base.base;
+   int ret;
+   uint32_t tile_flags;
+
+   if (!mt)
+      return NULL;
+
+   mt->base.vtbl = &nv50_miptree_vtbl;
+   *pt = *templ;
+   pipe_reference_init(&pt->reference, 1);
+   pt->screen = pscreen;
+
+   tile_flags = nv50_mt_choose_storage_type(mt, TRUE);
+
+   if (!nv50_miptree_init_ms_mode(mt)) {
+      FREE(mt);
+      return NULL;
+   }
 
-   alloc_size = mt->total_size;
+   if (tile_flags & NOUVEAU_BO_TILE_LAYOUT_MASK) {
+      nv50_miptree_init_layout_tiled(mt);
+   } else
+   if (!nv50_miptree_init_layout_linear(mt)) {
+      FREE(mt);
+      return NULL;
+   }
 
-   ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 256, alloc_size,
+   ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 4096,
+                             mt->total_size,
                              mt->level[0].tile_mode, tile_flags,
                              &mt->base.bo);
    if (ret) {
@@ -255,58 +331,90 @@ nv50_miptree_from_handle(struct pipe_screen *pscreen,
 }
 
 
+/* Offset of zslice @z from start of level @l. */
+INLINE unsigned
+nv50_mt_zslice_offset(const struct nv50_miptree *mt, unsigned l, unsigned z)
+{
+   const struct pipe_resource *pt = &mt->base.base;
+
+   unsigned tds = NV50_TILE_SHIFT_Z(mt->level[l].tile_mode);
+   unsigned ths = NV50_TILE_SHIFT_Y(mt->level[l].tile_mode);
+
+   unsigned nby = util_format_get_nblocksy(pt->format,
+                                           u_minify(pt->height0, l));
+
+   /* to next 2D tile slice within a 3D tile */
+   unsigned stride_2d = NV50_TILE_SIZE_2D(mt->level[l].tile_mode);
+
+   /* to slice in the next (in z direction) 3D tile */
+   unsigned stride_3d = (align(nby, (1 << ths)) * mt->level[l].pitch) << tds;
+
+   return (z & ((1 << tds) - 1)) * stride_2d + (z >> tds) * stride_3d;
+}
+
 /* Surface functions.
  */
 
-struct pipe_surface *
-nv50_miptree_surface_new(struct pipe_context *pipe,
-                         struct pipe_resource *pt,
-                         const struct pipe_surface *templ)
+struct nv50_surface *
+nv50_surface_from_miptree(struct nv50_miptree *mt,
+                          const struct pipe_surface *templ)
 {
-   struct nv50_miptree *mt = nv50_miptree(pt); /* guaranteed */
-   struct nv50_surface *ns;
    struct pipe_surface *ps;
-   struct nv50_miptree_level *lvl = &mt->level[templ->u.tex.level];
-
-   ns = CALLOC_STRUCT(nv50_surface);
+   struct nv50_surface *ns = CALLOC_STRUCT(nv50_surface);
    if (!ns)
       return NULL;
    ps = &ns->base;
 
    pipe_reference_init(&ps->reference, 1);
-   pipe_resource_reference(&ps->texture, pt);
-   ps->context = pipe;
+   pipe_resource_reference(&ps->texture, &mt->base.base);
+
    ps->format = templ->format;
    ps->usage = templ->usage;
    ps->u.tex.level = templ->u.tex.level;
    ps->u.tex.first_layer = templ->u.tex.first_layer;
    ps->u.tex.last_layer = templ->u.tex.last_layer;
 
-   ns->width = u_minify(pt->width0, ps->u.tex.level);
-   ns->height = u_minify(pt->height0, ps->u.tex.level);
+   ns->width = u_minify(mt->base.base.width0, ps->u.tex.level);
+   ns->height = u_minify(mt->base.base.height0, ps->u.tex.level);
    ns->depth = ps->u.tex.last_layer - ps->u.tex.first_layer + 1;
-   ns->offset = lvl->offset;
+   ns->offset = mt->level[templ->u.tex.level].offset;
 
    /* comment says there are going to be removed, but they're used by the st */
    ps->width = ns->width;
    ps->height = ns->height;
 
-   if (mt->layout_3d) {
-      unsigned zslice = ps->u.tex.first_layer;
+   ns->width <<= mt->ms_x;
+   ns->height <<= mt->ms_y;
+
+   return ns;
+}
+
+struct pipe_surface *
+nv50_miptree_surface_new(struct pipe_context *pipe,
+                         struct pipe_resource *pt,
+                         const struct pipe_surface *templ)
+{
+   struct nv50_miptree *mt = nv50_miptree(pt);
+   struct nv50_surface *ns = nv50_surface_from_miptree(mt, templ);
+   if (!ns)
+      return NULL;
+   ns->base.context = pipe;
+
+   if (ns->base.u.tex.first_layer) {
+      const unsigned l = ns->base.u.tex.level;
+      const unsigned z = ns->base.u.tex.first_layer;
 
-      /* TODO: re-layout the texture to use only depth 1 tiles in this case: */
-      if (ns->depth > 1 && (zslice & (NV50_TILE_DEPTH(lvl->tile_mode) - 1)))
-         NOUVEAU_ERR("Creating unsupported 3D surface of slices [%u:%u].\n",
-                     zslice, ps->u.tex.last_layer);
+      if (mt->layout_3d) {
+         ns->offset += nv50_mt_zslice_offset(mt, l, z);
 
-      ns->offset += calc_zslice_offset(lvl->tile_mode, zslice, lvl->pitch,
-                                       util_format_get_nblocksy(pt->format,
-                                                                ns->height));
-   } else {
-      ns->offset += mt->layer_stride * ps->u.tex.first_layer;
+         if (z & (NV50_TILE_SIZE_Z(mt->level[l].tile_mode) - 1))
+            NOUVEAU_ERR("Creating unsupported 3D surface !\n");
+      } else {
+         ns->offset += mt->layer_stride * z;
+      }
    }
 
-   return ps;
+   return &ns->base;
 }
 
 void
diff --git a/src/gallium/drivers/nv50/nv50_resource.h b/src/gallium/drivers/nv50/nv50_resource.h
index 0e9f0a2..a771edf 100644
--- a/src/gallium/drivers/nv50/nv50_resource.h
+++ b/src/gallium/drivers/nv50/nv50_resource.h
@@ -9,22 +9,32 @@
 #include "nouveau/nouveau_buffer.h"
 #undef NOUVEAU_NVC0
 
+#ifndef __NVC0_RESOURCE_H__ /* make sure we don't use these in nvc0: */
+
 void
 nv50_init_resource_functions(struct pipe_context *pcontext);
 
 void
 nv50_screen_init_resource_functions(struct pipe_screen *pscreen);
 
-#define NV50_TILE_DIM_SHIFT(m, d) (((m) >> (d * 4)) & 0xf)
 
-#define NV50_TILE_PITCH(m)  (64 << 0)
-#define NV50_TILE_HEIGHT(m) ( 4 << NV50_TILE_DIM_SHIFT(m, 0))
-#define NV50_TILE_DEPTH(m)  ( 1 << NV50_TILE_DIM_SHIFT(m, 1))
+#define NV50_TILE_SHIFT_X(m) 6
+#define NV50_TILE_SHIFT_Y(m) ((((m) >> 0) & 0xf) + 2)
+#define NV50_TILE_SHIFT_Z(m) ((((m) >> 4) & 0xf) + 0)
+
+#define NV50_TILE_SIZE_X(m) 64
+#define NV50_TILE_SIZE_Y(m) ( 4 << (((m) >> 0) & 0xf))
+#define NV50_TILE_SIZE_Z(m) ( 1 << (((m) >> 4) & 0xf))
+
+#define NV50_TILE_SIZE_2D(m) (NV50_TILE_SIZE_X(m) << NV50_TILE_SHIFT_Y(m))
+
+#define NV50_TILE_SIZE(m) (NV50_TILE_SIZE_2D(m) << NV50_TILE_SHIFT_Z(m))
+
+#endif /* __NVC0_RESOURCE_H__ */
 
-#define NV50_TILE_SIZE_2D(m) ((64 * 4) <<                     \
-                              NV50_TILE_DIM_SHIFT(m, 0))
+uint32_t
+nvc0_tex_choose_tile_dims(unsigned nx, unsigned ny, unsigned nz);
 
-#define NV50_TILE_SIZE(m) (NV50_TILE_SIZE_2D(m) << NV50_TILE_DIM_SHIFT(m, 1))
 
 struct nv50_miptree_level {
    uint32_t offset;
@@ -40,6 +50,9 @@ struct nv50_miptree {
    uint32_t total_size;
    uint32_t layer_stride;
    boolean layout_3d; /* TRUE if layer count varies with mip level */
+   uint8_t ms_x;      /* log2 of number of samples in x/y dimension */
+   uint8_t ms_y;
+   uint8_t ms_mode;
 };
 
 static INLINE struct nv50_miptree *
@@ -50,21 +63,57 @@ nv50_miptree(struct pipe_resource *pt)
 
 /* Internal functions:
  */
+boolean
+nv50_miptree_init_layout_linear(struct nv50_miptree *mt);
+
 struct pipe_resource *
 nv50_miptree_create(struct pipe_screen *pscreen,
                     const struct pipe_resource *tmp);
 
+void
+nv50_miptree_destroy(struct pipe_screen *pscreen, struct pipe_resource *pt);
+
 struct pipe_resource *
 nv50_miptree_from_handle(struct pipe_screen *pscreen,
                          const struct pipe_resource *template,
                          struct winsys_handle *whandle);
 
+boolean
+nv50_miptree_get_handle(struct pipe_screen *pscreen,
+                        struct pipe_resource *pt,
+                        struct winsys_handle *whandle);
+
+struct nv50_surface {
+   struct pipe_surface base;
+   uint32_t offset;
+   uint32_t width;
+   uint16_t height;
+   uint16_t depth;
+};
+
+static INLINE struct nv50_surface *
+nv50_surface(struct pipe_surface *ps)
+{
+   return (struct nv50_surface *)ps;
+}
+
+#ifndef __NVC0_RESOURCE_H__
+
+unsigned
+nv50_mt_zslice_offset(const struct nv50_miptree *mt, unsigned l, unsigned z);
+
 struct pipe_surface *
 nv50_miptree_surface_new(struct pipe_context *,
                          struct pipe_resource *,
                          const struct pipe_surface *templ);
 
+#endif /* __NVC0_RESOURCE_H__ */
+
+struct nv50_surface *
+nv50_surface_from_miptree(struct nv50_miptree *mt,
+                          const struct pipe_surface *templ);
+
 void
 nv50_miptree_surface_del(struct pipe_context *, struct pipe_surface *);
 
-#endif
+#endif /* __NV50_RESOURCE_H__ */
diff --git a/src/gallium/drivers/nvc0/nvc0_3d.xml.h b/src/gallium/drivers/nvc0/nvc0_3d.xml.h
index 2ca0bc2..6fba20c 100644
--- a/src/gallium/drivers/nvc0/nvc0_3d.xml.h
+++ b/src/gallium/drivers/nvc0/nvc0_3d.xml.h
@@ -819,13 +819,17 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define NVC0_3D_LAYER_USE_GP					0x00010000
 
 #define NVC0_3D_MULTISAMPLE_MODE				0x000015d0
-#define NVC0_3D_MULTISAMPLE_MODE_1X				0x00000000
-#define NVC0_3D_MULTISAMPLE_MODE_2XMS				0x00000001
-#define NVC0_3D_MULTISAMPLE_MODE_4XMS				0x00000002
-#define NVC0_3D_MULTISAMPLE_MODE_8XMS				0x00000003
-#define NVC0_3D_MULTISAMPLE_MODE_4XMS_4XCS			0x00000008
-#define NVC0_3D_MULTISAMPLE_MODE_4XMS_12XCS			0x00000009
-#define NVC0_3D_MULTISAMPLE_MODE_8XMS_8XCS			0x0000000a
+#define NVC0_3D_MULTISAMPLE_MODE_MS1				0x00000000
+#define NVC0_3D_MULTISAMPLE_MODE_MS2				0x00000001
+#define NVC0_3D_MULTISAMPLE_MODE_MS4				0x00000002
+#define NVC0_3D_MULTISAMPLE_MODE_MS8				0x00000003
+#define NVC0_3D_MULTISAMPLE_MODE_MS8_ALT			0x00000004
+#define NVC0_3D_MULTISAMPLE_MODE_MS2_ALT			0x00000005
+#define NVC0_3D_MULTISAMPLE_MODE_UNK6				0x00000006
+#define NVC0_3D_MULTISAMPLE_MODE_MS4_CS4			0x00000008
+#define NVC0_3D_MULTISAMPLE_MODE_MS4_CS12			0x00000009
+#define NVC0_3D_MULTISAMPLE_MODE_MS8_CS8			0x0000000a
+#define NVC0_3D_MULTISAMPLE_MODE_MS8_CS24			0x0000000b
 
 #define NVC0_3D_VERTEX_BEGIN_D3D				0x000015d4
 #define NVC0_3D_VERTEX_BEGIN_D3D_PRIMITIVE__MASK		0x0fffffff
diff --git a/src/gallium/drivers/nvc0/nvc0_context.h b/src/gallium/drivers/nvc0/nvc0_context.h
index b05cc33..e592091 100644
--- a/src/gallium/drivers/nvc0/nvc0_context.h
+++ b/src/gallium/drivers/nvc0/nvc0_context.h
@@ -137,20 +137,6 @@ nvc0_context(struct pipe_context *pipe)
    return (struct nvc0_context *)pipe;
 }
 
-struct nvc0_surface {
-   struct pipe_surface base;
-   uint32_t offset;
-   uint32_t width;
-   uint16_t height;
-   uint16_t depth;
-};
-
-static INLINE struct nvc0_surface *
-nvc0_surface(struct pipe_surface *ps)
-{
-   return (struct nvc0_surface *)ps;
-}
-
 /* nvc0_context.c */
 struct pipe_context *nvc0_create(struct pipe_screen *, void *);
 
diff --git a/src/gallium/drivers/nvc0/nvc0_miptree.c b/src/gallium/drivers/nvc0/nvc0_miptree.c
index bced324..5da73df 100644
--- a/src/gallium/drivers/nvc0/nvc0_miptree.c
+++ b/src/gallium/drivers/nvc0/nvc0_miptree.c
@@ -29,8 +29,8 @@
 #include "nvc0_resource.h"
 #include "nvc0_transfer.h"
 
-static INLINE uint32_t
-get_tile_dims(unsigned nx, unsigned ny, unsigned nz)
+uint32_t
+nvc0_tex_choose_tile_dims(unsigned nx, unsigned ny, unsigned nz)
 {
    uint32_t tile_mode = 0x000;
 
@@ -57,66 +57,182 @@ get_tile_dims(unsigned nx, unsigned ny, unsigned nz)
    return tile_mode | 0x100;
 }
 
-uint32_t
-nvc0_miptree_zslice_offset(struct nvc0_miptree *mt, unsigned l, unsigned z)
+static uint32_t
+nvc0_mt_choose_storage_type(struct nv50_miptree *mt, boolean compressed)
 {
-   unsigned nblocksy; /* height of texture level aligned to tile height */
+   const unsigned ms = util_logbase2(mt->base.base.nr_samples);
 
-   unsigned stride_2d; /* to next slice within a 3D tile */
-   unsigned stride_3d; /* to slice in the next (in z direction !) 3D tile */
+   uint32_t tile_flags;
 
-   unsigned tile_d_shift = NVC0_TILE_DIM_SHIFT(mt->level[l].tile_mode, 2);
-   unsigned tile_d = 1 << tile_d_shift;
+   compressed = FALSE; /* not yet supported */
 
-   nblocksy = util_format_get_nblocksy(mt->base.base.format,
-                                       u_minify(mt->base.base.height0, l));
+   if (mt->base.base.bind & PIPE_BIND_CURSOR)
+      return NOUVEAU_BO_TILE_SCANOUT;
 
-   nblocksy = align(nblocksy, NVC0_TILE_HEIGHT(mt->level[l].tile_mode));
+   switch (mt->base.base.format) {
+   case PIPE_FORMAT_Z16_UNORM:
+      if (compressed)
+         tile_flags = 0x0200 + (ms << 8);
+      else
+         tile_flags = 0x0100;
+      break;
+   case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
+      if (compressed)
+         tile_flags = 0x5100 + (ms << 8);
+      else
+         tile_flags = 0x4600;
+      break;
+   case PIPE_FORMAT_Z24X8_UNORM:
+   case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
+      if (compressed)
+         tile_flags = 0x1700 + (ms << 8);
+      else
+         tile_flags = 0x1100;
+      break;
+   case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED:
+      if (compressed)
+         tile_flags = 0xce00 + (ms << 8);
+      else
+         tile_flags = 0xc300;
+      break;
+   default:
+      switch (util_format_get_blocksizebits(mt->base.base.format)) {
+      case 128:
+         if (compressed)
+            tile_flags = 0xf400 + (ms << 9);
+         else
+            tile_flags = 0xfe00;
+         break;
+      case 64:
+         if (compressed) {
+            switch (ms) {
+            case 0: tile_flags = 0xe600; break;
+            case 1: tile_flags = 0xeb00; break;
+            case 2: tile_flags = 0xed00; break;
+            case 3: tile_flags = 0xf200; break;
+            default:
+               return 0;
+            }
+         } else {
+            tile_flags = 0xfe00;
+         }
+         break;
+      case 32:
+         if (compressed) {
+            switch (ms) {
+            case 0: tile_flags = 0xdb00; break;
+            case 1: tile_flags = 0xdd00; break;
+            case 2: tile_flags = 0xdf00; break;
+            case 3: tile_flags = 0xe400; break;
+            default:
+               return 0;
+            }
+         } else {
+            tile_flags = 0xfe00;
+         }
+         break;
+      case 16:
+      case 8:
+         tile_flags = 0xfe00;
+         break;
+      default:
+         return 0;
+      }
+      break;
+   }
 
-   stride_2d = NVC0_TILE_SIZE_2D(mt->level[l].tile_mode);
+   if (mt->base.base.bind & PIPE_BIND_SCANOUT)
+      tile_flags |= NOUVEAU_BO_TILE_SCANOUT;
 
-   stride_3d = (nblocksy * mt->level[l].pitch) << tile_d_shift;
+   return tile_flags;
+}
 
-   return (z & (tile_d - 1)) * stride_2d + (z >> tile_d_shift) * stride_3d;
+static INLINE boolean
+nvc0_miptree_init_ms_mode(struct nv50_miptree *mt)
+{
+   switch (mt->base.base.nr_samples) {
+   case 8:
+      mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS8;
+      mt->ms_x = 2;
+      mt->ms_y = 1;
+      break;
+   case 4:
+      mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS4;
+      mt->ms_x = 1;
+      mt->ms_y = 1;
+      break;
+   case 2:
+      mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS2;
+      mt->ms_x = 1;
+      break;
+   case 1:
+   case 0:
+      mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS1;
+      break;
+   default:
+      NOUVEAU_ERR("invalid nr_samples: %u\n", mt->base.base.nr_samples);
+      return FALSE;
+   }
+   return TRUE;
 }
 
+boolean
+nv50_miptree_init_layout_linear(struct nv50_miptree *);
+
 static void
-nvc0_miptree_destroy(struct pipe_screen *pscreen, struct pipe_resource *pt)
+nvc0_miptree_init_layout_tiled(struct nv50_miptree *mt)
 {
-   struct nvc0_miptree *mt = nvc0_miptree(pt);
+   struct pipe_resource *pt = &mt->base.base;
+   unsigned w, h, d, l;
+   const unsigned blocksize = util_format_get_blocksize(pt->format);
 
-   nouveau_screen_bo_release(pscreen, mt->base.bo);
+   mt->layout_3d = pt->target == PIPE_TEXTURE_3D;
 
-   FREE(mt);
-}
+   w = pt->width0 << mt->ms_x;
+   h = pt->height0 << mt->ms_y;
 
-static boolean
-nvc0_miptree_get_handle(struct pipe_screen *pscreen,
-                        struct pipe_resource *pt,
-                        struct winsys_handle *whandle)
-{
-   struct nvc0_miptree *mt = nvc0_miptree(pt);
-   unsigned stride;
+   /* For 3D textures, a mipmap is spanned by all the layers, for array
+    * textures and cube maps, each layer contains its own mipmaps.
+    */
+   d = mt->layout_3d ? pt->depth0 : 1;
 
-   if (!mt || !mt->base.bo)
-      return FALSE;
+   for (l = 0; l <= pt->last_level; ++l) {
+      struct nv50_miptree_level *lvl = &mt->level[l];
+      unsigned tsx, tsy, tsz;
+      unsigned nbx = util_format_get_nblocksx(pt->format, w);
+      unsigned nby = util_format_get_nblocksy(pt->format, h);
+
+      lvl->offset = mt->total_size;
+
+      lvl->tile_mode = nvc0_tex_choose_tile_dims(nbx, nby, d);
+
+      tsx = NVC0_TILE_SIZE_X(lvl->tile_mode); /* x is tile row pitch in bytes */
+      tsy = NVC0_TILE_SIZE_Y(lvl->tile_mode);
+      tsz = NVC0_TILE_SIZE_Z(lvl->tile_mode);
+
+      lvl->pitch = align(nbx * blocksize, tsx);
 
-   stride = util_format_get_stride(mt->base.base.format,
-                                   mt->base.base.width0);
+      mt->total_size += lvl->pitch * align(nby, tsy) * align(d, tsz);
 
-   return nouveau_screen_bo_get_handle(pscreen,
-                                       mt->base.bo,
-                                       stride,
-                                       whandle);
+      w = u_minify(w, 1);
+      h = u_minify(h, 1);
+      d = u_minify(d, 1);
+   }
+
+   if (pt->array_size > 1) {
+      mt->layer_stride = align(mt->total_size,
+                               NVC0_TILE_SIZE(mt->level[0].tile_mode));
+      mt->total_size = mt->layer_stride * pt->array_size;
+   }
 }
 
 const struct u_resource_vtbl nvc0_miptree_vtbl =
 {
-   nvc0_miptree_get_handle,         /* get_handle */
-   nvc0_miptree_destroy,            /* resource_destroy */
+   nv50_miptree_get_handle,         /* get_handle */
+   nv50_miptree_destroy,            /* resource_destroy */
    nvc0_miptree_transfer_new,       /* get_transfer */
    nvc0_miptree_transfer_del,       /* transfer_destroy */
-   nvc0_miptree_transfer_map,	      /* transfer_map */
+   nvc0_miptree_transfer_map,       /* transfer_map */
    u_default_transfer_flush_region, /* transfer_flush_region */
    nvc0_miptree_transfer_unmap,     /* transfer_unmap */
    u_default_transfer_inline_write  /* transfer_inline_write */
@@ -127,10 +243,9 @@ nvc0_miptree_create(struct pipe_screen *pscreen,
                     const struct pipe_resource *templ)
 {
    struct nouveau_device *dev = nouveau_screen(pscreen)->device;
-   struct nvc0_miptree *mt = CALLOC_STRUCT(nvc0_miptree);
+   struct nv50_miptree *mt = CALLOC_STRUCT(nv50_miptree);
    struct pipe_resource *pt = &mt->base.base;
    int ret;
-   unsigned w, h, d, l, alloc_size;
    uint32_t tile_flags;
 
    if (!mt)
@@ -141,84 +256,23 @@ nvc0_miptree_create(struct pipe_screen *pscreen,
    pipe_reference_init(&pt->reference, 1);
    pt->screen = pscreen;
 
-   mt->layout_3d = pt->target == PIPE_TEXTURE_3D;
-
-   w = pt->width0;
-   h = pt->height0;
-   d = mt->layout_3d ? pt->depth0 : 1;
+   tile_flags = nvc0_mt_choose_storage_type(mt, TRUE);
 
-   switch (pt->format) {
-   case PIPE_FORMAT_Z16_UNORM:
-      tile_flags = 0x0700; /* COMPRESSED */
-      tile_flags = 0x0100; /* NORMAL */
-      break;
-   case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
-      tile_flags = 0x5300; /* MSAA 4, COMPRESSED */
-      tile_flags = 0x4600; /* NORMAL */
-      break;
-   case PIPE_FORMAT_Z24X8_UNORM:
-   case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
-      tile_flags = 0x1100; /* NORMAL */
-      if (w * h >= 128 * 128 && 0)
-         tile_flags = 0x1700; /* COMPRESSED, requires magic */
-      break;
-   case PIPE_FORMAT_R32G32B32A32_FLOAT:
-      tile_flags = 0xf500; /* COMPRESSED */
-      tile_flags = 0xf700; /* MSAA 2 */
-      tile_flags = 0xf900; /* MSAA 4 */
-      tile_flags = 0xfe00; /* NORMAL */
-      break;
-   case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED:
-      tile_flags = 0xce00; /* COMPRESSED */
-      tile_flags = 0xcf00; /* MSAA 2, COMPRESSED */
-      tile_flags = 0xd000; /* MSAA 4, COMPRESSED */
-      tile_flags = 0xc300; /* NORMAL */
-      break;
-   case PIPE_FORMAT_R16G16B16A16_UNORM:
-      tile_flags = 0xe900; /* COMPRESSED */
-      tile_flags = 0xfe00; /* NORMAL */
-      break;
-   default:
-      tile_flags = 0xe000; /* MSAA 4, COMPRESSED 32 BIT */
-      tile_flags = 0xfe00; /* NORMAL 32 BIT */
-      if (w * h >= 128 * 128 && 0)
-         tile_flags = 0xdb00; /* COMPRESSED 32 BIT, requires magic */
-      break;
-   }
-
-   /* For 3D textures, a mipmap is spanned by all the layers, for array
-    * textures and cube maps, each layer contains its own mipmaps.
-    */
-   for (l = 0; l <= pt->last_level; ++l) {
-      struct nvc0_miptree_level *lvl = &mt->level[l];
-      unsigned nbx = util_format_get_nblocksx(pt->format, w);
-      unsigned nby = util_format_get_nblocksy(pt->format, h);
-      unsigned blocksize = util_format_get_blocksize(pt->format);
-
-      lvl->offset = mt->total_size;
-      lvl->tile_mode = get_tile_dims(nbx, nby, d);
-      lvl->pitch = align(nbx * blocksize, NVC0_TILE_PITCH(lvl->tile_mode));
-
-      mt->total_size += lvl->pitch *
-         align(nby, NVC0_TILE_HEIGHT(lvl->tile_mode)) *
-         align(d, NVC0_TILE_DEPTH(lvl->tile_mode));
-
-      w = u_minify(w, 1);
-      h = u_minify(h, 1);
-      d = u_minify(d, 1);
+   if (!nvc0_miptree_init_ms_mode(mt)) {
+      FREE(mt);
+      return NULL;
    }
 
-   if (pt->array_size > 1) {
-      mt->layer_stride = align(mt->total_size,
-                               NVC0_TILE_SIZE(mt->level[0].tile_mode));
-      mt->total_size = mt->layer_stride * pt->array_size;
+   if (tile_flags & NOUVEAU_BO_TILE_LAYOUT_MASK) {
+      nvc0_miptree_init_layout_tiled(mt);
+   } else
+   if (!nv50_miptree_init_layout_linear(mt)) {
+      FREE(mt);
+      return NULL;
    }
 
-   alloc_size = mt->total_size;
-   if (tile_flags == 0x1700)
-      alloc_size *= 3; /* HiZ, XXX: correct size */
-
-   ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 256, alloc_size,
+   ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 4096,
+                             mt->total_size,
                              mt->level[0].tile_mode, tile_flags,
                              &mt->base.bo);
    if (ret) {
@@ -230,44 +284,26 @@ nvc0_miptree_create(struct pipe_screen *pscreen,
    return pt;
 }
 
-struct pipe_resource *
-nvc0_miptree_from_handle(struct pipe_screen *pscreen,
-                         const struct pipe_resource *templ,
-                         struct winsys_handle *whandle)
+/* Offset of zslice @z from start of level @l. */
+INLINE unsigned
+nvc0_mt_zslice_offset(const struct nv50_miptree *mt, unsigned l, unsigned z)
 {
-   struct nvc0_miptree *mt;
-   unsigned stride;
-
-   /* only supports 2D, non-mipmapped textures for the moment */
-   if ((templ->target != PIPE_TEXTURE_2D &&
-        templ->target != PIPE_TEXTURE_RECT) ||
-       templ->last_level != 0 ||
-       templ->depth0 != 1 ||
-       templ->array_size > 1)
-      return NULL;
+   const struct pipe_resource *pt = &mt->base.base;
 
-   mt = CALLOC_STRUCT(nvc0_miptree);
-   if (!mt)
-      return NULL;
+   unsigned tds = NVC0_TILE_SHIFT_Z(mt->level[l].tile_mode);
+   unsigned ths = NVC0_TILE_SHIFT_Y(mt->level[l].tile_mode);
 
-   mt->base.bo = nouveau_screen_bo_from_handle(pscreen, whandle, &stride);
-   if (mt->base.bo == NULL) {
-      FREE(mt);
-      return NULL;
-   }
+   unsigned nby = util_format_get_nblocksy(pt->format,
+                                           u_minify(pt->height0, l));
 
-   mt->base.base = *templ;
-   mt->base.vtbl = &nvc0_miptree_vtbl;
-   pipe_reference_init(&mt->base.base.reference, 1);
-   mt->base.base.screen = pscreen;
-   mt->level[0].pitch = stride;
-   mt->level[0].offset = 0;
-   mt->level[0].tile_mode = mt->base.bo->tile_mode;
-
-   /* no need to adjust bo reference count */
-   return &mt->base.base;
-}
+   /* to next 2D tile slice within a 3D tile */
+   unsigned stride_2d = NVC0_TILE_SIZE_2D(mt->level[l].tile_mode);
+
+   /* to slice in the next (in z direction) 3D tile */
+   unsigned stride_3d = (align(nby, (1 << ths)) * mt->level[l].pitch) << tds;
 
+   return (z & (1 << (tds - 1))) * stride_2d + (z >> tds) * stride_3d;
+}
 
 /* Surface functions.
  */
@@ -277,43 +313,9 @@ nvc0_miptree_surface_new(struct pipe_context *pipe,
                          struct pipe_resource *pt,
                          const struct pipe_surface *templ)
 {
-   struct nvc0_miptree *mt = nvc0_miptree(pt); /* guaranteed */
-   struct nvc0_surface *ns;
-   struct pipe_surface *ps;
-   struct nvc0_miptree_level *lvl = &mt->level[templ->u.tex.level];
-
-   ns = CALLOC_STRUCT(nvc0_surface);
+   struct nv50_surface *ns = nv50_surface_from_miptree(nv50_miptree(pt), templ);
    if (!ns)
       return NULL;
-   ps = &ns->base;
-
-   pipe_reference_init(&ps->reference, 1);
-   pipe_resource_reference(&ps->texture, pt);
-   ps->context = pipe;
-   ps->format = templ->format;
-   ps->usage = templ->usage;
-   ps->u.tex.level = templ->u.tex.level;
-   ps->u.tex.first_layer = templ->u.tex.first_layer;
-   ps->u.tex.last_layer = templ->u.tex.last_layer;
-
-   ns->width = u_minify(pt->width0, ps->u.tex.level);
-   ns->height = u_minify(pt->height0, ps->u.tex.level);
-   ns->depth = ps->u.tex.last_layer - ps->u.tex.first_layer + 1;
-   ns->offset = lvl->offset;
-
-   /* comment says there are going to be removed, but they're used by the st */
-   ps->width = ns->width;
-   ps->height = ns->height;
-
-   return ps;
-}
-
-void
-nvc0_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps)
-{
-   struct nvc0_surface *s = nvc0_surface(ps);
-
-   pipe_resource_reference(&ps->texture, NULL);
-
-   FREE(s);
+   ns->base.context = pipe;
+   return &ns->base;
 }
diff --git a/src/gallium/drivers/nvc0/nvc0_resource.c b/src/gallium/drivers/nvc0/nvc0_resource.c
index 44e6631..a028972 100644
--- a/src/gallium/drivers/nvc0/nvc0_resource.c
+++ b/src/gallium/drivers/nvc0/nvc0_resource.c
@@ -21,10 +21,14 @@ nvc0_resource_from_handle(struct pipe_screen * screen,
                           const struct pipe_resource *templ,
                           struct winsys_handle *whandle)
 {
-   if (templ->target == PIPE_BUFFER)
+   if (templ->target == PIPE_BUFFER) {
       return NULL;
-   else
-      return nvc0_miptree_from_handle(screen, templ, whandle);
+   } else {
+      struct pipe_resource *res = nv50_miptree_from_handle(screen,
+                                                           templ, whandle);
+      nv04_resource(res)->vtbl = &nvc0_miptree_vtbl;
+      return res;
+   }
 }
 
 void
@@ -37,7 +41,7 @@ nvc0_init_resource_functions(struct pipe_context *pcontext)
    pcontext->transfer_destroy = u_transfer_destroy_vtbl;
    pcontext->transfer_inline_write = u_transfer_inline_write_vtbl;
    pcontext->create_surface = nvc0_miptree_surface_new;
-   pcontext->surface_destroy = nvc0_miptree_surface_del;
+   pcontext->surface_destroy = nv50_miptree_surface_del;
 }
 
 void
diff --git a/src/gallium/drivers/nvc0/nvc0_resource.h b/src/gallium/drivers/nvc0/nvc0_resource.h
index f1c445b..d699895 100644
--- a/src/gallium/drivers/nvc0/nvc0_resource.h
+++ b/src/gallium/drivers/nvc0/nvc0_resource.h
@@ -2,53 +2,29 @@
 #ifndef __NVC0_RESOURCE_H__
 #define __NVC0_RESOURCE_H__
 
-#include "util/u_transfer.h"
-#include "util/u_double_list.h"
-#define NOUVEAU_NVC0
-#include "nouveau/nouveau_winsys.h"
-#include "nouveau/nouveau_fence.h"
-#include "nouveau/nouveau_buffer.h"
-#undef NOUVEAU_NVC0
+#include "nv50/nv50_resource.h"
 
-void
-nvc0_init_resource_functions(struct pipe_context *pcontext);
-
-void
-nvc0_screen_init_resource_functions(struct pipe_screen *pscreen);
 
-#define NVC0_TILE_DIM_SHIFT(m, d) (((m) >> (d * 4)) & 0xf)
+#define NVC0_TILE_SHIFT_X(m) ((((m) >> 0) & 0xf) + 6)
+#define NVC0_TILE_SHIFT_Y(m) ((((m) >> 4) & 0xf) + 3)
+#define NVC0_TILE_SHIFT_Z(m) ((((m) >> 8) & 0xf) + 0)
 
-#define NVC0_TILE_PITCH(m)  (64 << NVC0_TILE_DIM_SHIFT(m, 0))
-#define NVC0_TILE_HEIGHT(m) ( 8 << NVC0_TILE_DIM_SHIFT(m, 1))
-#define NVC0_TILE_DEPTH(m)  ( 1 << NVC0_TILE_DIM_SHIFT(m, 2))
+#define NVC0_TILE_SIZE_X(m) (64 << (((m) >> 0) & 0xf))
+#define NVC0_TILE_SIZE_Y(m) ( 8 << (((m) >> 4) & 0xf))
+#define NVC0_TILE_SIZE_Z(m) ( 1 << (((m) >> 8) & 0xf))
 
-#define NVC0_TILE_SIZE_2D(m) (((64 * 8) <<                     \
-                               NVC0_TILE_DIM_SHIFT(m, 0)) <<   \
-                              NVC0_TILE_DIM_SHIFT(m, 1))
+/* it's ok to mask only in the end because max value is 3 * 5 */
 
-#define NVC0_TILE_SIZE(m) (NVC0_TILE_SIZE_2D(m) << NVC0_TILE_DIM_SHIFT(m, 2))
+#define NVC0_TILE_SIZE_2D(m) ((64 * 8) << (((m) + ((m) >> 4)) & 0xf))
 
-struct nvc0_miptree_level {
-   uint32_t offset;
-   uint32_t pitch;
-   uint32_t tile_mode;
-};
+#define NVC0_TILE_SIZE(m) ((64 * 8) << (((m) + ((m) >> 4) + ((m) >> 8)) & 0xf))
 
-#define NVC0_MAX_TEXTURE_LEVELS 16
 
-struct nvc0_miptree {
-   struct nv04_resource base;
-   struct nvc0_miptree_level level[NVC0_MAX_TEXTURE_LEVELS];
-   uint32_t total_size;
-   uint32_t layer_stride;
-   boolean layout_3d; /* TRUE if layer count varies with mip level */
-};
+void
+nvc0_init_resource_functions(struct pipe_context *pcontext);
 
-static INLINE struct nvc0_miptree *
-nvc0_miptree(struct pipe_resource *pt)
-{
-   return (struct nvc0_miptree *)pt;
-}
+void
+nvc0_screen_init_resource_functions(struct pipe_screen *pscreen);
 
 /* Internal functions:
  */
@@ -56,20 +32,14 @@ struct pipe_resource *
 nvc0_miptree_create(struct pipe_screen *pscreen,
                     const struct pipe_resource *tmp);
 
-struct pipe_resource *
-nvc0_miptree_from_handle(struct pipe_screen *pscreen,
-                         const struct pipe_resource *template,
-                         struct winsys_handle *whandle);
+const struct u_resource_vtbl nvc0_miptree_vtbl;
 
 struct pipe_surface *
 nvc0_miptree_surface_new(struct pipe_context *,
                          struct pipe_resource *,
                          const struct pipe_surface *templ);
 
-void
-nvc0_miptree_surface_del(struct pipe_context *, struct pipe_surface *);
-
-uint32_t
-nvc0_miptree_zslice_offset(struct nvc0_miptree *, unsigned l, unsigned z);
+unsigned
+nvc0_mt_zslice_offset(const struct nv50_miptree *, unsigned l, unsigned z);
 
 #endif
diff --git a/src/gallium/drivers/nvc0/nvc0_screen.c b/src/gallium/drivers/nvc0/nvc0_screen.c
index 1bd7fa9..a2e45b1 100644
--- a/src/gallium/drivers/nvc0/nvc0_screen.c
+++ b/src/gallium/drivers/nvc0/nvc0_screen.c
@@ -437,7 +437,7 @@ nvc0_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
    BEGIN_RING(chan, RING_3D(MULTISAMPLE_ENABLE), 1);
    OUT_RING  (chan, 0);
    BEGIN_RING(chan, RING_3D(MULTISAMPLE_MODE), 1);
-   OUT_RING  (chan, NVC0_3D_MULTISAMPLE_MODE_1X);
+   OUT_RING  (chan, NVC0_3D_MULTISAMPLE_MODE_MS1);
    BEGIN_RING(chan, RING_3D(MULTISAMPLE_CTRL), 1);
    OUT_RING  (chan, 0);
    BEGIN_RING(chan, RING_3D(LINE_WIDTH_SEPARATE), 1);
diff --git a/src/gallium/drivers/nvc0/nvc0_screen.h b/src/gallium/drivers/nvc0/nvc0_screen.h
index 015807e..a3133b2 100644
--- a/src/gallium/drivers/nvc0/nvc0_screen.h
+++ b/src/gallium/drivers/nvc0/nvc0_screen.h
@@ -4,6 +4,7 @@
 #define NOUVEAU_NVC0
 #include "nouveau/nouveau_screen.h"
 #include "nouveau/nouveau_mm.h"
+#include "nouveau/nouveau_fence.h"
 #undef NOUVEAU_NVC0
 #include "nvc0_winsys.h"
 #include "nvc0_stateobj.h"
diff --git a/src/gallium/drivers/nvc0/nvc0_state_validate.c b/src/gallium/drivers/nvc0/nvc0_state_validate.c
index f300f37..bd40a23 100644
--- a/src/gallium/drivers/nvc0/nvc0_state_validate.c
+++ b/src/gallium/drivers/nvc0/nvc0_state_validate.c
@@ -8,8 +8,8 @@ nvc0_validate_zcull(struct nvc0_context *nvc0)
 {
     struct nouveau_channel *chan = nvc0->screen->base.channel;
     struct pipe_framebuffer_state *fb = &nvc0->framebuffer;
-    struct nvc0_surface *sf = nvc0_surface(fb->zsbuf);
-    struct nvc0_miptree *mt = nvc0_miptree(sf->base.texture);
+    struct nv50_surface *sf = nv50_surface(fb->zsbuf);
+    struct nv50_miptree *mt = nv50_miptree(sf->base.texture);
     struct nouveau_bo *bo = mt->base.bo;
     uint32_t size;
     uint32_t offset = align(mt->total_size, 1 << 17);
@@ -72,8 +72,8 @@ nvc0_validate_fb(struct nvc0_context *nvc0)
     MARK_RING(chan, 9 * fb->nr_cbufs, 2 * fb->nr_cbufs);
 
     for (i = 0; i < fb->nr_cbufs; ++i) {
-        struct nvc0_miptree *mt = nvc0_miptree(fb->cbufs[i]->texture);
-        struct nvc0_surface *sf = nvc0_surface(fb->cbufs[i]);
+        struct nv50_miptree *mt = nv50_miptree(fb->cbufs[i]->texture);
+        struct nv50_surface *sf = nv50_surface(fb->cbufs[i]);
         struct nouveau_bo *bo = mt->base.bo;
         uint32_t offset = sf->offset;
 
@@ -100,8 +100,8 @@ nvc0_validate_fb(struct nvc0_context *nvc0)
     }
 
     if (fb->zsbuf) {
-        struct nvc0_miptree *mt = nvc0_miptree(fb->zsbuf->texture);
-        struct nvc0_surface *sf = nvc0_surface(fb->zsbuf);
+        struct nv50_miptree *mt = nv50_miptree(fb->zsbuf->texture);
+        struct nv50_surface *sf = nv50_surface(fb->zsbuf);
         struct nouveau_bo *bo = mt->base.bo;
         int unk = mt->base.base.target == PIPE_TEXTURE_2D;
         uint32_t offset = sf->offset;
diff --git a/src/gallium/drivers/nvc0/nvc0_surface.c b/src/gallium/drivers/nvc0/nvc0_surface.c
index 6be3702..e1e4c30 100644
--- a/src/gallium/drivers/nvc0/nvc0_surface.c
+++ b/src/gallium/drivers/nvc0/nvc0_surface.c
@@ -75,7 +75,7 @@ nvc0_2d_format(enum pipe_format format)
 
 static int
 nvc0_2d_texture_set(struct nouveau_channel *chan, int dst,
-                    struct nvc0_miptree *mt, unsigned level, unsigned layer)
+                    struct nv50_miptree *mt, unsigned level, unsigned layer)
 {
    struct nouveau_bo *bo = mt->base.bo;
    uint32_t width, height, depth;
@@ -103,7 +103,7 @@ nvc0_2d_texture_set(struct nouveau_channel *chan, int dst,
       depth = 1;
    } else
    if (!dst) {
-      offset += nvc0_miptree_zslice_offset(mt, level, layer);
+      offset += nvc0_mt_zslice_offset(mt, level, layer);
       layer = 0;
    }
 
@@ -145,9 +145,9 @@ nvc0_2d_texture_set(struct nouveau_channel *chan, int dst,
 
 static int
 nvc0_2d_texture_do_copy(struct nouveau_channel *chan,
-                        struct nvc0_miptree *dst, unsigned dst_level,
+                        struct nv50_miptree *dst, unsigned dst_level,
                         unsigned dx, unsigned dy, unsigned dz,
-                        struct nvc0_miptree *src, unsigned src_level,
+                        struct nv50_miptree *src, unsigned src_level,
                         unsigned sx, unsigned sy, unsigned sz,
                         unsigned w, unsigned h)
 {
@@ -192,7 +192,7 @@ nvc0_setup_m2mf_rect(struct nvc0_m2mf_rect *rect,
                      struct pipe_resource *restrict res, unsigned l,
                      unsigned x, unsigned y, unsigned z)
 {
-   struct nvc0_miptree *mt = nvc0_miptree(res);
+   struct nv50_miptree *mt = nv50_miptree(res);
    const unsigned w = u_minify(res->width0, l);
    const unsigned h = u_minify(res->height0, l);
 
@@ -257,15 +257,15 @@ nvc0_resource_copy_region(struct pipe_context *pipe,
       for (i = 0; i < src_box->depth; ++i) {
          nvc0_m2mf_transfer_rect(&screen->base.base, &drect, &srect, nx, ny);
 
-         if (nvc0_miptree(dst)->layout_3d)
+         if (nv50_miptree(dst)->layout_3d)
             drect.z++;
          else
-            drect.base += nvc0_miptree(dst)->layer_stride;
+            drect.base += nv50_miptree(dst)->layer_stride;
 
-         if (nvc0_miptree(src)->layout_3d)
+         if (nv50_miptree(src)->layout_3d)
             srect.z++;
          else
-            srect.base += nvc0_miptree(src)->layer_stride;
+            srect.base += nv50_miptree(src)->layer_stride;
       }
       return;
    }
@@ -275,9 +275,9 @@ nvc0_resource_copy_region(struct pipe_context *pipe,
 
    for (; dst_layer < dstz + src_box->depth; ++dst_layer, ++src_layer) {
       ret = nvc0_2d_texture_do_copy(screen->base.channel,
-                                    nvc0_miptree(dst), dst_level,
+                                    nv50_miptree(dst), dst_level,
                                     dstx, dsty, dst_layer,
-                                    nvc0_miptree(src), src_level,
+                                    nv50_miptree(src), src_level,
                                     src_box->x, src_box->y, src_layer,
                                     src_box->width, src_box->height);
       if (ret)
@@ -295,8 +295,8 @@ nvc0_clear_render_target(struct pipe_context *pipe,
 	struct nvc0_context *nv50 = nvc0_context(pipe);
 	struct nvc0_screen *screen = nv50->screen;
 	struct nouveau_channel *chan = screen->base.channel;
-	struct nvc0_miptree *mt = nvc0_miptree(dst->texture);
-	struct nvc0_surface *sf = nvc0_surface(dst);
+	struct nv50_miptree *mt = nv50_miptree(dst->texture);
+	struct nv50_surface *sf = nv50_surface(dst);
 	struct nouveau_bo *bo = mt->base.bo;
 
 	BEGIN_RING(chan, RING_3D(CLEAR_COLOR(0)), 4);
@@ -347,8 +347,8 @@ nvc0_clear_depth_stencil(struct pipe_context *pipe,
 	struct nvc0_context *nv50 = nvc0_context(pipe);
 	struct nvc0_screen *screen = nv50->screen;
 	struct nouveau_channel *chan = screen->base.channel;
-	struct nvc0_miptree *mt = nvc0_miptree(dst->texture);
-	struct nvc0_surface *sf = nvc0_surface(dst);
+	struct nv50_miptree *mt = nv50_miptree(dst->texture);
+	struct nv50_surface *sf = nv50_surface(dst);
 	struct nouveau_bo *bo = mt->base.bo;
 	uint32_t mode = 0;
 	int unk = mt->base.base.target == PIPE_TEXTURE_2D;
diff --git a/src/gallium/drivers/nvc0/nvc0_tex.c b/src/gallium/drivers/nvc0/nvc0_tex.c
index 24850b1..4b82fdf 100644
--- a/src/gallium/drivers/nvc0/nvc0_tex.c
+++ b/src/gallium/drivers/nvc0/nvc0_tex.c
@@ -60,7 +60,7 @@ nvc0_create_sampler_view(struct pipe_context *pipe,
    uint32_t swz[4];
    uint32_t depth;
    struct nv50_tic_entry *view;
-   struct nvc0_miptree *mt = nvc0_miptree(texture);
+   struct nv50_miptree *mt = nv50_miptree(texture);
    boolean tex_int;
 
    view = MALLOC_STRUCT(nv50_tic_entry);
@@ -189,7 +189,7 @@ nvc0_validate_tic(struct nvc0_context *nvc0, int s)
          OUT_RING  (chan, (i << 1) | 0);
          continue;
       }
-      res = &nvc0_miptree(tic->pipe.texture)->base;
+      res = &nv50_miptree(tic->pipe.texture)->base;
 
       if (tic->id < 0) {
          uint32_t offset = tic->tic[1];
diff --git a/src/gallium/drivers/nvc0/nvc0_transfer.c b/src/gallium/drivers/nvc0/nvc0_transfer.c
index 0509113..1170f12 100644
--- a/src/gallium/drivers/nvc0/nvc0_transfer.c
+++ b/src/gallium/drivers/nvc0/nvc0_transfer.c
@@ -239,8 +239,8 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx,
    struct nvc0_context *nvc0 = nvc0_context(pctx);
    struct pipe_screen *pscreen = pctx->screen;
    struct nouveau_device *dev = nvc0->screen->base.device;
-   struct nvc0_miptree *mt = nvc0_miptree(res);
-   struct nvc0_miptree_level *lvl = &mt->level[level];
+   struct nv50_miptree *mt = nv50_miptree(res);
+   struct nv50_miptree_level *lvl = &mt->level[level];
    struct nvc0_transfer *tx;
    uint32_t size;
    uint32_t w, h, d, z, layer;
@@ -334,7 +334,7 @@ nvc0_miptree_transfer_del(struct pipe_context *pctx,
 {
    struct pipe_screen *pscreen = pctx->screen;
    struct nvc0_transfer *tx = (struct nvc0_transfer *)transfer;
-   struct nvc0_miptree *mt = nvc0_miptree(tx->base.resource);
+   struct nv50_miptree *mt = nv50_miptree(tx->base.resource);
    unsigned i;
 
    if (tx->base.usage & PIPE_TRANSFER_WRITE) {




More information about the mesa-commit mailing list