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