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