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