101e04c3fSmrg/*
201e04c3fSmrg * Copyright (C) 2017 Rob Clark <robclark@freedesktop.org>
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 FROM,
2001e04c3fSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2101e04c3fSmrg * SOFTWARE.
2201e04c3fSmrg *
2301e04c3fSmrg * Authors:
2401e04c3fSmrg *    Rob Clark <robclark@freedesktop.org>
2501e04c3fSmrg */
2601e04c3fSmrg
2701e04c3fSmrg#include "util/u_blitter.h"
289f464c52Smaya#include "util/u_surface.h"
2901e04c3fSmrg
3001e04c3fSmrg#include "freedreno_blitter.h"
3101e04c3fSmrg#include "freedreno_context.h"
329f464c52Smaya#include "freedreno_fence.h"
337ec681f3Smrg#include "freedreno_resource.h"
3401e04c3fSmrg
3501e04c3fSmrg/* generic blit using u_blitter.. slightly modified version of util_blitter_blit
3601e04c3fSmrg * which also handles PIPE_BUFFER:
3701e04c3fSmrg */
3801e04c3fSmrg
3901e04c3fSmrgstatic void
4001e04c3fSmrgdefault_dst_texture(struct pipe_surface *dst_templ, struct pipe_resource *dst,
417ec681f3Smrg                    unsigned dstlevel, unsigned dstz)
4201e04c3fSmrg{
437ec681f3Smrg   memset(dst_templ, 0, sizeof(*dst_templ));
447ec681f3Smrg   dst_templ->u.tex.level = dstlevel;
457ec681f3Smrg   dst_templ->u.tex.first_layer = dstz;
467ec681f3Smrg   dst_templ->u.tex.last_layer = dstz;
4701e04c3fSmrg}
4801e04c3fSmrg
4901e04c3fSmrgstatic void
5001e04c3fSmrgdefault_src_texture(struct pipe_sampler_view *src_templ,
517ec681f3Smrg                    struct pipe_resource *src, unsigned srclevel)
5201e04c3fSmrg{
537ec681f3Smrg   bool cube_as_2darray =
547ec681f3Smrg      src->screen->get_param(src->screen, PIPE_CAP_SAMPLER_VIEW_TARGET);
557ec681f3Smrg
567ec681f3Smrg   memset(src_templ, 0, sizeof(*src_templ));
577ec681f3Smrg
587ec681f3Smrg   if (cube_as_2darray && (src->target == PIPE_TEXTURE_CUBE ||
597ec681f3Smrg                           src->target == PIPE_TEXTURE_CUBE_ARRAY))
607ec681f3Smrg      src_templ->target = PIPE_TEXTURE_2D_ARRAY;
617ec681f3Smrg   else
627ec681f3Smrg      src_templ->target = src->target;
637ec681f3Smrg
647ec681f3Smrg   if (src->target == PIPE_BUFFER) {
657ec681f3Smrg      src_templ->target = PIPE_TEXTURE_1D;
667ec681f3Smrg   }
677ec681f3Smrg   src_templ->u.tex.first_level = srclevel;
687ec681f3Smrg   src_templ->u.tex.last_level = srclevel;
697ec681f3Smrg   src_templ->u.tex.first_layer = 0;
707ec681f3Smrg   src_templ->u.tex.last_layer = src->target == PIPE_TEXTURE_3D
717ec681f3Smrg                                    ? u_minify(src->depth0, srclevel) - 1
727ec681f3Smrg                                    : (unsigned)(src->array_size - 1);
737ec681f3Smrg   src_templ->swizzle_r = PIPE_SWIZZLE_X;
747ec681f3Smrg   src_templ->swizzle_g = PIPE_SWIZZLE_Y;
757ec681f3Smrg   src_templ->swizzle_b = PIPE_SWIZZLE_Z;
767ec681f3Smrg   src_templ->swizzle_a = PIPE_SWIZZLE_W;
7701e04c3fSmrg}
7801e04c3fSmrg
799f464c52Smayastatic void
807ec681f3Smrgfd_blitter_pipe_begin(struct fd_context *ctx, bool render_cond) assert_dt
819f464c52Smaya{
827ec681f3Smrg   util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vtx.vertexbuf.vb);
837ec681f3Smrg   util_blitter_save_vertex_elements(ctx->blitter, ctx->vtx.vtx);
847ec681f3Smrg   util_blitter_save_vertex_shader(ctx->blitter, ctx->prog.vs);
857ec681f3Smrg   util_blitter_save_tessctrl_shader(ctx->blitter, ctx->prog.hs);
867ec681f3Smrg   util_blitter_save_tesseval_shader(ctx->blitter, ctx->prog.ds);
877ec681f3Smrg   util_blitter_save_geometry_shader(ctx->blitter, ctx->prog.gs);
887ec681f3Smrg   util_blitter_save_so_targets(ctx->blitter, ctx->streamout.num_targets,
897ec681f3Smrg                                ctx->streamout.targets);
907ec681f3Smrg   util_blitter_save_rasterizer(ctx->blitter, ctx->rasterizer);
917ec681f3Smrg   util_blitter_save_viewport(ctx->blitter, &ctx->viewport);
927ec681f3Smrg   util_blitter_save_scissor(ctx->blitter, &ctx->scissor);
937ec681f3Smrg   util_blitter_save_fragment_shader(ctx->blitter, ctx->prog.fs);
947ec681f3Smrg   util_blitter_save_blend(ctx->blitter, ctx->blend);
957ec681f3Smrg   util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->zsa);
967ec681f3Smrg   util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref);
977ec681f3Smrg   util_blitter_save_sample_mask(ctx->blitter, ctx->sample_mask);
987ec681f3Smrg   util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer);
997ec681f3Smrg   util_blitter_save_fragment_sampler_states(
1007ec681f3Smrg      ctx->blitter, ctx->tex[PIPE_SHADER_FRAGMENT].num_samplers,
1017ec681f3Smrg      (void **)ctx->tex[PIPE_SHADER_FRAGMENT].samplers);
1027ec681f3Smrg   util_blitter_save_fragment_sampler_views(
1037ec681f3Smrg      ctx->blitter, ctx->tex[PIPE_SHADER_FRAGMENT].num_textures,
1047ec681f3Smrg      ctx->tex[PIPE_SHADER_FRAGMENT].textures);
1057ec681f3Smrg   if (!render_cond)
1067ec681f3Smrg      util_blitter_save_render_condition(ctx->blitter, ctx->cond_query,
1077ec681f3Smrg                                         ctx->cond_cond, ctx->cond_mode);
1087ec681f3Smrg
1097ec681f3Smrg   if (ctx->batch)
1107ec681f3Smrg      fd_batch_update_queries(ctx->batch);
1119f464c52Smaya}
1129f464c52Smaya
1139f464c52Smayastatic void
1147ec681f3Smrgfd_blitter_pipe_end(struct fd_context *ctx) assert_dt
1159f464c52Smaya{
1169f464c52Smaya}
1179f464c52Smaya
1189f464c52Smayabool
11901e04c3fSmrgfd_blitter_blit(struct fd_context *ctx, const struct pipe_blit_info *info)
12001e04c3fSmrg{
1217ec681f3Smrg   struct pipe_context *pctx = &ctx->base;
1227ec681f3Smrg   struct pipe_resource *dst = info->dst.resource;
1237ec681f3Smrg   struct pipe_resource *src = info->src.resource;
1247ec681f3Smrg   struct pipe_context *pipe = &ctx->base;
1257ec681f3Smrg   struct pipe_surface *dst_view, dst_templ;
1267ec681f3Smrg   struct pipe_sampler_view src_templ, *src_view;
1277ec681f3Smrg
1287ec681f3Smrg   /* If the blit is updating the whole contents of the resource,
1297ec681f3Smrg    * invalidate it so we don't trigger any unnecessary tile loads in the 3D
1307ec681f3Smrg    * path.
1317ec681f3Smrg    */
1327ec681f3Smrg   if (util_blit_covers_whole_resource(info))
1337ec681f3Smrg      pctx->invalidate_resource(pctx, info->dst.resource);
1347ec681f3Smrg
1357ec681f3Smrg   /* The blit format may not match the resource format in this path, so
1367ec681f3Smrg    * we need to validate that we can use the src/dst resource with the
1377ec681f3Smrg    * requested format (and uncompress if necessary).  Normally this would
1387ec681f3Smrg    * happen in ->set_sampler_view(), ->set_framebuffer_state(), etc.  But
1397ec681f3Smrg    * that would cause recursion back into u_blitter, which ends in tears.
1407ec681f3Smrg    *
1417ec681f3Smrg    * To avoid recursion, this needs to be done before util_blitter_save_*()
1427ec681f3Smrg    */
1437ec681f3Smrg   if (ctx->validate_format) {
1447ec681f3Smrg      ctx->validate_format(ctx, fd_resource(dst), info->dst.format);
1457ec681f3Smrg      ctx->validate_format(ctx, fd_resource(src), info->src.format);
1467ec681f3Smrg   }
1477ec681f3Smrg
1487ec681f3Smrg   if (src == dst)
1497ec681f3Smrg      pipe->flush(pipe, NULL, 0);
1507ec681f3Smrg
1517ec681f3Smrg   DBG_BLIT(info, NULL);
1527ec681f3Smrg
1537ec681f3Smrg   fd_blitter_pipe_begin(ctx, info->render_condition_enable);
1547ec681f3Smrg
1557ec681f3Smrg   /* Initialize the surface. */
1567ec681f3Smrg   default_dst_texture(&dst_templ, dst, info->dst.level, info->dst.box.z);
1577ec681f3Smrg   dst_templ.format = info->dst.format;
1587ec681f3Smrg   dst_view = pipe->create_surface(pipe, dst, &dst_templ);
1597ec681f3Smrg
1607ec681f3Smrg   /* Initialize the sampler view. */
1617ec681f3Smrg   default_src_texture(&src_templ, src, info->src.level);
1627ec681f3Smrg   src_templ.format = info->src.format;
1637ec681f3Smrg   src_view = pipe->create_sampler_view(pipe, src, &src_templ);
1647ec681f3Smrg
1657ec681f3Smrg   /* Copy. */
1667ec681f3Smrg   util_blitter_blit_generic(
1677ec681f3Smrg      ctx->blitter, dst_view, &info->dst.box, src_view, &info->src.box,
1687ec681f3Smrg      src->width0, src->height0, info->mask, info->filter,
1697ec681f3Smrg      info->scissor_enable ? &info->scissor : NULL, info->alpha_blend, false);
1707ec681f3Smrg
1717ec681f3Smrg   pipe_surface_reference(&dst_view, NULL);
1727ec681f3Smrg   pipe_sampler_view_reference(&src_view, NULL);
1737ec681f3Smrg
1747ec681f3Smrg   fd_blitter_pipe_end(ctx);
1757ec681f3Smrg
1767ec681f3Smrg   /* While this shouldn't technically be necessary, it is required for
1777ec681f3Smrg    * dEQP-GLES31.functional.stencil_texturing.format.stencil_index8_cube and
1787ec681f3Smrg    * 2d_array to pass.
1797ec681f3Smrg    */
1807ec681f3Smrg   fd_bc_flush_writer(ctx, fd_resource(info->dst.resource));
1817ec681f3Smrg
1827ec681f3Smrg   /* The fallback blitter must never fail: */
1837ec681f3Smrg   return true;
1849f464c52Smaya}
1859f464c52Smaya
1869f464c52Smaya/* Generic clear implementation (partially) using u_blitter: */
1879f464c52Smayavoid
1889f464c52Smayafd_blitter_clear(struct pipe_context *pctx, unsigned buffers,
1897ec681f3Smrg                 const union pipe_color_union *color, double depth,
1907ec681f3Smrg                 unsigned stencil)
1919f464c52Smaya{
1927ec681f3Smrg   struct fd_context *ctx = fd_context(pctx);
1937ec681f3Smrg   struct pipe_framebuffer_state *pfb = &ctx->batch->framebuffer;
1947ec681f3Smrg   struct blitter_context *blitter = ctx->blitter;
1957ec681f3Smrg
1967ec681f3Smrg   /* Note: don't use discard=true, if there was something to
1977ec681f3Smrg    * discard, that would have been already handled in fd_clear().
1987ec681f3Smrg    */
1997ec681f3Smrg   fd_blitter_pipe_begin(ctx, false);
2007ec681f3Smrg
2017ec681f3Smrg   util_blitter_save_fragment_constant_buffer_slot(
2027ec681f3Smrg      ctx->blitter, ctx->constbuf[PIPE_SHADER_FRAGMENT].cb);
2037ec681f3Smrg
2047ec681f3Smrg   util_blitter_common_clear_setup(blitter, pfb->width, pfb->height, buffers,
2057ec681f3Smrg                                   NULL, NULL);
2067ec681f3Smrg
2077ec681f3Smrg   struct pipe_stencil_ref sr = {.ref_value = {stencil & 0xff}};
2087ec681f3Smrg   pctx->set_stencil_ref(pctx, sr);
2097ec681f3Smrg
2107ec681f3Smrg   struct pipe_constant_buffer cb = {
2117ec681f3Smrg      .buffer_size = 16,
2127ec681f3Smrg      .user_buffer = &color->ui,
2137ec681f3Smrg   };
2147ec681f3Smrg   pctx->set_constant_buffer(pctx, PIPE_SHADER_FRAGMENT, 0, false, &cb);
2157ec681f3Smrg
2167ec681f3Smrg   unsigned rs_idx = pfb->samples > 1 ? 1 : 0;
2177ec681f3Smrg   if (!ctx->clear_rs_state[rs_idx]) {
2187ec681f3Smrg      const struct pipe_rasterizer_state tmpl = {
2197ec681f3Smrg         .cull_face = PIPE_FACE_NONE,
2207ec681f3Smrg         .half_pixel_center = 1,
2217ec681f3Smrg         .bottom_edge_rule = 1,
2227ec681f3Smrg         .flatshade = 1,
2237ec681f3Smrg         .depth_clip_near = 1,
2247ec681f3Smrg         .depth_clip_far = 1,
2257ec681f3Smrg         .multisample = pfb->samples > 1,
2267ec681f3Smrg      };
2277ec681f3Smrg      ctx->clear_rs_state[rs_idx] = pctx->create_rasterizer_state(pctx, &tmpl);
2287ec681f3Smrg   }
2297ec681f3Smrg   pctx->bind_rasterizer_state(pctx, ctx->clear_rs_state[rs_idx]);
2307ec681f3Smrg
2317ec681f3Smrg   struct pipe_viewport_state vp = {
2327ec681f3Smrg      .scale = {0.5f * pfb->width, -0.5f * pfb->height, depth},
2337ec681f3Smrg      .translate = {0.5f * pfb->width, 0.5f * pfb->height, 0.0f},
2347ec681f3Smrg   };
2357ec681f3Smrg   pctx->set_viewport_states(pctx, 0, 1, &vp);
2367ec681f3Smrg
2377ec681f3Smrg   pctx->bind_vertex_elements_state(pctx, ctx->solid_vbuf_state.vtx);
2387ec681f3Smrg   pctx->set_vertex_buffers(pctx, blitter->vb_slot, 1, 0, false,
2397ec681f3Smrg                            &ctx->solid_vbuf_state.vertexbuf.vb[0]);
2407ec681f3Smrg   pctx->set_stream_output_targets(pctx, 0, NULL, NULL);
2417ec681f3Smrg
2427ec681f3Smrg   if (pfb->layers > 1)
2437ec681f3Smrg      pctx->bind_vs_state(pctx, ctx->solid_layered_prog.vs);
2447ec681f3Smrg   else
2457ec681f3Smrg      pctx->bind_vs_state(pctx, ctx->solid_prog.vs);
2467ec681f3Smrg
2477ec681f3Smrg   pctx->bind_fs_state(pctx, ctx->solid_prog.fs);
2487ec681f3Smrg
2497ec681f3Smrg   /* Clear geom/tess shaders, lest the draw emit code think we are
2507ec681f3Smrg    * trying to use use them:
2517ec681f3Smrg    */
2527ec681f3Smrg   pctx->bind_gs_state(pctx, NULL);
2537ec681f3Smrg   pctx->bind_tcs_state(pctx, NULL);
2547ec681f3Smrg   pctx->bind_tes_state(pctx, NULL);
2557ec681f3Smrg
2567ec681f3Smrg   struct pipe_draw_info info = {
2577ec681f3Smrg      .mode = PIPE_PRIM_MAX, /* maps to DI_PT_RECTLIST */
2587ec681f3Smrg      .index_bounds_valid = true,
2597ec681f3Smrg      .max_index = 1,
2607ec681f3Smrg      .instance_count = MAX2(1, pfb->layers),
2617ec681f3Smrg   };
2627ec681f3Smrg   struct pipe_draw_start_count_bias draw = {
2637ec681f3Smrg      .count = 2,
2647ec681f3Smrg   };
2657ec681f3Smrg
2667ec681f3Smrg   pctx->draw_vbo(pctx, &info, 0, NULL, &draw, 1);
2677ec681f3Smrg
2687ec681f3Smrg   /* We expect that this should not have triggered a change in pfb: */
2697ec681f3Smrg   assert(util_framebuffer_state_equal(pfb, &ctx->framebuffer));
2707ec681f3Smrg
2717ec681f3Smrg   util_blitter_restore_constant_buffer_state(blitter);
2727ec681f3Smrg   util_blitter_restore_vertex_states(blitter);
2737ec681f3Smrg   util_blitter_restore_fragment_states(blitter);
2747ec681f3Smrg   util_blitter_restore_textures(blitter);
2757ec681f3Smrg   util_blitter_restore_fb_state(blitter);
2767ec681f3Smrg   util_blitter_restore_render_cond(blitter);
2777ec681f3Smrg   util_blitter_unset_running_flag(blitter);
2787ec681f3Smrg
2797ec681f3Smrg   fd_blitter_pipe_end(ctx);
2809f464c52Smaya}
2819f464c52Smaya
2829f464c52Smaya/**
2839f464c52Smaya * Optimal hardware path for blitting pixels.
2849f464c52Smaya * Scaling, format conversion, up- and downsampling (resolve) are allowed.
2859f464c52Smaya */
2869f464c52Smayabool
2879f464c52Smayafd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info)
2889f464c52Smaya{
2897ec681f3Smrg   struct fd_context *ctx = fd_context(pctx);
2907ec681f3Smrg   struct pipe_blit_info info = *blit_info;
2919f464c52Smaya
2927ec681f3Smrg   if (info.render_condition_enable && !fd_render_condition_check(pctx))
2937ec681f3Smrg      return true;
2949f464c52Smaya
2957ec681f3Smrg   if (ctx->blit && ctx->blit(ctx, &info))
2967ec681f3Smrg      return true;
2979f464c52Smaya
2987ec681f3Smrg   if (info.mask & PIPE_MASK_S) {
2997ec681f3Smrg      DBG("cannot blit stencil, skipping");
3007ec681f3Smrg      info.mask &= ~PIPE_MASK_S;
3017ec681f3Smrg   }
3029f464c52Smaya
3037ec681f3Smrg   if (!util_blitter_is_blit_supported(ctx->blitter, &info)) {
3047ec681f3Smrg      DBG("blit unsupported %s -> %s",
3057ec681f3Smrg          util_format_short_name(info.src.resource->format),
3067ec681f3Smrg          util_format_short_name(info.dst.resource->format));
3077ec681f3Smrg      return false;
3087ec681f3Smrg   }
3099f464c52Smaya
3107ec681f3Smrg   return fd_blitter_blit(ctx, &info);
3119f464c52Smaya}
3129f464c52Smaya
3139f464c52Smaya/**
3149f464c52Smaya * _copy_region using pipe (3d engine)
3159f464c52Smaya */
3169f464c52Smayastatic bool
3177ec681f3Smrgfd_blitter_pipe_copy_region(struct fd_context *ctx, struct pipe_resource *dst,
3187ec681f3Smrg                            unsigned dst_level, unsigned dstx, unsigned dsty,
3197ec681f3Smrg                            unsigned dstz, struct pipe_resource *src,
3207ec681f3Smrg                            unsigned src_level,
3217ec681f3Smrg                            const struct pipe_box *src_box) assert_dt
3229f464c52Smaya{
3237ec681f3Smrg   /* not until we allow rendertargets to be buffers */
3247ec681f3Smrg   if (dst->target == PIPE_BUFFER || src->target == PIPE_BUFFER)
3257ec681f3Smrg      return false;
3267ec681f3Smrg
3277ec681f3Smrg   if (!util_blitter_is_copy_supported(ctx->blitter, dst, src))
3287ec681f3Smrg      return false;
3299f464c52Smaya
3307ec681f3Smrg   if (src == dst) {
3317ec681f3Smrg      struct pipe_context *pctx = &ctx->base;
3327ec681f3Smrg      pctx->flush(pctx, NULL, 0);
3337ec681f3Smrg   }
3349f464c52Smaya
3357ec681f3Smrg   /* TODO we could invalidate if dst box covers dst level fully. */
3367ec681f3Smrg   fd_blitter_pipe_begin(ctx, false);
3377ec681f3Smrg   util_blitter_copy_texture(ctx->blitter, dst, dst_level, dstx, dsty, dstz,
3387ec681f3Smrg                             src, src_level, src_box);
3397ec681f3Smrg   fd_blitter_pipe_end(ctx);
3409f464c52Smaya
3417ec681f3Smrg   return true;
3429f464c52Smaya}
3439f464c52Smaya
3449f464c52Smaya/**
3459f464c52Smaya * Copy a block of pixels from one resource to another.
3469f464c52Smaya * The resource must be of the same format.
3479f464c52Smaya */
3489f464c52Smayavoid
3497ec681f3Smrgfd_resource_copy_region(struct pipe_context *pctx, struct pipe_resource *dst,
3507ec681f3Smrg                        unsigned dst_level, unsigned dstx, unsigned dsty,
3517ec681f3Smrg                        unsigned dstz, struct pipe_resource *src,
3527ec681f3Smrg                        unsigned src_level, const struct pipe_box *src_box)
3539f464c52Smaya{
3547ec681f3Smrg   struct fd_context *ctx = fd_context(pctx);
3557ec681f3Smrg
3567ec681f3Smrg   /* The blitter path handles compressed formats only if src and dst format
3577ec681f3Smrg    * match, in other cases just fall back to sw:
3587ec681f3Smrg    */
3597ec681f3Smrg   if ((src->format != dst->format) &&
3607ec681f3Smrg       (util_format_is_compressed(src->format) ||
3617ec681f3Smrg        util_format_is_compressed(dst->format))) {
3627ec681f3Smrg      perf_debug_ctx(ctx, "copy_region falls back to sw for {%"PRSC_FMT"} to {%"PRSC_FMT"}",
3637ec681f3Smrg                     PRSC_ARGS(src), PRSC_ARGS(dst));
3647ec681f3Smrg      goto fallback;
3657ec681f3Smrg   }
3667ec681f3Smrg
3677ec681f3Smrg   if (ctx->blit) {
3687ec681f3Smrg      struct pipe_blit_info info;
3697ec681f3Smrg
3707ec681f3Smrg      memset(&info, 0, sizeof info);
3717ec681f3Smrg      info.dst.resource = dst;
3727ec681f3Smrg      info.dst.level = dst_level;
3737ec681f3Smrg      info.dst.box.x = dstx;
3747ec681f3Smrg      info.dst.box.y = dsty;
3757ec681f3Smrg      info.dst.box.z = dstz;
3767ec681f3Smrg      info.dst.box.width = src_box->width;
3777ec681f3Smrg      info.dst.box.height = src_box->height;
3787ec681f3Smrg      assert(info.dst.box.width >= 0);
3797ec681f3Smrg      assert(info.dst.box.height >= 0);
3807ec681f3Smrg      info.dst.box.depth = 1;
3817ec681f3Smrg      info.dst.format = dst->format;
3827ec681f3Smrg      info.src.resource = src;
3837ec681f3Smrg      info.src.level = src_level;
3847ec681f3Smrg      info.src.box = *src_box;
3857ec681f3Smrg      info.src.format = src->format;
3867ec681f3Smrg      info.mask = util_format_get_mask(src->format);
3877ec681f3Smrg      info.filter = PIPE_TEX_FILTER_NEAREST;
3887ec681f3Smrg      info.scissor_enable = 0;
3897ec681f3Smrg
3907ec681f3Smrg      if (ctx->blit(ctx, &info))
3917ec681f3Smrg         return;
3927ec681f3Smrg   }
3937ec681f3Smrg
3947ec681f3Smrg   /* try blit on 3d pipe: */
3957ec681f3Smrg   if (fd_blitter_pipe_copy_region(ctx, dst, dst_level, dstx, dsty, dstz, src,
3967ec681f3Smrg                                   src_level, src_box))
3977ec681f3Smrg      return;
3987ec681f3Smrg
3997ec681f3Smrg   /* else fallback to pure sw: */
4007ec681f3Smrgfallback:
4017ec681f3Smrg   util_resource_copy_region(pctx, dst, dst_level, dstx, dsty, dstz, src,
4027ec681f3Smrg                             src_level, src_box);
40301e04c3fSmrg}
404