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