1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (C) 2017 Rob Clark <robclark@freedesktop.org> 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 FROM, 20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21bf215546Sopenharmony_ci * SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci * Authors: 24bf215546Sopenharmony_ci * Rob Clark <robclark@freedesktop.org> 25bf215546Sopenharmony_ci */ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "freedreno_blitter.h" 28bf215546Sopenharmony_ci#include "freedreno_resource.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "fd5_blitter.h" 31bf215546Sopenharmony_ci#include "fd5_emit.h" 32bf215546Sopenharmony_ci#include "fd5_format.h" 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci/* Make sure none of the requested dimensions extend beyond the size of the 35bf215546Sopenharmony_ci * resource. Not entirely sure why this happens, but sometimes it does, and 36bf215546Sopenharmony_ci * w/ 2d blt doesn't have wrap modes like a sampler, so force those cases 37bf215546Sopenharmony_ci * back to u_blitter 38bf215546Sopenharmony_ci */ 39bf215546Sopenharmony_cistatic bool 40bf215546Sopenharmony_ciok_dims(const struct pipe_resource *r, const struct pipe_box *b, int lvl) 41bf215546Sopenharmony_ci{ 42bf215546Sopenharmony_ci return (b->x >= 0) && (b->x + b->width <= u_minify(r->width0, lvl)) && 43bf215546Sopenharmony_ci (b->y >= 0) && (b->y + b->height <= u_minify(r->height0, lvl)) && 44bf215546Sopenharmony_ci (b->z >= 0) && (b->z + b->depth <= u_minify(r->depth0, lvl)); 45bf215546Sopenharmony_ci} 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_ci/* Not sure if format restrictions differ for src and dst, or if 48bf215546Sopenharmony_ci * they only matter when src fmt != dst fmt.. but there appear to 49bf215546Sopenharmony_ci * be *some* limitations so let's just start rejecting stuff that 50bf215546Sopenharmony_ci * piglit complains about 51bf215546Sopenharmony_ci */ 52bf215546Sopenharmony_cistatic bool 53bf215546Sopenharmony_ciok_format(enum pipe_format fmt) 54bf215546Sopenharmony_ci{ 55bf215546Sopenharmony_ci if (util_format_is_compressed(fmt)) 56bf215546Sopenharmony_ci return false; 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci switch (fmt) { 59bf215546Sopenharmony_ci case PIPE_FORMAT_R10G10B10A2_SSCALED: 60bf215546Sopenharmony_ci case PIPE_FORMAT_R10G10B10A2_SNORM: 61bf215546Sopenharmony_ci case PIPE_FORMAT_B10G10R10A2_USCALED: 62bf215546Sopenharmony_ci case PIPE_FORMAT_B10G10R10A2_SSCALED: 63bf215546Sopenharmony_ci case PIPE_FORMAT_B10G10R10A2_SNORM: 64bf215546Sopenharmony_ci case PIPE_FORMAT_R10G10B10A2_UNORM: 65bf215546Sopenharmony_ci case PIPE_FORMAT_R10G10B10A2_USCALED: 66bf215546Sopenharmony_ci case PIPE_FORMAT_B10G10R10A2_UNORM: 67bf215546Sopenharmony_ci case PIPE_FORMAT_R10SG10SB10SA2U_NORM: 68bf215546Sopenharmony_ci case PIPE_FORMAT_B10G10R10A2_UINT: 69bf215546Sopenharmony_ci case PIPE_FORMAT_R10G10B10A2_UINT: 70bf215546Sopenharmony_ci return false; 71bf215546Sopenharmony_ci default: 72bf215546Sopenharmony_ci break; 73bf215546Sopenharmony_ci } 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci if (fd5_pipe2color(fmt) == RB5_NONE) 76bf215546Sopenharmony_ci return false; 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci return true; 79bf215546Sopenharmony_ci} 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_cistatic bool 82bf215546Sopenharmony_cican_do_blit(const struct pipe_blit_info *info) 83bf215546Sopenharmony_ci{ 84bf215546Sopenharmony_ci /* I think we can do scaling, but not in z dimension since that would 85bf215546Sopenharmony_ci * require blending.. 86bf215546Sopenharmony_ci */ 87bf215546Sopenharmony_ci if (info->dst.box.depth != info->src.box.depth) 88bf215546Sopenharmony_ci return false; 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci if (!ok_format(info->dst.format)) 91bf215546Sopenharmony_ci return false; 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_ci if (!ok_format(info->src.format)) 94bf215546Sopenharmony_ci return false; 95bf215546Sopenharmony_ci 96bf215546Sopenharmony_ci /* hw ignores {SRC,DST}_INFO.COLOR_SWAP if {SRC,DST}_INFO.TILE_MODE 97bf215546Sopenharmony_ci * is set (not linear). We can kind of get around that when tiling/ 98bf215546Sopenharmony_ci * untiling by setting both src and dst COLOR_SWAP=WZYX, but that 99bf215546Sopenharmony_ci * means the formats must match: 100bf215546Sopenharmony_ci */ 101bf215546Sopenharmony_ci if ((fd_resource(info->dst.resource)->layout.tile_mode || 102bf215546Sopenharmony_ci fd_resource(info->src.resource)->layout.tile_mode) && 103bf215546Sopenharmony_ci info->dst.format != info->src.format) 104bf215546Sopenharmony_ci return false; 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ci /* until we figure out a few more registers: */ 107bf215546Sopenharmony_ci if ((info->dst.box.width != info->src.box.width) || 108bf215546Sopenharmony_ci (info->dst.box.height != info->src.box.height)) 109bf215546Sopenharmony_ci return false; 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci /* src box can be inverted, which we don't support.. dst box cannot: */ 112bf215546Sopenharmony_ci if ((info->src.box.width < 0) || (info->src.box.height < 0)) 113bf215546Sopenharmony_ci return false; 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci if (!ok_dims(info->src.resource, &info->src.box, info->src.level)) 116bf215546Sopenharmony_ci return false; 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci if (!ok_dims(info->dst.resource, &info->dst.box, info->dst.level)) 119bf215546Sopenharmony_ci return false; 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci assert(info->dst.box.width >= 0); 122bf215546Sopenharmony_ci assert(info->dst.box.height >= 0); 123bf215546Sopenharmony_ci assert(info->dst.box.depth >= 0); 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci if ((info->dst.resource->nr_samples > 1) || 126bf215546Sopenharmony_ci (info->src.resource->nr_samples > 1)) 127bf215546Sopenharmony_ci return false; 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci if (info->scissor_enable) 130bf215546Sopenharmony_ci return false; 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci if (info->window_rectangle_include) 133bf215546Sopenharmony_ci return false; 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci if (info->render_condition_enable) 136bf215546Sopenharmony_ci return false; 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci if (info->alpha_blend) 139bf215546Sopenharmony_ci return false; 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci if (info->filter != PIPE_TEX_FILTER_NEAREST) 142bf215546Sopenharmony_ci return false; 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci if (info->mask != util_format_get_mask(info->src.format)) 145bf215546Sopenharmony_ci return false; 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci if (info->mask != util_format_get_mask(info->dst.format)) 148bf215546Sopenharmony_ci return false; 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci return true; 151bf215546Sopenharmony_ci} 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_cistatic void 154bf215546Sopenharmony_ciemit_setup(struct fd_ringbuffer *ring) 155bf215546Sopenharmony_ci{ 156bf215546Sopenharmony_ci OUT_PKT4(ring, REG_A5XX_RB_RENDER_CNTL, 1); 157bf215546Sopenharmony_ci OUT_RING(ring, 0x00000008); 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_ci OUT_PKT4(ring, REG_A5XX_RB_2D_BLIT_CNTL, 1); 160bf215546Sopenharmony_ci OUT_RING(ring, 0x86000000); /* RB_2D_BLIT_CNTL */ 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci OUT_PKT4(ring, REG_A5XX_GRAS_2D_BLIT_CNTL, 1); 163bf215546Sopenharmony_ci OUT_RING(ring, 0x86000000); /* 2D_BLIT_CNTL */ 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci OUT_PKT4(ring, REG_A5XX_UNKNOWN_2184, 1); 166bf215546Sopenharmony_ci OUT_RING(ring, 0x00000009); /* UNKNOWN_2184 */ 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci OUT_PKT4(ring, REG_A5XX_RB_CNTL, 1); 169bf215546Sopenharmony_ci OUT_RING(ring, A5XX_RB_CNTL_BYPASS); 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci OUT_PKT4(ring, REG_A5XX_RB_MODE_CNTL, 1); 172bf215546Sopenharmony_ci OUT_RING(ring, 0x00000004); /* RB_MODE_CNTL */ 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci OUT_PKT4(ring, REG_A5XX_SP_MODE_CNTL, 1); 175bf215546Sopenharmony_ci OUT_RING(ring, 0x0000000c); /* SP_MODE_CNTL */ 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci OUT_PKT4(ring, REG_A5XX_TPL1_MODE_CNTL, 1); 178bf215546Sopenharmony_ci OUT_RING(ring, 0x00000344); /* TPL1_MODE_CNTL */ 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci OUT_PKT4(ring, REG_A5XX_HLSQ_MODE_CNTL, 1); 181bf215546Sopenharmony_ci OUT_RING(ring, 0x00000002); /* HLSQ_MODE_CNTL */ 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_ci OUT_PKT4(ring, REG_A5XX_GRAS_CL_CNTL, 1); 184bf215546Sopenharmony_ci OUT_RING(ring, 0x00000181); /* GRAS_CL_CNTL */ 185bf215546Sopenharmony_ci} 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci/* buffers need to be handled specially since x/width can exceed the bounds 188bf215546Sopenharmony_ci * supported by hw.. if necessary decompose into (potentially) two 2D blits 189bf215546Sopenharmony_ci */ 190bf215546Sopenharmony_cistatic void 191bf215546Sopenharmony_ciemit_blit_buffer(struct fd_ringbuffer *ring, const struct pipe_blit_info *info) 192bf215546Sopenharmony_ci{ 193bf215546Sopenharmony_ci const struct pipe_box *sbox = &info->src.box; 194bf215546Sopenharmony_ci const struct pipe_box *dbox = &info->dst.box; 195bf215546Sopenharmony_ci struct fd_resource *src, *dst; 196bf215546Sopenharmony_ci unsigned sshift, dshift; 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ci src = fd_resource(info->src.resource); 199bf215546Sopenharmony_ci dst = fd_resource(info->dst.resource); 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci assert(src->layout.cpp == 1); 202bf215546Sopenharmony_ci assert(dst->layout.cpp == 1); 203bf215546Sopenharmony_ci assert(info->src.resource->format == info->dst.resource->format); 204bf215546Sopenharmony_ci assert((sbox->y == 0) && (sbox->height == 1)); 205bf215546Sopenharmony_ci assert((dbox->y == 0) && (dbox->height == 1)); 206bf215546Sopenharmony_ci assert((sbox->z == 0) && (sbox->depth == 1)); 207bf215546Sopenharmony_ci assert((dbox->z == 0) && (dbox->depth == 1)); 208bf215546Sopenharmony_ci assert(sbox->width == dbox->width); 209bf215546Sopenharmony_ci assert(info->src.level == 0); 210bf215546Sopenharmony_ci assert(info->dst.level == 0); 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci /* 213bf215546Sopenharmony_ci * Buffers can have dimensions bigger than max width, remap into 214bf215546Sopenharmony_ci * multiple 1d blits to fit within max dimension 215bf215546Sopenharmony_ci * 216bf215546Sopenharmony_ci * Note that blob uses .ARRAY_PITCH=128 for blitting buffers, which 217bf215546Sopenharmony_ci * seems to prevent overfetch related faults. Not quite sure what 218bf215546Sopenharmony_ci * the deal is there. 219bf215546Sopenharmony_ci * 220bf215546Sopenharmony_ci * Low 6 bits of SRC/DST addresses need to be zero (ie. address 221bf215546Sopenharmony_ci * aligned to 64) so we need to shift src/dst x1/x2 to make up the 222bf215546Sopenharmony_ci * difference. On top of already splitting up the blit so width 223bf215546Sopenharmony_ci * isn't > 16k. 224bf215546Sopenharmony_ci * 225bf215546Sopenharmony_ci * We perhaps could do a bit better, if src and dst are aligned but 226bf215546Sopenharmony_ci * in the worst case this means we have to split the copy up into 227bf215546Sopenharmony_ci * 16k (0x4000) minus 64 (0x40). 228bf215546Sopenharmony_ci */ 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci sshift = sbox->x & 0x3f; 231bf215546Sopenharmony_ci dshift = dbox->x & 0x3f; 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci for (unsigned off = 0; off < sbox->width; off += (0x4000 - 0x40)) { 234bf215546Sopenharmony_ci unsigned soff, doff, w, p; 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci soff = (sbox->x + off) & ~0x3f; 237bf215546Sopenharmony_ci doff = (dbox->x + off) & ~0x3f; 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_ci w = MIN2(sbox->width - off, (0x4000 - 0x40)); 240bf215546Sopenharmony_ci p = align(w, 64); 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_ci assert((soff + w) <= fd_bo_size(src->bo)); 243bf215546Sopenharmony_ci assert((doff + w) <= fd_bo_size(dst->bo)); 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci OUT_PKT7(ring, CP_SET_RENDER_MODE, 1); 246bf215546Sopenharmony_ci OUT_RING(ring, CP_SET_RENDER_MODE_0_MODE(BLIT2D)); 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_ci /* 249bf215546Sopenharmony_ci * Emit source: 250bf215546Sopenharmony_ci */ 251bf215546Sopenharmony_ci OUT_PKT4(ring, REG_A5XX_RB_2D_SRC_INFO, 9); 252bf215546Sopenharmony_ci OUT_RING(ring, A5XX_RB_2D_SRC_INFO_COLOR_FORMAT(RB5_R8_UNORM) | 253bf215546Sopenharmony_ci A5XX_RB_2D_SRC_INFO_TILE_MODE(TILE5_LINEAR) | 254bf215546Sopenharmony_ci A5XX_RB_2D_SRC_INFO_COLOR_SWAP(WZYX)); 255bf215546Sopenharmony_ci OUT_RELOC(ring, src->bo, soff, 0, 0); /* RB_2D_SRC_LO/HI */ 256bf215546Sopenharmony_ci OUT_RING(ring, A5XX_RB_2D_SRC_SIZE_PITCH(p) | 257bf215546Sopenharmony_ci A5XX_RB_2D_SRC_SIZE_ARRAY_PITCH(128)); 258bf215546Sopenharmony_ci OUT_RING(ring, 0x00000000); 259bf215546Sopenharmony_ci OUT_RING(ring, 0x00000000); 260bf215546Sopenharmony_ci OUT_RING(ring, 0x00000000); 261bf215546Sopenharmony_ci OUT_RING(ring, 0x00000000); 262bf215546Sopenharmony_ci OUT_RING(ring, 0x00000000); 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ci OUT_PKT4(ring, REG_A5XX_GRAS_2D_SRC_INFO, 1); 265bf215546Sopenharmony_ci OUT_RING(ring, A5XX_GRAS_2D_SRC_INFO_COLOR_FORMAT(RB5_R8_UNORM) | 266bf215546Sopenharmony_ci A5XX_GRAS_2D_SRC_INFO_COLOR_SWAP(WZYX)); 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ci /* 269bf215546Sopenharmony_ci * Emit destination: 270bf215546Sopenharmony_ci */ 271bf215546Sopenharmony_ci OUT_PKT4(ring, REG_A5XX_RB_2D_DST_INFO, 9); 272bf215546Sopenharmony_ci OUT_RING(ring, A5XX_RB_2D_DST_INFO_COLOR_FORMAT(RB5_R8_UNORM) | 273bf215546Sopenharmony_ci A5XX_RB_2D_DST_INFO_TILE_MODE(TILE5_LINEAR) | 274bf215546Sopenharmony_ci A5XX_RB_2D_DST_INFO_COLOR_SWAP(WZYX)); 275bf215546Sopenharmony_ci OUT_RELOC(ring, dst->bo, doff, 0, 0); /* RB_2D_DST_LO/HI */ 276bf215546Sopenharmony_ci OUT_RING(ring, A5XX_RB_2D_DST_SIZE_PITCH(p) | 277bf215546Sopenharmony_ci A5XX_RB_2D_DST_SIZE_ARRAY_PITCH(128)); 278bf215546Sopenharmony_ci OUT_RING(ring, 0x00000000); 279bf215546Sopenharmony_ci OUT_RING(ring, 0x00000000); 280bf215546Sopenharmony_ci OUT_RING(ring, 0x00000000); 281bf215546Sopenharmony_ci OUT_RING(ring, 0x00000000); 282bf215546Sopenharmony_ci OUT_RING(ring, 0x00000000); 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci OUT_PKT4(ring, REG_A5XX_GRAS_2D_DST_INFO, 1); 285bf215546Sopenharmony_ci OUT_RING(ring, A5XX_GRAS_2D_DST_INFO_COLOR_FORMAT(RB5_R8_UNORM) | 286bf215546Sopenharmony_ci A5XX_GRAS_2D_DST_INFO_COLOR_SWAP(WZYX)); 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_ci /* 289bf215546Sopenharmony_ci * Blit command: 290bf215546Sopenharmony_ci */ 291bf215546Sopenharmony_ci OUT_PKT7(ring, CP_BLIT, 5); 292bf215546Sopenharmony_ci OUT_RING(ring, CP_BLIT_0_OP(BLIT_OP_COPY)); 293bf215546Sopenharmony_ci OUT_RING(ring, CP_BLIT_1_SRC_X1(sshift) | CP_BLIT_1_SRC_Y1(0)); 294bf215546Sopenharmony_ci OUT_RING(ring, CP_BLIT_2_SRC_X2(sshift + w - 1) | CP_BLIT_2_SRC_Y2(0)); 295bf215546Sopenharmony_ci OUT_RING(ring, CP_BLIT_3_DST_X1(dshift) | CP_BLIT_3_DST_Y1(0)); 296bf215546Sopenharmony_ci OUT_RING(ring, CP_BLIT_4_DST_X2(dshift + w - 1) | CP_BLIT_4_DST_Y2(0)); 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci OUT_PKT7(ring, CP_SET_RENDER_MODE, 1); 299bf215546Sopenharmony_ci OUT_RING(ring, CP_SET_RENDER_MODE_0_MODE(END2D)); 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci OUT_WFI5(ring); 302bf215546Sopenharmony_ci } 303bf215546Sopenharmony_ci} 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_cistatic void 306bf215546Sopenharmony_ciemit_blit(struct fd_ringbuffer *ring, const struct pipe_blit_info *info) 307bf215546Sopenharmony_ci{ 308bf215546Sopenharmony_ci const struct pipe_box *sbox = &info->src.box; 309bf215546Sopenharmony_ci const struct pipe_box *dbox = &info->dst.box; 310bf215546Sopenharmony_ci struct fd_resource *src, *dst; 311bf215546Sopenharmony_ci enum a5xx_color_fmt sfmt, dfmt; 312bf215546Sopenharmony_ci enum a5xx_tile_mode stile, dtile; 313bf215546Sopenharmony_ci enum a3xx_color_swap sswap, dswap; 314bf215546Sopenharmony_ci unsigned spitch, dpitch; 315bf215546Sopenharmony_ci unsigned sx1, sy1, sx2, sy2; 316bf215546Sopenharmony_ci unsigned dx1, dy1, dx2, dy2; 317bf215546Sopenharmony_ci 318bf215546Sopenharmony_ci src = fd_resource(info->src.resource); 319bf215546Sopenharmony_ci dst = fd_resource(info->dst.resource); 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci sfmt = fd5_pipe2color(info->src.format); 322bf215546Sopenharmony_ci dfmt = fd5_pipe2color(info->dst.format); 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ci stile = fd_resource_tile_mode(info->src.resource, info->src.level); 325bf215546Sopenharmony_ci dtile = fd_resource_tile_mode(info->dst.resource, info->dst.level); 326bf215546Sopenharmony_ci 327bf215546Sopenharmony_ci sswap = fd5_pipe2swap(info->src.format); 328bf215546Sopenharmony_ci dswap = fd5_pipe2swap(info->dst.format); 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_ci spitch = fd_resource_pitch(src, info->src.level); 331bf215546Sopenharmony_ci dpitch = fd_resource_pitch(dst, info->dst.level); 332bf215546Sopenharmony_ci 333bf215546Sopenharmony_ci /* if dtile, then dswap ignored by hw, and likewise if stile then sswap 334bf215546Sopenharmony_ci * ignored by hw.. but in this case we have already rejected the blit 335bf215546Sopenharmony_ci * if src and dst formats differ, so juse use WZYX for both src and 336bf215546Sopenharmony_ci * dst swap mode (so we don't change component order) 337bf215546Sopenharmony_ci */ 338bf215546Sopenharmony_ci if (stile || dtile) { 339bf215546Sopenharmony_ci assert(info->src.format == info->dst.format); 340bf215546Sopenharmony_ci sswap = dswap = WZYX; 341bf215546Sopenharmony_ci } 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci sx1 = sbox->x; 344bf215546Sopenharmony_ci sy1 = sbox->y; 345bf215546Sopenharmony_ci sx2 = sbox->x + sbox->width - 1; 346bf215546Sopenharmony_ci sy2 = sbox->y + sbox->height - 1; 347bf215546Sopenharmony_ci 348bf215546Sopenharmony_ci dx1 = dbox->x; 349bf215546Sopenharmony_ci dy1 = dbox->y; 350bf215546Sopenharmony_ci dx2 = dbox->x + dbox->width - 1; 351bf215546Sopenharmony_ci dy2 = dbox->y + dbox->height - 1; 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_ci uint32_t sarray_pitch = fd_resource_layer_stride(src, info->src.level); 354bf215546Sopenharmony_ci uint32_t darray_pitch = fd_resource_layer_stride(dst, info->dst.level); 355bf215546Sopenharmony_ci 356bf215546Sopenharmony_ci for (unsigned i = 0; i < info->dst.box.depth; i++) { 357bf215546Sopenharmony_ci unsigned soff = fd_resource_offset(src, info->src.level, sbox->z + i); 358bf215546Sopenharmony_ci unsigned doff = fd_resource_offset(dst, info->dst.level, dbox->z + i); 359bf215546Sopenharmony_ci 360bf215546Sopenharmony_ci assert((soff + (sbox->height * spitch)) <= fd_bo_size(src->bo)); 361bf215546Sopenharmony_ci assert((doff + (dbox->height * dpitch)) <= fd_bo_size(dst->bo)); 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_ci OUT_PKT7(ring, CP_SET_RENDER_MODE, 1); 364bf215546Sopenharmony_ci OUT_RING(ring, CP_SET_RENDER_MODE_0_MODE(BLIT2D)); 365bf215546Sopenharmony_ci 366bf215546Sopenharmony_ci /* 367bf215546Sopenharmony_ci * Emit source: 368bf215546Sopenharmony_ci */ 369bf215546Sopenharmony_ci OUT_PKT4(ring, REG_A5XX_RB_2D_SRC_INFO, 9); 370bf215546Sopenharmony_ci OUT_RING(ring, A5XX_RB_2D_SRC_INFO_COLOR_FORMAT(sfmt) | 371bf215546Sopenharmony_ci A5XX_RB_2D_SRC_INFO_TILE_MODE(stile) | 372bf215546Sopenharmony_ci A5XX_RB_2D_SRC_INFO_COLOR_SWAP(sswap)); 373bf215546Sopenharmony_ci OUT_RELOC(ring, src->bo, soff, 0, 0); /* RB_2D_SRC_LO/HI */ 374bf215546Sopenharmony_ci OUT_RING(ring, A5XX_RB_2D_SRC_SIZE_PITCH(spitch) | 375bf215546Sopenharmony_ci A5XX_RB_2D_SRC_SIZE_ARRAY_PITCH(sarray_pitch)); 376bf215546Sopenharmony_ci OUT_RING(ring, 0x00000000); 377bf215546Sopenharmony_ci OUT_RING(ring, 0x00000000); 378bf215546Sopenharmony_ci OUT_RING(ring, 0x00000000); 379bf215546Sopenharmony_ci OUT_RING(ring, 0x00000000); 380bf215546Sopenharmony_ci OUT_RING(ring, 0x00000000); 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_ci OUT_PKT4(ring, REG_A5XX_GRAS_2D_SRC_INFO, 1); 383bf215546Sopenharmony_ci OUT_RING(ring, A5XX_GRAS_2D_SRC_INFO_COLOR_FORMAT(sfmt) | 384bf215546Sopenharmony_ci A5XX_GRAS_2D_SRC_INFO_TILE_MODE(stile) | 385bf215546Sopenharmony_ci A5XX_GRAS_2D_SRC_INFO_COLOR_SWAP(sswap)); 386bf215546Sopenharmony_ci 387bf215546Sopenharmony_ci /* 388bf215546Sopenharmony_ci * Emit destination: 389bf215546Sopenharmony_ci */ 390bf215546Sopenharmony_ci OUT_PKT4(ring, REG_A5XX_RB_2D_DST_INFO, 9); 391bf215546Sopenharmony_ci OUT_RING(ring, A5XX_RB_2D_DST_INFO_COLOR_FORMAT(dfmt) | 392bf215546Sopenharmony_ci A5XX_RB_2D_DST_INFO_TILE_MODE(dtile) | 393bf215546Sopenharmony_ci A5XX_RB_2D_DST_INFO_COLOR_SWAP(dswap)); 394bf215546Sopenharmony_ci OUT_RELOC(ring, dst->bo, doff, 0, 0); /* RB_2D_DST_LO/HI */ 395bf215546Sopenharmony_ci OUT_RING(ring, A5XX_RB_2D_DST_SIZE_PITCH(dpitch) | 396bf215546Sopenharmony_ci A5XX_RB_2D_DST_SIZE_ARRAY_PITCH(darray_pitch)); 397bf215546Sopenharmony_ci OUT_RING(ring, 0x00000000); 398bf215546Sopenharmony_ci OUT_RING(ring, 0x00000000); 399bf215546Sopenharmony_ci OUT_RING(ring, 0x00000000); 400bf215546Sopenharmony_ci OUT_RING(ring, 0x00000000); 401bf215546Sopenharmony_ci OUT_RING(ring, 0x00000000); 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_ci OUT_PKT4(ring, REG_A5XX_GRAS_2D_DST_INFO, 1); 404bf215546Sopenharmony_ci OUT_RING(ring, A5XX_GRAS_2D_DST_INFO_COLOR_FORMAT(dfmt) | 405bf215546Sopenharmony_ci A5XX_GRAS_2D_DST_INFO_TILE_MODE(dtile) | 406bf215546Sopenharmony_ci A5XX_GRAS_2D_DST_INFO_COLOR_SWAP(dswap)); 407bf215546Sopenharmony_ci 408bf215546Sopenharmony_ci /* 409bf215546Sopenharmony_ci * Blit command: 410bf215546Sopenharmony_ci */ 411bf215546Sopenharmony_ci OUT_PKT7(ring, CP_BLIT, 5); 412bf215546Sopenharmony_ci OUT_RING(ring, CP_BLIT_0_OP(BLIT_OP_COPY)); 413bf215546Sopenharmony_ci OUT_RING(ring, CP_BLIT_1_SRC_X1(sx1) | CP_BLIT_1_SRC_Y1(sy1)); 414bf215546Sopenharmony_ci OUT_RING(ring, CP_BLIT_2_SRC_X2(sx2) | CP_BLIT_2_SRC_Y2(sy2)); 415bf215546Sopenharmony_ci OUT_RING(ring, CP_BLIT_3_DST_X1(dx1) | CP_BLIT_3_DST_Y1(dy1)); 416bf215546Sopenharmony_ci OUT_RING(ring, CP_BLIT_4_DST_X2(dx2) | CP_BLIT_4_DST_Y2(dy2)); 417bf215546Sopenharmony_ci 418bf215546Sopenharmony_ci OUT_PKT7(ring, CP_SET_RENDER_MODE, 1); 419bf215546Sopenharmony_ci OUT_RING(ring, CP_SET_RENDER_MODE_0_MODE(END2D)); 420bf215546Sopenharmony_ci } 421bf215546Sopenharmony_ci} 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_cibool 424bf215546Sopenharmony_cifd5_blitter_blit(struct fd_context *ctx, 425bf215546Sopenharmony_ci const struct pipe_blit_info *info) assert_dt 426bf215546Sopenharmony_ci{ 427bf215546Sopenharmony_ci struct fd_batch *batch; 428bf215546Sopenharmony_ci 429bf215546Sopenharmony_ci if (!can_do_blit(info)) { 430bf215546Sopenharmony_ci return false; 431bf215546Sopenharmony_ci } 432bf215546Sopenharmony_ci 433bf215546Sopenharmony_ci struct fd_resource *src = fd_resource(info->src.resource); 434bf215546Sopenharmony_ci struct fd_resource *dst = fd_resource(info->dst.resource); 435bf215546Sopenharmony_ci 436bf215546Sopenharmony_ci batch = fd_bc_alloc_batch(ctx, true); 437bf215546Sopenharmony_ci 438bf215546Sopenharmony_ci fd_screen_lock(ctx->screen); 439bf215546Sopenharmony_ci 440bf215546Sopenharmony_ci fd_batch_resource_read(batch, src); 441bf215546Sopenharmony_ci fd_batch_resource_write(batch, dst); 442bf215546Sopenharmony_ci 443bf215546Sopenharmony_ci fd_screen_unlock(ctx->screen); 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_ci DBG_BLIT(info, batch); 446bf215546Sopenharmony_ci 447bf215546Sopenharmony_ci fd_batch_update_queries(batch); 448bf215546Sopenharmony_ci 449bf215546Sopenharmony_ci emit_setup(batch->draw); 450bf215546Sopenharmony_ci 451bf215546Sopenharmony_ci if ((info->src.resource->target == PIPE_BUFFER) && 452bf215546Sopenharmony_ci (info->dst.resource->target == PIPE_BUFFER)) { 453bf215546Sopenharmony_ci assert(fd_resource(info->src.resource)->layout.tile_mode == TILE5_LINEAR); 454bf215546Sopenharmony_ci assert(fd_resource(info->dst.resource)->layout.tile_mode == TILE5_LINEAR); 455bf215546Sopenharmony_ci emit_blit_buffer(batch->draw, info); 456bf215546Sopenharmony_ci } else { 457bf215546Sopenharmony_ci /* I don't *think* we need to handle blits between buffer <-> !buffer */ 458bf215546Sopenharmony_ci assert(info->src.resource->target != PIPE_BUFFER); 459bf215546Sopenharmony_ci assert(info->dst.resource->target != PIPE_BUFFER); 460bf215546Sopenharmony_ci emit_blit(batch->draw, info); 461bf215546Sopenharmony_ci } 462bf215546Sopenharmony_ci 463bf215546Sopenharmony_ci fd_batch_needs_flush(batch); 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci fd_batch_flush(batch); 466bf215546Sopenharmony_ci fd_batch_reference(&batch, NULL); 467bf215546Sopenharmony_ci 468bf215546Sopenharmony_ci /* Acc query state will have been dirtied by our fd_batch_update_queries, so 469bf215546Sopenharmony_ci * the ctx->batch may need to turn its queries back on. 470bf215546Sopenharmony_ci */ 471bf215546Sopenharmony_ci ctx->update_active_queries = true; 472bf215546Sopenharmony_ci 473bf215546Sopenharmony_ci return true; 474bf215546Sopenharmony_ci} 475bf215546Sopenharmony_ci 476bf215546Sopenharmony_ciunsigned 477bf215546Sopenharmony_cifd5_tile_mode(const struct pipe_resource *tmpl) 478bf215546Sopenharmony_ci{ 479bf215546Sopenharmony_ci /* basically just has to be a format we can blit, so uploads/downloads 480bf215546Sopenharmony_ci * via linear staging buffer works: 481bf215546Sopenharmony_ci */ 482bf215546Sopenharmony_ci if (ok_format(tmpl->format)) 483bf215546Sopenharmony_ci return TILE5_3; 484bf215546Sopenharmony_ci 485bf215546Sopenharmony_ci return TILE5_LINEAR; 486bf215546Sopenharmony_ci} 487