1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2015 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#include "util/format/u_format.h" 25bf215546Sopenharmony_ci#include "util/u_surface.h" 26bf215546Sopenharmony_ci#include "util/u_blitter.h" 27bf215546Sopenharmony_ci#include "compiler/nir/nir_builder.h" 28bf215546Sopenharmony_ci#include "vc4_context.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_cistatic struct pipe_surface * 31bf215546Sopenharmony_civc4_get_blit_surface(struct pipe_context *pctx, 32bf215546Sopenharmony_ci struct pipe_resource *prsc, unsigned level) 33bf215546Sopenharmony_ci{ 34bf215546Sopenharmony_ci struct pipe_surface tmpl; 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci memset(&tmpl, 0, sizeof(tmpl)); 37bf215546Sopenharmony_ci tmpl.format = prsc->format; 38bf215546Sopenharmony_ci tmpl.u.tex.level = level; 39bf215546Sopenharmony_ci tmpl.u.tex.first_layer = 0; 40bf215546Sopenharmony_ci tmpl.u.tex.last_layer = 0; 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci return pctx->create_surface(pctx, prsc, &tmpl); 43bf215546Sopenharmony_ci} 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_cistatic bool 46bf215546Sopenharmony_ciis_tile_unaligned(unsigned size, unsigned tile_size) 47bf215546Sopenharmony_ci{ 48bf215546Sopenharmony_ci return size & (tile_size - 1); 49bf215546Sopenharmony_ci} 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_cistatic bool 52bf215546Sopenharmony_civc4_tile_blit(struct pipe_context *pctx, const struct pipe_blit_info *info) 53bf215546Sopenharmony_ci{ 54bf215546Sopenharmony_ci struct vc4_context *vc4 = vc4_context(pctx); 55bf215546Sopenharmony_ci bool msaa = (info->src.resource->nr_samples > 1 || 56bf215546Sopenharmony_ci info->dst.resource->nr_samples > 1); 57bf215546Sopenharmony_ci int tile_width = msaa ? 32 : 64; 58bf215546Sopenharmony_ci int tile_height = msaa ? 32 : 64; 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ci if (util_format_is_depth_or_stencil(info->dst.resource->format)) 61bf215546Sopenharmony_ci return false; 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci if (info->scissor_enable) 64bf215546Sopenharmony_ci return false; 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci if ((info->mask & PIPE_MASK_RGBA) == 0) 67bf215546Sopenharmony_ci return false; 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci if (info->dst.box.x != info->src.box.x || 70bf215546Sopenharmony_ci info->dst.box.y != info->src.box.y || 71bf215546Sopenharmony_ci info->dst.box.width != info->src.box.width || 72bf215546Sopenharmony_ci info->dst.box.height != info->src.box.height) { 73bf215546Sopenharmony_ci return false; 74bf215546Sopenharmony_ci } 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ci int dst_surface_width = u_minify(info->dst.resource->width0, 77bf215546Sopenharmony_ci info->dst.level); 78bf215546Sopenharmony_ci int dst_surface_height = u_minify(info->dst.resource->height0, 79bf215546Sopenharmony_ci info->dst.level); 80bf215546Sopenharmony_ci if (is_tile_unaligned(info->dst.box.x, tile_width) || 81bf215546Sopenharmony_ci is_tile_unaligned(info->dst.box.y, tile_height) || 82bf215546Sopenharmony_ci (is_tile_unaligned(info->dst.box.width, tile_width) && 83bf215546Sopenharmony_ci info->dst.box.x + info->dst.box.width != dst_surface_width) || 84bf215546Sopenharmony_ci (is_tile_unaligned(info->dst.box.height, tile_height) && 85bf215546Sopenharmony_ci info->dst.box.y + info->dst.box.height != dst_surface_height)) { 86bf215546Sopenharmony_ci return false; 87bf215546Sopenharmony_ci } 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci /* VC4_PACKET_LOAD_TILE_BUFFER_GENERAL uses the 90bf215546Sopenharmony_ci * VC4_PACKET_TILE_RENDERING_MODE_CONFIG's width (determined by our 91bf215546Sopenharmony_ci * destination surface) to determine the stride. This may be wrong 92bf215546Sopenharmony_ci * when reading from texture miplevels > 0, which are stored in 93bf215546Sopenharmony_ci * POT-sized areas. For MSAA, the tile addresses are computed 94bf215546Sopenharmony_ci * explicitly by the RCL, but still use the destination width to 95bf215546Sopenharmony_ci * determine the stride (which could be fixed by explicitly supplying 96bf215546Sopenharmony_ci * it in the ABI). 97bf215546Sopenharmony_ci */ 98bf215546Sopenharmony_ci struct vc4_resource *rsc = vc4_resource(info->src.resource); 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci uint32_t stride; 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci if (info->src.resource->nr_samples > 1) 103bf215546Sopenharmony_ci stride = align(dst_surface_width, 32) * 4 * rsc->cpp; 104bf215546Sopenharmony_ci else if (rsc->slices[info->src.level].tiling == VC4_TILING_FORMAT_T) 105bf215546Sopenharmony_ci stride = align(dst_surface_width * rsc->cpp, 128); 106bf215546Sopenharmony_ci else 107bf215546Sopenharmony_ci stride = align(dst_surface_width * rsc->cpp, 16); 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci if (stride != rsc->slices[info->src.level].stride) 110bf215546Sopenharmony_ci return false; 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci if (info->dst.resource->format != info->src.resource->format) 113bf215546Sopenharmony_ci return false; 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci if (false) { 116bf215546Sopenharmony_ci fprintf(stderr, "RCL blit from %d,%d to %d,%d (%d,%d)\n", 117bf215546Sopenharmony_ci info->src.box.x, 118bf215546Sopenharmony_ci info->src.box.y, 119bf215546Sopenharmony_ci info->dst.box.x, 120bf215546Sopenharmony_ci info->dst.box.y, 121bf215546Sopenharmony_ci info->dst.box.width, 122bf215546Sopenharmony_ci info->dst.box.height); 123bf215546Sopenharmony_ci } 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci struct pipe_surface *dst_surf = 126bf215546Sopenharmony_ci vc4_get_blit_surface(pctx, info->dst.resource, info->dst.level); 127bf215546Sopenharmony_ci struct pipe_surface *src_surf = 128bf215546Sopenharmony_ci vc4_get_blit_surface(pctx, info->src.resource, info->src.level); 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci vc4_flush_jobs_reading_resource(vc4, info->src.resource); 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci struct vc4_job *job = vc4_get_job(vc4, dst_surf, NULL); 133bf215546Sopenharmony_ci pipe_surface_reference(&job->color_read, src_surf); 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci job->draw_min_x = info->dst.box.x; 136bf215546Sopenharmony_ci job->draw_min_y = info->dst.box.y; 137bf215546Sopenharmony_ci job->draw_max_x = info->dst.box.x + info->dst.box.width; 138bf215546Sopenharmony_ci job->draw_max_y = info->dst.box.y + info->dst.box.height; 139bf215546Sopenharmony_ci job->draw_width = dst_surf->width; 140bf215546Sopenharmony_ci job->draw_height = dst_surf->height; 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci job->tile_width = tile_width; 143bf215546Sopenharmony_ci job->tile_height = tile_height; 144bf215546Sopenharmony_ci job->msaa = msaa; 145bf215546Sopenharmony_ci job->needs_flush = true; 146bf215546Sopenharmony_ci job->resolve |= PIPE_CLEAR_COLOR; 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci vc4_job_submit(vc4, job); 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci pipe_surface_reference(&dst_surf, NULL); 151bf215546Sopenharmony_ci pipe_surface_reference(&src_surf, NULL); 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci return true; 154bf215546Sopenharmony_ci} 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_civoid 157bf215546Sopenharmony_civc4_blitter_save(struct vc4_context *vc4) 158bf215546Sopenharmony_ci{ 159bf215546Sopenharmony_ci util_blitter_save_fragment_constant_buffer_slot(vc4->blitter, 160bf215546Sopenharmony_ci vc4->constbuf[PIPE_SHADER_FRAGMENT].cb); 161bf215546Sopenharmony_ci util_blitter_save_vertex_buffer_slot(vc4->blitter, vc4->vertexbuf.vb); 162bf215546Sopenharmony_ci util_blitter_save_vertex_elements(vc4->blitter, vc4->vtx); 163bf215546Sopenharmony_ci util_blitter_save_vertex_shader(vc4->blitter, vc4->prog.bind_vs); 164bf215546Sopenharmony_ci util_blitter_save_rasterizer(vc4->blitter, vc4->rasterizer); 165bf215546Sopenharmony_ci util_blitter_save_viewport(vc4->blitter, &vc4->viewport); 166bf215546Sopenharmony_ci util_blitter_save_scissor(vc4->blitter, &vc4->scissor); 167bf215546Sopenharmony_ci util_blitter_save_fragment_shader(vc4->blitter, vc4->prog.bind_fs); 168bf215546Sopenharmony_ci util_blitter_save_blend(vc4->blitter, vc4->blend); 169bf215546Sopenharmony_ci util_blitter_save_depth_stencil_alpha(vc4->blitter, vc4->zsa); 170bf215546Sopenharmony_ci util_blitter_save_stencil_ref(vc4->blitter, &vc4->stencil_ref); 171bf215546Sopenharmony_ci util_blitter_save_sample_mask(vc4->blitter, vc4->sample_mask, 0); 172bf215546Sopenharmony_ci util_blitter_save_framebuffer(vc4->blitter, &vc4->framebuffer); 173bf215546Sopenharmony_ci util_blitter_save_fragment_sampler_states(vc4->blitter, 174bf215546Sopenharmony_ci vc4->fragtex.num_samplers, 175bf215546Sopenharmony_ci (void **)vc4->fragtex.samplers); 176bf215546Sopenharmony_ci util_blitter_save_fragment_sampler_views(vc4->blitter, 177bf215546Sopenharmony_ci vc4->fragtex.num_textures, vc4->fragtex.textures); 178bf215546Sopenharmony_ci} 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_cistatic void *vc4_get_yuv_vs(struct pipe_context *pctx) 181bf215546Sopenharmony_ci{ 182bf215546Sopenharmony_ci struct vc4_context *vc4 = vc4_context(pctx); 183bf215546Sopenharmony_ci struct pipe_screen *pscreen = pctx->screen; 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci if (vc4->yuv_linear_blit_vs) 186bf215546Sopenharmony_ci return vc4->yuv_linear_blit_vs; 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci const struct nir_shader_compiler_options *options = 189bf215546Sopenharmony_ci pscreen->get_compiler_options(pscreen, 190bf215546Sopenharmony_ci PIPE_SHADER_IR_NIR, 191bf215546Sopenharmony_ci PIPE_SHADER_VERTEX); 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_VERTEX, options, 194bf215546Sopenharmony_ci "linear_blit_vs"); 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci const struct glsl_type *vec4 = glsl_vec4_type(); 197bf215546Sopenharmony_ci nir_variable *pos_in = nir_variable_create(b.shader, nir_var_shader_in, 198bf215546Sopenharmony_ci vec4, "pos"); 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci nir_variable *pos_out = nir_variable_create(b.shader, nir_var_shader_out, 201bf215546Sopenharmony_ci vec4, "gl_Position"); 202bf215546Sopenharmony_ci pos_out->data.location = VARYING_SLOT_POS; 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci nir_store_var(&b, pos_out, nir_load_var(&b, pos_in), 0xf); 205bf215546Sopenharmony_ci 206bf215546Sopenharmony_ci struct pipe_shader_state shader_tmpl = { 207bf215546Sopenharmony_ci .type = PIPE_SHADER_IR_NIR, 208bf215546Sopenharmony_ci .ir.nir = b.shader, 209bf215546Sopenharmony_ci }; 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci vc4->yuv_linear_blit_vs = pctx->create_vs_state(pctx, &shader_tmpl); 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_ci return vc4->yuv_linear_blit_vs; 214bf215546Sopenharmony_ci} 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_cistatic void *vc4_get_yuv_fs(struct pipe_context *pctx, int cpp) 217bf215546Sopenharmony_ci{ 218bf215546Sopenharmony_ci struct vc4_context *vc4 = vc4_context(pctx); 219bf215546Sopenharmony_ci struct pipe_screen *pscreen = pctx->screen; 220bf215546Sopenharmony_ci struct pipe_shader_state **cached_shader; 221bf215546Sopenharmony_ci const char *name; 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci if (cpp == 1) { 224bf215546Sopenharmony_ci cached_shader = &vc4->yuv_linear_blit_fs_8bit; 225bf215546Sopenharmony_ci name = "linear_blit_8bit_fs"; 226bf215546Sopenharmony_ci } else { 227bf215546Sopenharmony_ci cached_shader = &vc4->yuv_linear_blit_fs_16bit; 228bf215546Sopenharmony_ci name = "linear_blit_16bit_fs"; 229bf215546Sopenharmony_ci } 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci if (*cached_shader) 232bf215546Sopenharmony_ci return *cached_shader; 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ci const struct nir_shader_compiler_options *options = 235bf215546Sopenharmony_ci pscreen->get_compiler_options(pscreen, 236bf215546Sopenharmony_ci PIPE_SHADER_IR_NIR, 237bf215546Sopenharmony_ci PIPE_SHADER_FRAGMENT); 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_ci nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT, 240bf215546Sopenharmony_ci options, "%s", name); 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_ci const struct glsl_type *vec4 = glsl_vec4_type(); 243bf215546Sopenharmony_ci const struct glsl_type *glsl_int = glsl_int_type(); 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci nir_variable *color_out = nir_variable_create(b.shader, nir_var_shader_out, 246bf215546Sopenharmony_ci vec4, "f_color"); 247bf215546Sopenharmony_ci color_out->data.location = FRAG_RESULT_COLOR; 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_ci nir_variable *pos_in = nir_variable_create(b.shader, nir_var_shader_in, 250bf215546Sopenharmony_ci vec4, "pos"); 251bf215546Sopenharmony_ci pos_in->data.location = VARYING_SLOT_POS; 252bf215546Sopenharmony_ci nir_ssa_def *pos = nir_load_var(&b, pos_in); 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_ci nir_ssa_def *one = nir_imm_int(&b, 1); 255bf215546Sopenharmony_ci nir_ssa_def *two = nir_imm_int(&b, 2); 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_ci nir_ssa_def *x = nir_f2i32(&b, nir_channel(&b, pos, 0)); 258bf215546Sopenharmony_ci nir_ssa_def *y = nir_f2i32(&b, nir_channel(&b, pos, 1)); 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ci nir_variable *stride_in = nir_variable_create(b.shader, nir_var_uniform, 261bf215546Sopenharmony_ci glsl_int, "stride"); 262bf215546Sopenharmony_ci nir_ssa_def *stride = nir_load_var(&b, stride_in); 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ci nir_ssa_def *x_offset; 265bf215546Sopenharmony_ci nir_ssa_def *y_offset; 266bf215546Sopenharmony_ci if (cpp == 1) { 267bf215546Sopenharmony_ci nir_ssa_def *intra_utile_x_offset = 268bf215546Sopenharmony_ci nir_ishl(&b, nir_iand(&b, x, one), two); 269bf215546Sopenharmony_ci nir_ssa_def *inter_utile_x_offset = 270bf215546Sopenharmony_ci nir_ishl(&b, nir_iand(&b, x, nir_imm_int(&b, ~3)), one); 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_ci x_offset = nir_iadd(&b, 273bf215546Sopenharmony_ci intra_utile_x_offset, 274bf215546Sopenharmony_ci inter_utile_x_offset); 275bf215546Sopenharmony_ci y_offset = nir_imul(&b, 276bf215546Sopenharmony_ci nir_iadd(&b, 277bf215546Sopenharmony_ci nir_ishl(&b, y, one), 278bf215546Sopenharmony_ci nir_ushr(&b, nir_iand(&b, x, two), one)), 279bf215546Sopenharmony_ci stride); 280bf215546Sopenharmony_ci } else { 281bf215546Sopenharmony_ci x_offset = nir_ishl(&b, x, two); 282bf215546Sopenharmony_ci y_offset = nir_imul(&b, y, stride); 283bf215546Sopenharmony_ci } 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci nir_ssa_def *load = 286bf215546Sopenharmony_ci nir_load_ubo(&b, 1, 32, one, nir_iadd(&b, x_offset, y_offset), 287bf215546Sopenharmony_ci .align_mul = 4, 288bf215546Sopenharmony_ci .align_offset = 0, 289bf215546Sopenharmony_ci .range_base = 0, 290bf215546Sopenharmony_ci .range = ~0); 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci nir_store_var(&b, color_out, 293bf215546Sopenharmony_ci nir_unpack_unorm_4x8(&b, load), 294bf215546Sopenharmony_ci 0xf); 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci struct pipe_shader_state shader_tmpl = { 297bf215546Sopenharmony_ci .type = PIPE_SHADER_IR_NIR, 298bf215546Sopenharmony_ci .ir.nir = b.shader, 299bf215546Sopenharmony_ci }; 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci *cached_shader = pctx->create_fs_state(pctx, &shader_tmpl); 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_ci return *cached_shader; 304bf215546Sopenharmony_ci} 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_cistatic bool 307bf215546Sopenharmony_civc4_yuv_blit(struct pipe_context *pctx, const struct pipe_blit_info *info) 308bf215546Sopenharmony_ci{ 309bf215546Sopenharmony_ci struct vc4_context *vc4 = vc4_context(pctx); 310bf215546Sopenharmony_ci struct vc4_resource *src = vc4_resource(info->src.resource); 311bf215546Sopenharmony_ci struct vc4_resource *dst = vc4_resource(info->dst.resource); 312bf215546Sopenharmony_ci bool ok; 313bf215546Sopenharmony_ci 314bf215546Sopenharmony_ci if (src->tiled) 315bf215546Sopenharmony_ci return false; 316bf215546Sopenharmony_ci if (src->base.format != PIPE_FORMAT_R8_UNORM && 317bf215546Sopenharmony_ci src->base.format != PIPE_FORMAT_R8G8_UNORM) 318bf215546Sopenharmony_ci return false; 319bf215546Sopenharmony_ci 320bf215546Sopenharmony_ci /* YUV blits always turn raster-order to tiled */ 321bf215546Sopenharmony_ci assert(dst->base.format == src->base.format); 322bf215546Sopenharmony_ci assert(dst->tiled); 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ci /* Always 1:1 and at the origin */ 325bf215546Sopenharmony_ci assert(info->src.box.x == 0 && info->dst.box.x == 0); 326bf215546Sopenharmony_ci assert(info->src.box.y == 0 && info->dst.box.y == 0); 327bf215546Sopenharmony_ci assert(info->src.box.width == info->dst.box.width); 328bf215546Sopenharmony_ci assert(info->src.box.height == info->dst.box.height); 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_ci if ((src->slices[info->src.level].offset & 3) || 331bf215546Sopenharmony_ci (src->slices[info->src.level].stride & 3)) { 332bf215546Sopenharmony_ci perf_debug("YUV-blit src texture offset/stride misaligned: 0x%08x/%d\n", 333bf215546Sopenharmony_ci src->slices[info->src.level].offset, 334bf215546Sopenharmony_ci src->slices[info->src.level].stride); 335bf215546Sopenharmony_ci goto fallback; 336bf215546Sopenharmony_ci } 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci vc4_blitter_save(vc4); 339bf215546Sopenharmony_ci 340bf215546Sopenharmony_ci /* Create a renderable surface mapping the T-tiled shadow buffer. 341bf215546Sopenharmony_ci */ 342bf215546Sopenharmony_ci struct pipe_surface dst_tmpl; 343bf215546Sopenharmony_ci util_blitter_default_dst_texture(&dst_tmpl, info->dst.resource, 344bf215546Sopenharmony_ci info->dst.level, info->dst.box.z); 345bf215546Sopenharmony_ci dst_tmpl.format = PIPE_FORMAT_RGBA8888_UNORM; 346bf215546Sopenharmony_ci struct pipe_surface *dst_surf = 347bf215546Sopenharmony_ci pctx->create_surface(pctx, info->dst.resource, &dst_tmpl); 348bf215546Sopenharmony_ci if (!dst_surf) { 349bf215546Sopenharmony_ci fprintf(stderr, "Failed to create YUV dst surface\n"); 350bf215546Sopenharmony_ci util_blitter_unset_running_flag(vc4->blitter); 351bf215546Sopenharmony_ci return false; 352bf215546Sopenharmony_ci } 353bf215546Sopenharmony_ci dst_surf->width = align(dst_surf->width, 8) / 2; 354bf215546Sopenharmony_ci if (dst->cpp == 1) 355bf215546Sopenharmony_ci dst_surf->height /= 2; 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_ci /* Set the constant buffer. */ 358bf215546Sopenharmony_ci uint32_t stride = src->slices[info->src.level].stride; 359bf215546Sopenharmony_ci struct pipe_constant_buffer cb_uniforms = { 360bf215546Sopenharmony_ci .user_buffer = &stride, 361bf215546Sopenharmony_ci .buffer_size = sizeof(stride), 362bf215546Sopenharmony_ci }; 363bf215546Sopenharmony_ci pctx->set_constant_buffer(pctx, PIPE_SHADER_FRAGMENT, 0, false, &cb_uniforms); 364bf215546Sopenharmony_ci struct pipe_constant_buffer cb_src = { 365bf215546Sopenharmony_ci .buffer = info->src.resource, 366bf215546Sopenharmony_ci .buffer_offset = src->slices[info->src.level].offset, 367bf215546Sopenharmony_ci .buffer_size = (src->bo->size - 368bf215546Sopenharmony_ci src->slices[info->src.level].offset), 369bf215546Sopenharmony_ci }; 370bf215546Sopenharmony_ci pctx->set_constant_buffer(pctx, PIPE_SHADER_FRAGMENT, 1, false, &cb_src); 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_ci /* Unbind the textures, to make sure we don't try to recurse into the 373bf215546Sopenharmony_ci * shadow blit. 374bf215546Sopenharmony_ci */ 375bf215546Sopenharmony_ci pctx->set_sampler_views(pctx, PIPE_SHADER_FRAGMENT, 0, 0, 0, false, NULL); 376bf215546Sopenharmony_ci pctx->bind_sampler_states(pctx, PIPE_SHADER_FRAGMENT, 0, 0, NULL); 377bf215546Sopenharmony_ci 378bf215546Sopenharmony_ci util_blitter_custom_shader(vc4->blitter, dst_surf, 379bf215546Sopenharmony_ci vc4_get_yuv_vs(pctx), 380bf215546Sopenharmony_ci vc4_get_yuv_fs(pctx, src->cpp)); 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_ci util_blitter_restore_textures(vc4->blitter); 383bf215546Sopenharmony_ci util_blitter_restore_constant_buffer_state(vc4->blitter); 384bf215546Sopenharmony_ci /* Restore cb1 (util_blitter doesn't handle this one). */ 385bf215546Sopenharmony_ci struct pipe_constant_buffer cb_disabled = { 0 }; 386bf215546Sopenharmony_ci pctx->set_constant_buffer(pctx, PIPE_SHADER_FRAGMENT, 1, false, &cb_disabled); 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_ci pipe_surface_reference(&dst_surf, NULL); 389bf215546Sopenharmony_ci 390bf215546Sopenharmony_ci return true; 391bf215546Sopenharmony_ci 392bf215546Sopenharmony_cifallback: 393bf215546Sopenharmony_ci /* Do an immediate SW fallback, since the render blit path 394bf215546Sopenharmony_ci * would just recurse. 395bf215546Sopenharmony_ci */ 396bf215546Sopenharmony_ci ok = util_try_blit_via_copy_region(pctx, info, false); 397bf215546Sopenharmony_ci assert(ok); (void)ok; 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_ci return true; 400bf215546Sopenharmony_ci} 401bf215546Sopenharmony_ci 402bf215546Sopenharmony_cistatic bool 403bf215546Sopenharmony_civc4_render_blit(struct pipe_context *ctx, struct pipe_blit_info *info) 404bf215546Sopenharmony_ci{ 405bf215546Sopenharmony_ci struct vc4_context *vc4 = vc4_context(ctx); 406bf215546Sopenharmony_ci 407bf215546Sopenharmony_ci if (!util_blitter_is_blit_supported(vc4->blitter, info)) { 408bf215546Sopenharmony_ci fprintf(stderr, "blit unsupported %s -> %s\n", 409bf215546Sopenharmony_ci util_format_short_name(info->src.resource->format), 410bf215546Sopenharmony_ci util_format_short_name(info->dst.resource->format)); 411bf215546Sopenharmony_ci return false; 412bf215546Sopenharmony_ci } 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_ci /* Enable the scissor, so we get a minimal set of tiles rendered. */ 415bf215546Sopenharmony_ci if (!info->scissor_enable) { 416bf215546Sopenharmony_ci info->scissor_enable = true; 417bf215546Sopenharmony_ci info->scissor.minx = info->dst.box.x; 418bf215546Sopenharmony_ci info->scissor.miny = info->dst.box.y; 419bf215546Sopenharmony_ci info->scissor.maxx = info->dst.box.x + info->dst.box.width; 420bf215546Sopenharmony_ci info->scissor.maxy = info->dst.box.y + info->dst.box.height; 421bf215546Sopenharmony_ci } 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci vc4_blitter_save(vc4); 424bf215546Sopenharmony_ci util_blitter_blit(vc4->blitter, info); 425bf215546Sopenharmony_ci 426bf215546Sopenharmony_ci return true; 427bf215546Sopenharmony_ci} 428bf215546Sopenharmony_ci 429bf215546Sopenharmony_ci/* Optimal hardware path for blitting pixels. 430bf215546Sopenharmony_ci * Scaling, format conversion, up- and downsampling (resolve) are allowed. 431bf215546Sopenharmony_ci */ 432bf215546Sopenharmony_civoid 433bf215546Sopenharmony_civc4_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) 434bf215546Sopenharmony_ci{ 435bf215546Sopenharmony_ci struct pipe_blit_info info = *blit_info; 436bf215546Sopenharmony_ci 437bf215546Sopenharmony_ci if (vc4_yuv_blit(pctx, blit_info)) 438bf215546Sopenharmony_ci return; 439bf215546Sopenharmony_ci 440bf215546Sopenharmony_ci if (vc4_tile_blit(pctx, blit_info)) 441bf215546Sopenharmony_ci return; 442bf215546Sopenharmony_ci 443bf215546Sopenharmony_ci if (info.mask & PIPE_MASK_S) { 444bf215546Sopenharmony_ci if (util_try_blit_via_copy_region(pctx, &info, false)) 445bf215546Sopenharmony_ci return; 446bf215546Sopenharmony_ci 447bf215546Sopenharmony_ci info.mask &= ~PIPE_MASK_S; 448bf215546Sopenharmony_ci fprintf(stderr, "cannot blit stencil, skipping\n"); 449bf215546Sopenharmony_ci } 450bf215546Sopenharmony_ci 451bf215546Sopenharmony_ci if (vc4_render_blit(pctx, &info)) 452bf215546Sopenharmony_ci return; 453bf215546Sopenharmony_ci 454bf215546Sopenharmony_ci fprintf(stderr, "Unsupported blit\n"); 455bf215546Sopenharmony_ci} 456