Subversion Repositories Kolibri OS

Rev

Rev 4358 | 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, bool multisampled)
  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.    if (_mesa_is_format_compressed(format))
  123.       return 4;
  124.  
  125.    if (format == MESA_FORMAT_S8)
  126.       return brw->gen >= 7 ? 8 : 4;
  127.  
  128.    if (multisampled)
  129.       return 4;
  130.  
  131.    GLenum base_format = _mesa_get_format_base_format(format);
  132.  
  133.    if (brw->gen >= 6 &&
  134.        (base_format == GL_DEPTH_COMPONENT ||
  135.         base_format == GL_DEPTH_STENCIL)) {
  136.       return 4;
  137.    }
  138.  
  139.    return 2;
  140. }
  141.  
  142. static void
  143. brw_miptree_layout_2d(struct intel_mipmap_tree *mt)
  144. {
  145.    unsigned x = 0;
  146.    unsigned y = 0;
  147.    unsigned width = mt->physical_width0;
  148.    unsigned height = mt->physical_height0;
  149.    unsigned depth = mt->physical_depth0; /* number of array layers. */
  150.  
  151.    mt->total_width = mt->physical_width0;
  152.  
  153.    if (mt->compressed) {
  154.        mt->total_width = ALIGN(mt->physical_width0, mt->align_w);
  155.    }
  156.  
  157.    /* May need to adjust width to accomodate the placement of
  158.     * the 2nd mipmap.  This occurs when the alignment
  159.     * constraints of mipmap placement push the right edge of the
  160.     * 2nd mipmap out past the width of its parent.
  161.     */
  162.    if (mt->first_level != mt->last_level) {
  163.        unsigned mip1_width;
  164.  
  165.        if (mt->compressed) {
  166.           mip1_width = ALIGN(minify(mt->physical_width0, 1), mt->align_w) +
  167.              ALIGN(minify(mt->physical_width0, 2), mt->align_w);
  168.        } else {
  169.           mip1_width = ALIGN(minify(mt->physical_width0, 1), mt->align_w) +
  170.              minify(mt->physical_width0, 2);
  171.        }
  172.  
  173.        if (mip1_width > mt->total_width) {
  174.            mt->total_width = mip1_width;
  175.        }
  176.    }
  177.  
  178.    mt->total_height = 0;
  179.  
  180.    for (unsigned level = mt->first_level; level <= mt->last_level; level++) {
  181.       unsigned img_height;
  182.  
  183.       intel_miptree_set_level_info(mt, level, x, y, width,
  184.                                    height, depth);
  185.  
  186.       img_height = ALIGN(height, mt->align_h);
  187.       if (mt->compressed)
  188.          img_height /= mt->align_h;
  189.  
  190.       /* Because the images are packed better, the final offset
  191.        * might not be the maximal one:
  192.        */
  193.       mt->total_height = MAX2(mt->total_height, y + img_height);
  194.  
  195.       /* Layout_below: step right after second mipmap.
  196.        */
  197.       if (level == mt->first_level + 1) {
  198.          x += ALIGN(width, mt->align_w);
  199.       } else {
  200.          y += img_height;
  201.       }
  202.  
  203.       width  = minify(width, 1);
  204.       height = minify(height, 1);
  205.    }
  206. }
  207.  
  208. static void
  209. align_cube(struct intel_mipmap_tree *mt)
  210. {
  211.    /* The 965's sampler lays cachelines out according to how accesses
  212.     * in the texture surfaces run, so they may be "vertical" through
  213.     * memory.  As a result, the docs say in Surface Padding Requirements:
  214.     * Sampling Engine Surfaces that two extra rows of padding are required.
  215.     */
  216.    if (mt->target == GL_TEXTURE_CUBE_MAP)
  217.       mt->total_height += 2;
  218. }
  219.  
  220. static void
  221. brw_miptree_layout_texture_array(struct brw_context *brw,
  222.                                  struct intel_mipmap_tree *mt)
  223. {
  224.    unsigned qpitch = 0;
  225.    int h0, h1;
  226.  
  227.    h0 = ALIGN(mt->physical_height0, mt->align_h);
  228.    h1 = ALIGN(minify(mt->physical_height0, 1), mt->align_h);
  229.    if (mt->array_spacing_lod0)
  230.       qpitch = h0;
  231.    else
  232.       qpitch = (h0 + h1 + (brw->gen >= 7 ? 12 : 11) * mt->align_h);
  233.    if (mt->compressed)
  234.       qpitch /= 4;
  235.  
  236.    brw_miptree_layout_2d(mt);
  237.  
  238.    for (unsigned level = mt->first_level; level <= mt->last_level; level++) {
  239.       for (int q = 0; q < mt->physical_depth0; q++) {
  240.          intel_miptree_set_image_offset(mt, level, q, 0, q * qpitch);
  241.       }
  242.    }
  243.    mt->total_height = qpitch * mt->physical_depth0;
  244.  
  245.    align_cube(mt);
  246. }
  247.  
  248. static void
  249. brw_miptree_layout_texture_3d(struct brw_context *brw,
  250.                               struct intel_mipmap_tree *mt)
  251. {
  252.    unsigned yscale = mt->compressed ? 4 : 1;
  253.  
  254.    mt->total_width = 0;
  255.    mt->total_height = 0;
  256.  
  257.    unsigned ysum = 0;
  258.    for (unsigned level = mt->first_level; level <= mt->last_level; level++) {
  259.       unsigned WL = MAX2(mt->physical_width0 >> level, 1);
  260.       unsigned HL = MAX2(mt->physical_height0 >> level, 1);
  261.       unsigned DL = MAX2(mt->physical_depth0 >> level, 1);
  262.       unsigned wL = ALIGN(WL, mt->align_w);
  263.       unsigned hL = ALIGN(HL, mt->align_h);
  264.  
  265.       if (mt->target == GL_TEXTURE_CUBE_MAP)
  266.          DL = 6;
  267.  
  268.       intel_miptree_set_level_info(mt, level, 0, 0, WL, HL, DL);
  269.  
  270.       for (unsigned q = 0; q < DL; q++) {
  271.          unsigned x = (q % (1 << level)) * wL;
  272.          unsigned y = ysum + (q >> level) * hL;
  273.  
  274.          intel_miptree_set_image_offset(mt, level, q, x, y / yscale);
  275.          mt->total_width = MAX2(mt->total_width, x + wL);
  276.          mt->total_height = MAX2(mt->total_height, (y + hL) / yscale);
  277.       }
  278.  
  279.       ysum += ALIGN(DL, 1 << level) / (1 << level) * hL;
  280.    }
  281.  
  282.    align_cube(mt);
  283. }
  284.  
  285. void
  286. brw_miptree_layout(struct brw_context *brw, struct intel_mipmap_tree *mt)
  287. {
  288.    bool multisampled = mt->num_samples > 1;
  289.    mt->align_w = intel_horizontal_texture_alignment_unit(brw, mt->format);
  290.    mt->align_h =
  291.       intel_vertical_texture_alignment_unit(brw, mt->format, multisampled);
  292.  
  293.    switch (mt->target) {
  294.    case GL_TEXTURE_CUBE_MAP:
  295.       if (brw->gen == 4) {
  296.          /* Gen4 stores cube maps as 3D textures. */
  297.          assert(mt->physical_depth0 == 6);
  298.          brw_miptree_layout_texture_3d(brw, mt);
  299.       } else {
  300.          /* All other hardware stores cube maps as 2D arrays. */
  301.          brw_miptree_layout_texture_array(brw, mt);
  302.       }
  303.       break;
  304.  
  305.    case GL_TEXTURE_3D:
  306.       brw_miptree_layout_texture_3d(brw, mt);
  307.       break;
  308.  
  309.    case GL_TEXTURE_1D_ARRAY:
  310.    case GL_TEXTURE_2D_ARRAY:
  311.    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
  312.    case GL_TEXTURE_CUBE_MAP_ARRAY:
  313.       brw_miptree_layout_texture_array(brw, mt);
  314.       break;
  315.  
  316.    default:
  317.       switch (mt->msaa_layout) {
  318.       case INTEL_MSAA_LAYOUT_UMS:
  319.       case INTEL_MSAA_LAYOUT_CMS:
  320.          brw_miptree_layout_texture_array(brw, mt);
  321.          break;
  322.       case INTEL_MSAA_LAYOUT_NONE:
  323.       case INTEL_MSAA_LAYOUT_IMS:
  324.          brw_miptree_layout_2d(mt);
  325.          break;
  326.       }
  327.       break;
  328.    }
  329.    DBG("%s: %dx%dx%d\n", __FUNCTION__,
  330.        mt->total_width, mt->total_height, mt->cpp);
  331. }
  332.  
  333.