ilo: add support for HiZ allocation
[mesa.git] / src / gallium / drivers / ilo / ilo_resource.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2012-2013 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
28 #include "ilo_screen.h"
29 #include "ilo_resource.h"
30
31 /* use PIPE_BIND_CUSTOM to indicate MCS */
32 #define ILO_BIND_MCS PIPE_BIND_CUSTOM
33
34 struct tex_layout {
35 const struct ilo_dev_info *dev;
36 const struct pipe_resource *templ;
37
38 enum pipe_format format;
39 unsigned block_width, block_height, block_size;
40 bool compressed;
41 bool has_depth, has_stencil;
42 bool hiz, separate_stencil;
43
44 enum intel_tiling_mode tiling;
45 bool can_be_linear;
46
47 bool array_spacing_full;
48 bool interleaved;
49
50 struct {
51 int w, h, d;
52 struct ilo_texture_slice *slices;
53 } levels[PIPE_MAX_TEXTURE_LEVELS];
54
55 int align_i, align_j;
56 int qpitch;
57
58 int width, height;
59 };
60
61 static void
62 tex_layout_init_qpitch(struct tex_layout *layout)
63 {
64 const struct pipe_resource *templ = layout->templ;
65 int h0, h1;
66
67 if (templ->array_size <= 1)
68 return;
69
70 h0 = align(layout->levels[0].h, layout->align_j);
71
72 if (!layout->array_spacing_full) {
73 layout->qpitch = h0;
74 return;
75 }
76
77 h1 = align(layout->levels[1].h, layout->align_j);
78
79 /*
80 * From the Sandy Bridge PRM, volume 1 part 1, page 115:
81 *
82 * "The following equation is used for surface formats other than
83 * compressed textures:
84 *
85 * QPitch = (h0 + h1 + 11j)"
86 *
87 * "The equation for compressed textures (BC* and FXT1 surface formats)
88 * follows:
89 *
90 * QPitch = (h0 + h1 + 11j) / 4"
91 *
92 * "[DevSNB] Errata: Sampler MSAA Qpitch will be 4 greater than the
93 * value calculated in the equation above, for every other odd Surface
94 * Height starting from 1 i.e. 1,5,9,13"
95 *
96 * From the Ivy Bridge PRM, volume 1 part 1, page 111-112:
97 *
98 * "If Surface Array Spacing is set to ARYSPC_FULL (note that the depth
99 * buffer and stencil buffer have an implied value of ARYSPC_FULL):
100 *
101 * QPitch = (h0 + h1 + 12j)
102 * QPitch = (h0 + h1 + 12j) / 4 (compressed)
103 *
104 * (There are many typos or missing words here...)"
105 *
106 * To access the N-th slice, an offset of (Stride * QPitch * N) is added to
107 * the base address. The PRM divides QPitch by 4 for compressed formats
108 * because the block height for those formats are 4, and it wants QPitch to
109 * mean the number of memory rows, as opposed to texel rows, between
110 * slices. Since we use texel rows in tex->slice_offsets, we do not need
111 * to divide QPitch by 4.
112 */
113 layout->qpitch = h0 + h1 +
114 ((layout->dev->gen >= ILO_GEN(7)) ? 12 : 11) * layout->align_j;
115
116 if (layout->dev->gen == ILO_GEN(6) && templ->nr_samples > 1 &&
117 templ->height0 % 4 == 1)
118 layout->qpitch += 4;
119 }
120
121 static void
122 tex_layout_init_alignments(struct tex_layout *layout)
123 {
124 const struct pipe_resource *templ = layout->templ;
125
126 /*
127 * From the Sandy Bridge PRM, volume 1 part 1, page 113:
128 *
129 * "surface format align_i align_j
130 * YUV 4:2:2 formats 4 *see below
131 * BC1-5 4 4
132 * FXT1 8 4
133 * all other formats 4 *see below"
134 *
135 * "- align_j = 4 for any depth buffer
136 * - align_j = 2 for separate stencil buffer
137 * - align_j = 4 for any render target surface is multisampled (4x)
138 * - align_j = 4 for any render target surface with Surface Vertical
139 * Alignment = VALIGN_4
140 * - align_j = 2 for any render target surface with Surface Vertical
141 * Alignment = VALIGN_2
142 * - align_j = 2 for all other render target surface
143 * - align_j = 2 for any sampling engine surface with Surface Vertical
144 * Alignment = VALIGN_2
145 * - align_j = 4 for any sampling engine surface with Surface Vertical
146 * Alignment = VALIGN_4"
147 *
148 * From the Sandy Bridge PRM, volume 4 part 1, page 86:
149 *
150 * "This field (Surface Vertical Alignment) must be set to VALIGN_2 if
151 * the Surface Format is 96 bits per element (BPE)."
152 *
153 * They can be rephrased as
154 *
155 * align_i align_j
156 * compressed formats block width block height
157 * PIPE_FORMAT_S8_UINT 4 2
158 * other depth/stencil formats 4 4
159 * 4x multisampled 4 4
160 * bpp 96 4 2
161 * others 4 2 or 4
162 */
163
164 /*
165 * From the Ivy Bridge PRM, volume 1 part 1, page 110:
166 *
167 * "surface defined by surface format align_i align_j
168 * 3DSTATE_DEPTH_BUFFER D16_UNORM 8 4
169 * not D16_UNORM 4 4
170 * 3DSTATE_STENCIL_BUFFER N/A 8 8
171 * SURFACE_STATE BC*, ETC*, EAC* 4 4
172 * FXT1 8 4
173 * all others (set by SURFACE_STATE)"
174 *
175 * From the Ivy Bridge PRM, volume 4 part 1, page 63:
176 *
177 * "- This field (Surface Vertical Aligment) is intended to be set to
178 * VALIGN_4 if the surface was rendered as a depth buffer, for a
179 * multisampled (4x) render target, or for a multisampled (8x)
180 * render target, since these surfaces support only alignment of 4.
181 * - Use of VALIGN_4 for other surfaces is supported, but uses more
182 * memory.
183 * - This field must be set to VALIGN_4 for all tiled Y Render Target
184 * surfaces.
185 * - Value of 1 is not supported for format YCRCB_NORMAL (0x182),
186 * YCRCB_SWAPUVY (0x183), YCRCB_SWAPUV (0x18f), YCRCB_SWAPY (0x190)
187 * - If Number of Multisamples is not MULTISAMPLECOUNT_1, this field
188 * must be set to VALIGN_4."
189 * - VALIGN_4 is not supported for surface format R32G32B32_FLOAT."
190 *
191 * "- This field (Surface Horizontal Aligment) is intended to be set to
192 * HALIGN_8 only if the surface was rendered as a depth buffer with
193 * Z16 format or a stencil buffer, since these surfaces support only
194 * alignment of 8.
195 * - Use of HALIGN_8 for other surfaces is supported, but uses more
196 * memory.
197 * - This field must be set to HALIGN_4 if the Surface Format is BC*.
198 * - This field must be set to HALIGN_8 if the Surface Format is
199 * FXT1."
200 *
201 * They can be rephrased as
202 *
203 * align_i align_j
204 * compressed formats block width block height
205 * PIPE_FORMAT_Z16_UNORM 8 4
206 * PIPE_FORMAT_S8_UINT 8 8
207 * other depth/stencil formats 4 or 8 4
208 * 2x or 4x multisampled 4 or 8 4
209 * tiled Y 4 or 8 4 (if rt)
210 * PIPE_FORMAT_R32G32B32_FLOAT 4 or 8 2
211 * others 4 or 8 2 or 4
212 */
213
214 if (layout->compressed) {
215 /* this happens to be the case */
216 layout->align_i = layout->block_width;
217 layout->align_j = layout->block_height;
218 }
219 else if (layout->has_depth || layout->has_stencil) {
220 if (layout->dev->gen >= ILO_GEN(7)) {
221 switch (layout->format) {
222 case PIPE_FORMAT_Z16_UNORM:
223 layout->align_i = 8;
224 layout->align_j = 4;
225 break;
226 case PIPE_FORMAT_S8_UINT:
227 layout->align_i = 8;
228 layout->align_j = 8;
229 break;
230 default:
231 /*
232 * From the Ivy Bridge PRM, volume 2 part 1, page 319:
233 *
234 * "The 3 LSBs of both offsets (Depth Coordinate Offset Y and
235 * Depth Coordinate Offset X) must be zero to ensure correct
236 * alignment"
237 *
238 * We will make use of them and setting align_i to 8 help us meet
239 * the requirement.
240 */
241 layout->align_i = (templ->last_level > 0) ? 8 : 4;
242 layout->align_j = 4;
243 break;
244 }
245 }
246 else {
247 switch (layout->format) {
248 case PIPE_FORMAT_S8_UINT:
249 layout->align_i = 4;
250 layout->align_j = 2;
251 break;
252 default:
253 layout->align_i = 4;
254 layout->align_j = 4;
255 break;
256 }
257 }
258 }
259 else {
260 const bool valign_4 = (templ->nr_samples > 1) ||
261 (layout->dev->gen >= ILO_GEN(7) &&
262 layout->tiling == INTEL_TILING_Y &&
263 (templ->bind & PIPE_BIND_RENDER_TARGET));
264
265 if (valign_4)
266 assert(layout->block_size != 12);
267
268 layout->align_i = 4;
269 layout->align_j = (valign_4) ? 4 : 2;
270 }
271
272 /*
273 * the fact that align i and j are multiples of block width and height
274 * respectively is what makes the size of the bo a multiple of the block
275 * size, slices start at block boundaries, and many of the computations
276 * work.
277 */
278 assert(layout->align_i % layout->block_width == 0);
279 assert(layout->align_j % layout->block_height == 0);
280
281 /* make sure align() works */
282 assert(util_is_power_of_two(layout->align_i) &&
283 util_is_power_of_two(layout->align_j));
284 assert(util_is_power_of_two(layout->block_width) &&
285 util_is_power_of_two(layout->block_height));
286 }
287
288 static void
289 tex_layout_init_levels(struct tex_layout *layout)
290 {
291 const struct pipe_resource *templ = layout->templ;
292 int last_level, lv;
293
294 last_level = templ->last_level;
295
296 /* need at least 2 levels to compute full qpitch */
297 if (last_level == 0 && templ->array_size > 1 && layout->array_spacing_full)
298 last_level++;
299
300 /* compute mip level sizes */
301 for (lv = 0; lv <= last_level; lv++) {
302 int w, h, d;
303
304 w = u_minify(templ->width0, lv);
305 h = u_minify(templ->height0, lv);
306 d = u_minify(templ->depth0, lv);
307
308 /*
309 * From the Sandy Bridge PRM, volume 1 part 1, page 114:
310 *
311 * "The dimensions of the mip maps are first determined by applying
312 * the sizing algorithm presented in Non-Power-of-Two Mipmaps
313 * above. Then, if necessary, they are padded out to compression
314 * block boundaries."
315 */
316 w = align(w, layout->block_width);
317 h = align(h, layout->block_height);
318
319 /*
320 * From the Sandy Bridge PRM, volume 1 part 1, page 111:
321 *
322 * "If the surface is multisampled (4x), these values must be
323 * adjusted as follows before proceeding:
324 *
325 * W_L = ceiling(W_L / 2) * 4
326 * H_L = ceiling(H_L / 2) * 4"
327 *
328 * From the Ivy Bridge PRM, volume 1 part 1, page 108:
329 *
330 * "If the surface is multisampled and it is a depth or stencil
331 * surface or Multisampled Surface StorageFormat in SURFACE_STATE
332 * is MSFMT_DEPTH_STENCIL, W_L and H_L must be adjusted as follows
333 * before proceeding:
334 *
335 * #samples W_L = H_L =
336 * 2 ceiling(W_L / 2) * 4 HL [no adjustment]
337 * 4 ceiling(W_L / 2) * 4 ceiling(H_L / 2) * 4
338 * 8 ceiling(W_L / 2) * 8 ceiling(H_L / 2) * 4
339 * 16 ceiling(W_L / 2) * 8 ceiling(H_L / 2) * 8"
340 *
341 * For interleaved samples (4x), where pixels
342 *
343 * (x, y ) (x+1, y )
344 * (x, y+1) (x+1, y+1)
345 *
346 * would be is occupied by
347 *
348 * (x, y , si0) (x+1, y , si0) (x, y , si1) (x+1, y , si1)
349 * (x, y+1, si0) (x+1, y+1, si0) (x, y+1, si1) (x+1, y+1, si1)
350 * (x, y , si2) (x+1, y , si2) (x, y , si3) (x+1, y , si3)
351 * (x, y+1, si2) (x+1, y+1, si2) (x, y+1, si3) (x+1, y+1, si3)
352 *
353 * Thus the need to
354 *
355 * w = align(w, 2) * 2;
356 * y = align(y, 2) * 2;
357 */
358 if (layout->interleaved) {
359 switch (templ->nr_samples) {
360 case 0:
361 case 1:
362 break;
363 case 2:
364 w = align(w, 2) * 2;
365 break;
366 case 4:
367 w = align(w, 2) * 2;
368 h = align(h, 2) * 2;
369 break;
370 case 8:
371 w = align(w, 2) * 4;
372 h = align(h, 2) * 2;
373 break;
374 case 16:
375 w = align(w, 2) * 4;
376 h = align(h, 2) * 4;
377 break;
378 default:
379 assert(!"unsupported sample count");
380 break;
381 }
382 }
383
384 layout->levels[lv].w = w;
385 layout->levels[lv].h = h;
386 layout->levels[lv].d = d;
387 }
388 }
389
390 static void
391 tex_layout_init_spacing(struct tex_layout *layout)
392 {
393 const struct pipe_resource *templ = layout->templ;
394
395 if (layout->dev->gen >= ILO_GEN(7)) {
396 /*
397 * It is not explicitly states, but render targets are expected to be
398 * UMS/CMS (samples non-interleaved) and depth/stencil buffers are
399 * expected to be IMS (samples interleaved).
400 *
401 * See "Multisampled Surface Storage Format" field of SURFACE_STATE.
402 */
403 if (layout->has_depth || layout->has_stencil) {
404 layout->interleaved = true;
405
406 /*
407 * From the Ivy Bridge PRM, volume 1 part 1, page 111:
408 *
409 * "note that the depth buffer and stencil buffer have an implied
410 * value of ARYSPC_FULL"
411 */
412 layout->array_spacing_full = true;
413 }
414 else {
415 layout->interleaved = false;
416
417 /*
418 * From the Ivy Bridge PRM, volume 4 part 1, page 66:
419 *
420 * "If Multisampled Surface Storage Format is MSFMT_MSS and
421 * Number of Multisamples is not MULTISAMPLECOUNT_1, this field
422 * (Surface Array Spacing) must be set to ARYSPC_LOD0."
423 *
424 * As multisampled resources are not mipmapped, we never use
425 * ARYSPC_FULL for them.
426 */
427 if (templ->nr_samples > 1)
428 assert(templ->last_level == 0);
429 layout->array_spacing_full = (templ->last_level > 0);
430 }
431 }
432 else {
433 /* GEN6 supports only interleaved samples */
434 layout->interleaved = true;
435
436 /*
437 * From the Sandy Bridge PRM, volume 1 part 1, page 115:
438 *
439 * "The separate stencil buffer does not support mip mapping, thus
440 * the storage for LODs other than LOD 0 is not needed. The
441 * following QPitch equation applies only to the separate stencil
442 * buffer:
443 *
444 * QPitch = h_0"
445 *
446 * GEN6 does not support compact spacing otherwise.
447 */
448 layout->array_spacing_full = (layout->format != PIPE_FORMAT_S8_UINT);
449 }
450 }
451
452 static void
453 tex_layout_init_tiling(struct tex_layout *layout)
454 {
455 const struct pipe_resource *templ = layout->templ;
456 const enum pipe_format format = layout->format;
457 const unsigned tile_none = 1 << INTEL_TILING_NONE;
458 const unsigned tile_x = 1 << INTEL_TILING_X;
459 const unsigned tile_y = 1 << INTEL_TILING_Y;
460 unsigned valid_tilings = tile_none | tile_x | tile_y;
461
462 /*
463 * From the Sandy Bridge PRM, volume 1 part 2, page 32:
464 *
465 * "Display/Overlay Y-Major not supported.
466 * X-Major required for Async Flips"
467 */
468 if (unlikely(templ->bind & PIPE_BIND_SCANOUT))
469 valid_tilings &= tile_x;
470
471 /*
472 * From the Sandy Bridge PRM, volume 3 part 2, page 158:
473 *
474 * "The cursor surface address must be 4K byte aligned. The cursor must
475 * be in linear memory, it cannot be tiled."
476 */
477 if (unlikely(templ->bind & (PIPE_BIND_CURSOR | PIPE_BIND_LINEAR)))
478 valid_tilings &= tile_none;
479
480 /*
481 * From the Ivy Bridge PRM, volume 4 part 1, page 76:
482 *
483 * "The MCS surface must be stored as Tile Y."
484 */
485 if (templ->bind & ILO_BIND_MCS)
486 valid_tilings &= tile_y;
487
488 /*
489 * From the Sandy Bridge PRM, volume 2 part 1, page 318:
490 *
491 * "[DevSNB+]: This field (Tiled Surface) must be set to TRUE. Linear
492 * Depth Buffer is not supported."
493 *
494 * "The Depth Buffer, if tiled, must use Y-Major tiling."
495 *
496 * From the Sandy Bridge PRM, volume 1 part 2, page 22:
497 *
498 * "W-Major Tile Format is used for separate stencil."
499 *
500 * Since the HW does not support W-tiled fencing, we have to do it in the
501 * driver.
502 */
503 if (templ->bind & PIPE_BIND_DEPTH_STENCIL) {
504 switch (format) {
505 case PIPE_FORMAT_S8_UINT:
506 valid_tilings &= tile_none;
507 break;
508 default:
509 valid_tilings &= tile_y;
510 break;
511 }
512 }
513
514 if (templ->bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW)) {
515 if (templ->bind & PIPE_BIND_RENDER_TARGET) {
516 /*
517 * From the Sandy Bridge PRM, volume 1 part 2, page 32:
518 *
519 * "NOTE: 128BPE Format Color buffer ( render target ) MUST be
520 * either TileX or Linear."
521 */
522 if (layout->block_size == 16)
523 valid_tilings &= ~tile_y;
524
525 /*
526 * From the Ivy Bridge PRM, volume 4 part 1, page 63:
527 *
528 * "This field (Surface Vertical Aligment) must be set to
529 * VALIGN_4 for all tiled Y Render Target surfaces."
530 *
531 * "VALIGN_4 is not supported for surface format
532 * R32G32B32_FLOAT."
533 */
534 if (layout->dev->gen >= ILO_GEN(7) && layout->block_size == 12)
535 valid_tilings &= ~tile_y;
536 }
537
538 /*
539 * Also, heuristically set a minimum width/height for enabling tiling.
540 */
541 if (templ->width0 < 64 && (valid_tilings & ~tile_x))
542 valid_tilings &= ~tile_x;
543
544 if ((templ->width0 < 32 || templ->height0 < 16) &&
545 (templ->width0 < 16 || templ->height0 < 32) &&
546 (valid_tilings & ~tile_y))
547 valid_tilings &= ~tile_y;
548 }
549 else {
550 /* force linear if we are not sure where the texture is bound to */
551 if (valid_tilings & tile_none)
552 valid_tilings &= tile_none;
553 }
554
555 /* no conflicting binding flags */
556 assert(valid_tilings);
557
558 /* prefer tiled than linear */
559 if (valid_tilings & tile_y)
560 layout->tiling = INTEL_TILING_Y;
561 else if (valid_tilings & tile_x)
562 layout->tiling = INTEL_TILING_X;
563 else
564 layout->tiling = INTEL_TILING_NONE;
565
566 layout->can_be_linear = valid_tilings & tile_none;
567 }
568
569 static void
570 tex_layout_init_format(struct tex_layout *layout)
571 {
572 const struct pipe_resource *templ = layout->templ;
573 enum pipe_format format;
574 const struct util_format_description *desc;
575 bool separate_stencil;
576
577 /* GEN7+ requires separate stencil buffers */
578 separate_stencil = (layout->dev->gen >= ILO_GEN(7));
579
580 switch (templ->format) {
581 case PIPE_FORMAT_ETC1_RGB8:
582 format = PIPE_FORMAT_R8G8B8X8_UNORM;
583 break;
584 case PIPE_FORMAT_Z24_UNORM_S8_UINT:
585 if (separate_stencil) {
586 format = PIPE_FORMAT_Z24X8_UNORM;
587 layout->separate_stencil = true;
588 }
589 else {
590 format = templ->format;
591 }
592 break;
593 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
594 if (separate_stencil) {
595 format = PIPE_FORMAT_Z32_FLOAT;
596 layout->separate_stencil = true;
597 }
598 else {
599 format = templ->format;
600 }
601 break;
602 default:
603 format = templ->format;
604 break;
605 }
606
607 layout->format = format;
608
609 layout->block_width = util_format_get_blockwidth(format);
610 layout->block_height = util_format_get_blockheight(format);
611 layout->block_size = util_format_get_blocksize(format);
612 layout->compressed = util_format_is_compressed(format);
613
614 desc = util_format_description(format);
615 layout->has_depth = util_format_has_depth(desc);
616 layout->has_stencil = util_format_has_stencil(desc);
617
618 /* we are not ready yet */
619 layout->hiz = false;
620 }
621
622 static void
623 tex_layout_init(struct tex_layout *layout,
624 struct pipe_screen *screen,
625 const struct pipe_resource *templ,
626 struct ilo_texture_slice **slices)
627 {
628 struct ilo_screen *is = ilo_screen(screen);
629
630 memset(layout, 0, sizeof(*layout));
631
632 layout->dev = &is->dev;
633 layout->templ = templ;
634
635 /* note that there are dependencies between these functions */
636 tex_layout_init_format(layout);
637 tex_layout_init_tiling(layout);
638 tex_layout_init_spacing(layout);
639 tex_layout_init_levels(layout);
640 tex_layout_init_alignments(layout);
641 tex_layout_init_qpitch(layout);
642
643 if (slices) {
644 int lv;
645
646 for (lv = 0; lv <= templ->last_level; lv++)
647 layout->levels[lv].slices = slices[lv];
648 }
649 }
650
651 static bool
652 tex_layout_force_linear(struct tex_layout *layout)
653 {
654 if (!layout->can_be_linear)
655 return false;
656
657 /*
658 * we may be able to switch from VALIGN_4 to VALIGN_2 when the layout was
659 * Y-tiled, but let's keep it simple
660 */
661 layout->tiling = INTEL_TILING_NONE;
662
663 return true;
664 }
665
666 /**
667 * Layout a 2D texture.
668 */
669 static void
670 tex_layout_2d(struct tex_layout *layout)
671 {
672 const struct pipe_resource *templ = layout->templ;
673 unsigned int level_x, level_y, num_slices;
674 int lv;
675
676 level_x = 0;
677 level_y = 0;
678 for (lv = 0; lv <= templ->last_level; lv++) {
679 const unsigned int level_w = layout->levels[lv].w;
680 const unsigned int level_h = layout->levels[lv].h;
681 int slice;
682
683 /* set slice offsets */
684 if (layout->levels[lv].slices) {
685 for (slice = 0; slice < templ->array_size; slice++) {
686 layout->levels[lv].slices[slice].x = level_x;
687 /* slices are qpitch apart in Y-direction */
688 layout->levels[lv].slices[slice].y =
689 level_y + layout->qpitch * slice;
690 }
691 }
692
693 /* extend the size of the monolithic bo to cover this mip level */
694 if (layout->width < level_x + level_w)
695 layout->width = level_x + level_w;
696 if (layout->height < level_y + level_h)
697 layout->height = level_y + level_h;
698
699 /* MIPLAYOUT_BELOW */
700 if (lv == 1)
701 level_x += align(level_w, layout->align_i);
702 else
703 level_y += align(level_h, layout->align_j);
704 }
705
706 num_slices = templ->array_size;
707 /* samples of the same index are stored in a slice */
708 if (templ->nr_samples > 1 && !layout->interleaved)
709 num_slices *= templ->nr_samples;
710
711 /* we did not take slices into consideration in the computation above */
712 layout->height += layout->qpitch * (num_slices - 1);
713 }
714
715 /**
716 * Layout a 3D texture.
717 */
718 static void
719 tex_layout_3d(struct tex_layout *layout)
720 {
721 const struct pipe_resource *templ = layout->templ;
722 unsigned int level_y;
723 int lv;
724
725 level_y = 0;
726 for (lv = 0; lv <= templ->last_level; lv++) {
727 const unsigned int level_w = layout->levels[lv].w;
728 const unsigned int level_h = layout->levels[lv].h;
729 const unsigned int level_d = layout->levels[lv].d;
730 const unsigned int slice_pitch = align(level_w, layout->align_i);
731 const unsigned int slice_qpitch = align(level_h, layout->align_j);
732 const unsigned int num_slices_per_row = 1 << lv;
733 int slice;
734
735 for (slice = 0; slice < level_d; slice += num_slices_per_row) {
736 int i;
737
738 /* set slice offsets */
739 if (layout->levels[lv].slices) {
740 for (i = 0; i < num_slices_per_row && slice + i < level_d; i++) {
741 layout->levels[lv].slices[slice + i].x = slice_pitch * i;
742 layout->levels[lv].slices[slice + i].y = level_y;
743 }
744 }
745
746 /* move on to the next slice row */
747 level_y += slice_qpitch;
748 }
749
750 /* rightmost slice */
751 slice = MIN2(num_slices_per_row, level_d) - 1;
752
753 /* extend the size of the monolithic bo to cover this slice */
754 if (layout->width < slice_pitch * slice + level_w)
755 layout->width = slice_pitch * slice + level_w;
756 if (lv == templ->last_level)
757 layout->height = (level_y - slice_qpitch) + level_h;
758 }
759 }
760
761 static void
762 tex_layout_validate(struct tex_layout *layout)
763 {
764 /*
765 * From the Sandy Bridge PRM, volume 1 part 1, page 118:
766 *
767 * "To determine the necessary padding on the bottom and right side of
768 * the surface, refer to the table in Section 7.18.3.4 for the i and j
769 * parameters for the surface format in use. The surface must then be
770 * extended to the next multiple of the alignment unit size in each
771 * dimension, and all texels contained in this extended surface must
772 * have valid GTT entries."
773 *
774 * "For cube surfaces, an additional two rows of padding are required
775 * at the bottom of the surface. This must be ensured regardless of
776 * whether the surface is stored tiled or linear. This is due to the
777 * potential rotation of cache line orientation from memory to cache."
778 *
779 * "For compressed textures (BC* and FXT1 surface formats), padding at
780 * the bottom of the surface is to an even compressed row, which is
781 * equal to a multiple of 8 uncompressed texel rows. Thus, for padding
782 * purposes, these surfaces behave as if j = 8 only for surface
783 * padding purposes. The value of 4 for j still applies for mip level
784 * alignment and QPitch calculation."
785 */
786 if (layout->templ->bind & PIPE_BIND_SAMPLER_VIEW) {
787 layout->width = align(layout->width, layout->align_i);
788 layout->height = align(layout->height, layout->align_j);
789
790 if (layout->templ->target == PIPE_TEXTURE_CUBE)
791 layout->height += 2;
792
793 if (layout->compressed)
794 layout->height = align(layout->height, layout->align_j * 2);
795 }
796
797 /*
798 * From the Sandy Bridge PRM, volume 1 part 1, page 118:
799 *
800 * "If the surface contains an odd number of rows of data, a final row
801 * below the surface must be allocated."
802 */
803 if (layout->templ->bind & PIPE_BIND_RENDER_TARGET)
804 layout->height = align(layout->height, 2);
805
806 /*
807 * From the Sandy Bridge PRM, volume 1 part 2, page 22:
808 *
809 * "A 4KB tile is subdivided into 8-high by 8-wide array of Blocks for
810 * W-Major Tiles (W Tiles). Each Block is 8 rows by 8 bytes."
811 *
812 * Since we ask for INTEL_TILING_NONE instead of the non-existent
813 * INTEL_TILING_W, we need to manually align the width and height to the
814 * tile boundaries.
815 */
816 if (layout->templ->format == PIPE_FORMAT_S8_UINT) {
817 layout->width = align(layout->width, 64);
818 layout->height = align(layout->height, 64);
819 }
820
821 assert(layout->width % layout->block_width == 0);
822 assert(layout->height % layout->block_height == 0);
823 assert(layout->qpitch % layout->block_height == 0);
824 }
825
826 static size_t
827 tex_layout_estimate_size(const struct tex_layout *layout)
828 {
829 unsigned stride, height;
830
831 stride = (layout->width / layout->block_width) * layout->block_size;
832 height = layout->height / layout->block_height;
833
834 switch (layout->tiling) {
835 case INTEL_TILING_X:
836 stride = align(stride, 512);
837 height = align(height, 8);
838 break;
839 case INTEL_TILING_Y:
840 stride = align(stride, 128);
841 height = align(height, 32);
842 break;
843 default:
844 height = align(height, 2);
845 break;
846 }
847
848 return stride * height;
849 }
850
851 static void
852 tex_layout_apply(const struct tex_layout *layout, struct ilo_texture *tex)
853 {
854 tex->bo_format = layout->format;
855
856 /* in blocks */
857 tex->bo_width = layout->width / layout->block_width;
858 tex->bo_height = layout->height / layout->block_height;
859 tex->bo_cpp = layout->block_size;
860 tex->tiling = layout->tiling;
861
862 tex->compressed = layout->compressed;
863 tex->block_width = layout->block_width;
864 tex->block_height = layout->block_height;
865
866 tex->halign_8 = (layout->align_i == 8);
867 tex->valign_4 = (layout->align_j == 4);
868 tex->array_spacing_full = layout->array_spacing_full;
869 tex->interleaved = layout->interleaved;
870 }
871
872 static void
873 tex_free_slices(struct ilo_texture *tex)
874 {
875 FREE(tex->slice_offsets[0]);
876 }
877
878 static bool
879 tex_alloc_slices(struct ilo_texture *tex)
880 {
881 const struct pipe_resource *templ = &tex->base;
882 struct ilo_texture_slice *slices;
883 int depth, lv;
884
885 /* sum the depths of all levels */
886 depth = 0;
887 for (lv = 0; lv <= templ->last_level; lv++)
888 depth += u_minify(templ->depth0, lv);
889
890 /*
891 * There are (depth * tex->base.array_size) slices in total. Either depth
892 * is one (non-3D) or templ->array_size is one (non-array), but it does
893 * not matter.
894 */
895 slices = CALLOC(depth * templ->array_size, sizeof(*slices));
896 if (!slices)
897 return false;
898
899 tex->slice_offsets[0] = slices;
900
901 /* point to the respective positions in the buffer */
902 for (lv = 1; lv <= templ->last_level; lv++) {
903 tex->slice_offsets[lv] = tex->slice_offsets[lv - 1] +
904 u_minify(templ->depth0, lv - 1) * templ->array_size;
905 }
906
907 return true;
908 }
909
910 static bool
911 tex_create_bo(struct ilo_texture *tex,
912 const struct winsys_handle *handle)
913 {
914 struct ilo_screen *is = ilo_screen(tex->base.screen);
915 const char *name;
916 struct intel_bo *bo;
917 enum intel_tiling_mode tiling;
918 unsigned long pitch;
919
920 switch (tex->base.target) {
921 case PIPE_TEXTURE_1D:
922 name = "1D texture";
923 break;
924 case PIPE_TEXTURE_2D:
925 name = "2D texture";
926 break;
927 case PIPE_TEXTURE_3D:
928 name = "3D texture";
929 break;
930 case PIPE_TEXTURE_CUBE:
931 name = "cube texture";
932 break;
933 case PIPE_TEXTURE_RECT:
934 name = "rectangle texture";
935 break;
936 case PIPE_TEXTURE_1D_ARRAY:
937 name = "1D array texture";
938 break;
939 case PIPE_TEXTURE_2D_ARRAY:
940 name = "2D array texture";
941 break;
942 case PIPE_TEXTURE_CUBE_ARRAY:
943 name = "cube array texture";
944 break;
945 default:
946 name ="unknown texture";
947 break;
948 }
949
950 if (handle) {
951 bo = intel_winsys_import_handle(is->winsys, name, handle,
952 tex->bo_width, tex->bo_height, tex->bo_cpp,
953 &tiling, &pitch);
954 }
955 else {
956 bo = intel_winsys_alloc_texture(is->winsys, name,
957 tex->bo_width, tex->bo_height, tex->bo_cpp,
958 tex->tiling, tex->bo_flags, &pitch);
959
960 tiling = tex->tiling;
961 }
962
963 if (!bo)
964 return false;
965
966 if (tex->bo)
967 intel_bo_unreference(tex->bo);
968
969 tex->bo = bo;
970 tex->tiling = tiling;
971 tex->bo_stride = pitch;
972
973 return true;
974 }
975
976 static bool
977 tex_create_separate_stencil(struct ilo_texture *tex)
978 {
979 struct pipe_resource templ = tex->base;
980 struct pipe_resource *s8;
981
982 /*
983 * Unless PIPE_BIND_DEPTH_STENCIL is set, the resource may have other
984 * tilings. But that should be fine since it will never be bound as the
985 * stencil buffer, and our transfer code can handle all tilings.
986 */
987 templ.format = PIPE_FORMAT_S8_UINT;
988
989 s8 = tex->base.screen->resource_create(tex->base.screen, &templ);
990 if (!s8)
991 return false;
992
993 tex->separate_s8 = ilo_texture(s8);
994
995 assert(tex->separate_s8->bo_format == PIPE_FORMAT_S8_UINT);
996
997 return true;
998 }
999
1000 static bool
1001 tex_create_hiz(struct ilo_texture *tex, const struct tex_layout *layout)
1002 {
1003 struct ilo_screen *is = ilo_screen(tex->base.screen);
1004 const struct pipe_resource *templ = layout->templ;
1005 const int hz_align_j = 8;
1006 unsigned hz_width, hz_height;
1007 unsigned long pitch;
1008 int i;
1009
1010 /*
1011 * See the Sandy Bridge PRM, volume 2 part 1, page 312, and the Ivy Bridge
1012 * PRM, volume 2 part 1, page 312-313.
1013 *
1014 * It seems HiZ buffer is aligned to 8x8, with every two rows packed into a
1015 * memory row.
1016 */
1017
1018 hz_width = align(layout->levels[0].w, 16);
1019
1020 if (templ->target == PIPE_TEXTURE_3D) {
1021 hz_height = 0;
1022
1023 for (i = 0; i <= templ->last_level; i++) {
1024 const unsigned h = align(layout->levels[i].h, hz_align_j);
1025 hz_height += h * layout->levels[i].d;
1026 }
1027
1028 hz_height /= 2;
1029 }
1030 else {
1031 const unsigned h0 = align(layout->levels[0].h, hz_align_j);
1032 unsigned hz_qpitch = h0;
1033
1034 if (layout->array_spacing_full) {
1035 const unsigned h1 = align(layout->levels[1].h, hz_align_j);
1036 const unsigned htail =
1037 ((layout->dev->gen >= ILO_GEN(7)) ? 12 : 11) * hz_align_j;
1038
1039 hz_qpitch += h1 + htail;
1040 }
1041
1042 hz_height = hz_qpitch * templ->array_size / 2;
1043
1044 if (layout->dev->gen >= ILO_GEN(7))
1045 hz_height = align(hz_height, 8);
1046 }
1047
1048 /*
1049 * On GEN6, Depth Coordinate Offsets may be set to the values returned by
1050 * ilo_texture_get_slice_offset(), which can be as large as (63, 31). Pad
1051 * the HiZ bo to avoid out-of-bound accesses.
1052 */
1053 if (layout->dev->gen == ILO_GEN(6)) {
1054 hz_width += 64;
1055 hz_height += 32 / 2;
1056 }
1057
1058 tex->hiz.bo = intel_winsys_alloc_texture(is->winsys,
1059 "hiz texture", hz_width, hz_height, 1,
1060 INTEL_TILING_Y, INTEL_ALLOC_FOR_RENDER, &pitch);
1061 if (!tex->hiz.bo)
1062 return false;
1063
1064 tex->hiz.bo_stride = pitch;
1065
1066 return true;
1067 }
1068
1069 static void
1070 tex_destroy(struct ilo_texture *tex)
1071 {
1072 if (tex->separate_s8)
1073 tex_destroy(tex->separate_s8);
1074
1075 intel_bo_unreference(tex->bo);
1076 tex_free_slices(tex);
1077 FREE(tex);
1078 }
1079
1080 static struct pipe_resource *
1081 tex_create(struct pipe_screen *screen,
1082 const struct pipe_resource *templ,
1083 const struct winsys_handle *handle)
1084 {
1085 struct tex_layout layout;
1086 struct ilo_texture *tex;
1087
1088 tex = CALLOC_STRUCT(ilo_texture);
1089 if (!tex)
1090 return NULL;
1091
1092 tex->base = *templ;
1093 tex->base.screen = screen;
1094 pipe_reference_init(&tex->base.reference, 1);
1095
1096 if (!tex_alloc_slices(tex)) {
1097 FREE(tex);
1098 return NULL;
1099 }
1100
1101 tex->imported = (handle != NULL);
1102
1103 if (tex->base.bind & (PIPE_BIND_DEPTH_STENCIL |
1104 PIPE_BIND_RENDER_TARGET))
1105 tex->bo_flags |= INTEL_ALLOC_FOR_RENDER;
1106
1107 tex_layout_init(&layout, screen, templ, tex->slice_offsets);
1108
1109 switch (templ->target) {
1110 case PIPE_TEXTURE_1D:
1111 case PIPE_TEXTURE_2D:
1112 case PIPE_TEXTURE_CUBE:
1113 case PIPE_TEXTURE_RECT:
1114 case PIPE_TEXTURE_1D_ARRAY:
1115 case PIPE_TEXTURE_2D_ARRAY:
1116 case PIPE_TEXTURE_CUBE_ARRAY:
1117 tex_layout_2d(&layout);
1118 break;
1119 case PIPE_TEXTURE_3D:
1120 tex_layout_3d(&layout);
1121 break;
1122 default:
1123 assert(!"unknown resource target");
1124 break;
1125 }
1126
1127 tex_layout_validate(&layout);
1128
1129 /* make sure the bo can be mapped through GTT if tiled */
1130 if (layout.tiling != INTEL_TILING_NONE) {
1131 /*
1132 * Usually only the first 256MB of the GTT is mappable.
1133 *
1134 * See also how intel_context::max_gtt_map_object_size is calculated.
1135 */
1136 const size_t mappable_gtt_size = 256 * 1024 * 1024;
1137 const size_t size = tex_layout_estimate_size(&layout);
1138
1139 /* be conservative */
1140 if (size > mappable_gtt_size / 4)
1141 tex_layout_force_linear(&layout);
1142 }
1143
1144 tex_layout_apply(&layout, tex);
1145
1146 if (!tex_create_bo(tex, handle)) {
1147 tex_free_slices(tex);
1148 FREE(tex);
1149 return NULL;
1150 }
1151
1152 /* allocate separate stencil resource */
1153 if (layout.separate_stencil && !tex_create_separate_stencil(tex)) {
1154 tex_destroy(tex);
1155 return NULL;
1156 }
1157
1158 if (layout.hiz)
1159 tex_create_hiz(tex, &layout);
1160
1161 return &tex->base;
1162 }
1163
1164 static bool
1165 tex_get_handle(struct ilo_texture *tex, struct winsys_handle *handle)
1166 {
1167 struct ilo_screen *is = ilo_screen(tex->base.screen);
1168 int err;
1169
1170 err = intel_winsys_export_handle(is->winsys, tex->bo,
1171 tex->tiling, tex->bo_stride, handle);
1172
1173 return !err;
1174 }
1175
1176 /**
1177 * Estimate the texture size. For large textures, the errors should be pretty
1178 * small.
1179 */
1180 static size_t
1181 tex_estimate_size(struct pipe_screen *screen,
1182 const struct pipe_resource *templ)
1183 {
1184 struct tex_layout layout;
1185
1186 tex_layout_init(&layout, screen, templ, NULL);
1187
1188 switch (templ->target) {
1189 case PIPE_TEXTURE_3D:
1190 tex_layout_3d(&layout);
1191 break;
1192 default:
1193 tex_layout_2d(&layout);
1194 break;
1195 }
1196
1197 tex_layout_validate(&layout);
1198
1199 return tex_layout_estimate_size(&layout);
1200 }
1201
1202 static bool
1203 buf_create_bo(struct ilo_buffer *buf)
1204 {
1205 struct ilo_screen *is = ilo_screen(buf->base.screen);
1206 const char *name;
1207 struct intel_bo *bo;
1208
1209 switch (buf->base.bind) {
1210 case PIPE_BIND_VERTEX_BUFFER:
1211 name = "vertex buffer";
1212 break;
1213 case PIPE_BIND_INDEX_BUFFER:
1214 name = "index buffer";
1215 break;
1216 case PIPE_BIND_CONSTANT_BUFFER:
1217 name = "constant buffer";
1218 break;
1219 case PIPE_BIND_STREAM_OUTPUT:
1220 name = "stream output";
1221 break;
1222 default:
1223 name = "unknown buffer";
1224 break;
1225 }
1226
1227 bo = intel_winsys_alloc_buffer(is->winsys,
1228 name, buf->bo_size, buf->bo_flags);
1229 if (!bo)
1230 return false;
1231
1232 if (buf->bo)
1233 intel_bo_unreference(buf->bo);
1234
1235 buf->bo = bo;
1236
1237 return true;
1238 }
1239
1240 static void
1241 buf_destroy(struct ilo_buffer *buf)
1242 {
1243 intel_bo_unreference(buf->bo);
1244 FREE(buf);
1245 }
1246
1247 static struct pipe_resource *
1248 buf_create(struct pipe_screen *screen, const struct pipe_resource *templ)
1249 {
1250 struct ilo_buffer *buf;
1251
1252 buf = CALLOC_STRUCT(ilo_buffer);
1253 if (!buf)
1254 return NULL;
1255
1256 buf->base = *templ;
1257 buf->base.screen = screen;
1258 pipe_reference_init(&buf->base.reference, 1);
1259
1260 buf->bo_size = templ->width0;
1261 buf->bo_flags = 0;
1262
1263 /*
1264 * From the Sandy Bridge PRM, volume 1 part 1, page 118:
1265 *
1266 * "For buffers, which have no inherent "height," padding requirements
1267 * are different. A buffer must be padded to the next multiple of 256
1268 * array elements, with an additional 16 bytes added beyond that to
1269 * account for the L1 cache line."
1270 */
1271 if (templ->bind & PIPE_BIND_SAMPLER_VIEW)
1272 buf->bo_size = align(buf->bo_size, 256) + 16;
1273
1274 if (!buf_create_bo(buf)) {
1275 FREE(buf);
1276 return NULL;
1277 }
1278
1279 return &buf->base;
1280 }
1281
1282 static boolean
1283 ilo_can_create_resource(struct pipe_screen *screen,
1284 const struct pipe_resource *templ)
1285 {
1286 /*
1287 * We do not know if we will fail until we try to allocate the bo.
1288 * So just set a limit on the texture size.
1289 */
1290 const size_t max_size = 1 * 1024 * 1024 * 1024;
1291 size_t size;
1292
1293 if (templ->target == PIPE_BUFFER)
1294 size = templ->width0;
1295 else
1296 size = tex_estimate_size(screen, templ);
1297
1298 return (size <= max_size);
1299 }
1300
1301 static struct pipe_resource *
1302 ilo_resource_create(struct pipe_screen *screen,
1303 const struct pipe_resource *templ)
1304 {
1305 if (templ->target == PIPE_BUFFER)
1306 return buf_create(screen, templ);
1307 else
1308 return tex_create(screen, templ, NULL);
1309 }
1310
1311 static struct pipe_resource *
1312 ilo_resource_from_handle(struct pipe_screen *screen,
1313 const struct pipe_resource *templ,
1314 struct winsys_handle *handle)
1315 {
1316 if (templ->target == PIPE_BUFFER)
1317 return NULL;
1318 else
1319 return tex_create(screen, templ, handle);
1320 }
1321
1322 static boolean
1323 ilo_resource_get_handle(struct pipe_screen *screen,
1324 struct pipe_resource *res,
1325 struct winsys_handle *handle)
1326 {
1327 if (res->target == PIPE_BUFFER)
1328 return false;
1329 else
1330 return tex_get_handle(ilo_texture(res), handle);
1331
1332 }
1333
1334 static void
1335 ilo_resource_destroy(struct pipe_screen *screen,
1336 struct pipe_resource *res)
1337 {
1338 if (res->target == PIPE_BUFFER)
1339 buf_destroy(ilo_buffer(res));
1340 else
1341 tex_destroy(ilo_texture(res));
1342 }
1343
1344 /**
1345 * Initialize resource-related functions.
1346 */
1347 void
1348 ilo_init_resource_functions(struct ilo_screen *is)
1349 {
1350 is->base.can_create_resource = ilo_can_create_resource;
1351 is->base.resource_create = ilo_resource_create;
1352 is->base.resource_from_handle = ilo_resource_from_handle;
1353 is->base.resource_get_handle = ilo_resource_get_handle;
1354 is->base.resource_destroy = ilo_resource_destroy;
1355 }
1356
1357 bool
1358 ilo_buffer_alloc_bo(struct ilo_buffer *buf)
1359 {
1360 return buf_create_bo(buf);
1361 }
1362
1363 bool
1364 ilo_texture_alloc_bo(struct ilo_texture *tex)
1365 {
1366 /* a shared bo cannot be reallocated */
1367 if (tex->imported)
1368 return false;
1369
1370 return tex_create_bo(tex, NULL);
1371 }
1372
1373 /**
1374 * Return the offset (in bytes) to a slice within the bo.
1375 *
1376 * The returned offset is aligned to tile size. Since slices are not
1377 * guaranteed to start at tile boundaries, the X and Y offsets (in pixels)
1378 * from the tile origin to the slice are also returned. X offset is always a
1379 * multiple of 4 and Y offset is always a multiple of 2.
1380 */
1381 unsigned
1382 ilo_texture_get_slice_offset(const struct ilo_texture *tex,
1383 int level, int slice,
1384 unsigned *x_offset, unsigned *y_offset)
1385 {
1386 unsigned tile_w, tile_h, tile_size, row_size;
1387 unsigned x, y, slice_offset;
1388
1389 /* see the Sandy Bridge PRM, volume 1 part 2, page 24 */
1390
1391 switch (tex->tiling) {
1392 case INTEL_TILING_NONE:
1393 /* W-tiled */
1394 if (tex->bo_format == PIPE_FORMAT_S8_UINT) {
1395 tile_w = 64;
1396 tile_h = 64;
1397 }
1398 else {
1399 tile_w = 1;
1400 tile_h = 1;
1401 }
1402 break;
1403 case INTEL_TILING_X:
1404 tile_w = 512;
1405 tile_h = 8;
1406 break;
1407 case INTEL_TILING_Y:
1408 tile_w = 128;
1409 tile_h = 32;
1410 break;
1411 default:
1412 assert(!"unknown tiling");
1413 tile_w = 1;
1414 tile_h = 1;
1415 break;
1416 }
1417
1418 tile_size = tile_w * tile_h;
1419 row_size = tex->bo_stride * tile_h;
1420
1421 /* in bytes */
1422 x = tex->slice_offsets[level][slice].x / tex->block_width * tex->bo_cpp;
1423 y = tex->slice_offsets[level][slice].y / tex->block_height;
1424 slice_offset = row_size * (y / tile_h) + tile_size * (x / tile_w);
1425
1426 /*
1427 * Since tex->bo_stride is a multiple of tile_w, slice_offset should be
1428 * aligned at this point.
1429 */
1430 assert(slice_offset % tile_size == 0);
1431
1432 /*
1433 * because of the possible values of align_i and align_j in
1434 * tex_layout_init_alignments(), x_offset is guaranteed to be a multiple of
1435 * 4 and y_offset is guaranteed to be a multiple of 2.
1436 */
1437 if (x_offset) {
1438 /* in pixels */
1439 x = (x % tile_w) / tex->bo_cpp * tex->block_width;
1440 assert(x % 4 == 0);
1441
1442 *x_offset = x;
1443 }
1444
1445 if (y_offset) {
1446 /* in pixels */
1447 y = (y % tile_h) * tex->block_height;
1448 assert(y % 2 == 0);
1449
1450 *y_offset = y;
1451 }
1452
1453 return slice_offset;
1454 }