1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2016 Intel Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci *  Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci *  copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci *  to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci *  and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci *  Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci *  The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci *  paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci *  Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci *  IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#ifndef ISL_SURFACE_STATE_H
25bf215546Sopenharmony_ci#define ISL_SURFACE_STATE_H
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include <stdint.h>
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci/**
30bf215546Sopenharmony_ci * @file isl_surface_state.h
31bf215546Sopenharmony_ci *
32bf215546Sopenharmony_ci * ============================= GENXML CODE =============================
33bf215546Sopenharmony_ci *              [This file is compiled once per generation.]
34bf215546Sopenharmony_ci * =======================================================================
35bf215546Sopenharmony_ci *
36bf215546Sopenharmony_ci * Helpers for encoding SURFACE_STATE and XY_BLOCK_COPY_BLT commands.
37bf215546Sopenharmony_ci */
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_ciUNUSED static const uint8_t
40bf215546Sopenharmony_ciisl_encode_halign(uint8_t halign)
41bf215546Sopenharmony_ci{
42bf215546Sopenharmony_ci   switch (halign) {
43bf215546Sopenharmony_ci#if GFX_VERx10 >= 125
44bf215546Sopenharmony_ci   case  16: return HALIGN_16;
45bf215546Sopenharmony_ci   case  32: return HALIGN_32;
46bf215546Sopenharmony_ci   case  64: return HALIGN_64;
47bf215546Sopenharmony_ci   case 128: return HALIGN_128;
48bf215546Sopenharmony_ci#elif GFX_VER >= 8
49bf215546Sopenharmony_ci   case   4: return HALIGN_4;
50bf215546Sopenharmony_ci   case   8: return HALIGN_8;
51bf215546Sopenharmony_ci   case  16: return HALIGN_16;
52bf215546Sopenharmony_ci#elif GFX_VER >= 7
53bf215546Sopenharmony_ci   case   4: return HALIGN_4;
54bf215546Sopenharmony_ci   case   8: return HALIGN_8;
55bf215546Sopenharmony_ci#endif
56bf215546Sopenharmony_ci   default: unreachable("Invalid halign");
57bf215546Sopenharmony_ci   }
58bf215546Sopenharmony_ci}
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_ciUNUSED static const uint8_t
61bf215546Sopenharmony_ciisl_encode_valign(uint8_t valign)
62bf215546Sopenharmony_ci{
63bf215546Sopenharmony_ci   switch (valign) {
64bf215546Sopenharmony_ci#if GFX_VER >= 8
65bf215546Sopenharmony_ci   case   4: return VALIGN_4;
66bf215546Sopenharmony_ci   case   8: return VALIGN_8;
67bf215546Sopenharmony_ci   case  16: return VALIGN_16;
68bf215546Sopenharmony_ci#elif GFX_VER >= 6
69bf215546Sopenharmony_ci   case   2: return VALIGN_2;
70bf215546Sopenharmony_ci   case   4: return VALIGN_4;
71bf215546Sopenharmony_ci#endif
72bf215546Sopenharmony_ci   default: unreachable("Invalid valign");
73bf215546Sopenharmony_ci   }
74bf215546Sopenharmony_ci}
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci/**
77bf215546Sopenharmony_ci * Get the horizontal and vertical alignment in the units expected by the
78bf215546Sopenharmony_ci * hardware.  Note that this does NOT give you the actual hardware enum values
79bf215546Sopenharmony_ci * but an index into the isl_encode_[hv]align arrays above.
80bf215546Sopenharmony_ci */
81bf215546Sopenharmony_ciUNUSED static struct isl_extent3d
82bf215546Sopenharmony_ciisl_get_image_alignment(const struct isl_surf *surf)
83bf215546Sopenharmony_ci{
84bf215546Sopenharmony_ci   if (GFX_VERx10 >= 125) {
85bf215546Sopenharmony_ci      if (surf->tiling == ISL_TILING_64) {
86bf215546Sopenharmony_ci         /* The hardware ignores the alignment values. Anyway, the surface's
87bf215546Sopenharmony_ci          * true alignment is likely outside the enum range of HALIGN* and
88bf215546Sopenharmony_ci          * VALIGN*.
89bf215546Sopenharmony_ci          */
90bf215546Sopenharmony_ci         return isl_extent3d(128, 4, 1);
91bf215546Sopenharmony_ci      } else if (isl_format_get_layout(surf->format)->bpb % 3 == 0) {
92bf215546Sopenharmony_ci         /* On XeHP, RENDER_SURFACE_STATE.SurfaceHorizontalAlignment is in
93bf215546Sopenharmony_ci          * units of elements for 24, 48, and 96 bpb formats.
94bf215546Sopenharmony_ci          */
95bf215546Sopenharmony_ci         return isl_surf_get_image_alignment_el(surf);
96bf215546Sopenharmony_ci      } else {
97bf215546Sopenharmony_ci         /* On XeHP, RENDER_SURFACE_STATE.SurfaceHorizontalAlignment is in
98bf215546Sopenharmony_ci          * units of bytes for formats that are powers of two.
99bf215546Sopenharmony_ci          */
100bf215546Sopenharmony_ci         const uint32_t bs = isl_format_get_layout(surf->format)->bpb / 8;
101bf215546Sopenharmony_ci         return isl_extent3d(surf->image_alignment_el.w * bs,
102bf215546Sopenharmony_ci                             surf->image_alignment_el.h,
103bf215546Sopenharmony_ci                             surf->image_alignment_el.d);
104bf215546Sopenharmony_ci      }
105bf215546Sopenharmony_ci   } else if (GFX_VER >= 9) {
106bf215546Sopenharmony_ci      if (isl_tiling_is_std_y(surf->tiling) ||
107bf215546Sopenharmony_ci          surf->dim_layout == ISL_DIM_LAYOUT_GFX9_1D) {
108bf215546Sopenharmony_ci         /* The hardware ignores the alignment values. Anyway, the surface's
109bf215546Sopenharmony_ci          * true alignment is likely outside the enum range of HALIGN* and
110bf215546Sopenharmony_ci          * VALIGN*.
111bf215546Sopenharmony_ci          */
112bf215546Sopenharmony_ci         return isl_extent3d(4, 4, 1);
113bf215546Sopenharmony_ci      } else {
114bf215546Sopenharmony_ci         /* In Skylake, RENDER_SUFFACE_STATE.SurfaceVerticalAlignment is in units
115bf215546Sopenharmony_ci          * of surface elements (not pixels nor samples). For compressed formats,
116bf215546Sopenharmony_ci          * a "surface element" is defined as a compression block.  For example,
117bf215546Sopenharmony_ci          * if SurfaceVerticalAlignment is VALIGN_4 and SurfaceFormat is an ETC2
118bf215546Sopenharmony_ci          * format (ETC2 has a block height of 4), then the vertical alignment is
119bf215546Sopenharmony_ci          * 4 compression blocks or, equivalently, 16 pixels.
120bf215546Sopenharmony_ci          */
121bf215546Sopenharmony_ci         return isl_surf_get_image_alignment_el(surf);
122bf215546Sopenharmony_ci      }
123bf215546Sopenharmony_ci   } else {
124bf215546Sopenharmony_ci      /* Pre-Skylake, RENDER_SUFFACE_STATE.SurfaceVerticalAlignment is in
125bf215546Sopenharmony_ci       * units of surface samples.  For example, if SurfaceVerticalAlignment
126bf215546Sopenharmony_ci       * is VALIGN_4 and the surface is singlesampled, then for any surface
127bf215546Sopenharmony_ci       * format (compressed or not) the vertical alignment is
128bf215546Sopenharmony_ci       * 4 pixels.
129bf215546Sopenharmony_ci       */
130bf215546Sopenharmony_ci      return isl_surf_get_image_alignment_sa(surf);
131bf215546Sopenharmony_ci   }
132bf215546Sopenharmony_ci}
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ciUNUSED static uint32_t
135bf215546Sopenharmony_ciisl_get_qpitch(const struct isl_surf *surf)
136bf215546Sopenharmony_ci{
137bf215546Sopenharmony_ci   switch (surf->dim_layout) {
138bf215546Sopenharmony_ci   default:
139bf215546Sopenharmony_ci      unreachable("Bad isl_surf_dim");
140bf215546Sopenharmony_ci   case ISL_DIM_LAYOUT_GFX4_2D:
141bf215546Sopenharmony_ci      if (GFX_VER >= 9) {
142bf215546Sopenharmony_ci         if (surf->dim == ISL_SURF_DIM_3D && surf->tiling == ISL_TILING_W) {
143bf215546Sopenharmony_ci            /* This is rather annoying and completely undocumented.  It
144bf215546Sopenharmony_ci             * appears that the hardware has a bug (or undocumented feature)
145bf215546Sopenharmony_ci             * regarding stencil buffers most likely related to the way
146bf215546Sopenharmony_ci             * W-tiling is handled as modified Y-tiling.  If you bind a 3-D
147bf215546Sopenharmony_ci             * stencil buffer normally, and use texelFetch on it, the z or
148bf215546Sopenharmony_ci             * array index will get implicitly multiplied by 2 for no obvious
149bf215546Sopenharmony_ci             * reason.  The fix appears to be to divide qpitch by 2 for
150bf215546Sopenharmony_ci             * W-tiled surfaces.
151bf215546Sopenharmony_ci             */
152bf215546Sopenharmony_ci            return isl_surf_get_array_pitch_el_rows(surf) / 2;
153bf215546Sopenharmony_ci         } else {
154bf215546Sopenharmony_ci            return isl_surf_get_array_pitch_el_rows(surf);
155bf215546Sopenharmony_ci         }
156bf215546Sopenharmony_ci      } else {
157bf215546Sopenharmony_ci         /* From the Broadwell PRM for RENDER_SURFACE_STATE.QPitch
158bf215546Sopenharmony_ci          *
159bf215546Sopenharmony_ci          *    "This field must be set to an integer multiple of the Surface
160bf215546Sopenharmony_ci          *    Vertical Alignment. For compressed textures (BC*, FXT1,
161bf215546Sopenharmony_ci          *    ETC*, and EAC* Surface Formats), this field is in units of
162bf215546Sopenharmony_ci          *    rows in the uncompressed surface, and must be set to an
163bf215546Sopenharmony_ci          *    integer multiple of the vertical alignment parameter "j"
164bf215546Sopenharmony_ci          *    defined in the Common Surface Formats section."
165bf215546Sopenharmony_ci          */
166bf215546Sopenharmony_ci         return isl_surf_get_array_pitch_sa_rows(surf);
167bf215546Sopenharmony_ci      }
168bf215546Sopenharmony_ci   case ISL_DIM_LAYOUT_GFX9_1D:
169bf215546Sopenharmony_ci      /* QPitch is usually expressed as rows of surface elements (where
170bf215546Sopenharmony_ci       * a surface element is an compression block or a single surface
171bf215546Sopenharmony_ci       * sample). Skylake 1D is an outlier.
172bf215546Sopenharmony_ci       *
173bf215546Sopenharmony_ci       * From the Skylake BSpec >> Memory Views >> Common Surface
174bf215546Sopenharmony_ci       * Formats >> Surface Layout and Tiling >> 1D Surfaces:
175bf215546Sopenharmony_ci       *
176bf215546Sopenharmony_ci       *    Surface QPitch specifies the distance in pixels between array
177bf215546Sopenharmony_ci       *    slices.
178bf215546Sopenharmony_ci       */
179bf215546Sopenharmony_ci      return isl_surf_get_array_pitch_el(surf);
180bf215546Sopenharmony_ci   case ISL_DIM_LAYOUT_GFX4_3D:
181bf215546Sopenharmony_ci      /* QPitch doesn't make sense for ISL_DIM_LAYOUT_GFX4_3D since it uses a
182bf215546Sopenharmony_ci       * different pitch at each LOD.  Also, the QPitch field is ignored for
183bf215546Sopenharmony_ci       * these surfaces.  From the Broadwell PRM documentation for QPitch:
184bf215546Sopenharmony_ci       *
185bf215546Sopenharmony_ci       *    This field specifies the distance in rows between array slices. It
186bf215546Sopenharmony_ci       *    is used only in the following cases:
187bf215546Sopenharmony_ci       *     - Surface Array is enabled OR
188bf215546Sopenharmony_ci       *     - Number of Mulitsamples is not NUMSAMPLES_1 and Multisampled
189bf215546Sopenharmony_ci       *       Surface Storage Format set to MSFMT_MSS OR
190bf215546Sopenharmony_ci       *     - Surface Type is SURFTYPE_CUBE
191bf215546Sopenharmony_ci       *
192bf215546Sopenharmony_ci       * None of the three conditions above can possibly apply to a 3D surface
193bf215546Sopenharmony_ci       * so it is safe to just set QPitch to 0.
194bf215546Sopenharmony_ci       */
195bf215546Sopenharmony_ci      return 0;
196bf215546Sopenharmony_ci   }
197bf215546Sopenharmony_ci}
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci#endif
200