blob: 527912d9cfca7cdeb0a37056e3c6dc4fe50dbb5a [file] [log] [blame]
Chia-I Wu4bc47012014-08-14 13:03:25 +08001/*
2 * Mesa 3-D graphics library
3 *
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:
25 * Chia-I Wu <olv@lunarg.com>
26 */
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
36enum intel_layout_walk_type {
37 /*
38 * Array layers of an LOD are packed together vertically. This maps to
39 * ARYSPC_LOD0 for non-mipmapped 2D textures, and is extended to support
40 * mipmapped stencil textures and HiZ on GEN6.
41 */
42 INTEL_LAYOUT_WALK_LOD,
43
44 /*
45 * LODs of an array layer are packed together. This maps to ARYSPC_FULL
46 * and is used for mipmapped 2D textures.
47 */
48 INTEL_LAYOUT_WALK_LAYER,
49
50 /*
51 * 3D slices of an LOD are packed together, horizontally with wrapping.
52 * Used for 3D textures.
53 */
54 INTEL_LAYOUT_WALK_3D,
55};
Chia-I Wu4bc47012014-08-14 13:03:25 +080056
Chia-I Wu8a8d8b62014-08-14 13:26:26 +080057enum intel_layout_aux_type {
58 INTEL_LAYOUT_AUX_NONE,
59 INTEL_LAYOUT_AUX_HIZ,
60 INTEL_LAYOUT_AUX_MCS,
Chia-I Wu4bc47012014-08-14 13:03:25 +080061};
62
Chia-I Wu457d0a62014-08-18 13:02:26 +080063struct intel_layout_lod {
64 /* physical position */
65 unsigned x;
66 unsigned y;
67
68 /*
69 * Physical size of an LOD slice. There may be multiple slices when the
70 * walk type is not INTEL_LAYOUT_WALK_LAYER.
71 */
72 unsigned slice_width;
73 unsigned slice_height;
74};
75
Chia-I Wu4bc47012014-08-14 13:03:25 +080076/**
77 * Texture layout.
78 */
Chia-I Wu8a8d8b62014-08-14 13:26:26 +080079struct intel_layout {
Chia-I Wu457d0a62014-08-18 13:02:26 +080080 enum intel_layout_aux_type aux;
81
82 /* physical width0, height0, and format */
83 unsigned width0;
84 unsigned height0;
Chia-I Wu8a8d8b62014-08-14 13:26:26 +080085 XGL_FORMAT format;
Chia-I Wu4bc47012014-08-14 13:03:25 +080086 bool separate_stencil;
87
88 /*
89 * width, height, and size of pixel blocks, for conversion between 2D
90 * coordinates and memory offsets
91 */
92 unsigned block_width;
93 unsigned block_height;
94 unsigned block_size;
95
Chia-I Wu457d0a62014-08-18 13:02:26 +080096 enum intel_layout_walk_type walk;
Chia-I Wu4bc47012014-08-14 13:03:25 +080097 bool interleaved_samples;
Chia-I Wu4bc47012014-08-14 13:03:25 +080098
99 /* bitmask of valid tiling modes */
100 unsigned valid_tilings;
101 enum intel_tiling_mode tiling;
102
103 /* mipmap alignments */
104 unsigned align_i;
105 unsigned align_j;
106
Chia-I Wu457d0a62014-08-18 13:02:26 +0800107 struct intel_layout_lod lods[INTEL_LAYOUT_MAX_LEVELS];
Chia-I Wu4bc47012014-08-14 13:03:25 +0800108
Chia-I Wu457d0a62014-08-18 13:02:26 +0800109 /* physical height of layers for INTEL_LAYOUT_WALK_LAYER */
Chia-I Wu4bc47012014-08-14 13:03:25 +0800110 unsigned layer_height;
111
112 /* distance in bytes between two pixel block rows */
113 unsigned bo_stride;
114 /* number of pixel block rows */
115 unsigned bo_height;
116
Chia-I Wu457d0a62014-08-18 13:02:26 +0800117 /* bitmask of levels that can use aux */
118 unsigned aux_enables;
119 unsigned aux_offsets[INTEL_LAYOUT_MAX_LEVELS];
Chia-I Wu4bc47012014-08-14 13:03:25 +0800120 unsigned aux_stride;
121 unsigned aux_height;
122};
123
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800124void intel_layout_init(struct intel_layout *layout,
125 const struct intel_dev *dev,
126 const XGL_IMAGE_CREATE_INFO *info);
Chia-I Wu4bc47012014-08-14 13:03:25 +0800127
128bool
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800129intel_layout_update_for_imported_bo(struct intel_layout *layout,
130 enum intel_tiling_mode tiling,
131 unsigned bo_stride);
Chia-I Wu4bc47012014-08-14 13:03:25 +0800132
133/**
Chia-I Wu457d0a62014-08-18 13:02:26 +0800134 * Convert from pixel position to 2D memory offset.
Chia-I Wu4bc47012014-08-14 13:03:25 +0800135 */
136static inline void
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800137intel_layout_pos_to_mem(const struct intel_layout *layout,
Chia-I Wu457d0a62014-08-18 13:02:26 +0800138 unsigned pos_x, unsigned pos_y,
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800139 unsigned *mem_x, unsigned *mem_y)
Chia-I Wu4bc47012014-08-14 13:03:25 +0800140{
Chia-I Wu457d0a62014-08-18 13:02:26 +0800141 assert(pos_x % layout->block_width == 0);
142 assert(pos_y % layout->block_height == 0);
Chia-I Wu4bc47012014-08-14 13:03:25 +0800143
Chia-I Wu457d0a62014-08-18 13:02:26 +0800144 *mem_x = pos_x / layout->block_width * layout->block_size;
145 *mem_y = pos_y / layout->block_height;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800146}
147
148/**
Chia-I Wu457d0a62014-08-18 13:02:26 +0800149 * Convert from 2D memory offset to linear offset.
Chia-I Wu4bc47012014-08-14 13:03:25 +0800150 */
151static inline unsigned
Chia-I Wu457d0a62014-08-18 13:02:26 +0800152intel_layout_mem_to_linear(const struct intel_layout *layout,
153 unsigned mem_x, unsigned mem_y)
Chia-I Wu4bc47012014-08-14 13:03:25 +0800154{
155 return mem_y * layout->bo_stride + mem_x;
156}
157
158/**
Chia-I Wu457d0a62014-08-18 13:02:26 +0800159 * Convert from 2D memory offset to raw offset.
160 */
161static inline unsigned
162intel_layout_mem_to_raw(const struct intel_layout *layout,
163 unsigned mem_x, unsigned mem_y)
164{
165 unsigned tile_w, tile_h;
166
167 switch (layout->tiling) {
168 case INTEL_TILING_NONE:
169 if (layout->format.numericFormat == XGL_NUM_FMT_DS &&
170 layout->format.channelFormat == XGL_CH_FMT_R8) {
171 /* W-tile */
172 tile_w = 64;
173 tile_h = 64;
174 } else {
175 tile_w = 1;
176 tile_h = 1;
177 }
178 break;
179 case INTEL_TILING_X:
180 tile_w = 512;
181 tile_h = 8;
182 break;
183 case INTEL_TILING_Y:
184 tile_w = 128;
185 tile_h = 32;
186 break;
187 default:
188 assert(!"unknown tiling");
189 tile_w = 1;
190 tile_h = 1;
191 break;
192 }
193
194 assert(mem_x % tile_w == 0);
195 assert(mem_y % tile_h == 0);
196
197 return mem_y * layout->bo_stride + mem_x * tile_h;
198}
199
200/**
Chia-I Wu4bc47012014-08-14 13:03:25 +0800201 * Return the stride, in bytes, between slices within a level.
202 */
203static inline unsigned
Chia-I Wu457d0a62014-08-18 13:02:26 +0800204intel_layout_get_slice_stride(const struct intel_layout *layout, unsigned level)
Chia-I Wu4bc47012014-08-14 13:03:25 +0800205{
Chia-I Wu457d0a62014-08-18 13:02:26 +0800206 unsigned h;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800207
Chia-I Wu457d0a62014-08-18 13:02:26 +0800208 switch (layout->walk) {
209 case INTEL_LAYOUT_WALK_LOD:
210 h = layout->lods[level].slice_height;
211 break;
212 case INTEL_LAYOUT_WALK_LAYER:
213 h = layout->layer_height;
214 break;
215 case INTEL_LAYOUT_WALK_3D:
216 if (level == 0) {
217 h = layout->lods[0].slice_height;
218 break;
219 }
220 /* fall through */
221 default:
222 assert(!"no single stride to walk across slices");
223 h = 0;
224 break;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800225 }
226
Chia-I Wu457d0a62014-08-18 13:02:26 +0800227 assert(h % layout->block_height == 0);
Chia-I Wu4bc47012014-08-14 13:03:25 +0800228
Chia-I Wu457d0a62014-08-18 13:02:26 +0800229 return (h / layout->block_height) * layout->bo_stride;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800230}
231
232/**
233 * Return the physical size, in bytes, of a slice in a level.
234 */
235static inline unsigned
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800236intel_layout_get_slice_size(const struct intel_layout *layout, unsigned level)
Chia-I Wu4bc47012014-08-14 13:03:25 +0800237{
Chia-I Wu457d0a62014-08-18 13:02:26 +0800238 const unsigned w = layout->lods[level].slice_width;
239 const unsigned h = layout->lods[level].slice_height;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800240
241 assert(w % layout->block_width == 0);
242 assert(h % layout->block_height == 0);
243
244 return (w / layout->block_width * layout->block_size) *
245 (h / layout->block_height);
246}
247
248/**
249 * Return the pixel position of a slice.
250 */
251static inline void
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800252intel_layout_get_slice_pos(const struct intel_layout *layout,
253 unsigned level, unsigned slice,
254 unsigned *x, unsigned *y)
Chia-I Wu4bc47012014-08-14 13:03:25 +0800255{
Chia-I Wu457d0a62014-08-18 13:02:26 +0800256 switch (layout->walk) {
257 case INTEL_LAYOUT_WALK_LOD:
258 *x = layout->lods[level].x;
259 *y = layout->lods[level].y + layout->lods[level].slice_height * slice;
260 break;
261 case INTEL_LAYOUT_WALK_LAYER:
262 *x = layout->lods[level].x;
263 *y = layout->lods[level].y + layout->layer_height * slice;
264 break;
265 case INTEL_LAYOUT_WALK_3D:
266 {
267 /* slices are packed horizontally with wrapping */
268 const unsigned sx = slice & ((1 << level) - 1);
269 const unsigned sy = slice >> level;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800270
Chia-I Wu457d0a62014-08-18 13:02:26 +0800271 *x = layout->lods[level].x + layout->lods[level].slice_width * sx;
272 *y = layout->lods[level].y + layout->lods[level].slice_height * sy;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800273
Chia-I Wu457d0a62014-08-18 13:02:26 +0800274 /* should not overlap with the next level */
275 if (level + 1 < ARRAY_SIZE(layout->lods) &&
276 layout->lods[level + 1].y) {
277 assert(*y + layout->lods[level].slice_height <=
278 layout->lods[level + 1].y);
279 }
280 break;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800281 }
Chia-I Wu457d0a62014-08-18 13:02:26 +0800282 default:
283 assert(!"unknown layout walk type");
284 break;
Chia-I Wu4bc47012014-08-14 13:03:25 +0800285 }
286
287 /* should not exceed the bo size */
Chia-I Wu457d0a62014-08-18 13:02:26 +0800288 assert(*y + layout->lods[level].slice_height <=
Chia-I Wu4bc47012014-08-14 13:03:25 +0800289 layout->bo_height * layout->block_height);
290}
291
Chia-I Wu8a8d8b62014-08-14 13:26:26 +0800292#endif /* LAYOUT_H */