xref: /aosp_15_r20/external/mesa3d/src/broadcom/common/v3d_tiling.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2014-2017 Broadcom
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*61046927SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  */
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker /** @file v3d_tiling.c
25*61046927SAndroid Build Coastguard Worker  *
26*61046927SAndroid Build Coastguard Worker  * Handles information about the V3D tiling formats, and loading and storing
27*61046927SAndroid Build Coastguard Worker  * from them.
28*61046927SAndroid Build Coastguard Worker  */
29*61046927SAndroid Build Coastguard Worker 
30*61046927SAndroid Build Coastguard Worker #include <stdint.h>
31*61046927SAndroid Build Coastguard Worker #include "util/box.h"
32*61046927SAndroid Build Coastguard Worker #include "v3d_tiling.h"
33*61046927SAndroid Build Coastguard Worker #include "broadcom/common/v3d_cpu_tiling.h"
34*61046927SAndroid Build Coastguard Worker 
35*61046927SAndroid Build Coastguard Worker /** Return the width in pixels of a 64-byte microtile. */
36*61046927SAndroid Build Coastguard Worker uint32_t
v3d_utile_width(int cpp)37*61046927SAndroid Build Coastguard Worker v3d_utile_width(int cpp)
38*61046927SAndroid Build Coastguard Worker {
39*61046927SAndroid Build Coastguard Worker         switch (cpp) {
40*61046927SAndroid Build Coastguard Worker         case 1:
41*61046927SAndroid Build Coastguard Worker         case 2:
42*61046927SAndroid Build Coastguard Worker                 return 8;
43*61046927SAndroid Build Coastguard Worker         case 4:
44*61046927SAndroid Build Coastguard Worker         case 8:
45*61046927SAndroid Build Coastguard Worker                 return 4;
46*61046927SAndroid Build Coastguard Worker         case 16:
47*61046927SAndroid Build Coastguard Worker                 return 2;
48*61046927SAndroid Build Coastguard Worker         default:
49*61046927SAndroid Build Coastguard Worker                 unreachable("unknown cpp");
50*61046927SAndroid Build Coastguard Worker         }
51*61046927SAndroid Build Coastguard Worker }
52*61046927SAndroid Build Coastguard Worker 
53*61046927SAndroid Build Coastguard Worker /** Return the height in pixels of a 64-byte microtile. */
54*61046927SAndroid Build Coastguard Worker uint32_t
v3d_utile_height(int cpp)55*61046927SAndroid Build Coastguard Worker v3d_utile_height(int cpp)
56*61046927SAndroid Build Coastguard Worker {
57*61046927SAndroid Build Coastguard Worker         switch (cpp) {
58*61046927SAndroid Build Coastguard Worker         case 1:
59*61046927SAndroid Build Coastguard Worker                 return 8;
60*61046927SAndroid Build Coastguard Worker         case 2:
61*61046927SAndroid Build Coastguard Worker         case 4:
62*61046927SAndroid Build Coastguard Worker                 return 4;
63*61046927SAndroid Build Coastguard Worker         case 8:
64*61046927SAndroid Build Coastguard Worker         case 16:
65*61046927SAndroid Build Coastguard Worker                 return 2;
66*61046927SAndroid Build Coastguard Worker         default:
67*61046927SAndroid Build Coastguard Worker                 unreachable("unknown cpp");
68*61046927SAndroid Build Coastguard Worker         }
69*61046927SAndroid Build Coastguard Worker }
70*61046927SAndroid Build Coastguard Worker 
71*61046927SAndroid Build Coastguard Worker /**
72*61046927SAndroid Build Coastguard Worker  * Returns the byte address for a given pixel within a utile.
73*61046927SAndroid Build Coastguard Worker  *
74*61046927SAndroid Build Coastguard Worker  * Utiles are 64b blocks of pixels in raster order, with 32bpp being a 4x4
75*61046927SAndroid Build Coastguard Worker  * arrangement.
76*61046927SAndroid Build Coastguard Worker  */
77*61046927SAndroid Build Coastguard Worker static inline uint32_t
v3d_get_utile_pixel_offset(uint32_t cpp,uint32_t x,uint32_t y)78*61046927SAndroid Build Coastguard Worker v3d_get_utile_pixel_offset(uint32_t cpp, uint32_t x, uint32_t y)
79*61046927SAndroid Build Coastguard Worker {
80*61046927SAndroid Build Coastguard Worker         uint32_t utile_w = v3d_utile_width(cpp);
81*61046927SAndroid Build Coastguard Worker 
82*61046927SAndroid Build Coastguard Worker         assert(x < utile_w && y < v3d_utile_height(cpp));
83*61046927SAndroid Build Coastguard Worker 
84*61046927SAndroid Build Coastguard Worker         return x * cpp + y * utile_w * cpp;
85*61046927SAndroid Build Coastguard Worker }
86*61046927SAndroid Build Coastguard Worker 
87*61046927SAndroid Build Coastguard Worker /**
88*61046927SAndroid Build Coastguard Worker  * Returns the byte offset for a given pixel in a LINEARTILE layout.
89*61046927SAndroid Build Coastguard Worker  *
90*61046927SAndroid Build Coastguard Worker  * LINEARTILE is a single line of utiles in either the X or Y direction.
91*61046927SAndroid Build Coastguard Worker  */
92*61046927SAndroid Build Coastguard Worker static inline uint32_t
v3d_get_lt_pixel_offset(uint32_t cpp,uint32_t image_h,uint32_t x,uint32_t y)93*61046927SAndroid Build Coastguard Worker v3d_get_lt_pixel_offset(uint32_t cpp, uint32_t image_h, uint32_t x, uint32_t y)
94*61046927SAndroid Build Coastguard Worker {
95*61046927SAndroid Build Coastguard Worker         uint32_t utile_w = v3d_utile_width(cpp);
96*61046927SAndroid Build Coastguard Worker         uint32_t utile_h = v3d_utile_height(cpp);
97*61046927SAndroid Build Coastguard Worker         uint32_t utile_index_x = x / utile_w;
98*61046927SAndroid Build Coastguard Worker         uint32_t utile_index_y = y / utile_h;
99*61046927SAndroid Build Coastguard Worker 
100*61046927SAndroid Build Coastguard Worker         assert(utile_index_x == 0 || utile_index_y == 0);
101*61046927SAndroid Build Coastguard Worker 
102*61046927SAndroid Build Coastguard Worker         return (64 * (utile_index_x + utile_index_y) +
103*61046927SAndroid Build Coastguard Worker                 v3d_get_utile_pixel_offset(cpp,
104*61046927SAndroid Build Coastguard Worker                                            x & (utile_w - 1),
105*61046927SAndroid Build Coastguard Worker                                            y & (utile_h - 1)));
106*61046927SAndroid Build Coastguard Worker }
107*61046927SAndroid Build Coastguard Worker 
108*61046927SAndroid Build Coastguard Worker /**
109*61046927SAndroid Build Coastguard Worker  * Returns the byte offset for a given pixel in a UBLINEAR layout.
110*61046927SAndroid Build Coastguard Worker  *
111*61046927SAndroid Build Coastguard Worker  * UBLINEAR is the layout where pixels are arranged in UIF blocks (2x2
112*61046927SAndroid Build Coastguard Worker  * utiles), and the UIF blocks are in 1 or 2 columns in raster order.
113*61046927SAndroid Build Coastguard Worker  */
114*61046927SAndroid Build Coastguard Worker static inline uint32_t
v3d_get_ublinear_pixel_offset(uint32_t cpp,uint32_t x,uint32_t y,int ublinear_number)115*61046927SAndroid Build Coastguard Worker v3d_get_ublinear_pixel_offset(uint32_t cpp, uint32_t x, uint32_t y,
116*61046927SAndroid Build Coastguard Worker                               int ublinear_number)
117*61046927SAndroid Build Coastguard Worker {
118*61046927SAndroid Build Coastguard Worker         uint32_t utile_w = v3d_utile_width(cpp);
119*61046927SAndroid Build Coastguard Worker         uint32_t utile_h = v3d_utile_height(cpp);
120*61046927SAndroid Build Coastguard Worker         uint32_t ub_w = utile_w * 2;
121*61046927SAndroid Build Coastguard Worker         uint32_t ub_h = utile_h * 2;
122*61046927SAndroid Build Coastguard Worker         uint32_t ub_x = x / ub_w;
123*61046927SAndroid Build Coastguard Worker         uint32_t ub_y = y / ub_h;
124*61046927SAndroid Build Coastguard Worker 
125*61046927SAndroid Build Coastguard Worker         return (256 * (ub_y * ublinear_number +
126*61046927SAndroid Build Coastguard Worker                        ub_x) +
127*61046927SAndroid Build Coastguard Worker                 ((x & utile_w) ? 64 : 0) +
128*61046927SAndroid Build Coastguard Worker                 ((y & utile_h) ? 128 : 0) +
129*61046927SAndroid Build Coastguard Worker                 + v3d_get_utile_pixel_offset(cpp,
130*61046927SAndroid Build Coastguard Worker                                              x & (utile_w - 1),
131*61046927SAndroid Build Coastguard Worker                                              y & (utile_h - 1)));
132*61046927SAndroid Build Coastguard Worker }
133*61046927SAndroid Build Coastguard Worker 
134*61046927SAndroid Build Coastguard Worker static inline uint32_t
v3d_get_ublinear_2_column_pixel_offset(uint32_t cpp,uint32_t image_h,uint32_t x,uint32_t y)135*61046927SAndroid Build Coastguard Worker v3d_get_ublinear_2_column_pixel_offset(uint32_t cpp, uint32_t image_h,
136*61046927SAndroid Build Coastguard Worker                                        uint32_t x, uint32_t y)
137*61046927SAndroid Build Coastguard Worker {
138*61046927SAndroid Build Coastguard Worker         return v3d_get_ublinear_pixel_offset(cpp, x, y, 2);
139*61046927SAndroid Build Coastguard Worker }
140*61046927SAndroid Build Coastguard Worker 
141*61046927SAndroid Build Coastguard Worker static inline uint32_t
v3d_get_ublinear_1_column_pixel_offset(uint32_t cpp,uint32_t image_h,uint32_t x,uint32_t y)142*61046927SAndroid Build Coastguard Worker v3d_get_ublinear_1_column_pixel_offset(uint32_t cpp, uint32_t image_h,
143*61046927SAndroid Build Coastguard Worker                                        uint32_t x, uint32_t y)
144*61046927SAndroid Build Coastguard Worker {
145*61046927SAndroid Build Coastguard Worker         return v3d_get_ublinear_pixel_offset(cpp, x, y, 1);
146*61046927SAndroid Build Coastguard Worker }
147*61046927SAndroid Build Coastguard Worker 
148*61046927SAndroid Build Coastguard Worker /**
149*61046927SAndroid Build Coastguard Worker  * Returns the byte offset for a given pixel in a UIF layout.
150*61046927SAndroid Build Coastguard Worker  *
151*61046927SAndroid Build Coastguard Worker  * UIF is the general V3D tiling layout shared across 3D, media, and scanout.
152*61046927SAndroid Build Coastguard Worker  * It stores pixels in UIF blocks (2x2 utiles), and UIF blocks are stored in
153*61046927SAndroid Build Coastguard Worker  * 4x4 groups, and those 4x4 groups are then stored in raster order.
154*61046927SAndroid Build Coastguard Worker  */
155*61046927SAndroid Build Coastguard Worker static inline uint32_t
v3d_get_uif_pixel_offset(uint32_t cpp,uint32_t image_h,uint32_t x,uint32_t y,bool do_xor)156*61046927SAndroid Build Coastguard Worker v3d_get_uif_pixel_offset(uint32_t cpp, uint32_t image_h, uint32_t x, uint32_t y,
157*61046927SAndroid Build Coastguard Worker                          bool do_xor)
158*61046927SAndroid Build Coastguard Worker {
159*61046927SAndroid Build Coastguard Worker         uint32_t utile_w = v3d_utile_width(cpp);
160*61046927SAndroid Build Coastguard Worker         uint32_t utile_h = v3d_utile_height(cpp);
161*61046927SAndroid Build Coastguard Worker         uint32_t mb_width = utile_w * 2;
162*61046927SAndroid Build Coastguard Worker         uint32_t mb_height = utile_h * 2;
163*61046927SAndroid Build Coastguard Worker         uint32_t log2_mb_width = ffs(mb_width) - 1;
164*61046927SAndroid Build Coastguard Worker         uint32_t log2_mb_height = ffs(mb_height) - 1;
165*61046927SAndroid Build Coastguard Worker 
166*61046927SAndroid Build Coastguard Worker         /* Macroblock X, y */
167*61046927SAndroid Build Coastguard Worker         uint32_t mb_x = x >> log2_mb_width;
168*61046927SAndroid Build Coastguard Worker         uint32_t mb_y = y >> log2_mb_height;
169*61046927SAndroid Build Coastguard Worker         /* X, y within the macroblock */
170*61046927SAndroid Build Coastguard Worker         uint32_t mb_pixel_x = x - (mb_x << log2_mb_width);
171*61046927SAndroid Build Coastguard Worker         uint32_t mb_pixel_y = y - (mb_y << log2_mb_height);
172*61046927SAndroid Build Coastguard Worker 
173*61046927SAndroid Build Coastguard Worker         if (do_xor && (mb_x / 4) & 1)
174*61046927SAndroid Build Coastguard Worker                 mb_y ^= 0x10;
175*61046927SAndroid Build Coastguard Worker 
176*61046927SAndroid Build Coastguard Worker         uint32_t mb_h = align(image_h, 1 << log2_mb_height) >> log2_mb_height;
177*61046927SAndroid Build Coastguard Worker         uint32_t mb_id = ((mb_x / 4) * ((mb_h - 1) * 4)) + mb_x + mb_y * 4;
178*61046927SAndroid Build Coastguard Worker 
179*61046927SAndroid Build Coastguard Worker         uint32_t mb_base_addr = mb_id * 256;
180*61046927SAndroid Build Coastguard Worker 
181*61046927SAndroid Build Coastguard Worker         bool top = mb_pixel_y < utile_h;
182*61046927SAndroid Build Coastguard Worker         bool left = mb_pixel_x < utile_w;
183*61046927SAndroid Build Coastguard Worker 
184*61046927SAndroid Build Coastguard Worker         /* Docs have this in pixels, we do bytes here. */
185*61046927SAndroid Build Coastguard Worker         uint32_t mb_tile_offset = (!top * 128 + !left * 64);
186*61046927SAndroid Build Coastguard Worker 
187*61046927SAndroid Build Coastguard Worker         uint32_t utile_x = mb_pixel_x & (utile_w - 1);
188*61046927SAndroid Build Coastguard Worker         uint32_t utile_y = mb_pixel_y & (utile_h - 1);
189*61046927SAndroid Build Coastguard Worker 
190*61046927SAndroid Build Coastguard Worker         uint32_t mb_pixel_address = (mb_base_addr +
191*61046927SAndroid Build Coastguard Worker                                      mb_tile_offset +
192*61046927SAndroid Build Coastguard Worker                                      v3d_get_utile_pixel_offset(cpp,
193*61046927SAndroid Build Coastguard Worker                                                                 utile_x,
194*61046927SAndroid Build Coastguard Worker                                                                 utile_y));
195*61046927SAndroid Build Coastguard Worker 
196*61046927SAndroid Build Coastguard Worker         return mb_pixel_address;
197*61046927SAndroid Build Coastguard Worker }
198*61046927SAndroid Build Coastguard Worker 
199*61046927SAndroid Build Coastguard Worker static inline uint32_t
v3d_get_uif_xor_pixel_offset(uint32_t cpp,uint32_t image_h,uint32_t x,uint32_t y)200*61046927SAndroid Build Coastguard Worker v3d_get_uif_xor_pixel_offset(uint32_t cpp, uint32_t image_h,
201*61046927SAndroid Build Coastguard Worker                              uint32_t x, uint32_t y)
202*61046927SAndroid Build Coastguard Worker {
203*61046927SAndroid Build Coastguard Worker         return v3d_get_uif_pixel_offset(cpp, image_h, x, y, true);
204*61046927SAndroid Build Coastguard Worker }
205*61046927SAndroid Build Coastguard Worker 
206*61046927SAndroid Build Coastguard Worker static inline uint32_t
v3d_get_uif_no_xor_pixel_offset(uint32_t cpp,uint32_t image_h,uint32_t x,uint32_t y)207*61046927SAndroid Build Coastguard Worker v3d_get_uif_no_xor_pixel_offset(uint32_t cpp, uint32_t image_h,
208*61046927SAndroid Build Coastguard Worker                                 uint32_t x, uint32_t y)
209*61046927SAndroid Build Coastguard Worker {
210*61046927SAndroid Build Coastguard Worker         return v3d_get_uif_pixel_offset(cpp, image_h, x, y, false);
211*61046927SAndroid Build Coastguard Worker }
212*61046927SAndroid Build Coastguard Worker 
213*61046927SAndroid Build Coastguard Worker /* Loads/stores non-utile-aligned boxes by walking over the destination
214*61046927SAndroid Build Coastguard Worker  * rectangle, computing the address on the GPU, and storing/loading a pixel at
215*61046927SAndroid Build Coastguard Worker  * a time.
216*61046927SAndroid Build Coastguard Worker  */
217*61046927SAndroid Build Coastguard Worker static inline void
v3d_move_pixels_unaligned(void * gpu,uint32_t gpu_stride,void * cpu,uint32_t cpu_stride,int cpp,uint32_t image_h,const struct pipe_box * box,uint32_t (* get_pixel_offset)(uint32_t cpp,uint32_t image_h,uint32_t x,uint32_t y),bool is_load)218*61046927SAndroid Build Coastguard Worker v3d_move_pixels_unaligned(void *gpu, uint32_t gpu_stride,
219*61046927SAndroid Build Coastguard Worker                           void *cpu, uint32_t cpu_stride,
220*61046927SAndroid Build Coastguard Worker                           int cpp, uint32_t image_h,
221*61046927SAndroid Build Coastguard Worker                           const struct pipe_box *box,
222*61046927SAndroid Build Coastguard Worker                           uint32_t (*get_pixel_offset)(uint32_t cpp,
223*61046927SAndroid Build Coastguard Worker                                                        uint32_t image_h,
224*61046927SAndroid Build Coastguard Worker                                                        uint32_t x, uint32_t y),
225*61046927SAndroid Build Coastguard Worker                           bool is_load)
226*61046927SAndroid Build Coastguard Worker {
227*61046927SAndroid Build Coastguard Worker         for (uint32_t y = 0; y < box->height; y++) {
228*61046927SAndroid Build Coastguard Worker                 void *cpu_row = cpu + y * cpu_stride;
229*61046927SAndroid Build Coastguard Worker 
230*61046927SAndroid Build Coastguard Worker                 for (int x = 0; x < box->width; x++) {
231*61046927SAndroid Build Coastguard Worker                         uint32_t pixel_offset = get_pixel_offset(cpp, image_h,
232*61046927SAndroid Build Coastguard Worker                                                                  box->x + x,
233*61046927SAndroid Build Coastguard Worker                                                                  box->y + y);
234*61046927SAndroid Build Coastguard Worker 
235*61046927SAndroid Build Coastguard Worker                         if (false) {
236*61046927SAndroid Build Coastguard Worker                                 fprintf(stderr, "%3d,%3d -> %d\n",
237*61046927SAndroid Build Coastguard Worker                                         box->x + x, box->y + y,
238*61046927SAndroid Build Coastguard Worker                                         pixel_offset);
239*61046927SAndroid Build Coastguard Worker                         }
240*61046927SAndroid Build Coastguard Worker 
241*61046927SAndroid Build Coastguard Worker                         if (is_load) {
242*61046927SAndroid Build Coastguard Worker                                 memcpy(cpu_row + x * cpp,
243*61046927SAndroid Build Coastguard Worker                                        gpu + pixel_offset,
244*61046927SAndroid Build Coastguard Worker                                        cpp);
245*61046927SAndroid Build Coastguard Worker                         } else {
246*61046927SAndroid Build Coastguard Worker                                 memcpy(gpu + pixel_offset,
247*61046927SAndroid Build Coastguard Worker                                        cpu_row + x * cpp,
248*61046927SAndroid Build Coastguard Worker                                        cpp);
249*61046927SAndroid Build Coastguard Worker                         }
250*61046927SAndroid Build Coastguard Worker                 }
251*61046927SAndroid Build Coastguard Worker         }
252*61046927SAndroid Build Coastguard Worker }
253*61046927SAndroid Build Coastguard Worker 
254*61046927SAndroid Build Coastguard Worker /* Breaks the image down into utiles and calls either the fast whole-utile
255*61046927SAndroid Build Coastguard Worker  * load/store functions, or the unaligned fallback case.
256*61046927SAndroid Build Coastguard Worker  */
257*61046927SAndroid Build Coastguard Worker static inline void
v3d_move_pixels_general_percpp(void * gpu,uint32_t gpu_stride,void * cpu,uint32_t cpu_stride,int cpp,uint32_t image_h,const struct pipe_box * box,uint32_t (* get_pixel_offset)(uint32_t cpp,uint32_t image_h,uint32_t x,uint32_t y),bool is_load)258*61046927SAndroid Build Coastguard Worker v3d_move_pixels_general_percpp(void *gpu, uint32_t gpu_stride,
259*61046927SAndroid Build Coastguard Worker                                void *cpu, uint32_t cpu_stride,
260*61046927SAndroid Build Coastguard Worker                                int cpp, uint32_t image_h,
261*61046927SAndroid Build Coastguard Worker                                const struct pipe_box *box,
262*61046927SAndroid Build Coastguard Worker                                uint32_t (*get_pixel_offset)(uint32_t cpp,
263*61046927SAndroid Build Coastguard Worker                                                             uint32_t image_h,
264*61046927SAndroid Build Coastguard Worker                                                             uint32_t x, uint32_t y),
265*61046927SAndroid Build Coastguard Worker                                bool is_load)
266*61046927SAndroid Build Coastguard Worker {
267*61046927SAndroid Build Coastguard Worker         uint32_t utile_w = v3d_utile_width(cpp);
268*61046927SAndroid Build Coastguard Worker         uint32_t utile_h = v3d_utile_height(cpp);
269*61046927SAndroid Build Coastguard Worker         uint32_t utile_gpu_stride = utile_w * cpp;
270*61046927SAndroid Build Coastguard Worker         uint32_t x1 = box->x;
271*61046927SAndroid Build Coastguard Worker         uint32_t y1 = box->y;
272*61046927SAndroid Build Coastguard Worker         uint32_t x2 = box->x + box->width;
273*61046927SAndroid Build Coastguard Worker         uint32_t y2 = box->y + box->height;
274*61046927SAndroid Build Coastguard Worker         uint32_t align_x1 = align(x1, utile_w);
275*61046927SAndroid Build Coastguard Worker         uint32_t align_y1 = align(y1, utile_h);
276*61046927SAndroid Build Coastguard Worker         uint32_t align_x2 = x2 & ~(utile_w - 1);
277*61046927SAndroid Build Coastguard Worker         uint32_t align_y2 = y2 & ~(utile_h - 1);
278*61046927SAndroid Build Coastguard Worker 
279*61046927SAndroid Build Coastguard Worker         /* Load/store all the whole utiles first. */
280*61046927SAndroid Build Coastguard Worker         for (uint32_t y = align_y1; y < align_y2; y += utile_h) {
281*61046927SAndroid Build Coastguard Worker                 void *cpu_row = cpu + (y - box->y) * cpu_stride;
282*61046927SAndroid Build Coastguard Worker 
283*61046927SAndroid Build Coastguard Worker                 for (uint32_t x = align_x1; x < align_x2; x += utile_w) {
284*61046927SAndroid Build Coastguard Worker                         void *utile_gpu = (gpu +
285*61046927SAndroid Build Coastguard Worker                                            get_pixel_offset(cpp, image_h, x, y));
286*61046927SAndroid Build Coastguard Worker                         void *utile_cpu = cpu_row + (x - box->x) * cpp;
287*61046927SAndroid Build Coastguard Worker 
288*61046927SAndroid Build Coastguard Worker                         if (is_load) {
289*61046927SAndroid Build Coastguard Worker                                 v3d_load_utile(utile_cpu, cpu_stride,
290*61046927SAndroid Build Coastguard Worker                                                utile_gpu, utile_gpu_stride);
291*61046927SAndroid Build Coastguard Worker                         } else {
292*61046927SAndroid Build Coastguard Worker                                 v3d_store_utile(utile_gpu, utile_gpu_stride,
293*61046927SAndroid Build Coastguard Worker                                                 utile_cpu, cpu_stride);
294*61046927SAndroid Build Coastguard Worker                         }
295*61046927SAndroid Build Coastguard Worker                 }
296*61046927SAndroid Build Coastguard Worker         }
297*61046927SAndroid Build Coastguard Worker 
298*61046927SAndroid Build Coastguard Worker         /* If there were no aligned utiles in the middle, load/store the whole
299*61046927SAndroid Build Coastguard Worker          * thing unaligned.
300*61046927SAndroid Build Coastguard Worker          */
301*61046927SAndroid Build Coastguard Worker         if (align_y2 <= align_y1 ||
302*61046927SAndroid Build Coastguard Worker             align_x2 <= align_x1) {
303*61046927SAndroid Build Coastguard Worker                 v3d_move_pixels_unaligned(gpu, gpu_stride,
304*61046927SAndroid Build Coastguard Worker                                           cpu, cpu_stride,
305*61046927SAndroid Build Coastguard Worker                                           cpp, image_h,
306*61046927SAndroid Build Coastguard Worker                                           box,
307*61046927SAndroid Build Coastguard Worker                                           get_pixel_offset, is_load);
308*61046927SAndroid Build Coastguard Worker                 return;
309*61046927SAndroid Build Coastguard Worker         }
310*61046927SAndroid Build Coastguard Worker 
311*61046927SAndroid Build Coastguard Worker         /* Load/store the partial utiles. */
312*61046927SAndroid Build Coastguard Worker         struct pipe_box partial_boxes[4] = {
313*61046927SAndroid Build Coastguard Worker                 /* Top */
314*61046927SAndroid Build Coastguard Worker                 {
315*61046927SAndroid Build Coastguard Worker                         .x = x1,
316*61046927SAndroid Build Coastguard Worker                         .width = x2 - x1,
317*61046927SAndroid Build Coastguard Worker                         .y = y1,
318*61046927SAndroid Build Coastguard Worker                         .height = align_y1 - y1,
319*61046927SAndroid Build Coastguard Worker                 },
320*61046927SAndroid Build Coastguard Worker                 /* Bottom */
321*61046927SAndroid Build Coastguard Worker                 {
322*61046927SAndroid Build Coastguard Worker                         .x = x1,
323*61046927SAndroid Build Coastguard Worker                         .width = x2 - x1,
324*61046927SAndroid Build Coastguard Worker                         .y = align_y2,
325*61046927SAndroid Build Coastguard Worker                         .height = y2 - align_y2,
326*61046927SAndroid Build Coastguard Worker                 },
327*61046927SAndroid Build Coastguard Worker                 /* Left */
328*61046927SAndroid Build Coastguard Worker                 {
329*61046927SAndroid Build Coastguard Worker                         .x = x1,
330*61046927SAndroid Build Coastguard Worker                         .width = align_x1 - x1,
331*61046927SAndroid Build Coastguard Worker                         .y = align_y1,
332*61046927SAndroid Build Coastguard Worker                         .height = align_y2 - align_y1,
333*61046927SAndroid Build Coastguard Worker                 },
334*61046927SAndroid Build Coastguard Worker                 /* Right */
335*61046927SAndroid Build Coastguard Worker                 {
336*61046927SAndroid Build Coastguard Worker                         .x = align_x2,
337*61046927SAndroid Build Coastguard Worker                         .width = x2 - align_x2,
338*61046927SAndroid Build Coastguard Worker                         .y = align_y1,
339*61046927SAndroid Build Coastguard Worker                         .height = align_y2 - align_y1,
340*61046927SAndroid Build Coastguard Worker                 },
341*61046927SAndroid Build Coastguard Worker         };
342*61046927SAndroid Build Coastguard Worker         for (int i = 0; i < ARRAY_SIZE(partial_boxes); i++) {
343*61046927SAndroid Build Coastguard Worker                 void *partial_cpu = (cpu +
344*61046927SAndroid Build Coastguard Worker                                      (partial_boxes[i].y - y1) * cpu_stride +
345*61046927SAndroid Build Coastguard Worker                                      (partial_boxes[i].x - x1) * cpp);
346*61046927SAndroid Build Coastguard Worker 
347*61046927SAndroid Build Coastguard Worker                 v3d_move_pixels_unaligned(gpu, gpu_stride,
348*61046927SAndroid Build Coastguard Worker                                           partial_cpu, cpu_stride,
349*61046927SAndroid Build Coastguard Worker                                           cpp, image_h,
350*61046927SAndroid Build Coastguard Worker                                           &partial_boxes[i],
351*61046927SAndroid Build Coastguard Worker                                           get_pixel_offset, is_load);
352*61046927SAndroid Build Coastguard Worker         }
353*61046927SAndroid Build Coastguard Worker }
354*61046927SAndroid Build Coastguard Worker 
355*61046927SAndroid Build Coastguard Worker static inline void
v3d_move_pixels_general(void * gpu,uint32_t gpu_stride,void * cpu,uint32_t cpu_stride,int cpp,uint32_t image_h,const struct pipe_box * box,uint32_t (* get_pixel_offset)(uint32_t cpp,uint32_t image_h,uint32_t x,uint32_t y),bool is_load)356*61046927SAndroid Build Coastguard Worker v3d_move_pixels_general(void *gpu, uint32_t gpu_stride,
357*61046927SAndroid Build Coastguard Worker                                void *cpu, uint32_t cpu_stride,
358*61046927SAndroid Build Coastguard Worker                                int cpp, uint32_t image_h,
359*61046927SAndroid Build Coastguard Worker                                const struct pipe_box *box,
360*61046927SAndroid Build Coastguard Worker                                uint32_t (*get_pixel_offset)(uint32_t cpp,
361*61046927SAndroid Build Coastguard Worker                                                             uint32_t image_h,
362*61046927SAndroid Build Coastguard Worker                                                             uint32_t x, uint32_t y),
363*61046927SAndroid Build Coastguard Worker                                bool is_load)
364*61046927SAndroid Build Coastguard Worker {
365*61046927SAndroid Build Coastguard Worker         switch (cpp) {
366*61046927SAndroid Build Coastguard Worker         case 1:
367*61046927SAndroid Build Coastguard Worker                 v3d_move_pixels_general_percpp(gpu, gpu_stride,
368*61046927SAndroid Build Coastguard Worker                                                cpu, cpu_stride,
369*61046927SAndroid Build Coastguard Worker                                                1, image_h, box,
370*61046927SAndroid Build Coastguard Worker                                                get_pixel_offset,
371*61046927SAndroid Build Coastguard Worker                                                is_load);
372*61046927SAndroid Build Coastguard Worker                 break;
373*61046927SAndroid Build Coastguard Worker         case 2:
374*61046927SAndroid Build Coastguard Worker                 v3d_move_pixels_general_percpp(gpu, gpu_stride,
375*61046927SAndroid Build Coastguard Worker                                                cpu, cpu_stride,
376*61046927SAndroid Build Coastguard Worker                                                2, image_h, box,
377*61046927SAndroid Build Coastguard Worker                                                get_pixel_offset,
378*61046927SAndroid Build Coastguard Worker                                                is_load);
379*61046927SAndroid Build Coastguard Worker                 break;
380*61046927SAndroid Build Coastguard Worker         case 4:
381*61046927SAndroid Build Coastguard Worker                 v3d_move_pixels_general_percpp(gpu, gpu_stride,
382*61046927SAndroid Build Coastguard Worker                                                cpu, cpu_stride,
383*61046927SAndroid Build Coastguard Worker                                                4, image_h, box,
384*61046927SAndroid Build Coastguard Worker                                                get_pixel_offset,
385*61046927SAndroid Build Coastguard Worker                                                is_load);
386*61046927SAndroid Build Coastguard Worker                 break;
387*61046927SAndroid Build Coastguard Worker         case 8:
388*61046927SAndroid Build Coastguard Worker                 v3d_move_pixels_general_percpp(gpu, gpu_stride,
389*61046927SAndroid Build Coastguard Worker                                                cpu, cpu_stride,
390*61046927SAndroid Build Coastguard Worker                                                8, image_h, box,
391*61046927SAndroid Build Coastguard Worker                                                get_pixel_offset,
392*61046927SAndroid Build Coastguard Worker                                                is_load);
393*61046927SAndroid Build Coastguard Worker                 break;
394*61046927SAndroid Build Coastguard Worker         case 16:
395*61046927SAndroid Build Coastguard Worker                 v3d_move_pixels_general_percpp(gpu, gpu_stride,
396*61046927SAndroid Build Coastguard Worker                                                cpu, cpu_stride,
397*61046927SAndroid Build Coastguard Worker                                                16, image_h, box,
398*61046927SAndroid Build Coastguard Worker                                                get_pixel_offset,
399*61046927SAndroid Build Coastguard Worker                                                is_load);
400*61046927SAndroid Build Coastguard Worker                 break;
401*61046927SAndroid Build Coastguard Worker         }
402*61046927SAndroid Build Coastguard Worker }
403*61046927SAndroid Build Coastguard Worker 
404*61046927SAndroid Build Coastguard Worker static inline void
v3d_move_tiled_image(void * gpu,uint32_t gpu_stride,void * cpu,uint32_t cpu_stride,enum v3d_tiling_mode tiling_format,int cpp,uint32_t image_h,const struct pipe_box * box,bool is_load)405*61046927SAndroid Build Coastguard Worker v3d_move_tiled_image(void *gpu, uint32_t gpu_stride,
406*61046927SAndroid Build Coastguard Worker                      void *cpu, uint32_t cpu_stride,
407*61046927SAndroid Build Coastguard Worker                      enum v3d_tiling_mode tiling_format,
408*61046927SAndroid Build Coastguard Worker                      int cpp,
409*61046927SAndroid Build Coastguard Worker                      uint32_t image_h,
410*61046927SAndroid Build Coastguard Worker                      const struct pipe_box *box,
411*61046927SAndroid Build Coastguard Worker                      bool is_load)
412*61046927SAndroid Build Coastguard Worker {
413*61046927SAndroid Build Coastguard Worker         switch (tiling_format) {
414*61046927SAndroid Build Coastguard Worker         case V3D_TILING_UIF_XOR:
415*61046927SAndroid Build Coastguard Worker                 v3d_move_pixels_general(gpu, gpu_stride,
416*61046927SAndroid Build Coastguard Worker                                         cpu, cpu_stride,
417*61046927SAndroid Build Coastguard Worker                                         cpp, image_h, box,
418*61046927SAndroid Build Coastguard Worker                                         v3d_get_uif_xor_pixel_offset,
419*61046927SAndroid Build Coastguard Worker                                         is_load);
420*61046927SAndroid Build Coastguard Worker                 break;
421*61046927SAndroid Build Coastguard Worker         case V3D_TILING_UIF_NO_XOR:
422*61046927SAndroid Build Coastguard Worker                 v3d_move_pixels_general(gpu, gpu_stride,
423*61046927SAndroid Build Coastguard Worker                                         cpu, cpu_stride,
424*61046927SAndroid Build Coastguard Worker                                         cpp, image_h, box,
425*61046927SAndroid Build Coastguard Worker                                         v3d_get_uif_no_xor_pixel_offset,
426*61046927SAndroid Build Coastguard Worker                                         is_load);
427*61046927SAndroid Build Coastguard Worker                 break;
428*61046927SAndroid Build Coastguard Worker         case V3D_TILING_UBLINEAR_2_COLUMN:
429*61046927SAndroid Build Coastguard Worker                 v3d_move_pixels_general(gpu, gpu_stride,
430*61046927SAndroid Build Coastguard Worker                                         cpu, cpu_stride,
431*61046927SAndroid Build Coastguard Worker                                         cpp, image_h, box,
432*61046927SAndroid Build Coastguard Worker                                         v3d_get_ublinear_2_column_pixel_offset,
433*61046927SAndroid Build Coastguard Worker                                         is_load);
434*61046927SAndroid Build Coastguard Worker                 break;
435*61046927SAndroid Build Coastguard Worker         case V3D_TILING_UBLINEAR_1_COLUMN:
436*61046927SAndroid Build Coastguard Worker                 v3d_move_pixels_general(gpu, gpu_stride,
437*61046927SAndroid Build Coastguard Worker                                         cpu, cpu_stride,
438*61046927SAndroid Build Coastguard Worker                                         cpp, image_h, box,
439*61046927SAndroid Build Coastguard Worker                                         v3d_get_ublinear_1_column_pixel_offset,
440*61046927SAndroid Build Coastguard Worker                                         is_load);
441*61046927SAndroid Build Coastguard Worker                 break;
442*61046927SAndroid Build Coastguard Worker         case V3D_TILING_LINEARTILE:
443*61046927SAndroid Build Coastguard Worker                 v3d_move_pixels_general(gpu, gpu_stride,
444*61046927SAndroid Build Coastguard Worker                                         cpu, cpu_stride,
445*61046927SAndroid Build Coastguard Worker                                         cpp, image_h, box,
446*61046927SAndroid Build Coastguard Worker                                         v3d_get_lt_pixel_offset,
447*61046927SAndroid Build Coastguard Worker                                         is_load);
448*61046927SAndroid Build Coastguard Worker                 break;
449*61046927SAndroid Build Coastguard Worker         default:
450*61046927SAndroid Build Coastguard Worker                 unreachable("Unsupported tiling format");
451*61046927SAndroid Build Coastguard Worker                 break;
452*61046927SAndroid Build Coastguard Worker         }
453*61046927SAndroid Build Coastguard Worker }
454*61046927SAndroid Build Coastguard Worker 
455*61046927SAndroid Build Coastguard Worker /**
456*61046927SAndroid Build Coastguard Worker  * Loads pixel data from the start (microtile-aligned) box in \p src to the
457*61046927SAndroid Build Coastguard Worker  * start of \p dst according to the given tiling format.
458*61046927SAndroid Build Coastguard Worker  */
459*61046927SAndroid Build Coastguard Worker void
v3d_load_tiled_image(void * dst,uint32_t dst_stride,void * src,uint32_t src_stride,enum v3d_tiling_mode tiling_format,int cpp,uint32_t image_h,const struct pipe_box * box)460*61046927SAndroid Build Coastguard Worker v3d_load_tiled_image(void *dst, uint32_t dst_stride,
461*61046927SAndroid Build Coastguard Worker                      void *src, uint32_t src_stride,
462*61046927SAndroid Build Coastguard Worker                      enum v3d_tiling_mode tiling_format, int cpp,
463*61046927SAndroid Build Coastguard Worker                      uint32_t image_h,
464*61046927SAndroid Build Coastguard Worker                      const struct pipe_box *box)
465*61046927SAndroid Build Coastguard Worker {
466*61046927SAndroid Build Coastguard Worker         v3d_move_tiled_image(src, src_stride,
467*61046927SAndroid Build Coastguard Worker                              dst, dst_stride,
468*61046927SAndroid Build Coastguard Worker                              tiling_format,
469*61046927SAndroid Build Coastguard Worker                              cpp,
470*61046927SAndroid Build Coastguard Worker                              image_h,
471*61046927SAndroid Build Coastguard Worker                              box,
472*61046927SAndroid Build Coastguard Worker                              true);
473*61046927SAndroid Build Coastguard Worker }
474*61046927SAndroid Build Coastguard Worker 
475*61046927SAndroid Build Coastguard Worker /**
476*61046927SAndroid Build Coastguard Worker  * Stores pixel data from the start of \p src into a (microtile-aligned) box in
477*61046927SAndroid Build Coastguard Worker  * \p dst according to the given tiling format.
478*61046927SAndroid Build Coastguard Worker  */
479*61046927SAndroid Build Coastguard Worker void
v3d_store_tiled_image(void * dst,uint32_t dst_stride,void * src,uint32_t src_stride,enum v3d_tiling_mode tiling_format,int cpp,uint32_t image_h,const struct pipe_box * box)480*61046927SAndroid Build Coastguard Worker v3d_store_tiled_image(void *dst, uint32_t dst_stride,
481*61046927SAndroid Build Coastguard Worker                       void *src, uint32_t src_stride,
482*61046927SAndroid Build Coastguard Worker                       enum v3d_tiling_mode tiling_format, int cpp,
483*61046927SAndroid Build Coastguard Worker                       uint32_t image_h,
484*61046927SAndroid Build Coastguard Worker                       const struct pipe_box *box)
485*61046927SAndroid Build Coastguard Worker {
486*61046927SAndroid Build Coastguard Worker         v3d_move_tiled_image(dst, dst_stride,
487*61046927SAndroid Build Coastguard Worker                              src, src_stride,
488*61046927SAndroid Build Coastguard Worker                              tiling_format,
489*61046927SAndroid Build Coastguard Worker                              cpp,
490*61046927SAndroid Build Coastguard Worker                              image_h,
491*61046927SAndroid Build Coastguard Worker                              box,
492*61046927SAndroid Build Coastguard Worker                              false);
493*61046927SAndroid Build Coastguard Worker }
494