blob: 473aa326ae0dc10db368c986480be50ee937fd1c [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,
Chia-I Wu794d12a2014-09-15 14:55:25 +0800128 const XGL_IMAGE_CREATE_INFO *info,
129 bool scanout);
Chia-I Wu4bc47012014-08-14 13:03:25 +0800130
131bool
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800132intel_layout_update_for_imported_bo(struct intel_layout *layout,
133 enum intel_tiling_mode tiling,
134 unsigned bo_stride);
Chia-I Wu4bc47012014-08-14 13:03:25 +0800135
136/**
Chia-I Wu457d0a62014-08-18 13:02:26 +0800137 * Convert from pixel position to 2D memory offset.
Chia-I Wu4bc47012014-08-14 13:03:25 +0800138 */
139static inline void
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800140intel_layout_pos_to_mem(const struct intel_layout *layout,
Chia-I Wu457d0a62014-08-18 13:02:26 +0800141 unsigned pos_x, unsigned pos_y,
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800142 unsigned *mem_x, unsigned *mem_y)
Chia-I Wu4bc47012014-08-14 13:03:25 +0800143{
Chia-I Wu457d0a62014-08-18 13:02:26 +0800144 assert(pos_x % layout->block_width == 0);
145 assert(pos_y % layout->block_height == 0);
Chia-I Wu4bc47012014-08-14 13:03:25 +0800146
Chia-I Wu457d0a62014-08-18 13:02:26 +0800147 *mem_x = pos_x / layout->block_width * layout->block_size;
148 *mem_y = pos_y / layout->block_height;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800149}
150
151/**
Chia-I Wu457d0a62014-08-18 13:02:26 +0800152 * Convert from 2D memory offset to linear offset.
Chia-I Wu4bc47012014-08-14 13:03:25 +0800153 */
154static inline unsigned
Chia-I Wu457d0a62014-08-18 13:02:26 +0800155intel_layout_mem_to_linear(const struct intel_layout *layout,
156 unsigned mem_x, unsigned mem_y)
Chia-I Wu4bc47012014-08-14 13:03:25 +0800157{
158 return mem_y * layout->bo_stride + mem_x;
159}
160
161/**
Chia-I Wu457d0a62014-08-18 13:02:26 +0800162 * Convert from 2D memory offset to raw offset.
163 */
164static inline unsigned
165intel_layout_mem_to_raw(const struct intel_layout *layout,
166 unsigned mem_x, unsigned mem_y)
167{
168 unsigned tile_w, tile_h;
169
170 switch (layout->tiling) {
171 case INTEL_TILING_NONE:
172 if (layout->format.numericFormat == XGL_NUM_FMT_DS &&
173 layout->format.channelFormat == XGL_CH_FMT_R8) {
174 /* W-tile */
175 tile_w = 64;
176 tile_h = 64;
177 } else {
178 tile_w = 1;
179 tile_h = 1;
180 }
181 break;
182 case INTEL_TILING_X:
183 tile_w = 512;
184 tile_h = 8;
185 break;
186 case INTEL_TILING_Y:
187 tile_w = 128;
188 tile_h = 32;
189 break;
190 default:
191 assert(!"unknown tiling");
192 tile_w = 1;
193 tile_h = 1;
194 break;
195 }
196
197 assert(mem_x % tile_w == 0);
198 assert(mem_y % tile_h == 0);
199
200 return mem_y * layout->bo_stride + mem_x * tile_h;
201}
202
203/**
Chia-I Wu4bc47012014-08-14 13:03:25 +0800204 * Return the stride, in bytes, between slices within a level.
205 */
206static inline unsigned
Chia-I Wu457d0a62014-08-18 13:02:26 +0800207intel_layout_get_slice_stride(const struct intel_layout *layout, unsigned level)
Chia-I Wu4bc47012014-08-14 13:03:25 +0800208{
Chia-I Wu457d0a62014-08-18 13:02:26 +0800209 unsigned h;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800210
Chia-I Wu457d0a62014-08-18 13:02:26 +0800211 switch (layout->walk) {
212 case INTEL_LAYOUT_WALK_LOD:
213 h = layout->lods[level].slice_height;
214 break;
215 case INTEL_LAYOUT_WALK_LAYER:
216 h = layout->layer_height;
217 break;
218 case INTEL_LAYOUT_WALK_3D:
219 if (level == 0) {
220 h = layout->lods[0].slice_height;
221 break;
222 }
223 /* fall through */
224 default:
225 assert(!"no single stride to walk across slices");
226 h = 0;
227 break;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800228 }
229
Chia-I Wu457d0a62014-08-18 13:02:26 +0800230 assert(h % layout->block_height == 0);
Chia-I Wu4bc47012014-08-14 13:03:25 +0800231
Chia-I Wu457d0a62014-08-18 13:02:26 +0800232 return (h / layout->block_height) * layout->bo_stride;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800233}
234
235/**
236 * Return the physical size, in bytes, of a slice in a level.
237 */
238static inline unsigned
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800239intel_layout_get_slice_size(const struct intel_layout *layout, unsigned level)
Chia-I Wu4bc47012014-08-14 13:03:25 +0800240{
Chia-I Wu457d0a62014-08-18 13:02:26 +0800241 const unsigned w = layout->lods[level].slice_width;
242 const unsigned h = layout->lods[level].slice_height;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800243
244 assert(w % layout->block_width == 0);
245 assert(h % layout->block_height == 0);
246
247 return (w / layout->block_width * layout->block_size) *
248 (h / layout->block_height);
249}
250
251/**
252 * Return the pixel position of a slice.
253 */
254static inline void
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800255intel_layout_get_slice_pos(const struct intel_layout *layout,
256 unsigned level, unsigned slice,
257 unsigned *x, unsigned *y)
Chia-I Wu4bc47012014-08-14 13:03:25 +0800258{
Chia-I Wu457d0a62014-08-18 13:02:26 +0800259 switch (layout->walk) {
260 case INTEL_LAYOUT_WALK_LOD:
261 *x = layout->lods[level].x;
262 *y = layout->lods[level].y + layout->lods[level].slice_height * slice;
263 break;
264 case INTEL_LAYOUT_WALK_LAYER:
265 *x = layout->lods[level].x;
266 *y = layout->lods[level].y + layout->layer_height * slice;
267 break;
268 case INTEL_LAYOUT_WALK_3D:
269 {
270 /* slices are packed horizontally with wrapping */
271 const unsigned sx = slice & ((1 << level) - 1);
272 const unsigned sy = slice >> level;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800273
Chia-I Wu457d0a62014-08-18 13:02:26 +0800274 *x = layout->lods[level].x + layout->lods[level].slice_width * sx;
275 *y = layout->lods[level].y + layout->lods[level].slice_height * sy;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800276
Chia-I Wu457d0a62014-08-18 13:02:26 +0800277 /* should not overlap with the next level */
278 if (level + 1 < ARRAY_SIZE(layout->lods) &&
279 layout->lods[level + 1].y) {
280 assert(*y + layout->lods[level].slice_height <=
281 layout->lods[level + 1].y);
282 }
283 break;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800284 }
Chia-I Wu457d0a62014-08-18 13:02:26 +0800285 default:
286 assert(!"unknown layout walk type");
287 break;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800288 }
289
290 /* should not exceed the bo size */
Chia-I Wu457d0a62014-08-18 13:02:26 +0800291 assert(*y + layout->lods[level].slice_height <=
Chia-I Wu4bc47012014-08-14 13:03:25 +0800292 layout->bo_height * layout->block_height);
293}
294
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800295#endif /* LAYOUT_H */