2 * Copyright © 2014 Broadcom
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 /** @file vc4_tiling.c
26 * Handles information about the VC4 tiling formats, and loading and storing
29 * Texture mipmap levels on VC4 are (with the exception of 32-bit RGBA raster
30 * textures for scanout) stored as groups of microtiles. If the texture is at
31 * least 4x4 microtiles (utiles), then those microtiles are arranged in a sort
32 * of Hilbert-fractal-ish layout (T), otherwise the microtiles are in raster
35 * Specifically, the T format has:
37 * - 64b utiles of pixels in a raster-order grid according to cpp. It's 4x4
38 * pixels at 32 bit depth.
40 * - 1k subtiles made of a 4x4 raster-order grid of 64b utiles (so usually
43 * - 4k tiles made of a 2x2 grid of 1k subtiles (so usually 32x32 pixels). On
44 * even 4k tile rows, they're arranged as (BL, TL, TR, BR), and on odd rows
45 * they're (TR, BR, BL, TL), where bottom left is start of memory.
47 * - an image made of 4k tiles in rows either left-to-right (even rows of 4k
48 * tiles) or right-to-left (odd rows of 4k tiles).
51 #include "vc4_screen.h"
52 #include "vc4_context.h"
53 #include "vc4_tiling.h"
56 * The texture unit decides what tiling format a particular miplevel is using
57 * this function, so we lay out our miptrees accordingly.
60 vc4_size_is_lt(uint32_t width
, uint32_t height
, int cpp
)
62 return (width
<= 4 * vc4_utile_width(cpp
) ||
63 height
<= 4 * vc4_utile_height(cpp
));
67 check_box_utile_alignment(const struct pipe_box
*box
, int cpp
)
69 assert(!(box
->x
& (vc4_utile_width(cpp
) - 1)));
70 assert(!(box
->y
& (vc4_utile_height(cpp
) - 1)));
71 assert(!(box
->width
& (vc4_utile_width(cpp
) - 1)));
72 assert(!(box
->height
& (vc4_utile_height(cpp
) - 1)));
76 * Takes a utile x and y (and the number of utiles of width of the image) and
77 * returns the offset to the utile within a VC4_TILING_FORMAT_TF image.
80 t_utile_address(uint32_t utile_x
, uint32_t utile_y
,
81 uint32_t utile_stride
)
83 /* T images have to be aligned to 8 utiles (4x4 subtiles, which are
86 assert(!(utile_stride
& 7));
87 uint32_t tile_stride
= utile_stride
>> 3;
88 /* 4k tile offsets. */
89 uint32_t tile_x
= utile_x
>> 3;
90 uint32_t tile_y
= utile_y
>> 3;
91 bool odd_tile_y
= tile_y
& 1;
93 /* Odd lines of 4k tiles go right-to-left. */
95 tile_x
= tile_stride
- tile_x
- 1;
97 uint32_t tile_offset
= 4096 * (tile_y
* tile_stride
+ tile_x
);
99 uint32_t stile_x
= (utile_x
>> 2) & 1;
100 uint32_t stile_y
= (utile_y
>> 2) & 1;
101 uint32_t stile_index
= (stile_y
<< 1) + stile_x
;
102 static const uint32_t odd_stile_map
[4] = {2, 1, 3, 0};
103 static const uint32_t even_stile_map
[4] = {0, 3, 1, 2};
105 uint32_t stile_offset
= 1024 * (odd_tile_y
?
106 odd_stile_map
[stile_index
] :
107 even_stile_map
[stile_index
]);
109 /* This function no longer handles the utile offset within a subtile.
110 * Walking subtiles is the job of the LT image handler.
112 assert(!(utile_x
& 3) && !(utile_y
& 3));
115 fprintf(stderr
, "utile %d,%d -> %d + %d + %d (stride %d,%d) = %d\n",
117 tile_offset
, stile_offset
, utile_offset
,
118 utile_stride
, tile_stride
,
119 tile_offset
+ stile_offset
+ utile_offset
);
122 return tile_offset
+ stile_offset
;
126 * Loads or stores a T texture image by breaking it down into subtiles
127 * (1024-byte, 4x4-utile) sub-images that we can use the LT tiling functions
131 vc4_t_image_helper(void *gpu
, uint32_t gpu_stride
,
132 void *cpu
, uint32_t cpu_stride
,
133 int cpp
, const struct pipe_box
*box
,
136 uint32_t utile_w
= vc4_utile_width(cpp
);
137 uint32_t utile_h
= vc4_utile_height(cpp
);
138 uint32_t utile_w_shift
= ffs(utile_w
) - 1;
139 uint32_t utile_h_shift
= ffs(utile_h
) - 1;
140 uint32_t stile_w
= 4 * utile_w
;
141 uint32_t stile_h
= 4 * utile_h
;
142 assert(stile_w
* stile_h
* cpp
== 1024);
143 uint32_t utile_stride
= gpu_stride
/ cpp
/ utile_w
;
144 uint32_t x1
= box
->x
;
145 uint32_t y1
= box
->y
;
146 uint32_t x2
= box
->x
+ box
->width
;
147 uint32_t y2
= box
->y
+ box
->height
;
148 struct pipe_box partial_box
;
149 uint32_t gpu_lt_stride
= stile_w
* cpp
;
151 for (uint32_t y
= y1
; y
< y2
; y
= align(y
+ 1, stile_h
)) {
152 partial_box
.y
= y
& (stile_h
- 1);
153 partial_box
.height
= MIN2(y2
- y
, stile_h
- partial_box
.y
);
155 uint32_t cpu_offset
= 0;
156 for (uint32_t x
= x1
; x
< x2
; x
= align(x
+ 1, stile_w
)) {
157 partial_box
.x
= x
& (stile_w
- 1);
158 partial_box
.width
= MIN2(x2
- x
,
159 stile_w
- partial_box
.x
);
161 /* The dst offset we want is the start of this
164 uint32_t gpu_offset
=
165 t_utile_address((x
>> utile_w_shift
) & ~0x3,
166 (y
>> utile_h_shift
) & ~0x3,
170 vc4_load_lt_image(cpu
+ cpu_offset
,
176 vc4_store_lt_image(gpu
+ gpu_offset
,
183 cpu_offset
+= partial_box
.width
* cpp
;
185 cpu
+= cpu_stride
* partial_box
.height
;
190 vc4_store_t_image(void *dst
, uint32_t dst_stride
,
191 void *src
, uint32_t src_stride
,
192 int cpp
, const struct pipe_box
*box
)
194 vc4_t_image_helper(dst
, dst_stride
,
200 vc4_load_t_image(void *dst
, uint32_t dst_stride
,
201 void *src
, uint32_t src_stride
,
202 int cpp
, const struct pipe_box
*box
)
204 vc4_t_image_helper(src
, src_stride
,
210 * Loads pixel data from the start (microtile-aligned) box in \p src to the
211 * start of \p dst according to the given tiling format.
214 vc4_load_tiled_image(void *dst
, uint32_t dst_stride
,
215 void *src
, uint32_t src_stride
,
216 uint8_t tiling_format
, int cpp
,
217 const struct pipe_box
*box
)
219 check_box_utile_alignment(box
, cpp
);
221 if (tiling_format
== VC4_TILING_FORMAT_LT
) {
222 vc4_load_lt_image(dst
, dst_stride
,
226 assert(tiling_format
== VC4_TILING_FORMAT_T
);
227 vc4_load_t_image(dst
, dst_stride
,
234 * Stores pixel data from the start of \p src into a (microtile-aligned) box in
235 * \p dst according to the given tiling format.
238 vc4_store_tiled_image(void *dst
, uint32_t dst_stride
,
239 void *src
, uint32_t src_stride
,
240 uint8_t tiling_format
, int cpp
,
241 const struct pipe_box
*box
)
243 check_box_utile_alignment(box
, cpp
);
245 if (tiling_format
== VC4_TILING_FORMAT_LT
) {
246 vc4_store_lt_image(dst
, dst_stride
,
250 assert(tiling_format
== VC4_TILING_FORMAT_T
);
251 vc4_store_t_image(dst
, dst_stride
,