blob: 2a16a08afbe1565f8effc99300fc374985fbe87e [file] [log] [blame]
Chia-I Wu4bc47012014-08-14 13:03:25 +08001/*
Chia-I Wu44e42362014-09-02 08:32:09 +08002 * XGL
Chia-I Wu4bc47012014-08-14 13:03:25 +08003 *
4 * Copyright (C) 2014 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
Chia-I Wu44e42362014-09-02 08:32:09 +080025 * Chia-I Wu <olv@lunarg.com>
Chia-I Wu4bc47012014-08-14 13:03:25 +080026 */
27
Chia-I Wu8a8d8b62014-08-14 13:26:26 +080028#ifndef LAYOUT_H
29#define LAYOUT_H
Chia-I Wu4bc47012014-08-14 13:03:25 +080030
Chia-I Wu8a8d8b62014-08-14 13:26:26 +080031#include "kmd/winsys.h"
32#include "intel.h"
Chia-I Wu4bc47012014-08-14 13:03:25 +080033
Chia-I Wu457d0a62014-08-18 13:02:26 +080034#define INTEL_LAYOUT_MAX_LEVELS 16
35
Chia-I Wucca7acf2014-08-27 10:37:43 +080036struct intel_dev;
37
Chia-I Wu457d0a62014-08-18 13:02:26 +080038enum intel_layout_walk_type {
39 /*
40 * Array layers of an LOD are packed together vertically. This maps to
41 * ARYSPC_LOD0 for non-mipmapped 2D textures, and is extended to support
42 * mipmapped stencil textures and HiZ on GEN6.
43 */
44 INTEL_LAYOUT_WALK_LOD,
45
46 /*
47 * LODs of an array layer are packed together. This maps to ARYSPC_FULL
48 * and is used for mipmapped 2D textures.
49 */
50 INTEL_LAYOUT_WALK_LAYER,
51
52 /*
53 * 3D slices of an LOD are packed together, horizontally with wrapping.
54 * Used for 3D textures.
55 */
56 INTEL_LAYOUT_WALK_3D,
57};
Chia-I Wu4bc47012014-08-14 13:03:25 +080058
Chia-I Wu8a8d8b62014-08-14 13:26:26 +080059enum intel_layout_aux_type {
60 INTEL_LAYOUT_AUX_NONE,
61 INTEL_LAYOUT_AUX_HIZ,
62 INTEL_LAYOUT_AUX_MCS,
Chia-I Wu4bc47012014-08-14 13:03:25 +080063};
64
Chia-I Wu457d0a62014-08-18 13:02:26 +080065struct intel_layout_lod {
66 /* physical position */
67 unsigned x;
68 unsigned y;
69
70 /*
71 * Physical size of an LOD slice. There may be multiple slices when the
72 * walk type is not INTEL_LAYOUT_WALK_LAYER.
73 */
74 unsigned slice_width;
75 unsigned slice_height;
76};
77
Chia-I Wu4bc47012014-08-14 13:03:25 +080078/**
79 * Texture layout.
80 */
Chia-I Wu8a8d8b62014-08-14 13:26:26 +080081struct intel_layout {
Chia-I Wu457d0a62014-08-18 13:02:26 +080082 enum intel_layout_aux_type aux;
83
84 /* physical width0, height0, and format */
85 unsigned width0;
86 unsigned height0;
Chia-I Wu8a8d8b62014-08-14 13:26:26 +080087 XGL_FORMAT format;
Chia-I Wu4bc47012014-08-14 13:03:25 +080088 bool separate_stencil;
89
90 /*
91 * width, height, and size of pixel blocks, for conversion between 2D
92 * coordinates and memory offsets
93 */
94 unsigned block_width;
95 unsigned block_height;
96 unsigned block_size;
97
Chia-I Wu457d0a62014-08-18 13:02:26 +080098 enum intel_layout_walk_type walk;
Chia-I Wu4bc47012014-08-14 13:03:25 +080099 bool interleaved_samples;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800100
101 /* bitmask of valid tiling modes */
102 unsigned valid_tilings;
103 enum intel_tiling_mode tiling;
104
105 /* mipmap alignments */
106 unsigned align_i;
107 unsigned align_j;
108
Chia-I Wu457d0a62014-08-18 13:02:26 +0800109 struct intel_layout_lod lods[INTEL_LAYOUT_MAX_LEVELS];
Chia-I Wu4bc47012014-08-14 13:03:25 +0800110
Chia-I Wu457d0a62014-08-18 13:02:26 +0800111 /* physical height of layers for INTEL_LAYOUT_WALK_LAYER */
Chia-I Wu4bc47012014-08-14 13:03:25 +0800112 unsigned layer_height;
113
114 /* distance in bytes between two pixel block rows */
115 unsigned bo_stride;
116 /* number of pixel block rows */
117 unsigned bo_height;
118
Chia-I Wu457d0a62014-08-18 13:02:26 +0800119 /* bitmask of levels that can use aux */
120 unsigned aux_enables;
121 unsigned aux_offsets[INTEL_LAYOUT_MAX_LEVELS];
Chia-I Wu4bc47012014-08-14 13:03:25 +0800122 unsigned aux_stride;
123 unsigned aux_height;
124};
125
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800126void intel_layout_init(struct intel_layout *layout,
127 const struct intel_dev *dev,
128 const XGL_IMAGE_CREATE_INFO *info);
Chia-I Wu4bc47012014-08-14 13:03:25 +0800129
130bool
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800131intel_layout_update_for_imported_bo(struct intel_layout *layout,
132 enum intel_tiling_mode tiling,
133 unsigned bo_stride);
Chia-I Wu4bc47012014-08-14 13:03:25 +0800134
135/**
Chia-I Wu457d0a62014-08-18 13:02:26 +0800136 * Convert from pixel position to 2D memory offset.
Chia-I Wu4bc47012014-08-14 13:03:25 +0800137 */
138static inline void
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800139intel_layout_pos_to_mem(const struct intel_layout *layout,
Chia-I Wu457d0a62014-08-18 13:02:26 +0800140 unsigned pos_x, unsigned pos_y,
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800141 unsigned *mem_x, unsigned *mem_y)
Chia-I Wu4bc47012014-08-14 13:03:25 +0800142{
Chia-I Wu457d0a62014-08-18 13:02:26 +0800143 assert(pos_x % layout->block_width == 0);
144 assert(pos_y % layout->block_height == 0);
Chia-I Wu4bc47012014-08-14 13:03:25 +0800145
Chia-I Wu457d0a62014-08-18 13:02:26 +0800146 *mem_x = pos_x / layout->block_width * layout->block_size;
147 *mem_y = pos_y / layout->block_height;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800148}
149
150/**
Chia-I Wu457d0a62014-08-18 13:02:26 +0800151 * Convert from 2D memory offset to linear offset.
Chia-I Wu4bc47012014-08-14 13:03:25 +0800152 */
153static inline unsigned
Chia-I Wu457d0a62014-08-18 13:02:26 +0800154intel_layout_mem_to_linear(const struct intel_layout *layout,
155 unsigned mem_x, unsigned mem_y)
Chia-I Wu4bc47012014-08-14 13:03:25 +0800156{
157 return mem_y * layout->bo_stride + mem_x;
158}
159
160/**
Chia-I Wu457d0a62014-08-18 13:02:26 +0800161 * Convert from 2D memory offset to raw offset.
162 */
163static inline unsigned
164intel_layout_mem_to_raw(const struct intel_layout *layout,
165 unsigned mem_x, unsigned mem_y)
166{
167 unsigned tile_w, tile_h;
168
169 switch (layout->tiling) {
170 case INTEL_TILING_NONE:
171 if (layout->format.numericFormat == XGL_NUM_FMT_DS &&
172 layout->format.channelFormat == XGL_CH_FMT_R8) {
173 /* W-tile */
174 tile_w = 64;
175 tile_h = 64;
176 } else {
177 tile_w = 1;
178 tile_h = 1;
179 }
180 break;
181 case INTEL_TILING_X:
182 tile_w = 512;
183 tile_h = 8;
184 break;
185 case INTEL_TILING_Y:
186 tile_w = 128;
187 tile_h = 32;
188 break;
189 default:
190 assert(!"unknown tiling");
191 tile_w = 1;
192 tile_h = 1;
193 break;
194 }
195
196 assert(mem_x % tile_w == 0);
197 assert(mem_y % tile_h == 0);
198
199 return mem_y * layout->bo_stride + mem_x * tile_h;
200}
201
202/**
Chia-I Wu4bc47012014-08-14 13:03:25 +0800203 * Return the stride, in bytes, between slices within a level.
204 */
205static inline unsigned
Chia-I Wu457d0a62014-08-18 13:02:26 +0800206intel_layout_get_slice_stride(const struct intel_layout *layout, unsigned level)
Chia-I Wu4bc47012014-08-14 13:03:25 +0800207{
Chia-I Wu457d0a62014-08-18 13:02:26 +0800208 unsigned h;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800209
Chia-I Wu457d0a62014-08-18 13:02:26 +0800210 switch (layout->walk) {
211 case INTEL_LAYOUT_WALK_LOD:
212 h = layout->lods[level].slice_height;
213 break;
214 case INTEL_LAYOUT_WALK_LAYER:
215 h = layout->layer_height;
216 break;
217 case INTEL_LAYOUT_WALK_3D:
218 if (level == 0) {
219 h = layout->lods[0].slice_height;
220 break;
221 }
222 /* fall through */
223 default:
224 assert(!"no single stride to walk across slices");
225 h = 0;
226 break;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800227 }
228
Chia-I Wu457d0a62014-08-18 13:02:26 +0800229 assert(h % layout->block_height == 0);
Chia-I Wu4bc47012014-08-14 13:03:25 +0800230
Chia-I Wu457d0a62014-08-18 13:02:26 +0800231 return (h / layout->block_height) * layout->bo_stride;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800232}
233
234/**
235 * Return the physical size, in bytes, of a slice in a level.
236 */
237static inline unsigned
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800238intel_layout_get_slice_size(const struct intel_layout *layout, unsigned level)
Chia-I Wu4bc47012014-08-14 13:03:25 +0800239{
Chia-I Wu457d0a62014-08-18 13:02:26 +0800240 const unsigned w = layout->lods[level].slice_width;
241 const unsigned h = layout->lods[level].slice_height;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800242
243 assert(w % layout->block_width == 0);
244 assert(h % layout->block_height == 0);
245
246 return (w / layout->block_width * layout->block_size) *
247 (h / layout->block_height);
248}
249
250/**
251 * Return the pixel position of a slice.
252 */
253static inline void
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800254intel_layout_get_slice_pos(const struct intel_layout *layout,
255 unsigned level, unsigned slice,
256 unsigned *x, unsigned *y)
Chia-I Wu4bc47012014-08-14 13:03:25 +0800257{
Chia-I Wu457d0a62014-08-18 13:02:26 +0800258 switch (layout->walk) {
259 case INTEL_LAYOUT_WALK_LOD:
260 *x = layout->lods[level].x;
261 *y = layout->lods[level].y + layout->lods[level].slice_height * slice;
262 break;
263 case INTEL_LAYOUT_WALK_LAYER:
264 *x = layout->lods[level].x;
265 *y = layout->lods[level].y + layout->layer_height * slice;
266 break;
267 case INTEL_LAYOUT_WALK_3D:
268 {
269 /* slices are packed horizontally with wrapping */
270 const unsigned sx = slice & ((1 << level) - 1);
271 const unsigned sy = slice >> level;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800272
Chia-I Wu457d0a62014-08-18 13:02:26 +0800273 *x = layout->lods[level].x + layout->lods[level].slice_width * sx;
274 *y = layout->lods[level].y + layout->lods[level].slice_height * sy;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800275
Chia-I Wu457d0a62014-08-18 13:02:26 +0800276 /* should not overlap with the next level */
277 if (level + 1 < ARRAY_SIZE(layout->lods) &&
278 layout->lods[level + 1].y) {
279 assert(*y + layout->lods[level].slice_height <=
280 layout->lods[level + 1].y);
281 }
282 break;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800283 }
Chia-I Wu457d0a62014-08-18 13:02:26 +0800284 default:
285 assert(!"unknown layout walk type");
286 break;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800287 }
288
289 /* should not exceed the bo size */
Chia-I Wu457d0a62014-08-18 13:02:26 +0800290 assert(*y + layout->lods[level].slice_height <=
Chia-I Wu4bc47012014-08-14 13:03:25 +0800291 layout->bo_height * layout->block_height);
292}
293
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800294#endif /* LAYOUT_H */