/**
  * struct svga3dsurface_loc - Surface location
+ * @sheet: The multisample sheet.
  * @sub_resource: Surface subresource. Defined as layer * num_mip_levels +
  * mip_level.
  * @x: X coordinate.
  * @z: Z coordinate.
  */
 struct svga3dsurface_loc {
+       u32 sheet;
        u32 sub_resource;
        u32 x, y, z;
 };
        u32 layer;
        int i;
 
-       if (offset >= cache->sheet_bytes)
-               offset %= cache->sheet_bytes;
+       loc->sheet = offset / cache->sheet_bytes;
+       offset -= loc->sheet * cache->sheet_bytes;
 
        layer = offset / cache->mip_chain_bytes;
        offset -= layer * cache->mip_chain_bytes;
                      u32 sub_resource,
                      struct svga3dsurface_loc *loc)
 {
+       loc->sheet = 0;
        loc->sub_resource = sub_resource;
        loc->x = loc->y = loc->z = 0;
 }
        const struct drm_vmw_size *size;
        u32 mip;
 
+       loc->sheet = 0;
        loc->sub_resource = sub_resource + 1;
        mip = sub_resource % cache->num_mip_levels;
        size = &cache->mip[mip].size;
 
        svga3dsurface_get_loc(cache, &loc2, end - 1);
        svga3dsurface_inc_loc(cache, &loc2);
 
+       if (loc1.sheet != loc2.sheet) {
+               u32 sub_res;
+
+               /*
+                * Multiple multisample sheets. To do this in an optimized
+                * fashion, compute the dirty region for each sheet and the
+                * resulting union. Since this is not a common case, just dirty
+                * the whole surface.
+                */
+               for (sub_res = 0; sub_res < dirty->num_subres; ++sub_res)
+                       vmw_subres_dirty_full(dirty, sub_res);
+               return;
+       }
        if (loc1.sub_resource + 1 == loc2.sub_resource) {
                /* Dirty range covers a single sub-resource */
                vmw_subres_dirty_add(dirty, &loc1, &loc2);