summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/ilo/ilo_resource.c
diff options
context:
space:
mode:
authorChia-I Wu <[email protected]>2012-12-13 05:23:34 +0800
committerChia-I Wu <[email protected]>2013-04-26 16:16:43 +0800
commitd3602dfac6fbd93173c34e46f1d54976ae1215ec (patch)
tree36a26fcaa847309e321cdf5f6ed56e5843204630 /src/gallium/drivers/ilo/ilo_resource.c
parent72357cf3bbe889e802419931ea3d4c55b01d33bd (diff)
ilo: add GEN6 GPE
GEN6 GPE (Graphics Processing Engine) is a low-level interface to emit 3D commands and states.
Diffstat (limited to 'src/gallium/drivers/ilo/ilo_resource.c')
-rw-r--r--src/gallium/drivers/ilo/ilo_resource.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/gallium/drivers/ilo/ilo_resource.c b/src/gallium/drivers/ilo/ilo_resource.c
index aa6afe9812e..f325c41945d 100644
--- a/src/gallium/drivers/ilo/ilo_resource.c
+++ b/src/gallium/drivers/ilo/ilo_resource.c
@@ -1093,3 +1093,101 @@ ilo_init_transfer_functions(struct ilo_context *ilo)
ilo->base.transfer_unmap = ilo_transfer_unmap;
ilo->base.transfer_inline_write = ilo_transfer_inline_write;
}
+
+/**
+ * Return the offset (in bytes) to a slice within the bo.
+ *
+ * When tile_aligned is true, the offset is to the tile containing the start
+ * address of the slice. x_offset and y_offset are offsets (in pixels) from
+ * the tile start to slice start. x_offset is always a multiple of 4 and
+ * y_offset is always a multiple of 2.
+ */
+unsigned
+ilo_resource_get_slice_offset(const struct ilo_resource *res,
+ int level, int slice, bool tile_aligned,
+ unsigned *x_offset, unsigned *y_offset)
+{
+ const unsigned x = res->slice_offsets[level][slice].x / res->block_width;
+ const unsigned y = res->slice_offsets[level][slice].y / res->block_height;
+ unsigned tile_w, tile_h, tile_size, row_size;
+ unsigned slice_offset;
+
+ /* see the Sandy Bridge PRM, volume 1 part 2, page 24 */
+
+ switch (res->tiling) {
+ case INTEL_TILING_NONE:
+ tile_w = res->bo_cpp;
+ 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 = res->bo_cpp;
+ tile_h = 1;
+ break;
+ }
+
+ tile_size = tile_w * tile_h;
+ row_size = res->bo_stride * tile_h;
+
+ /*
+ * for non-tiled resources, this is equivalent to
+ *
+ * slice_offset = y * res->bo_stride + x * res->bo_cpp;
+ */
+ slice_offset =
+ row_size * (y / tile_h) + tile_size * (x * res->bo_cpp / tile_w);
+
+ /*
+ * Since res->bo_stride is a multiple of tile_w, slice_offset should be
+ * aligned at this point.
+ */
+ assert(slice_offset % tile_size == 0);
+
+ if (tile_aligned) {
+ /*
+ * because of the possible values of align_i and align_j in
+ * layout_tex_init(), x_offset must be a multiple of 4 and y_offset must
+ * be a multiple of 2.
+ */
+ if (x_offset) {
+ assert(tile_w % res->bo_cpp == 0);
+ *x_offset = (x % (tile_w / res->bo_cpp)) * res->block_width;
+ assert(*x_offset % 4 == 0);
+ }
+ if (y_offset) {
+ *y_offset = (y % tile_h) * res->block_height;
+ assert(*y_offset % 2 == 0);
+ }
+ }
+ else {
+ const unsigned tx = (x * res->bo_cpp) % tile_w;
+ const unsigned ty = y % tile_h;
+
+ switch (res->tiling) {
+ case INTEL_TILING_NONE:
+ assert(tx == 0 && ty == 0);
+ break;
+ case INTEL_TILING_X:
+ slice_offset += tile_w * ty + tx;
+ break;
+ case INTEL_TILING_Y:
+ slice_offset += tile_h * 16 * (tx / 16) + ty * 16 + (tx % 16);
+ break;
+ }
+
+ if (x_offset)
+ *x_offset = 0;
+ if (y_offset)
+ *y_offset = 0;
+ }
+
+ return slice_offset;
+}