1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (C) 2022 Lima Project 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * SPDX-License-Identifier: MIT 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci */ 7bf215546Sopenharmony_ci 8bf215546Sopenharmony_ci#include "drm-uapi/lima_drm.h" 9bf215546Sopenharmony_ci 10bf215546Sopenharmony_ci#include "util/u_math.h" 11bf215546Sopenharmony_ci#include "util/format/u_format.h" 12bf215546Sopenharmony_ci#include "util/u_surface.h" 13bf215546Sopenharmony_ci#include "util/u_inlines.h" 14bf215546Sopenharmony_ci#include "util/hash_table.h" 15bf215546Sopenharmony_ci 16bf215546Sopenharmony_ci#include "lima_context.h" 17bf215546Sopenharmony_ci#include "lima_gpu.h" 18bf215546Sopenharmony_ci#include "lima_resource.h" 19bf215546Sopenharmony_ci#include "lima_texture.h" 20bf215546Sopenharmony_ci#include "lima_format.h" 21bf215546Sopenharmony_ci#include "lima_job.h" 22bf215546Sopenharmony_ci#include "lima_screen.h" 23bf215546Sopenharmony_ci#include "lima_bo.h" 24bf215546Sopenharmony_ci#include "lima_parser.h" 25bf215546Sopenharmony_ci#include "lima_util.h" 26bf215546Sopenharmony_ci#include "lima_blit.h" 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_civoid 29bf215546Sopenharmony_cilima_pack_blit_cmd(struct lima_job *job, 30bf215546Sopenharmony_ci struct util_dynarray *cmd_array, 31bf215546Sopenharmony_ci struct pipe_surface *psurf, 32bf215546Sopenharmony_ci const struct pipe_box *src, 33bf215546Sopenharmony_ci const struct pipe_box *dst, 34bf215546Sopenharmony_ci unsigned filter, 35bf215546Sopenharmony_ci bool scissor, 36bf215546Sopenharmony_ci unsigned sample_mask, 37bf215546Sopenharmony_ci unsigned mrt_idx) 38bf215546Sopenharmony_ci{ 39bf215546Sopenharmony_ci #define lima_blit_render_state_offset 0x0000 40bf215546Sopenharmony_ci #define lima_blit_gl_pos_offset 0x0040 41bf215546Sopenharmony_ci #define lima_blit_varying_offset 0x0080 42bf215546Sopenharmony_ci #define lima_blit_tex_desc_offset 0x00c0 43bf215546Sopenharmony_ci #define lima_blit_tex_array_offset 0x0100 44bf215546Sopenharmony_ci #define lima_blit_buffer_size 0x0140 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci struct lima_context *ctx = job->ctx; 47bf215546Sopenharmony_ci struct lima_surface *surf = lima_surface(psurf); 48bf215546Sopenharmony_ci int level = psurf->u.tex.level; 49bf215546Sopenharmony_ci unsigned first_layer = psurf->u.tex.first_layer; 50bf215546Sopenharmony_ci float fb_width = dst->width, fb_height = dst->height; 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci uint32_t va; 53bf215546Sopenharmony_ci void *cpu = lima_job_create_stream_bo( 54bf215546Sopenharmony_ci job, LIMA_PIPE_PP, lima_blit_buffer_size, &va); 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci struct lima_screen *screen = lima_screen(ctx->base.screen); 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci uint32_t reload_shader_first_instr_size = 59bf215546Sopenharmony_ci ((uint32_t *)(screen->pp_buffer->map + pp_reload_program_offset))[0] & 0x1f; 60bf215546Sopenharmony_ci uint32_t reload_shader_va = screen->pp_buffer->va + pp_reload_program_offset; 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci struct lima_render_state reload_render_state = { 63bf215546Sopenharmony_ci .alpha_blend = 0xf03b1ad2, 64bf215546Sopenharmony_ci .depth_test = 0x0000000e, 65bf215546Sopenharmony_ci .depth_range = 0xffff0000, 66bf215546Sopenharmony_ci .stencil_front = 0x00000007, 67bf215546Sopenharmony_ci .stencil_back = 0x00000007, 68bf215546Sopenharmony_ci .multi_sample = 0x00000007, 69bf215546Sopenharmony_ci .shader_address = reload_shader_va | reload_shader_first_instr_size, 70bf215546Sopenharmony_ci .varying_types = 0x00000001, 71bf215546Sopenharmony_ci .textures_address = va + lima_blit_tex_array_offset, 72bf215546Sopenharmony_ci .aux0 = 0x00004021, 73bf215546Sopenharmony_ci .varyings_address = va + lima_blit_varying_offset, 74bf215546Sopenharmony_ci }; 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ci reload_render_state.multi_sample |= (sample_mask << 12); 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci if (job->key.cbuf) { 79bf215546Sopenharmony_ci fb_width = job->key.cbuf->width; 80bf215546Sopenharmony_ci fb_height = job->key.cbuf->height; 81bf215546Sopenharmony_ci } else { 82bf215546Sopenharmony_ci fb_width = job->key.zsbuf->width; 83bf215546Sopenharmony_ci fb_height = job->key.zsbuf->height; 84bf215546Sopenharmony_ci } 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_ci if (util_format_is_depth_or_stencil(psurf->format)) { 87bf215546Sopenharmony_ci reload_render_state.alpha_blend &= 0x0fffffff; 88bf215546Sopenharmony_ci if (psurf->format != PIPE_FORMAT_Z16_UNORM) 89bf215546Sopenharmony_ci reload_render_state.depth_test |= 0x400; 90bf215546Sopenharmony_ci if (surf->reload & PIPE_CLEAR_DEPTH) 91bf215546Sopenharmony_ci reload_render_state.depth_test |= 0x801; 92bf215546Sopenharmony_ci if (surf->reload & PIPE_CLEAR_STENCIL) { 93bf215546Sopenharmony_ci reload_render_state.depth_test |= 0x1000; 94bf215546Sopenharmony_ci reload_render_state.stencil_front = 0x0000024f; 95bf215546Sopenharmony_ci reload_render_state.stencil_back = 0x0000024f; 96bf215546Sopenharmony_ci reload_render_state.stencil_test = 0x0000ffff; 97bf215546Sopenharmony_ci } 98bf215546Sopenharmony_ci } 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci memcpy(cpu + lima_blit_render_state_offset, &reload_render_state, 101bf215546Sopenharmony_ci sizeof(reload_render_state)); 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci lima_tex_desc *td = cpu + lima_blit_tex_desc_offset; 104bf215546Sopenharmony_ci memset(td, 0, lima_min_tex_desc_size); 105bf215546Sopenharmony_ci lima_texture_desc_set_res(ctx, td, psurf->texture, level, level, 106bf215546Sopenharmony_ci first_layer, mrt_idx); 107bf215546Sopenharmony_ci td->format = lima_format_get_texel_reload(psurf->format); 108bf215546Sopenharmony_ci td->unnorm_coords = 1; 109bf215546Sopenharmony_ci td->sampler_dim = LIMA_SAMPLER_DIM_2D; 110bf215546Sopenharmony_ci td->min_img_filter_nearest = 1; 111bf215546Sopenharmony_ci td->mag_img_filter_nearest = 1; 112bf215546Sopenharmony_ci td->wrap_s = LIMA_TEX_WRAP_CLAMP_TO_EDGE; 113bf215546Sopenharmony_ci td->wrap_t = LIMA_TEX_WRAP_CLAMP_TO_EDGE; 114bf215546Sopenharmony_ci td->wrap_r = LIMA_TEX_WRAP_CLAMP_TO_EDGE; 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_ci if (filter != PIPE_TEX_FILTER_NEAREST) { 117bf215546Sopenharmony_ci td->min_img_filter_nearest = 0; 118bf215546Sopenharmony_ci td->mag_img_filter_nearest = 0; 119bf215546Sopenharmony_ci } 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci uint32_t *ta = cpu + lima_blit_tex_array_offset; 122bf215546Sopenharmony_ci ta[0] = va + lima_blit_tex_desc_offset; 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci float reload_gl_pos[] = { 125bf215546Sopenharmony_ci dst->x + dst->width, dst->y, 0, 1, 126bf215546Sopenharmony_ci dst->x, dst->y, 0, 1, 127bf215546Sopenharmony_ci dst->x, dst->y + dst->height, 0, 1, 128bf215546Sopenharmony_ci }; 129bf215546Sopenharmony_ci memcpy(cpu + lima_blit_gl_pos_offset, reload_gl_pos, 130bf215546Sopenharmony_ci sizeof(reload_gl_pos)); 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci float reload_varying[] = { 133bf215546Sopenharmony_ci src->x + src->width, src->y, 134bf215546Sopenharmony_ci src->x, src->y, 135bf215546Sopenharmony_ci src->x, src->y + src->height, 136bf215546Sopenharmony_ci 0, 0, /* unused */ 137bf215546Sopenharmony_ci }; 138bf215546Sopenharmony_ci memcpy(cpu + lima_blit_varying_offset, reload_varying, 139bf215546Sopenharmony_ci sizeof(reload_varying)); 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci PLBU_CMD_BEGIN(cmd_array, scissor ? 22 : 20); 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ci PLBU_CMD_VIEWPORT_LEFT(0); 144bf215546Sopenharmony_ci PLBU_CMD_VIEWPORT_RIGHT(fui(fb_width)); 145bf215546Sopenharmony_ci PLBU_CMD_VIEWPORT_BOTTOM(0); 146bf215546Sopenharmony_ci PLBU_CMD_VIEWPORT_TOP(fui(fb_height)); 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci PLBU_CMD_RSW_VERTEX_ARRAY( 149bf215546Sopenharmony_ci va + lima_blit_render_state_offset, 150bf215546Sopenharmony_ci va + lima_blit_gl_pos_offset); 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci if (scissor) { 154bf215546Sopenharmony_ci int minx = MIN2(dst->x, dst->x + dst->width); 155bf215546Sopenharmony_ci int maxx = MAX2(dst->x, dst->x + dst->width); 156bf215546Sopenharmony_ci int miny = MIN2(dst->y, dst->y + dst->height); 157bf215546Sopenharmony_ci int maxy = MAX2(dst->y, dst->y + dst->height); 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_ci PLBU_CMD_SCISSORS(minx, maxx, miny, maxy); 160bf215546Sopenharmony_ci lima_damage_rect_union(&job->damage_rect, minx, maxx, miny, maxy); 161bf215546Sopenharmony_ci } 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_ci PLBU_CMD_UNKNOWN2(); 164bf215546Sopenharmony_ci PLBU_CMD_UNKNOWN1(); 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci PLBU_CMD_INDICES(screen->pp_buffer->va + pp_shared_index_offset); 167bf215546Sopenharmony_ci PLBU_CMD_INDEXED_DEST(va + lima_blit_gl_pos_offset); 168bf215546Sopenharmony_ci PLBU_CMD_DRAW_ELEMENTS(0xf, 0, 3); 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci PLBU_CMD_END(); 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci lima_dump_command_stream_print(job->dump, cpu, lima_blit_buffer_size, 173bf215546Sopenharmony_ci false, "blit plbu cmd at va %x\n", va); 174bf215546Sopenharmony_ci} 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_cistatic struct pipe_surface * 177bf215546Sopenharmony_cilima_get_blit_surface(struct pipe_context *pctx, 178bf215546Sopenharmony_ci struct pipe_resource *prsc, 179bf215546Sopenharmony_ci unsigned level) 180bf215546Sopenharmony_ci{ 181bf215546Sopenharmony_ci struct pipe_surface tmpl; 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_ci memset(&tmpl, 0, sizeof(tmpl)); 184bf215546Sopenharmony_ci tmpl.format = prsc->format; 185bf215546Sopenharmony_ci tmpl.u.tex.level = level; 186bf215546Sopenharmony_ci tmpl.u.tex.first_layer = 0; 187bf215546Sopenharmony_ci tmpl.u.tex.last_layer = 0; 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci return pctx->create_surface(pctx, prsc, &tmpl); 190bf215546Sopenharmony_ci} 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_cibool 193bf215546Sopenharmony_cilima_do_blit(struct pipe_context *pctx, 194bf215546Sopenharmony_ci const struct pipe_blit_info *info) 195bf215546Sopenharmony_ci{ 196bf215546Sopenharmony_ci struct lima_context *ctx = lima_context(pctx); 197bf215546Sopenharmony_ci unsigned reload_flags = PIPE_CLEAR_COLOR0; 198bf215546Sopenharmony_ci uint8_t identity[4] = { PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, 199bf215546Sopenharmony_ci PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W }; 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci if (lima_debug & LIMA_DEBUG_NO_BLIT) 202bf215546Sopenharmony_ci return false; 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci /* Blitting of swizzled formats (R and RG) isn't implemented yet */ 205bf215546Sopenharmony_ci if (memcmp(identity, 206bf215546Sopenharmony_ci lima_format_get_texel_swizzle(info->src.resource->format), 207bf215546Sopenharmony_ci sizeof(identity))) 208bf215546Sopenharmony_ci return false; 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci if (memcmp(identity, 211bf215546Sopenharmony_ci lima_format_get_texel_swizzle(info->dst.resource->format), 212bf215546Sopenharmony_ci sizeof(identity))) 213bf215546Sopenharmony_ci return false; 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci if (util_format_is_depth_or_stencil(info->src.resource->format)) { 216bf215546Sopenharmony_ci const struct util_format_description *desc = 217bf215546Sopenharmony_ci util_format_description(info->src.resource->format); 218bf215546Sopenharmony_ci reload_flags = 0; 219bf215546Sopenharmony_ci if (util_format_has_depth(desc)) 220bf215546Sopenharmony_ci reload_flags |= PIPE_CLEAR_DEPTH; 221bf215546Sopenharmony_ci if (util_format_has_stencil(desc)) 222bf215546Sopenharmony_ci reload_flags |= PIPE_CLEAR_STENCIL; 223bf215546Sopenharmony_ci } 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_ci if (!lima_format_pixel_supported(info->dst.resource->format)) 226bf215546Sopenharmony_ci return false; 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci if (!lima_format_texel_supported(info->src.resource->format)) 229bf215546Sopenharmony_ci return false; 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci if (info->dst.resource->target != PIPE_TEXTURE_2D || 232bf215546Sopenharmony_ci info->src.resource->target != PIPE_TEXTURE_2D) 233bf215546Sopenharmony_ci return false; 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ci if (info->dst.box.x < 0 || info->dst.box.y < 0 || 236bf215546Sopenharmony_ci info->src.box.x < 0 || info->src.box.y < 0) 237bf215546Sopenharmony_ci return false; 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_ci if (info->src.box.depth != 1 || 240bf215546Sopenharmony_ci info->dst.box.depth != 1) 241bf215546Sopenharmony_ci return false; 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci /* Scissored blit isn't implemented yet */ 244bf215546Sopenharmony_ci if (info->scissor_enable) 245bf215546Sopenharmony_ci return false; 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_ci if ((reload_flags & PIPE_CLEAR_COLOR) && !(info->mask & PIPE_MASK_RGBA)) 248bf215546Sopenharmony_ci return false; 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci if ((reload_flags & PIPE_CLEAR_DEPTH) && !(info->mask & PIPE_MASK_Z)) 251bf215546Sopenharmony_ci return false; 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci if ((reload_flags & PIPE_CLEAR_STENCIL) && !(info->mask & PIPE_MASK_S)) 254bf215546Sopenharmony_ci return false; 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci struct pipe_surface *dst_surf = 257bf215546Sopenharmony_ci lima_get_blit_surface(pctx, info->dst.resource, info->dst.level); 258bf215546Sopenharmony_ci struct lima_surface *lima_dst_surf = lima_surface(dst_surf); 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ci struct pipe_surface *src_surf = 261bf215546Sopenharmony_ci lima_get_blit_surface(pctx, info->src.resource, info->src.level); 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci struct lima_job *job; 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_ci if (util_format_is_depth_or_stencil(info->dst.resource->format)) 266bf215546Sopenharmony_ci job = lima_job_get_with_fb(ctx, NULL, dst_surf); 267bf215546Sopenharmony_ci else 268bf215546Sopenharmony_ci job = lima_job_get_with_fb(ctx, dst_surf, NULL); 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci struct lima_resource *src_res = lima_resource(src_surf->texture); 271bf215546Sopenharmony_ci struct lima_resource *dst_res = lima_resource(dst_surf->texture); 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci lima_flush_job_accessing_bo(ctx, src_res->bo, true); 274bf215546Sopenharmony_ci lima_flush_job_accessing_bo(ctx, dst_res->bo, true); 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ci lima_job_add_bo(job, LIMA_PIPE_PP, src_res->bo, LIMA_SUBMIT_BO_READ); 277bf215546Sopenharmony_ci _mesa_hash_table_insert(ctx->write_jobs, &dst_res->base, job); 278bf215546Sopenharmony_ci lima_job_add_bo(job, LIMA_PIPE_PP, dst_res->bo, LIMA_SUBMIT_BO_WRITE); 279bf215546Sopenharmony_ci 280bf215546Sopenharmony_ci if (info->src.resource->nr_samples > 1) { 281bf215546Sopenharmony_ci for (int i = 0; i < MIN2(info->src.resource->nr_samples, LIMA_MAX_SAMPLES); i++) { 282bf215546Sopenharmony_ci lima_pack_blit_cmd(job, &job->plbu_cmd_array, 283bf215546Sopenharmony_ci src_surf, &info->src.box, 284bf215546Sopenharmony_ci &info->dst.box, info->filter, true, 285bf215546Sopenharmony_ci 1 << i, i); 286bf215546Sopenharmony_ci } 287bf215546Sopenharmony_ci } else { 288bf215546Sopenharmony_ci lima_pack_blit_cmd(job, &job->plbu_cmd_array, 289bf215546Sopenharmony_ci src_surf, &info->src.box, 290bf215546Sopenharmony_ci &info->dst.box, info->filter, true, 291bf215546Sopenharmony_ci 0xf, 0); 292bf215546Sopenharmony_ci } 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci bool tile_aligned = false; 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci if (info->dst.box.x == 0 && info->dst.box.y == 0 && 297bf215546Sopenharmony_ci info->dst.box.width == lima_dst_surf->base.width && 298bf215546Sopenharmony_ci info->dst.box.height == lima_dst_surf->base.height) 299bf215546Sopenharmony_ci tile_aligned = true; 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci if (info->dst.box.x % 16 == 0 && info->dst.box.y % 16 == 0 && 302bf215546Sopenharmony_ci info->dst.box.width % 16 == 0 && info->dst.box.height % 16 == 0) 303bf215546Sopenharmony_ci tile_aligned = true; 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci /* Reload if dest is not aligned to tile boundaries */ 306bf215546Sopenharmony_ci if (!tile_aligned) 307bf215546Sopenharmony_ci lima_dst_surf->reload = reload_flags; 308bf215546Sopenharmony_ci else 309bf215546Sopenharmony_ci lima_dst_surf->reload = 0; 310bf215546Sopenharmony_ci 311bf215546Sopenharmony_ci job->resolve = reload_flags; 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_ci lima_do_job(job); 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_ci pipe_surface_reference(&dst_surf, NULL); 316bf215546Sopenharmony_ci pipe_surface_reference(&src_surf, NULL); 317bf215546Sopenharmony_ci 318bf215546Sopenharmony_ci return true; 319bf215546Sopenharmony_ci} 320