101e04c3fSmrg/* 201e04c3fSmrg * Copyright © 2015 Broadcom 301e04c3fSmrg * 401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 501e04c3fSmrg * copy of this software and associated documentation files (the "Software"), 601e04c3fSmrg * to deal in the Software without restriction, including without limitation 701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the 901e04c3fSmrg * Software is furnished to do so, subject to the following conditions: 1001e04c3fSmrg * 1101e04c3fSmrg * The above copyright notice and this permission notice (including the next 1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the 1301e04c3fSmrg * Software. 1401e04c3fSmrg * 1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2101e04c3fSmrg * IN THE SOFTWARE. 2201e04c3fSmrg */ 2301e04c3fSmrg 247ec681f3Smrg#include "util/format/u_format.h" 2501e04c3fSmrg#include "util/u_surface.h" 2601e04c3fSmrg#include "util/u_blitter.h" 2701e04c3fSmrg#include "compiler/nir/nir_builder.h" 2801e04c3fSmrg#include "vc4_context.h" 2901e04c3fSmrg 3001e04c3fSmrgstatic struct pipe_surface * 3101e04c3fSmrgvc4_get_blit_surface(struct pipe_context *pctx, 3201e04c3fSmrg struct pipe_resource *prsc, unsigned level) 3301e04c3fSmrg{ 3401e04c3fSmrg struct pipe_surface tmpl; 3501e04c3fSmrg 3601e04c3fSmrg memset(&tmpl, 0, sizeof(tmpl)); 3701e04c3fSmrg tmpl.format = prsc->format; 3801e04c3fSmrg tmpl.u.tex.level = level; 3901e04c3fSmrg tmpl.u.tex.first_layer = 0; 4001e04c3fSmrg tmpl.u.tex.last_layer = 0; 4101e04c3fSmrg 4201e04c3fSmrg return pctx->create_surface(pctx, prsc, &tmpl); 4301e04c3fSmrg} 4401e04c3fSmrg 4501e04c3fSmrgstatic bool 4601e04c3fSmrgis_tile_unaligned(unsigned size, unsigned tile_size) 4701e04c3fSmrg{ 4801e04c3fSmrg return size & (tile_size - 1); 4901e04c3fSmrg} 5001e04c3fSmrg 5101e04c3fSmrgstatic bool 5201e04c3fSmrgvc4_tile_blit(struct pipe_context *pctx, const struct pipe_blit_info *info) 5301e04c3fSmrg{ 5401e04c3fSmrg struct vc4_context *vc4 = vc4_context(pctx); 5501e04c3fSmrg bool msaa = (info->src.resource->nr_samples > 1 || 5601e04c3fSmrg info->dst.resource->nr_samples > 1); 5701e04c3fSmrg int tile_width = msaa ? 32 : 64; 5801e04c3fSmrg int tile_height = msaa ? 32 : 64; 5901e04c3fSmrg 6001e04c3fSmrg if (util_format_is_depth_or_stencil(info->dst.resource->format)) 6101e04c3fSmrg return false; 6201e04c3fSmrg 6301e04c3fSmrg if (info->scissor_enable) 6401e04c3fSmrg return false; 6501e04c3fSmrg 6601e04c3fSmrg if ((info->mask & PIPE_MASK_RGBA) == 0) 6701e04c3fSmrg return false; 6801e04c3fSmrg 6901e04c3fSmrg if (info->dst.box.x != info->src.box.x || 7001e04c3fSmrg info->dst.box.y != info->src.box.y || 7101e04c3fSmrg info->dst.box.width != info->src.box.width || 7201e04c3fSmrg info->dst.box.height != info->src.box.height) { 7301e04c3fSmrg return false; 7401e04c3fSmrg } 7501e04c3fSmrg 7601e04c3fSmrg int dst_surface_width = u_minify(info->dst.resource->width0, 7701e04c3fSmrg info->dst.level); 7801e04c3fSmrg int dst_surface_height = u_minify(info->dst.resource->height0, 7901e04c3fSmrg info->dst.level); 8001e04c3fSmrg if (is_tile_unaligned(info->dst.box.x, tile_width) || 8101e04c3fSmrg is_tile_unaligned(info->dst.box.y, tile_height) || 8201e04c3fSmrg (is_tile_unaligned(info->dst.box.width, tile_width) && 8301e04c3fSmrg info->dst.box.x + info->dst.box.width != dst_surface_width) || 8401e04c3fSmrg (is_tile_unaligned(info->dst.box.height, tile_height) && 8501e04c3fSmrg info->dst.box.y + info->dst.box.height != dst_surface_height)) { 8601e04c3fSmrg return false; 8701e04c3fSmrg } 8801e04c3fSmrg 8901e04c3fSmrg /* VC4_PACKET_LOAD_TILE_BUFFER_GENERAL uses the 9001e04c3fSmrg * VC4_PACKET_TILE_RENDERING_MODE_CONFIG's width (determined by our 9101e04c3fSmrg * destination surface) to determine the stride. This may be wrong 9201e04c3fSmrg * when reading from texture miplevels > 0, which are stored in 9301e04c3fSmrg * POT-sized areas. For MSAA, the tile addresses are computed 9401e04c3fSmrg * explicitly by the RCL, but still use the destination width to 9501e04c3fSmrg * determine the stride (which could be fixed by explicitly supplying 9601e04c3fSmrg * it in the ABI). 9701e04c3fSmrg */ 9801e04c3fSmrg struct vc4_resource *rsc = vc4_resource(info->src.resource); 9901e04c3fSmrg 10001e04c3fSmrg uint32_t stride; 10101e04c3fSmrg 10201e04c3fSmrg if (info->src.resource->nr_samples > 1) 10301e04c3fSmrg stride = align(dst_surface_width, 32) * 4 * rsc->cpp; 10401e04c3fSmrg else if (rsc->slices[info->src.level].tiling == VC4_TILING_FORMAT_T) 10501e04c3fSmrg stride = align(dst_surface_width * rsc->cpp, 128); 10601e04c3fSmrg else 10701e04c3fSmrg stride = align(dst_surface_width * rsc->cpp, 16); 10801e04c3fSmrg 10901e04c3fSmrg if (stride != rsc->slices[info->src.level].stride) 11001e04c3fSmrg return false; 11101e04c3fSmrg 11201e04c3fSmrg if (info->dst.resource->format != info->src.resource->format) 11301e04c3fSmrg return false; 11401e04c3fSmrg 11501e04c3fSmrg if (false) { 11601e04c3fSmrg fprintf(stderr, "RCL blit from %d,%d to %d,%d (%d,%d)\n", 11701e04c3fSmrg info->src.box.x, 11801e04c3fSmrg info->src.box.y, 11901e04c3fSmrg info->dst.box.x, 12001e04c3fSmrg info->dst.box.y, 12101e04c3fSmrg info->dst.box.width, 12201e04c3fSmrg info->dst.box.height); 12301e04c3fSmrg } 12401e04c3fSmrg 12501e04c3fSmrg struct pipe_surface *dst_surf = 12601e04c3fSmrg vc4_get_blit_surface(pctx, info->dst.resource, info->dst.level); 12701e04c3fSmrg struct pipe_surface *src_surf = 12801e04c3fSmrg vc4_get_blit_surface(pctx, info->src.resource, info->src.level); 12901e04c3fSmrg 13001e04c3fSmrg vc4_flush_jobs_reading_resource(vc4, info->src.resource); 13101e04c3fSmrg 13201e04c3fSmrg struct vc4_job *job = vc4_get_job(vc4, dst_surf, NULL); 13301e04c3fSmrg pipe_surface_reference(&job->color_read, src_surf); 13401e04c3fSmrg 13501e04c3fSmrg /* If we're resolving from MSAA to single sample, we still need to run 13601e04c3fSmrg * the engine in MSAA mode for the load. 13701e04c3fSmrg */ 13801e04c3fSmrg if (!job->msaa && info->src.resource->nr_samples > 1) { 13901e04c3fSmrg job->msaa = true; 14001e04c3fSmrg job->tile_width = 32; 14101e04c3fSmrg job->tile_height = 32; 14201e04c3fSmrg } 14301e04c3fSmrg 14401e04c3fSmrg job->draw_min_x = info->dst.box.x; 14501e04c3fSmrg job->draw_min_y = info->dst.box.y; 14601e04c3fSmrg job->draw_max_x = info->dst.box.x + info->dst.box.width; 14701e04c3fSmrg job->draw_max_y = info->dst.box.y + info->dst.box.height; 14801e04c3fSmrg job->draw_width = dst_surf->width; 14901e04c3fSmrg job->draw_height = dst_surf->height; 15001e04c3fSmrg 15101e04c3fSmrg job->tile_width = tile_width; 15201e04c3fSmrg job->tile_height = tile_height; 15301e04c3fSmrg job->msaa = msaa; 15401e04c3fSmrg job->needs_flush = true; 15501e04c3fSmrg job->resolve |= PIPE_CLEAR_COLOR; 15601e04c3fSmrg 15701e04c3fSmrg vc4_job_submit(vc4, job); 15801e04c3fSmrg 15901e04c3fSmrg pipe_surface_reference(&dst_surf, NULL); 16001e04c3fSmrg pipe_surface_reference(&src_surf, NULL); 16101e04c3fSmrg 16201e04c3fSmrg return true; 16301e04c3fSmrg} 16401e04c3fSmrg 16501e04c3fSmrgvoid 16601e04c3fSmrgvc4_blitter_save(struct vc4_context *vc4) 16701e04c3fSmrg{ 1687ec681f3Smrg util_blitter_save_fragment_constant_buffer_slot(vc4->blitter, 1697ec681f3Smrg vc4->constbuf[PIPE_SHADER_FRAGMENT].cb); 17001e04c3fSmrg util_blitter_save_vertex_buffer_slot(vc4->blitter, vc4->vertexbuf.vb); 17101e04c3fSmrg util_blitter_save_vertex_elements(vc4->blitter, vc4->vtx); 17201e04c3fSmrg util_blitter_save_vertex_shader(vc4->blitter, vc4->prog.bind_vs); 17301e04c3fSmrg util_blitter_save_rasterizer(vc4->blitter, vc4->rasterizer); 17401e04c3fSmrg util_blitter_save_viewport(vc4->blitter, &vc4->viewport); 17501e04c3fSmrg util_blitter_save_scissor(vc4->blitter, &vc4->scissor); 17601e04c3fSmrg util_blitter_save_fragment_shader(vc4->blitter, vc4->prog.bind_fs); 17701e04c3fSmrg util_blitter_save_blend(vc4->blitter, vc4->blend); 17801e04c3fSmrg util_blitter_save_depth_stencil_alpha(vc4->blitter, vc4->zsa); 17901e04c3fSmrg util_blitter_save_stencil_ref(vc4->blitter, &vc4->stencil_ref); 18001e04c3fSmrg util_blitter_save_sample_mask(vc4->blitter, vc4->sample_mask); 18101e04c3fSmrg util_blitter_save_framebuffer(vc4->blitter, &vc4->framebuffer); 18201e04c3fSmrg util_blitter_save_fragment_sampler_states(vc4->blitter, 18301e04c3fSmrg vc4->fragtex.num_samplers, 18401e04c3fSmrg (void **)vc4->fragtex.samplers); 18501e04c3fSmrg util_blitter_save_fragment_sampler_views(vc4->blitter, 18601e04c3fSmrg vc4->fragtex.num_textures, vc4->fragtex.textures); 18701e04c3fSmrg} 18801e04c3fSmrg 18901e04c3fSmrgstatic void *vc4_get_yuv_vs(struct pipe_context *pctx) 19001e04c3fSmrg{ 19101e04c3fSmrg struct vc4_context *vc4 = vc4_context(pctx); 19201e04c3fSmrg struct pipe_screen *pscreen = pctx->screen; 19301e04c3fSmrg 19401e04c3fSmrg if (vc4->yuv_linear_blit_vs) 19501e04c3fSmrg return vc4->yuv_linear_blit_vs; 19601e04c3fSmrg 19701e04c3fSmrg const struct nir_shader_compiler_options *options = 19801e04c3fSmrg pscreen->get_compiler_options(pscreen, 19901e04c3fSmrg PIPE_SHADER_IR_NIR, 20001e04c3fSmrg PIPE_SHADER_VERTEX); 20101e04c3fSmrg 2027ec681f3Smrg nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_VERTEX, options, 2037ec681f3Smrg "linear_blit_vs"); 20401e04c3fSmrg 20501e04c3fSmrg const struct glsl_type *vec4 = glsl_vec4_type(); 20601e04c3fSmrg nir_variable *pos_in = nir_variable_create(b.shader, nir_var_shader_in, 20701e04c3fSmrg vec4, "pos"); 20801e04c3fSmrg 20901e04c3fSmrg nir_variable *pos_out = nir_variable_create(b.shader, nir_var_shader_out, 21001e04c3fSmrg vec4, "gl_Position"); 21101e04c3fSmrg pos_out->data.location = VARYING_SLOT_POS; 21201e04c3fSmrg 21301e04c3fSmrg nir_store_var(&b, pos_out, nir_load_var(&b, pos_in), 0xf); 21401e04c3fSmrg 21501e04c3fSmrg struct pipe_shader_state shader_tmpl = { 21601e04c3fSmrg .type = PIPE_SHADER_IR_NIR, 21701e04c3fSmrg .ir.nir = b.shader, 21801e04c3fSmrg }; 21901e04c3fSmrg 22001e04c3fSmrg vc4->yuv_linear_blit_vs = pctx->create_vs_state(pctx, &shader_tmpl); 22101e04c3fSmrg 22201e04c3fSmrg return vc4->yuv_linear_blit_vs; 22301e04c3fSmrg} 22401e04c3fSmrg 22501e04c3fSmrgstatic void *vc4_get_yuv_fs(struct pipe_context *pctx, int cpp) 22601e04c3fSmrg{ 22701e04c3fSmrg struct vc4_context *vc4 = vc4_context(pctx); 22801e04c3fSmrg struct pipe_screen *pscreen = pctx->screen; 22901e04c3fSmrg struct pipe_shader_state **cached_shader; 23001e04c3fSmrg const char *name; 23101e04c3fSmrg 23201e04c3fSmrg if (cpp == 1) { 23301e04c3fSmrg cached_shader = &vc4->yuv_linear_blit_fs_8bit; 23401e04c3fSmrg name = "linear_blit_8bit_fs"; 23501e04c3fSmrg } else { 23601e04c3fSmrg cached_shader = &vc4->yuv_linear_blit_fs_16bit; 23701e04c3fSmrg name = "linear_blit_16bit_fs"; 23801e04c3fSmrg } 23901e04c3fSmrg 24001e04c3fSmrg if (*cached_shader) 24101e04c3fSmrg return *cached_shader; 24201e04c3fSmrg 24301e04c3fSmrg const struct nir_shader_compiler_options *options = 24401e04c3fSmrg pscreen->get_compiler_options(pscreen, 24501e04c3fSmrg PIPE_SHADER_IR_NIR, 24601e04c3fSmrg PIPE_SHADER_FRAGMENT); 24701e04c3fSmrg 2487ec681f3Smrg nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT, 2497ec681f3Smrg options, "%s", name); 25001e04c3fSmrg 25101e04c3fSmrg const struct glsl_type *vec4 = glsl_vec4_type(); 25201e04c3fSmrg const struct glsl_type *glsl_int = glsl_int_type(); 25301e04c3fSmrg 25401e04c3fSmrg nir_variable *color_out = nir_variable_create(b.shader, nir_var_shader_out, 25501e04c3fSmrg vec4, "f_color"); 25601e04c3fSmrg color_out->data.location = FRAG_RESULT_COLOR; 25701e04c3fSmrg 25801e04c3fSmrg nir_variable *pos_in = nir_variable_create(b.shader, nir_var_shader_in, 25901e04c3fSmrg vec4, "pos"); 26001e04c3fSmrg pos_in->data.location = VARYING_SLOT_POS; 26101e04c3fSmrg nir_ssa_def *pos = nir_load_var(&b, pos_in); 26201e04c3fSmrg 26301e04c3fSmrg nir_ssa_def *one = nir_imm_int(&b, 1); 26401e04c3fSmrg nir_ssa_def *two = nir_imm_int(&b, 2); 26501e04c3fSmrg 26601e04c3fSmrg nir_ssa_def *x = nir_f2i32(&b, nir_channel(&b, pos, 0)); 26701e04c3fSmrg nir_ssa_def *y = nir_f2i32(&b, nir_channel(&b, pos, 1)); 26801e04c3fSmrg 26901e04c3fSmrg nir_variable *stride_in = nir_variable_create(b.shader, nir_var_uniform, 27001e04c3fSmrg glsl_int, "stride"); 27101e04c3fSmrg nir_ssa_def *stride = nir_load_var(&b, stride_in); 27201e04c3fSmrg 27301e04c3fSmrg nir_ssa_def *x_offset; 27401e04c3fSmrg nir_ssa_def *y_offset; 27501e04c3fSmrg if (cpp == 1) { 27601e04c3fSmrg nir_ssa_def *intra_utile_x_offset = 27701e04c3fSmrg nir_ishl(&b, nir_iand(&b, x, one), two); 27801e04c3fSmrg nir_ssa_def *inter_utile_x_offset = 27901e04c3fSmrg nir_ishl(&b, nir_iand(&b, x, nir_imm_int(&b, ~3)), one); 28001e04c3fSmrg 28101e04c3fSmrg x_offset = nir_iadd(&b, 28201e04c3fSmrg intra_utile_x_offset, 28301e04c3fSmrg inter_utile_x_offset); 28401e04c3fSmrg y_offset = nir_imul(&b, 28501e04c3fSmrg nir_iadd(&b, 28601e04c3fSmrg nir_ishl(&b, y, one), 28701e04c3fSmrg nir_ushr(&b, nir_iand(&b, x, two), one)), 28801e04c3fSmrg stride); 28901e04c3fSmrg } else { 29001e04c3fSmrg x_offset = nir_ishl(&b, x, two); 29101e04c3fSmrg y_offset = nir_imul(&b, y, stride); 29201e04c3fSmrg } 29301e04c3fSmrg 2947ec681f3Smrg nir_ssa_def *load = 2957ec681f3Smrg nir_load_ubo(&b, 1, 32, one, nir_iadd(&b, x_offset, y_offset), 2967ec681f3Smrg .align_mul = 4, 2977ec681f3Smrg .align_offset = 0, 2987ec681f3Smrg .range_base = 0, 2997ec681f3Smrg .range = ~0); 30001e04c3fSmrg 30101e04c3fSmrg nir_store_var(&b, color_out, 3027ec681f3Smrg nir_unpack_unorm_4x8(&b, load), 30301e04c3fSmrg 0xf); 30401e04c3fSmrg 30501e04c3fSmrg struct pipe_shader_state shader_tmpl = { 30601e04c3fSmrg .type = PIPE_SHADER_IR_NIR, 30701e04c3fSmrg .ir.nir = b.shader, 30801e04c3fSmrg }; 30901e04c3fSmrg 31001e04c3fSmrg *cached_shader = pctx->create_fs_state(pctx, &shader_tmpl); 31101e04c3fSmrg 31201e04c3fSmrg return *cached_shader; 31301e04c3fSmrg} 31401e04c3fSmrg 31501e04c3fSmrgstatic bool 31601e04c3fSmrgvc4_yuv_blit(struct pipe_context *pctx, const struct pipe_blit_info *info) 31701e04c3fSmrg{ 31801e04c3fSmrg struct vc4_context *vc4 = vc4_context(pctx); 31901e04c3fSmrg struct vc4_resource *src = vc4_resource(info->src.resource); 32001e04c3fSmrg struct vc4_resource *dst = vc4_resource(info->dst.resource); 32101e04c3fSmrg bool ok; 32201e04c3fSmrg 32301e04c3fSmrg if (src->tiled) 32401e04c3fSmrg return false; 32501e04c3fSmrg if (src->base.format != PIPE_FORMAT_R8_UNORM && 32601e04c3fSmrg src->base.format != PIPE_FORMAT_R8G8_UNORM) 32701e04c3fSmrg return false; 32801e04c3fSmrg 32901e04c3fSmrg /* YUV blits always turn raster-order to tiled */ 33001e04c3fSmrg assert(dst->base.format == src->base.format); 33101e04c3fSmrg assert(dst->tiled); 33201e04c3fSmrg 33301e04c3fSmrg /* Always 1:1 and at the origin */ 33401e04c3fSmrg assert(info->src.box.x == 0 && info->dst.box.x == 0); 33501e04c3fSmrg assert(info->src.box.y == 0 && info->dst.box.y == 0); 33601e04c3fSmrg assert(info->src.box.width == info->dst.box.width); 33701e04c3fSmrg assert(info->src.box.height == info->dst.box.height); 33801e04c3fSmrg 33901e04c3fSmrg if ((src->slices[info->src.level].offset & 3) || 34001e04c3fSmrg (src->slices[info->src.level].stride & 3)) { 34101e04c3fSmrg perf_debug("YUV-blit src texture offset/stride misaligned: 0x%08x/%d\n", 34201e04c3fSmrg src->slices[info->src.level].offset, 34301e04c3fSmrg src->slices[info->src.level].stride); 34401e04c3fSmrg goto fallback; 34501e04c3fSmrg } 34601e04c3fSmrg 34701e04c3fSmrg vc4_blitter_save(vc4); 34801e04c3fSmrg 34901e04c3fSmrg /* Create a renderable surface mapping the T-tiled shadow buffer. 35001e04c3fSmrg */ 35101e04c3fSmrg struct pipe_surface dst_tmpl; 35201e04c3fSmrg util_blitter_default_dst_texture(&dst_tmpl, info->dst.resource, 35301e04c3fSmrg info->dst.level, info->dst.box.z); 35401e04c3fSmrg dst_tmpl.format = PIPE_FORMAT_RGBA8888_UNORM; 35501e04c3fSmrg struct pipe_surface *dst_surf = 35601e04c3fSmrg pctx->create_surface(pctx, info->dst.resource, &dst_tmpl); 35701e04c3fSmrg if (!dst_surf) { 35801e04c3fSmrg fprintf(stderr, "Failed to create YUV dst surface\n"); 35901e04c3fSmrg util_blitter_unset_running_flag(vc4->blitter); 36001e04c3fSmrg return false; 36101e04c3fSmrg } 3627ec681f3Smrg dst_surf->width = align(dst_surf->width, 8) / 2; 36301e04c3fSmrg if (dst->cpp == 1) 36401e04c3fSmrg dst_surf->height /= 2; 36501e04c3fSmrg 36601e04c3fSmrg /* Set the constant buffer. */ 36701e04c3fSmrg uint32_t stride = src->slices[info->src.level].stride; 36801e04c3fSmrg struct pipe_constant_buffer cb_uniforms = { 36901e04c3fSmrg .user_buffer = &stride, 37001e04c3fSmrg .buffer_size = sizeof(stride), 37101e04c3fSmrg }; 3727ec681f3Smrg pctx->set_constant_buffer(pctx, PIPE_SHADER_FRAGMENT, 0, false, &cb_uniforms); 37301e04c3fSmrg struct pipe_constant_buffer cb_src = { 37401e04c3fSmrg .buffer = info->src.resource, 37501e04c3fSmrg .buffer_offset = src->slices[info->src.level].offset, 37601e04c3fSmrg .buffer_size = (src->bo->size - 37701e04c3fSmrg src->slices[info->src.level].offset), 37801e04c3fSmrg }; 3797ec681f3Smrg pctx->set_constant_buffer(pctx, PIPE_SHADER_FRAGMENT, 1, false, &cb_src); 38001e04c3fSmrg 38101e04c3fSmrg /* Unbind the textures, to make sure we don't try to recurse into the 38201e04c3fSmrg * shadow blit. 38301e04c3fSmrg */ 3847ec681f3Smrg pctx->set_sampler_views(pctx, PIPE_SHADER_FRAGMENT, 0, 0, 0, false, NULL); 38501e04c3fSmrg pctx->bind_sampler_states(pctx, PIPE_SHADER_FRAGMENT, 0, 0, NULL); 38601e04c3fSmrg 38701e04c3fSmrg util_blitter_custom_shader(vc4->blitter, dst_surf, 38801e04c3fSmrg vc4_get_yuv_vs(pctx), 38901e04c3fSmrg vc4_get_yuv_fs(pctx, src->cpp)); 39001e04c3fSmrg 39101e04c3fSmrg util_blitter_restore_textures(vc4->blitter); 39201e04c3fSmrg util_blitter_restore_constant_buffer_state(vc4->blitter); 39301e04c3fSmrg /* Restore cb1 (util_blitter doesn't handle this one). */ 39401e04c3fSmrg struct pipe_constant_buffer cb_disabled = { 0 }; 3957ec681f3Smrg pctx->set_constant_buffer(pctx, PIPE_SHADER_FRAGMENT, 1, false, &cb_disabled); 39601e04c3fSmrg 39701e04c3fSmrg pipe_surface_reference(&dst_surf, NULL); 39801e04c3fSmrg 39901e04c3fSmrg return true; 40001e04c3fSmrg 40101e04c3fSmrgfallback: 40201e04c3fSmrg /* Do an immediate SW fallback, since the render blit path 40301e04c3fSmrg * would just recurse. 40401e04c3fSmrg */ 40501e04c3fSmrg ok = util_try_blit_via_copy_region(pctx, info); 40601e04c3fSmrg assert(ok); (void)ok; 40701e04c3fSmrg 40801e04c3fSmrg return true; 40901e04c3fSmrg} 41001e04c3fSmrg 41101e04c3fSmrgstatic bool 41201e04c3fSmrgvc4_render_blit(struct pipe_context *ctx, struct pipe_blit_info *info) 41301e04c3fSmrg{ 41401e04c3fSmrg struct vc4_context *vc4 = vc4_context(ctx); 41501e04c3fSmrg 41601e04c3fSmrg if (!util_blitter_is_blit_supported(vc4->blitter, info)) { 41701e04c3fSmrg fprintf(stderr, "blit unsupported %s -> %s\n", 41801e04c3fSmrg util_format_short_name(info->src.resource->format), 41901e04c3fSmrg util_format_short_name(info->dst.resource->format)); 42001e04c3fSmrg return false; 42101e04c3fSmrg } 42201e04c3fSmrg 42301e04c3fSmrg /* Enable the scissor, so we get a minimal set of tiles rendered. */ 42401e04c3fSmrg if (!info->scissor_enable) { 42501e04c3fSmrg info->scissor_enable = true; 42601e04c3fSmrg info->scissor.minx = info->dst.box.x; 42701e04c3fSmrg info->scissor.miny = info->dst.box.y; 42801e04c3fSmrg info->scissor.maxx = info->dst.box.x + info->dst.box.width; 42901e04c3fSmrg info->scissor.maxy = info->dst.box.y + info->dst.box.height; 43001e04c3fSmrg } 43101e04c3fSmrg 43201e04c3fSmrg vc4_blitter_save(vc4); 43301e04c3fSmrg util_blitter_blit(vc4->blitter, info); 43401e04c3fSmrg 43501e04c3fSmrg return true; 43601e04c3fSmrg} 43701e04c3fSmrg 43801e04c3fSmrg/* Optimal hardware path for blitting pixels. 43901e04c3fSmrg * Scaling, format conversion, up- and downsampling (resolve) are allowed. 44001e04c3fSmrg */ 44101e04c3fSmrgvoid 44201e04c3fSmrgvc4_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) 44301e04c3fSmrg{ 44401e04c3fSmrg struct pipe_blit_info info = *blit_info; 44501e04c3fSmrg 44601e04c3fSmrg if (vc4_yuv_blit(pctx, blit_info)) 44701e04c3fSmrg return; 44801e04c3fSmrg 44901e04c3fSmrg if (vc4_tile_blit(pctx, blit_info)) 45001e04c3fSmrg return; 45101e04c3fSmrg 45201e04c3fSmrg if (info.mask & PIPE_MASK_S) { 45301e04c3fSmrg if (util_try_blit_via_copy_region(pctx, &info)) 45401e04c3fSmrg return; 45501e04c3fSmrg 45601e04c3fSmrg info.mask &= ~PIPE_MASK_S; 45701e04c3fSmrg fprintf(stderr, "cannot blit stencil, skipping\n"); 45801e04c3fSmrg } 45901e04c3fSmrg 46001e04c3fSmrg if (vc4_render_blit(pctx, &info)) 46101e04c3fSmrg return; 46201e04c3fSmrg 46301e04c3fSmrg fprintf(stderr, "Unsupported blit\n"); 46401e04c3fSmrg} 465