intel: revive intel_layout_get_slice_tile_offset()
Surface Base Address are required to be page-aligned when the surface is
tiled. When one wants to directly point to a single miplevel or a single
array layer, one has to leverage X Offset and Y Offset to keep Surface Base
Address page-aligned. This function can return valid
(Surface Base Address, X Offset, Y Offset)
for any given subresource.
diff --git a/icd/intel/layout.c b/icd/intel/layout.c
index 205b0b5..ccc11a8 100644
--- a/icd/intel/layout.c
+++ b/icd/intel/layout.c
@@ -1329,3 +1329,87 @@
return true;
}
+
+/**
+ * Return the offset (in bytes) to a slice within the bo.
+ *
+ * The returned offset is aligned to tile size. Since slices are not
+ * guaranteed to start at tile boundaries, the X and Y offsets (in pixels)
+ * from the tile origin to the slice are also returned. X offset is always a
+ * multiple of 4 and Y offset is always a multiple of 2.
+ */
+unsigned
+intel_layout_get_slice_tile_offset(const struct intel_layout *layout,
+ unsigned level, unsigned slice,
+ unsigned *x_offset, unsigned *y_offset)
+{
+ unsigned tile_w, tile_h, tile_size, row_size;
+ unsigned tile_offset, x, y;
+
+ /* see the Sandy Bridge PRM, volume 1 part 2, page 24 */
+
+ switch (layout->tiling) {
+ case INTEL_TILING_NONE:
+ /* W-tiled */
+ if (layout->format.numericFormat == XGL_NUM_FMT_DS &&
+ layout->format.channelFormat == XGL_CH_FMT_R8) {
+ tile_w = 64;
+ tile_h = 64;
+ }
+ else {
+ tile_w = 1;
+ tile_h = 1;
+ }
+ break;
+ case INTEL_TILING_X:
+ tile_w = 512;
+ tile_h = 8;
+ break;
+ case INTEL_TILING_Y:
+ tile_w = 128;
+ tile_h = 32;
+ break;
+ default:
+ assert(!"unknown tiling");
+ tile_w = 1;
+ tile_h = 1;
+ break;
+ }
+
+ tile_size = tile_w * tile_h;
+ row_size = layout->bo_stride * tile_h;
+
+ intel_layout_get_slice_pos(layout, level, slice, &x, &y);
+ /* in bytes */
+ intel_layout_pos_to_mem(layout, x, y, &x, &y);
+ tile_offset = row_size * (y / tile_h) + tile_size * (x / tile_w);
+
+ /*
+ * Since tex->bo_stride is a multiple of tile_w, slice_offset should be
+ * aligned at this point.
+ */
+ assert(tile_offset % tile_size == 0);
+
+ /*
+ * because of the possible values of align_i and align_j in
+ * tex_layout_init_alignments(), x_offset is guaranteed to be a multiple of
+ * 4 and y_offset is guaranteed to be a multiple of 2.
+ */
+ if (x_offset) {
+ /* in pixels */
+ x = (x % tile_w) / layout->block_size * layout->block_width;
+ assert(x % 4 == 0);
+
+ *x_offset = x;
+ }
+
+ if (y_offset) {
+ /* in pixels */
+ y = (y % tile_h) * layout->block_height;
+ assert(y % 2 == 0);
+
+ *y_offset = y;
+ }
+
+ return tile_offset;
+}