-/* use PIPE_BIND_CUSTOM to indicate MCS */
-#define ILO_BIND_MCS PIPE_BIND_CUSTOM
-
-struct tex_layout {
- const struct ilo_dev_info *dev;
- const struct pipe_resource *templ;
-
- bool has_depth, has_stencil;
- bool hiz, separate_stencil;
-
- enum pipe_format format;
- unsigned block_width, block_height, block_size;
- bool compressed;
-
- enum intel_tiling_mode tiling;
- bool can_be_linear;
-
- bool array_spacing_full;
- bool interleaved;
-
- struct {
- int w, h, d;
- struct ilo_texture_slice *slices;
- } levels[PIPE_MAX_TEXTURE_LEVELS];
-
- int align_i, align_j;
- int qpitch;
-
- int width, height;
-};
-
-static void
-tex_layout_init_qpitch(struct tex_layout *layout)
-{
- const struct pipe_resource *templ = layout->templ;
- int h0, h1;
-
- if (templ->array_size <= 1)
- return;
-
- h0 = align(layout->levels[0].h, layout->align_j);
-
- if (!layout->array_spacing_full) {
- layout->qpitch = h0;
- return;
- }
-
- h1 = align(layout->levels[1].h, layout->align_j);
-
- /*
- * From the Sandy Bridge PRM, volume 1 part 1, page 115:
- *
- * "The following equation is used for surface formats other than
- * compressed textures:
- *
- * QPitch = (h0 + h1 + 11j)"
- *
- * "The equation for compressed textures (BC* and FXT1 surface formats)
- * follows:
- *
- * QPitch = (h0 + h1 + 11j) / 4"
- *
- * "[DevSNB] Errata: Sampler MSAA Qpitch will be 4 greater than the
- * value calculated in the equation above, for every other odd Surface
- * Height starting from 1 i.e. 1,5,9,13"
- *
- * From the Ivy Bridge PRM, volume 1 part 1, page 111-112:
- *
- * "If Surface Array Spacing is set to ARYSPC_FULL (note that the depth
- * buffer and stencil buffer have an implied value of ARYSPC_FULL):
- *
- * QPitch = (h0 + h1 + 12j)
- * QPitch = (h0 + h1 + 12j) / 4 (compressed)
- *
- * (There are many typos or missing words here...)"
- *
- * To access the N-th slice, an offset of (Stride * QPitch * N) is added to
- * the base address. The PRM divides QPitch by 4 for compressed formats
- * because the block height for those formats are 4, and it wants QPitch to
- * mean the number of memory rows, as opposed to texel rows, between
- * slices. Since we use texel rows in tex->slice_offsets, we do not need
- * to divide QPitch by 4.
- */
- layout->qpitch = h0 + h1 +
- ((layout->dev->gen >= ILO_GEN(7)) ? 12 : 11) * layout->align_j;
-
- if (layout->dev->gen == ILO_GEN(6) && templ->nr_samples > 1 &&
- templ->height0 % 4 == 1)
- layout->qpitch += 4;
-}
-
-static void
-tex_layout_init_alignments(struct tex_layout *layout)
-{
- const struct pipe_resource *templ = layout->templ;
-
- /*
- * From the Sandy Bridge PRM, volume 1 part 1, page 113:
- *
- * "surface format align_i align_j
- * YUV 4:2:2 formats 4 *see below
- * BC1-5 4 4
- * FXT1 8 4
- * all other formats 4 *see below"
- *
- * "- align_j = 4 for any depth buffer
- * - align_j = 2 for separate stencil buffer
- * - align_j = 4 for any render target surface is multisampled (4x)
- * - align_j = 4 for any render target surface with Surface Vertical
- * Alignment = VALIGN_4
- * - align_j = 2 for any render target surface with Surface Vertical
- * Alignment = VALIGN_2
- * - align_j = 2 for all other render target surface
- * - align_j = 2 for any sampling engine surface with Surface Vertical
- * Alignment = VALIGN_2
- * - align_j = 4 for any sampling engine surface with Surface Vertical
- * Alignment = VALIGN_4"
- *
- * From the Sandy Bridge PRM, volume 4 part 1, page 86:
- *
- * "This field (Surface Vertical Alignment) must be set to VALIGN_2 if
- * the Surface Format is 96 bits per element (BPE)."
- *
- * They can be rephrased as
- *
- * align_i align_j
- * compressed formats block width block height
- * PIPE_FORMAT_S8_UINT 4 2
- * other depth/stencil formats 4 4
- * 4x multisampled 4 4
- * bpp 96 4 2
- * others 4 2 or 4
- */
-
- /*
- * From the Ivy Bridge PRM, volume 1 part 1, page 110:
- *
- * "surface defined by surface format align_i align_j
- * 3DSTATE_DEPTH_BUFFER D16_UNORM 8 4
- * not D16_UNORM 4 4
- * 3DSTATE_STENCIL_BUFFER N/A 8 8
- * SURFACE_STATE BC*, ETC*, EAC* 4 4
- * FXT1 8 4
- * all others (set by SURFACE_STATE)"
- *
- * From the Ivy Bridge PRM, volume 4 part 1, page 63:
- *
- * "- This field (Surface Vertical Aligment) is intended to be set to
- * VALIGN_4 if the surface was rendered as a depth buffer, for a
- * multisampled (4x) render target, or for a multisampled (8x)
- * render target, since these surfaces support only alignment of 4.
- * - Use of VALIGN_4 for other surfaces is supported, but uses more
- * memory.
- * - This field must be set to VALIGN_4 for all tiled Y Render Target
- * surfaces.
- * - Value of 1 is not supported for format YCRCB_NORMAL (0x182),
- * YCRCB_SWAPUVY (0x183), YCRCB_SWAPUV (0x18f), YCRCB_SWAPY (0x190)
- * - If Number of Multisamples is not MULTISAMPLECOUNT_1, this field
- * must be set to VALIGN_4."
- * - VALIGN_4 is not supported for surface format R32G32B32_FLOAT."
- *
- * "- This field (Surface Horizontal Aligment) is intended to be set to
- * HALIGN_8 only if the surface was rendered as a depth buffer with
- * Z16 format or a stencil buffer, since these surfaces support only
- * alignment of 8.
- * - Use of HALIGN_8 for other surfaces is supported, but uses more
- * memory.
- * - This field must be set to HALIGN_4 if the Surface Format is BC*.
- * - This field must be set to HALIGN_8 if the Surface Format is
- * FXT1."
- *
- * They can be rephrased as
- *
- * align_i align_j
- * compressed formats block width block height
- * PIPE_FORMAT_Z16_UNORM 8 4
- * PIPE_FORMAT_S8_UINT 8 8
- * other depth/stencil formats 4 or 8 4
- * 2x or 4x multisampled 4 or 8 4
- * tiled Y 4 or 8 4 (if rt)
- * PIPE_FORMAT_R32G32B32_FLOAT 4 or 8 2
- * others 4 or 8 2 or 4
- */
-
- if (layout->compressed) {
- /* this happens to be the case */
- layout->align_i = layout->block_width;
- layout->align_j = layout->block_height;
- }
- else if (layout->has_depth || layout->has_stencil) {
- if (layout->dev->gen >= ILO_GEN(7)) {
- switch (layout->format) {
- case PIPE_FORMAT_Z16_UNORM:
- layout->align_i = 8;
- layout->align_j = 4;
- break;
- case PIPE_FORMAT_S8_UINT:
- layout->align_i = 8;
- layout->align_j = 8;
- break;
- default:
- layout->align_i = 4;
- layout->align_j = 4;
- break;
- }
- }
- else {
- switch (layout->format) {
- case PIPE_FORMAT_S8_UINT:
- layout->align_i = 4;
- layout->align_j = 2;
- break;
- default:
- layout->align_i = 4;
- layout->align_j = 4;
- break;
- }
- }
- }
- else {
- const bool valign_4 = (templ->nr_samples > 1) ||
- (layout->dev->gen >= ILO_GEN(7) &&
- layout->tiling == INTEL_TILING_Y &&
- (templ->bind & PIPE_BIND_RENDER_TARGET));
-
- if (valign_4)
- assert(layout->block_size != 12);
-
- layout->align_i = 4;
- layout->align_j = (valign_4) ? 4 : 2;
- }
-
- /*
- * the fact that align i and j are multiples of block width and height
- * respectively is what makes the size of the bo a multiple of the block
- * size, slices start at block boundaries, and many of the computations
- * work.
- */
- assert(layout->align_i % layout->block_width == 0);
- assert(layout->align_j % layout->block_height == 0);
-
- /* make sure align() works */
- assert(util_is_power_of_two(layout->align_i) &&
- util_is_power_of_two(layout->align_j));
- assert(util_is_power_of_two(layout->block_width) &&
- util_is_power_of_two(layout->block_height));
-}
-
-static void
-tex_layout_init_levels(struct tex_layout *layout)
-{
- const struct pipe_resource *templ = layout->templ;
- int last_level, lv;
-
- last_level = templ->last_level;
-
- /* need at least 2 levels to compute full qpitch */
- if (last_level == 0 && templ->array_size > 1 && layout->array_spacing_full)
- last_level++;
-
- /* compute mip level sizes */
- for (lv = 0; lv <= last_level; lv++) {
- int w, h, d;
-
- w = u_minify(templ->width0, lv);
- h = u_minify(templ->height0, lv);
- d = u_minify(templ->depth0, lv);
-
- /*
- * From the Sandy Bridge PRM, volume 1 part 1, page 114:
- *
- * "The dimensions of the mip maps are first determined by applying
- * the sizing algorithm presented in Non-Power-of-Two Mipmaps
- * above. Then, if necessary, they are padded out to compression
- * block boundaries."
- */
- w = align(w, layout->block_width);
- h = align(h, layout->block_height);
-
- /*
- * From the Sandy Bridge PRM, volume 1 part 1, page 111:
- *
- * "If the surface is multisampled (4x), these values must be
- * adjusted as follows before proceeding:
- *
- * W_L = ceiling(W_L / 2) * 4
- * H_L = ceiling(H_L / 2) * 4"
- *
- * From the Ivy Bridge PRM, volume 1 part 1, page 108:
- *
- * "If the surface is multisampled and it is a depth or stencil
- * surface or Multisampled Surface StorageFormat in SURFACE_STATE
- * is MSFMT_DEPTH_STENCIL, W_L and H_L must be adjusted as follows
- * before proceeding:
- *
- * #samples W_L = H_L =
- * 2 ceiling(W_L / 2) * 4 HL [no adjustment]
- * 4 ceiling(W_L / 2) * 4 ceiling(H_L / 2) * 4
- * 8 ceiling(W_L / 2) * 8 ceiling(H_L / 2) * 4
- * 16 ceiling(W_L / 2) * 8 ceiling(H_L / 2) * 8"
- *
- * For interleaved samples (4x), where pixels
- *
- * (x, y ) (x+1, y )
- * (x, y+1) (x+1, y+1)
- *
- * would be is occupied by
- *
- * (x, y , si0) (x+1, y , si0) (x, y , si1) (x+1, y , si1)
- * (x, y+1, si0) (x+1, y+1, si0) (x, y+1, si1) (x+1, y+1, si1)
- * (x, y , si2) (x+1, y , si2) (x, y , si3) (x+1, y , si3)
- * (x, y+1, si2) (x+1, y+1, si2) (x, y+1, si3) (x+1, y+1, si3)
- *
- * Thus the need to
- *
- * w = align(w, 2) * 2;
- * y = align(y, 2) * 2;
- */
- if (layout->interleaved) {
- switch (templ->nr_samples) {
- case 0:
- case 1:
- break;
- case 2:
- w = align(w, 2) * 2;
- break;
- case 4:
- w = align(w, 2) * 2;
- h = align(h, 2) * 2;
- break;
- case 8:
- w = align(w, 2) * 4;
- h = align(h, 2) * 2;
- break;
- case 16:
- w = align(w, 2) * 4;
- h = align(h, 2) * 4;
- break;
- default:
- assert(!"unsupported sample count");
- break;
- }
- }
-
- layout->levels[lv].w = w;
- layout->levels[lv].h = h;
- layout->levels[lv].d = d;
- }
-}
-
-static void
-tex_layout_init_spacing(struct tex_layout *layout)
-{
- const struct pipe_resource *templ = layout->templ;
-
- if (layout->dev->gen >= ILO_GEN(7)) {
- /*
- * It is not explicitly states, but render targets are expected to be
- * UMS/CMS (samples non-interleaved) and depth/stencil buffers are
- * expected to be IMS (samples interleaved).
- *
- * See "Multisampled Surface Storage Format" field of SURFACE_STATE.
- */
- if (layout->has_depth || layout->has_stencil) {
- layout->interleaved = true;
-
- /*
- * From the Ivy Bridge PRM, volume 1 part 1, page 111:
- *
- * "note that the depth buffer and stencil buffer have an implied
- * value of ARYSPC_FULL"
- */
- layout->array_spacing_full = true;
- }
- else {
- layout->interleaved = false;
-
- /*
- * From the Ivy Bridge PRM, volume 4 part 1, page 66:
- *
- * "If Multisampled Surface Storage Format is MSFMT_MSS and
- * Number of Multisamples is not MULTISAMPLECOUNT_1, this field
- * (Surface Array Spacing) must be set to ARYSPC_LOD0."
- *
- * As multisampled resources are not mipmapped, we never use
- * ARYSPC_FULL for them.
- */
- if (templ->nr_samples > 1)
- assert(templ->last_level == 0);
- layout->array_spacing_full = (templ->last_level > 0);
- }
- }
- else {
- /* GEN6 supports only interleaved samples */
- layout->interleaved = true;
-
- /*
- * From the Sandy Bridge PRM, volume 1 part 1, page 115:
- *
- * "The separate stencil buffer does not support mip mapping, thus
- * the storage for LODs other than LOD 0 is not needed. The
- * following QPitch equation applies only to the separate stencil
- * buffer:
- *
- * QPitch = h_0"
- *
- * GEN6 does not support compact spacing otherwise.
- */
- layout->array_spacing_full = (layout->format != PIPE_FORMAT_S8_UINT);
- }
-}
-
-static void
-tex_layout_init_tiling(struct tex_layout *layout)
-{
- const struct pipe_resource *templ = layout->templ;
- const enum pipe_format format = layout->format;
- const unsigned tile_none = 1 << INTEL_TILING_NONE;
- const unsigned tile_x = 1 << INTEL_TILING_X;
- const unsigned tile_y = 1 << INTEL_TILING_Y;
- unsigned valid_tilings = tile_none | tile_x | tile_y;
-
- /*
- * From the Sandy Bridge PRM, volume 1 part 2, page 32:
- *
- * "Display/Overlay Y-Major not supported.
- * X-Major required for Async Flips"
- */
- if (unlikely(templ->bind & PIPE_BIND_SCANOUT))
- valid_tilings &= tile_x;
-
- /*
- * From the Sandy Bridge PRM, volume 3 part 2, page 158:
- *
- * "The cursor surface address must be 4K byte aligned. The cursor must
- * be in linear memory, it cannot be tiled."
- */
- if (unlikely(templ->bind & (PIPE_BIND_CURSOR | PIPE_BIND_LINEAR)))
- valid_tilings &= tile_none;
-
- /*
- * From the Ivy Bridge PRM, volume 4 part 1, page 76:
- *
- * "The MCS surface must be stored as Tile Y."
- */
- if (templ->bind & ILO_BIND_MCS)
- valid_tilings &= tile_y;
-
- /*
- * From the Sandy Bridge PRM, volume 2 part 1, page 318:
- *
- * "[DevSNB+]: This field (Tiled Surface) must be set to TRUE. Linear
- * Depth Buffer is not supported."
- *
- * "The Depth Buffer, if tiled, must use Y-Major tiling."
- *
- * From the Sandy Bridge PRM, volume 1 part 2, page 22:
- *
- * "W-Major Tile Format is used for separate stencil."
- *
- * Since the HW does not support W-tiled fencing, we have to do it in the
- * driver.
- */
- if (templ->bind & PIPE_BIND_DEPTH_STENCIL) {
- switch (format) {
- case PIPE_FORMAT_S8_UINT:
- valid_tilings &= tile_none;