- switch (mt->target) {
- case GL_TEXTURE_CUBE_MAP:
- if (intel->gen >= 5) {
- GLuint align_h = 2;
- GLuint level;
- GLuint qpitch = 0;
- int h0, h1, q;
-
- /* On Ironlake, cube maps are finally represented as just a series
- * of MIPLAYOUT_BELOW 2D textures (like 2D texture arrays), separated
- * by a pitch of qpitch rows, where qpitch is defined by the equation
- * given in Volume 1 of the BSpec.
- */
- h0 = ALIGN(mt->height0, align_h);
- h1 = ALIGN(minify(h0), align_h);
- qpitch = (h0 + h1 + (intel->gen >= 7 ? 12 : 11) * align_h);
- if (mt->compressed)
- qpitch /= 4;
-
- i945_miptree_layout_2d(intel, mt, tiling, 6);
-
- for (level = mt->first_level; level <= mt->last_level; level++) {
- for (q = 0; q < 6; q++) {
- intel_miptree_set_image_offset(mt, level, q, 0, q * qpitch);
- }
- }
- mt->total_height = qpitch * 6;
-
- break;
+ if (mt->format == MESA_FORMAT_S_UINT8)
+ return 8;
+
+ if (brw->gen >= 7 && mt->format == MESA_FORMAT_Z_UNORM16)
+ return 8;
+
+ if (brw->gen == 8 && mt->mcs_mt && mt->num_samples <= 1)
+ return 16;
+
+ return 4;
+}
+
+static unsigned int
+intel_vertical_texture_alignment_unit(struct brw_context *brw,
+ mesa_format format, bool multisampled)
+{
+ /**
+ * From the "Alignment Unit Size" section of various specs, namely:
+ * - Gen3 Spec: "Memory Data Formats" Volume, Section 1.20.1.4
+ * - i965 and G45 PRMs: Volume 1, Section 6.17.3.4.
+ * - Ironlake and Sandybridge PRMs: Volume 1, Part 1, Section 7.18.3.4
+ * - BSpec (for Ivybridge and slight variations in separate stencil)
+ *
+ * +----------------------------------------------------------------------+
+ * | | alignment unit height ("j") |
+ * | Surface Property |-----------------------------|
+ * | | 915 | 965 | ILK | SNB | IVB |
+ * +----------------------------------------------------------------------+
+ * | BC1-5 compressed format (DXTn/S3TC) | 4 | 4 | 4 | 4 | 4 |
+ * | FXT1 compressed format | 4 | 4 | 4 | 4 | 4 |
+ * | Depth Buffer | 2 | 2 | 2 | 4 | 4 |
+ * | Separate Stencil Buffer | N/A | N/A | N/A | 4 | 8 |
+ * | Multisampled (4x or 8x) render target | N/A | N/A | N/A | 4 | 4 |
+ * | All Others | 2 | 2 | 2 | * | * |
+ * +----------------------------------------------------------------------+
+ *
+ * Where "*" means either VALIGN_2 or VALIGN_4 depending on the setting of
+ * the SURFACE_STATE "Surface Vertical Alignment" field.
+ */
+ if (_mesa_is_format_compressed(format))
+ return 4;
+
+ if (format == MESA_FORMAT_S_UINT8)
+ return brw->gen >= 7 ? 8 : 4;
+
+ /* Broadwell only supports VALIGN of 4, 8, and 16. The BSpec says 4
+ * should always be used, except for stencil buffers, which should be 8.
+ */
+ if (brw->gen >= 8)
+ return 4;
+
+ if (multisampled)
+ return 4;
+
+ GLenum base_format = _mesa_get_format_base_format(format);
+
+ if (brw->gen >= 6 &&
+ (base_format == GL_DEPTH_COMPONENT ||
+ base_format == GL_DEPTH_STENCIL)) {
+ return 4;
+ }
+
+ if (brw->gen == 7) {
+ /* On Gen7, we prefer a vertical alignment of 4 when possible, because
+ * that allows Y tiled render targets.
+ *
+ * From the Ivy Bridge PRM, Vol4 Part1 2.12.2.1 (SURFACE_STATE for most
+ * messages), on p64, under the heading "Surface Vertical Alignment":
+ *
+ * Value of 1 [VALIGN_4] is not supported for format YCRCB_NORMAL
+ * (0x182), YCRCB_SWAPUVY (0x183), YCRCB_SWAPUV (0x18f), YCRCB_SWAPY
+ * (0x190)
+ *
+ * VALIGN_4 is not supported for surface format R32G32B32_FLOAT.
+ */
+ if (base_format == GL_YCBCR_MESA || format == MESA_FORMAT_RGB_FLOAT32)
+ return 2;
+
+ return 4;
+ }
+
+ return 2;
+}
+
+static void
+gen9_miptree_layout_1d(struct intel_mipmap_tree *mt)
+{
+ unsigned x = 0;
+ unsigned width = mt->physical_width0;
+ unsigned depth = mt->physical_depth0; /* number of array layers. */
+
+ /* When this layout is used the horizontal alignment is fixed at 64 and the
+ * hardware ignores the value given in the surface state
+ */
+ const unsigned int align_w = 64;
+
+ mt->total_height = mt->physical_height0;
+ mt->total_width = 0;
+
+ for (unsigned level = mt->first_level; level <= mt->last_level; level++) {
+ unsigned img_width;
+
+ intel_miptree_set_level_info(mt, level, x, 0, depth);
+
+ img_width = ALIGN(width, align_w);
+
+ mt->total_width = MAX2(mt->total_width, x + img_width);
+
+ x += img_width;
+
+ width = minify(width, 1);
+ }
+}
+
+static void
+brw_miptree_layout_2d(struct intel_mipmap_tree *mt)
+{
+ unsigned x = 0;
+ unsigned y = 0;
+ unsigned width = mt->physical_width0;
+ unsigned height = mt->physical_height0;
+ unsigned depth = mt->physical_depth0; /* number of array layers. */
+
+ mt->total_width = mt->physical_width0;
+
+ if (mt->compressed) {
+ mt->total_width = ALIGN(mt->physical_width0, mt->align_w);
+ }
+
+ /* May need to adjust width to accomodate the placement of
+ * the 2nd mipmap. This occurs when the alignment
+ * constraints of mipmap placement push the right edge of the
+ * 2nd mipmap out past the width of its parent.
+ */
+ if (mt->first_level != mt->last_level) {
+ unsigned mip1_width;
+
+ if (mt->compressed) {
+ mip1_width = ALIGN(minify(mt->physical_width0, 1), mt->align_w) +
+ ALIGN(minify(mt->physical_width0, 2), mt->align_w);
+ } else {
+ mip1_width = ALIGN(minify(mt->physical_width0, 1), mt->align_w) +
+ minify(mt->physical_width0, 2);
+ }
+
+ if (mip1_width > mt->total_width) {
+ mt->total_width = mip1_width;
+ }
+ }
+
+ mt->total_height = 0;
+
+ for (unsigned level = mt->first_level; level <= mt->last_level; level++) {
+ unsigned img_height;
+
+ intel_miptree_set_level_info(mt, level, x, y, depth);
+
+ img_height = ALIGN(height, mt->align_h);
+ if (mt->compressed)
+ img_height /= mt->align_h;
+
+ if (mt->array_layout == ALL_SLICES_AT_EACH_LOD) {
+ /* Compact arrays with separated miplevels */
+ img_height *= depth;