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 * Takes a utile x and y (and the number of utiles of width of the image) and
68 * returns the offset to the utile within a VC4_TILING_FORMAT_TF image.
71 t_utile_address(uint32_t utile_x
, uint32_t utile_y
,
72 uint32_t utile_stride
)
74 /* T images have to be aligned to 8 utiles (4x4 subtiles, which are
77 assert(!(utile_stride
& 7));
78 uint32_t tile_stride
= utile_stride
>> 3;
79 /* 4k tile offsets. */
80 uint32_t tile_x
= utile_x
>> 3;
81 uint32_t tile_y
= utile_y
>> 3;
82 bool odd_tile_y
= tile_y
& 1;
84 /* Odd lines of 4k tiles go right-to-left. */
86 tile_x
= tile_stride
- tile_x
- 1;
88 uint32_t tile_offset
= 4096 * (tile_y
* tile_stride
+ tile_x
);
90 uint32_t stile_x
= (utile_x
>> 2) & 1;
91 uint32_t stile_y
= (utile_y
>> 2) & 1;
92 uint32_t stile_index
= (stile_y
<< 1) + stile_x
;
93 static const uint32_t odd_stile_map
[4] = {2, 1, 3, 0};
94 static const uint32_t even_stile_map
[4] = {0, 3, 1, 2};
96 uint32_t stile_offset
= 1024 * (odd_tile_y
?
97 odd_stile_map
[stile_index
] :
98 even_stile_map
[stile_index
]);
100 /* This function no longer handles the utile offset within a subtile.
101 * Walking subtiles is the job of the LT image handler.
103 assert(!(utile_x
& 3) && !(utile_y
& 3));
106 fprintf(stderr
, "utile %d,%d -> %d + %d + %d (stride %d,%d) = %d\n",
108 tile_offset
, stile_offset
, utile_offset
,
109 utile_stride
, tile_stride
,
110 tile_offset
+ stile_offset
+ utile_offset
);
113 return tile_offset
+ stile_offset
;
117 * Loads or stores a T texture image by breaking it down into subtiles
118 * (1024-byte, 4x4-utile) sub-images that we can use the LT tiling functions
122 vc4_t_image_helper(void *gpu
, uint32_t gpu_stride
,
123 void *cpu
, uint32_t cpu_stride
,
124 int cpp
, const struct pipe_box
*box
,
127 uint32_t utile_w
= vc4_utile_width(cpp
);
128 uint32_t utile_h
= vc4_utile_height(cpp
);
129 uint32_t utile_w_shift
= ffs(utile_w
) - 1;
130 uint32_t utile_h_shift
= ffs(utile_h
) - 1;
131 uint32_t stile_w
= 4 * utile_w
;
132 uint32_t stile_h
= 4 * utile_h
;
133 assert(stile_w
* stile_h
* cpp
== 1024);
134 uint32_t utile_stride
= gpu_stride
/ cpp
/ utile_w
;
135 uint32_t x1
= box
->x
;
136 uint32_t y1
= box
->y
;
137 uint32_t x2
= box
->x
+ box
->width
;
138 uint32_t y2
= box
->y
+ box
->height
;
139 struct pipe_box partial_box
;
140 uint32_t gpu_lt_stride
= stile_w
* cpp
;
142 for (uint32_t y
= y1
; y
< y2
; y
= align(y
+ 1, stile_h
)) {
143 partial_box
.y
= y
& (stile_h
- 1);
144 partial_box
.height
= MIN2(y2
- y
, stile_h
- partial_box
.y
);
146 uint32_t cpu_offset
= 0;
147 for (uint32_t x
= x1
; x
< x2
; x
= align(x
+ 1, stile_w
)) {
148 partial_box
.x
= x
& (stile_w
- 1);
149 partial_box
.width
= MIN2(x2
- x
,
150 stile_w
- partial_box
.x
);
152 /* The dst offset we want is the start of this
155 uint32_t gpu_offset
=
156 t_utile_address((x
>> utile_w_shift
) & ~0x3,
157 (y
>> utile_h_shift
) & ~0x3,
161 vc4_load_lt_image(cpu
+ cpu_offset
,
167 vc4_store_lt_image(gpu
+ gpu_offset
,
174 cpu_offset
+= partial_box
.width
* cpp
;
176 cpu
+= cpu_stride
* partial_box
.height
;
181 vc4_store_t_image(void *dst
, uint32_t dst_stride
,
182 void *src
, uint32_t src_stride
,
183 int cpp
, const struct pipe_box
*box
)
185 vc4_t_image_helper(dst
, dst_stride
,
191 vc4_load_t_image(void *dst
, uint32_t dst_stride
,
192 void *src
, uint32_t src_stride
,
193 int cpp
, const struct pipe_box
*box
)
195 vc4_t_image_helper(src
, src_stride
,
201 * Loads pixel data from the start (microtile-aligned) box in \p src to the
202 * start of \p dst according to the given tiling format.
205 vc4_load_tiled_image(void *dst
, uint32_t dst_stride
,
206 void *src
, uint32_t src_stride
,
207 uint8_t tiling_format
, int cpp
,
208 const struct pipe_box
*box
)
210 if (tiling_format
== VC4_TILING_FORMAT_LT
) {
211 vc4_load_lt_image(dst
, dst_stride
,
215 assert(tiling_format
== VC4_TILING_FORMAT_T
);
216 vc4_load_t_image(dst
, dst_stride
,
223 * Stores pixel data from the start of \p src into a (microtile-aligned) box in
224 * \p dst according to the given tiling format.
227 vc4_store_tiled_image(void *dst
, uint32_t dst_stride
,
228 void *src
, uint32_t src_stride
,
229 uint8_t tiling_format
, int cpp
,
230 const struct pipe_box
*box
)
232 if (tiling_format
== VC4_TILING_FORMAT_LT
) {
233 vc4_store_lt_image(dst
, dst_stride
,
237 assert(tiling_format
== VC4_TILING_FORMAT_T
);
238 vc4_store_t_image(dst
, dst_stride
,