Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
  3.  * Copyright © 2006 Intel Corporation
  4.  *
  5.  * Permission is hereby granted, free of charge, to any person obtaining
  6.  * a copy of this software and associated documentation files (the
  7.  * "Software"), to deal in the Software without restriction, including
  8.  * without limitation the rights to use, copy, modify, merge, publish,
  9.  * distribute, sublicense, and/or sell copies of the Software, and to
  10.  * permit persons to whom the Software is furnished to do so, subject to
  11.  * the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice (including the
  14.  * next paragraph) shall be included in all copies or substantial
  15.  * portions of the Software.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  20.  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
  21.  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  22.  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  23.  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24.  */
  25.  
  26. /**
  27.  * \file brw_tex_layout.cpp
  28.  *
  29.  * Code to lay out images in a mipmap tree.
  30.  *
  31.  * \author Keith Whitwell <keith@tungstengraphics.com>
  32.  * \author Michel Dänzer <michel@tungstengraphics.com>
  33.  */
  34.  
  35. #include "intel_mipmap_tree.h"
  36. #include "brw_context.h"
  37. #include "main/macros.h"
  38.  
  39. #define FILE_DEBUG_FLAG DEBUG_MIPTREE
  40.  
  41. static unsigned int
  42. intel_horizontal_texture_alignment_unit(struct brw_context *brw,
  43.                                        gl_format format)
  44. {
  45.    /**
  46.     * From the "Alignment Unit Size" section of various specs, namely:
  47.     * - Gen3 Spec: "Memory Data Formats" Volume,         Section 1.20.1.4
  48.     * - i965 and G45 PRMs:             Volume 1,         Section 6.17.3.4.
  49.     * - Ironlake and Sandybridge PRMs: Volume 1, Part 1, Section 7.18.3.4
  50.     * - BSpec (for Ivybridge and slight variations in separate stencil)
  51.     *
  52.     * +----------------------------------------------------------------------+
  53.     * |                                        | alignment unit width  ("i") |
  54.     * | Surface Property                       |-----------------------------|
  55.     * |                                        | 915 | 965 | ILK | SNB | IVB |
  56.     * +----------------------------------------------------------------------+
  57.     * | YUV 4:2:2 format                       |  8  |  4  |  4  |  4  |  4  |
  58.     * | BC1-5 compressed format (DXTn/S3TC)    |  4  |  4  |  4  |  4  |  4  |
  59.     * | FXT1  compressed format                |  8  |  8  |  8  |  8  |  8  |
  60.     * | Depth Buffer (16-bit)                  |  4  |  4  |  4  |  4  |  8  |
  61.     * | Depth Buffer (other)                   |  4  |  4  |  4  |  4  |  4  |
  62.     * | Separate Stencil Buffer                | N/A | N/A |  8  |  8  |  8  |
  63.     * | All Others                             |  4  |  4  |  4  |  4  |  4  |
  64.     * +----------------------------------------------------------------------+
  65.     *
  66.     * On IVB+, non-special cases can be overridden by setting the SURFACE_STATE
  67.     * "Surface Horizontal Alignment" field to HALIGN_4 or HALIGN_8.
  68.     */
  69.     if (_mesa_is_format_compressed(format)) {
  70.        /* The hardware alignment requirements for compressed textures
  71.         * happen to match the block boundaries.
  72.         */
  73.       unsigned int i, j;
  74.       _mesa_get_format_block_size(format, &i, &j);
  75.       return i;
  76.     }
  77.  
  78.    if (format == MESA_FORMAT_S8)
  79.       return 8;
  80.  
  81.    /* The depth alignment requirements in the table above are for rendering to
  82.     * depth miplevels using the LOD control fields.  We don't use LOD control
  83.     * fields, and instead use page offsets plus intra-tile x/y offsets, which
  84.     * require that the low 3 bits are zero.  To reduce the number of x/y
  85.     * offset workaround blits we do, align the X to 8, which depth texturing
  86.     * can handle (sadly, it can't handle 8 in the Y direction).
  87.     */
  88.    if (brw->gen >= 7 &&
  89.        _mesa_get_format_base_format(format) == GL_DEPTH_COMPONENT)
  90.       return 8;
  91.  
  92.    return 4;
  93. }
  94.  
  95. static unsigned int
  96. intel_vertical_texture_alignment_unit(struct brw_context *brw,
  97.                                      gl_format format)
  98. {
  99.    /**
  100.     * From the "Alignment Unit Size" section of various specs, namely:
  101.     * - Gen3 Spec: "Memory Data Formats" Volume,         Section 1.20.1.4
  102.     * - i965 and G45 PRMs:             Volume 1,         Section 6.17.3.4.
  103.     * - Ironlake and Sandybridge PRMs: Volume 1, Part 1, Section 7.18.3.4
  104.     * - BSpec (for Ivybridge and slight variations in separate stencil)
  105.     *
  106.     * +----------------------------------------------------------------------+
  107.     * |                                        | alignment unit height ("j") |
  108.     * | Surface Property                       |-----------------------------|
  109.     * |                                        | 915 | 965 | ILK | SNB | IVB |
  110.     * +----------------------------------------------------------------------+
  111.     * | BC1-5 compressed format (DXTn/S3TC)    |  4  |  4  |  4  |  4  |  4  |
  112.     * | FXT1  compressed format                |  4  |  4  |  4  |  4  |  4  |
  113.     * | Depth Buffer                           |  2  |  2  |  2  |  4  |  4  |
  114.     * | Separate Stencil Buffer                | N/A | N/A | N/A |  4  |  8  |
  115.     * | Multisampled (4x or 8x) render target  | N/A | N/A | N/A |  4  |  4  |
  116.     * | All Others                             |  2  |  2  |  2  |  2  |  2  |
  117.     * +----------------------------------------------------------------------+
  118.     *
  119.     * On SNB+, non-special cases can be overridden by setting the SURFACE_STATE
  120.     * "Surface Vertical Alignment" field to VALIGN_2 or VALIGN_4.
  121.     *
  122.     * We currently don't support multisampling.
  123.     */
  124.    if (_mesa_is_format_compressed(format))
  125.       return 4;
  126.  
  127.    if (format == MESA_FORMAT_S8)
  128.       return brw->gen >= 7 ? 8 : 4;
  129.  
  130.    GLenum base_format = _mesa_get_format_base_format(format);
  131.  
  132.    if (brw->gen >= 6 &&
  133.        (base_format == GL_DEPTH_COMPONENT ||
  134.         base_format == GL_DEPTH_STENCIL)) {
  135.       return 4;
  136.    }
  137.  
  138.    return 2;
  139. }
  140.  
  141. static void
  142. brw_miptree_layout_2d(struct intel_mipmap_tree *mt)
  143. {
  144.    unsigned x = 0;
  145.    unsigned y = 0;
  146.    unsigned width = mt->physical_width0;
  147.    unsigned height = mt->physical_height0;
  148.    unsigned depth = mt->physical_depth0; /* number of array layers. */
  149.  
  150.    mt->total_width = mt->physical_width0;
  151.  
  152.    if (mt->compressed) {
  153.        mt->total_width = ALIGN(mt->physical_width0, mt->align_w);
  154.    }
  155.  
  156.    /* May need to adjust width to accomodate the placement of
  157.     * the 2nd mipmap.  This occurs when the alignment
  158.     * constraints of mipmap placement push the right edge of the
  159.     * 2nd mipmap out past the width of its parent.
  160.     */
  161.    if (mt->first_level != mt->last_level) {
  162.        unsigned mip1_width;
  163.  
  164.        if (mt->compressed) {
  165.           mip1_width = ALIGN(minify(mt->physical_width0, 1), mt->align_w) +
  166.              ALIGN(minify(mt->physical_width0, 2), mt->align_w);
  167.        } else {
  168.           mip1_width = ALIGN(minify(mt->physical_width0, 1), mt->align_w) +
  169.              minify(mt->physical_width0, 2);
  170.        }
  171.  
  172.        if (mip1_width > mt->total_width) {
  173.            mt->total_width = mip1_width;
  174.        }
  175.    }
  176.  
  177.    mt->total_height = 0;
  178.  
  179.    for (unsigned level = mt->first_level; level <= mt->last_level; level++) {
  180.       unsigned img_height;
  181.  
  182.       intel_miptree_set_level_info(mt, level, x, y, width,
  183.                                    height, depth);
  184.  
  185.       img_height = ALIGN(height, mt->align_h);
  186.       if (mt->compressed)
  187.          img_height /= mt->align_h;
  188.  
  189.       /* Because the images are packed better, the final offset
  190.        * might not be the maximal one:
  191.        */
  192.       mt->total_height = MAX2(mt->total_height, y + img_height);
  193.  
  194.       /* Layout_below: step right after second mipmap.
  195.        */
  196.       if (level == mt->first_level + 1) {
  197.          x += ALIGN(width, mt->align_w);
  198.       } else {
  199.          y += img_height;
  200.       }
  201.  
  202.       width  = minify(width, 1);
  203.       height = minify(height, 1);
  204.    }
  205. }
  206.  
  207. static void
  208. align_cube(struct intel_mipmap_tree *mt)
  209. {
  210.    /* The 965's sampler lays cachelines out according to how accesses
  211.     * in the texture surfaces run, so they may be "vertical" through
  212.     * memory.  As a result, the docs say in Surface Padding Requirements:
  213.     * Sampling Engine Surfaces that two extra rows of padding are required.
  214.     */
  215.    if (mt->target == GL_TEXTURE_CUBE_MAP)
  216.       mt->total_height += 2;
  217. }
  218.  
  219. static void
  220. brw_miptree_layout_texture_array(struct brw_context *brw,
  221.                                  struct intel_mipmap_tree *mt)
  222. {
  223.    unsigned qpitch = 0;
  224.    int h0, h1;
  225.  
  226.    h0 = ALIGN(mt->physical_height0, mt->align_h);
  227.    h1 = ALIGN(minify(mt->physical_height0, 1), mt->align_h);
  228.    if (mt->array_spacing_lod0)
  229.       qpitch = h0;
  230.    else
  231.       qpitch = (h0 + h1 + (brw->gen >= 7 ? 12 : 11) * mt->align_h);
  232.    if (mt->compressed)
  233.       qpitch /= 4;
  234.  
  235.    brw_miptree_layout_2d(mt);
  236.  
  237.    for (unsigned level = mt->first_level; level <= mt->last_level; level++) {
  238.       for (int q = 0; q < mt->physical_depth0; q++) {
  239.          intel_miptree_set_image_offset(mt, level, q, 0, q * qpitch);
  240.       }
  241.    }
  242.    mt->total_height = qpitch * mt->physical_depth0;
  243.  
  244.    align_cube(mt);
  245. }
  246.  
  247. static void
  248. brw_miptree_layout_texture_3d(struct brw_context *brw,
  249.                               struct intel_mipmap_tree *mt)
  250. {
  251.    unsigned yscale = mt->compressed ? 4 : 1;
  252.  
  253.    mt->total_width = 0;
  254.    mt->total_height = 0;
  255.  
  256.    unsigned ysum = 0;
  257.    for (unsigned level = mt->first_level; level <= mt->last_level; level++) {
  258.       unsigned WL = MAX2(mt->physical_width0 >> level, 1);
  259.       unsigned HL = MAX2(mt->physical_height0 >> level, 1);
  260.       unsigned DL = MAX2(mt->physical_depth0 >> level, 1);
  261.       unsigned wL = ALIGN(WL, mt->align_w);
  262.       unsigned hL = ALIGN(HL, mt->align_h);
  263.  
  264.       if (mt->target == GL_TEXTURE_CUBE_MAP)
  265.          DL = 6;
  266.  
  267.       intel_miptree_set_level_info(mt, level, 0, 0, WL, HL, DL);
  268.  
  269.       for (unsigned q = 0; q < DL; q++) {
  270.          unsigned x = (q % (1 << level)) * wL;
  271.          unsigned y = ysum + (q >> level) * hL;
  272.  
  273.          intel_miptree_set_image_offset(mt, level, q, x, y / yscale);
  274.          mt->total_width = MAX2(mt->total_width, x + wL);
  275.          mt->total_height = MAX2(mt->total_height, (y + hL) / yscale);
  276.       }
  277.  
  278.       ysum += ALIGN(DL, 1 << level) / (1 << level) * hL;
  279.    }
  280.  
  281.    align_cube(mt);
  282. }
  283.  
  284. void
  285. brw_miptree_layout(struct brw_context *brw, struct intel_mipmap_tree *mt)
  286. {
  287.    mt->align_w = intel_horizontal_texture_alignment_unit(brw, mt->format);
  288.    mt->align_h = intel_vertical_texture_alignment_unit(brw, mt->format);
  289.  
  290.    switch (mt->target) {
  291.    case GL_TEXTURE_CUBE_MAP:
  292.       if (brw->gen == 4) {
  293.          /* Gen4 stores cube maps as 3D textures. */
  294.          assert(mt->physical_depth0 == 6);
  295.          brw_miptree_layout_texture_3d(brw, mt);
  296.       } else {
  297.          /* All other hardware stores cube maps as 2D arrays. */
  298.          brw_miptree_layout_texture_array(brw, mt);
  299.       }
  300.       break;
  301.  
  302.    case GL_TEXTURE_3D:
  303.       brw_miptree_layout_texture_3d(brw, mt);
  304.       break;
  305.  
  306.    case GL_TEXTURE_1D_ARRAY:
  307.    case GL_TEXTURE_2D_ARRAY:
  308.    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
  309.    case GL_TEXTURE_CUBE_MAP_ARRAY:
  310.       brw_miptree_layout_texture_array(brw, mt);
  311.       break;
  312.  
  313.    default:
  314.       switch (mt->msaa_layout) {
  315.       case INTEL_MSAA_LAYOUT_UMS:
  316.       case INTEL_MSAA_LAYOUT_CMS:
  317.          brw_miptree_layout_texture_array(brw, mt);
  318.          break;
  319.       case INTEL_MSAA_LAYOUT_NONE:
  320.       case INTEL_MSAA_LAYOUT_IMS:
  321.          brw_miptree_layout_2d(mt);
  322.          break;
  323.       }
  324.       break;
  325.    }
  326.    DBG("%s: %dx%dx%d\n", __FUNCTION__,
  327.        mt->total_width, mt->total_height, mt->cpp);
  328. }
  329.  
  330.