00779f8db07a9e2258521e4d490a88536228984b
[mesa.git] / src / mesa / drivers / dri / i965 / brw_tex_layout.c
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 "intel_tex_layout.h"
37 #include "intel_context.h"
38 #include "main/macros.h"
39
40 #define FILE_DEBUG_FLAG DEBUG_MIPTREE
41
42 static void
43 brw_miptree_layout_2d(struct intel_mipmap_tree *mt)
44 {
45 unsigned level;
46 unsigned x = 0;
47 unsigned y = 0;
48 unsigned width = mt->physical_width0;
49 unsigned height = mt->physical_height0;
50 unsigned depth = mt->physical_depth0; /* number of array layers. */
51
52 mt->total_width = mt->physical_width0;
53
54 if (mt->compressed) {
55 mt->total_width = ALIGN(mt->physical_width0, mt->align_w);
56 }
57
58 /* May need to adjust width to accomodate the placement of
59 * the 2nd mipmap. This occurs when the alignment
60 * constraints of mipmap placement push the right edge of the
61 * 2nd mipmap out past the width of its parent.
62 */
63 if (mt->first_level != mt->last_level) {
64 unsigned mip1_width;
65
66 if (mt->compressed) {
67 mip1_width = ALIGN(minify(mt->physical_width0, 1), mt->align_w) +
68 ALIGN(minify(mt->physical_width0, 2), mt->align_w);
69 } else {
70 mip1_width = ALIGN(minify(mt->physical_width0, 1), mt->align_w) +
71 minify(mt->physical_width0, 2);
72 }
73
74 if (mip1_width > mt->total_width) {
75 mt->total_width = mip1_width;
76 }
77 }
78
79 mt->total_height = 0;
80
81 for ( level = mt->first_level ; level <= mt->last_level ; level++ ) {
82 unsigned img_height;
83
84 intel_miptree_set_level_info(mt, level, x, y, width,
85 height, depth);
86
87 img_height = ALIGN(height, mt->align_h);
88 if (mt->compressed)
89 img_height /= mt->align_h;
90
91 /* Because the images are packed better, the final offset
92 * might not be the maximal one:
93 */
94 mt->total_height = MAX2(mt->total_height, y + img_height);
95
96 /* Layout_below: step right after second mipmap.
97 */
98 if (level == mt->first_level + 1) {
99 x += ALIGN(width, mt->align_w);
100 } else {
101 y += img_height;
102 }
103
104 width = minify(width, 1);
105 height = minify(height, 1);
106 }
107 }
108
109 static void
110 brw_miptree_layout_texture_array(struct intel_context *intel,
111 struct intel_mipmap_tree *mt)
112 {
113 unsigned level;
114 unsigned qpitch = 0;
115 int h0, h1, q;
116
117 h0 = ALIGN(mt->physical_height0, mt->align_h);
118 h1 = ALIGN(minify(mt->physical_height0, 1), mt->align_h);
119 if (mt->array_spacing_lod0)
120 qpitch = h0;
121 else
122 qpitch = (h0 + h1 + (intel->gen >= 7 ? 12 : 11) * mt->align_h);
123 if (mt->compressed)
124 qpitch /= 4;
125
126 brw_miptree_layout_2d(mt);
127
128 for (level = mt->first_level; level <= mt->last_level; level++) {
129 for (q = 0; q < mt->physical_depth0; q++) {
130 intel_miptree_set_image_offset(mt, level, q, 0, q * qpitch);
131 }
132 }
133 mt->total_height = qpitch * mt->physical_depth0;
134 }
135
136 static void
137 brw_miptree_layout_texture_3d(struct intel_context *intel,
138 struct intel_mipmap_tree *mt)
139 {
140 unsigned width = mt->physical_width0;
141 unsigned height = mt->physical_height0;
142 unsigned depth = mt->physical_depth0;
143 unsigned pack_x_pitch, pack_x_nr;
144 unsigned pack_y_pitch;
145 unsigned level;
146
147 mt->total_height = 0;
148
149 if (mt->compressed) {
150 mt->total_width = ALIGN(width, mt->align_w);
151 pack_y_pitch = (height + 3) / 4;
152 } else {
153 mt->total_width = mt->physical_width0;
154 pack_y_pitch = ALIGN(mt->physical_height0, mt->align_h);
155 }
156
157 pack_x_pitch = width;
158 pack_x_nr = 1;
159
160 for (level = mt->first_level ; level <= mt->last_level ; level++) {
161 int x = 0;
162 int y = 0;
163 int q, j;
164
165 intel_miptree_set_level_info(mt, level,
166 0, mt->total_height,
167 width, height, depth);
168
169 for (q = 0; q < depth; /* empty */) {
170 for (j = 0; j < pack_x_nr && q < depth; j++, q++) {
171 intel_miptree_set_image_offset(mt, level, q, x, y);
172 x += pack_x_pitch;
173 }
174 if (x > mt->total_width)
175 mt->total_width = x;
176
177 x = 0;
178 y += pack_y_pitch;
179 }
180
181 mt->total_height += y;
182 width = minify(width, 1);
183 height = minify(height, 1);
184 if (mt->target == GL_TEXTURE_3D)
185 depth = minify(depth, 1);
186
187 if (mt->compressed) {
188 pack_y_pitch = (height + 3) / 4;
189
190 if (pack_x_pitch > ALIGN(width, mt->align_w)) {
191 pack_x_pitch = ALIGN(width, mt->align_w);
192 pack_x_nr <<= 1;
193 }
194 } else {
195 pack_x_nr <<= 1;
196 if (pack_x_pitch > 4) {
197 pack_x_pitch >>= 1;
198 }
199
200 if (pack_y_pitch > 2) {
201 pack_y_pitch >>= 1;
202 pack_y_pitch = ALIGN(pack_y_pitch, mt->align_h);
203 }
204 }
205 }
206
207 /* The 965's sampler lays cachelines out according to how accesses
208 * in the texture surfaces run, so they may be "vertical" through
209 * memory. As a result, the docs say in Surface Padding Requirements:
210 * Sampling Engine Surfaces that two extra rows of padding are required.
211 */
212 if (mt->target == GL_TEXTURE_CUBE_MAP)
213 mt->total_height += 2;
214 }
215
216 void
217 brw_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree *mt)
218 {
219 switch (mt->target) {
220 case GL_TEXTURE_CUBE_MAP:
221 if (intel->gen == 4) {
222 /* Gen4 stores cube maps as 3D textures. */
223 assert(mt->physical_depth0 == 6);
224 brw_miptree_layout_texture_3d(intel, mt);
225 } else {
226 /* All other hardware stores cube maps as 2D arrays. */
227 brw_miptree_layout_texture_array(intel, mt);
228 }
229 break;
230
231 case GL_TEXTURE_3D:
232 brw_miptree_layout_texture_3d(intel, mt);
233 break;
234
235 case GL_TEXTURE_1D_ARRAY:
236 case GL_TEXTURE_2D_ARRAY:
237 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
238 case GL_TEXTURE_CUBE_MAP_ARRAY:
239 brw_miptree_layout_texture_array(intel, mt);
240 break;
241
242 default:
243 switch (mt->msaa_layout) {
244 case INTEL_MSAA_LAYOUT_UMS:
245 case INTEL_MSAA_LAYOUT_CMS:
246 brw_miptree_layout_texture_array(intel, mt);
247 break;
248 case INTEL_MSAA_LAYOUT_NONE:
249 case INTEL_MSAA_LAYOUT_IMS:
250 brw_miptree_layout_2d(mt);
251 break;
252 }
253 break;
254 }
255 DBG("%s: %dx%dx%d\n", __FUNCTION__,
256 mt->total_width, mt->total_height, mt->cpp);
257 }
258