17ec681f3Smrg#include "zink_context.h"
27ec681f3Smrg#include "zink_helpers.h"
37ec681f3Smrg#include "zink_query.h"
47ec681f3Smrg#include "zink_resource.h"
57ec681f3Smrg#include "zink_screen.h"
67ec681f3Smrg
77ec681f3Smrg#include "util/u_blitter.h"
87ec681f3Smrg#include "util/u_rect.h"
97ec681f3Smrg#include "util/u_surface.h"
107ec681f3Smrg#include "util/format/u_format.h"
117ec681f3Smrg
127ec681f3Smrgstatic void
137ec681f3Smrgapply_dst_clears(struct zink_context *ctx, const struct pipe_blit_info *info, bool discard_only)
147ec681f3Smrg{
157ec681f3Smrg   if (info->scissor_enable) {
167ec681f3Smrg      struct u_rect rect = { info->scissor.minx, info->scissor.maxx,
177ec681f3Smrg                             info->scissor.miny, info->scissor.maxy };
187ec681f3Smrg      zink_fb_clears_apply_or_discard(ctx, info->dst.resource, rect, discard_only);
197ec681f3Smrg   } else
207ec681f3Smrg      zink_fb_clears_apply_or_discard(ctx, info->dst.resource, zink_rect_from_box(&info->dst.box), discard_only);
217ec681f3Smrg}
227ec681f3Smrg
237ec681f3Smrgstatic bool
247ec681f3Smrgblit_resolve(struct zink_context *ctx, const struct pipe_blit_info *info)
257ec681f3Smrg{
267ec681f3Smrg   if (util_format_get_mask(info->dst.format) != info->mask ||
277ec681f3Smrg       util_format_get_mask(info->src.format) != info->mask ||
287ec681f3Smrg       util_format_is_depth_or_stencil(info->dst.format) ||
297ec681f3Smrg       info->scissor_enable ||
307ec681f3Smrg       info->alpha_blend)
317ec681f3Smrg      return false;
327ec681f3Smrg
337ec681f3Smrg   if (info->src.box.width != info->dst.box.width ||
347ec681f3Smrg       info->src.box.height != info->dst.box.height ||
357ec681f3Smrg       info->src.box.depth != info->dst.box.depth)
367ec681f3Smrg      return false;
377ec681f3Smrg
387ec681f3Smrg   if (info->render_condition_enable &&
397ec681f3Smrg       ctx->render_condition_active)
407ec681f3Smrg      return false;
417ec681f3Smrg
427ec681f3Smrg   struct zink_resource *src = zink_resource(info->src.resource);
437ec681f3Smrg   struct zink_resource *dst = zink_resource(info->dst.resource);
447ec681f3Smrg
457ec681f3Smrg   struct zink_screen *screen = zink_screen(ctx->base.screen);
467ec681f3Smrg   if (src->format != zink_get_format(screen, info->src.format) ||
477ec681f3Smrg       dst->format != zink_get_format(screen, info->dst.format))
487ec681f3Smrg      return false;
497ec681f3Smrg   if (info->dst.resource->target == PIPE_BUFFER)
507ec681f3Smrg      util_range_add(info->dst.resource, &dst->valid_buffer_range,
517ec681f3Smrg                     info->dst.box.x, info->dst.box.x + info->dst.box.width);
527ec681f3Smrg
537ec681f3Smrg   apply_dst_clears(ctx, info, false);
547ec681f3Smrg   zink_fb_clears_apply_region(ctx, info->src.resource, zink_rect_from_box(&info->src.box));
557ec681f3Smrg
567ec681f3Smrg   struct zink_batch *batch = &ctx->batch;
577ec681f3Smrg   zink_batch_no_rp(ctx);
587ec681f3Smrg   zink_batch_reference_resource_rw(batch, src, false);
597ec681f3Smrg   zink_batch_reference_resource_rw(batch, dst, true);
607ec681f3Smrg
617ec681f3Smrg   zink_resource_setup_transfer_layouts(ctx, src, dst);
627ec681f3Smrg
637ec681f3Smrg   VkImageResolve region = {0};
647ec681f3Smrg
657ec681f3Smrg   region.srcSubresource.aspectMask = src->aspect;
667ec681f3Smrg   region.srcSubresource.mipLevel = info->src.level;
677ec681f3Smrg   region.srcOffset.x = info->src.box.x;
687ec681f3Smrg   region.srcOffset.y = info->src.box.y;
697ec681f3Smrg
707ec681f3Smrg   if (src->base.b.array_size > 1) {
717ec681f3Smrg      region.srcOffset.z = 0;
727ec681f3Smrg      region.srcSubresource.baseArrayLayer = info->src.box.z;
737ec681f3Smrg      region.srcSubresource.layerCount = info->src.box.depth;
747ec681f3Smrg   } else {
757ec681f3Smrg      assert(info->src.box.depth == 1);
767ec681f3Smrg      region.srcOffset.z = info->src.box.z;
777ec681f3Smrg      region.srcSubresource.baseArrayLayer = 0;
787ec681f3Smrg      region.srcSubresource.layerCount = 1;
797ec681f3Smrg   }
807ec681f3Smrg
817ec681f3Smrg   region.dstSubresource.aspectMask = dst->aspect;
827ec681f3Smrg   region.dstSubresource.mipLevel = info->dst.level;
837ec681f3Smrg   region.dstOffset.x = info->dst.box.x;
847ec681f3Smrg   region.dstOffset.y = info->dst.box.y;
857ec681f3Smrg
867ec681f3Smrg   if (dst->base.b.array_size > 1) {
877ec681f3Smrg      region.dstOffset.z = 0;
887ec681f3Smrg      region.dstSubresource.baseArrayLayer = info->dst.box.z;
897ec681f3Smrg      region.dstSubresource.layerCount = info->dst.box.depth;
907ec681f3Smrg   } else {
917ec681f3Smrg      assert(info->dst.box.depth == 1);
927ec681f3Smrg      region.dstOffset.z = info->dst.box.z;
937ec681f3Smrg      region.dstSubresource.baseArrayLayer = 0;
947ec681f3Smrg      region.dstSubresource.layerCount = 1;
957ec681f3Smrg   }
967ec681f3Smrg
977ec681f3Smrg   region.extent.width = info->dst.box.width;
987ec681f3Smrg   region.extent.height = info->dst.box.height;
997ec681f3Smrg   region.extent.depth = info->dst.box.depth;
1007ec681f3Smrg   VKCTX(CmdResolveImage)(batch->state->cmdbuf, src->obj->image, src->layout,
1017ec681f3Smrg                     dst->obj->image, dst->layout,
1027ec681f3Smrg                     1, &region);
1037ec681f3Smrg
1047ec681f3Smrg   return true;
1057ec681f3Smrg}
1067ec681f3Smrg
1077ec681f3Smrgstatic VkFormatFeatureFlags
1087ec681f3Smrgget_resource_features(struct zink_screen *screen, struct zink_resource *res)
1097ec681f3Smrg{
1107ec681f3Smrg   VkFormatProperties props = screen->format_props[res->base.b.format];
1117ec681f3Smrg   return res->optimal_tiling ? props.optimalTilingFeatures :
1127ec681f3Smrg                                props.linearTilingFeatures;
1137ec681f3Smrg}
1147ec681f3Smrg
1157ec681f3Smrgstatic bool
1167ec681f3Smrgblit_native(struct zink_context *ctx, const struct pipe_blit_info *info)
1177ec681f3Smrg{
1187ec681f3Smrg   if (util_format_get_mask(info->dst.format) != info->mask ||
1197ec681f3Smrg       util_format_get_mask(info->src.format) != info->mask ||
1207ec681f3Smrg       info->scissor_enable ||
1217ec681f3Smrg       info->alpha_blend)
1227ec681f3Smrg      return false;
1237ec681f3Smrg
1247ec681f3Smrg   if (info->render_condition_enable &&
1257ec681f3Smrg       ctx->render_condition_active)
1267ec681f3Smrg      return false;
1277ec681f3Smrg
1287ec681f3Smrg   if (util_format_is_depth_or_stencil(info->dst.format) &&
1297ec681f3Smrg       info->dst.format != info->src.format)
1307ec681f3Smrg      return false;
1317ec681f3Smrg
1327ec681f3Smrg   /* vkCmdBlitImage must not be used for multisampled source or destination images. */
1337ec681f3Smrg   if (info->src.resource->nr_samples > 1 || info->dst.resource->nr_samples > 1)
1347ec681f3Smrg      return false;
1357ec681f3Smrg
1367ec681f3Smrg   struct zink_resource *src = zink_resource(info->src.resource);
1377ec681f3Smrg   struct zink_resource *dst = zink_resource(info->dst.resource);
1387ec681f3Smrg
1397ec681f3Smrg   struct zink_screen *screen = zink_screen(ctx->base.screen);
1407ec681f3Smrg   if (src->format != zink_get_format(screen, info->src.format) ||
1417ec681f3Smrg       dst->format != zink_get_format(screen, info->dst.format))
1427ec681f3Smrg      return false;
1437ec681f3Smrg
1447ec681f3Smrg   if (!(get_resource_features(screen, src) & VK_FORMAT_FEATURE_BLIT_SRC_BIT) ||
1457ec681f3Smrg       !(get_resource_features(screen, dst) & VK_FORMAT_FEATURE_BLIT_DST_BIT))
1467ec681f3Smrg      return false;
1477ec681f3Smrg
1487ec681f3Smrg   if ((util_format_is_pure_sint(info->src.format) !=
1497ec681f3Smrg        util_format_is_pure_sint(info->dst.format)) ||
1507ec681f3Smrg       (util_format_is_pure_uint(info->src.format) !=
1517ec681f3Smrg        util_format_is_pure_uint(info->dst.format)))
1527ec681f3Smrg      return false;
1537ec681f3Smrg
1547ec681f3Smrg   if (info->filter == PIPE_TEX_FILTER_LINEAR &&
1557ec681f3Smrg       !(get_resource_features(screen, src) &
1567ec681f3Smrg          VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT))
1577ec681f3Smrg      return false;
1587ec681f3Smrg
1597ec681f3Smrg   apply_dst_clears(ctx, info, false);
1607ec681f3Smrg   zink_fb_clears_apply_region(ctx, info->src.resource, zink_rect_from_box(&info->src.box));
1617ec681f3Smrg
1627ec681f3Smrg   struct zink_batch *batch = &ctx->batch;
1637ec681f3Smrg   zink_batch_no_rp(ctx);
1647ec681f3Smrg   zink_batch_reference_resource_rw(batch, src, false);
1657ec681f3Smrg   zink_batch_reference_resource_rw(batch, dst, true);
1667ec681f3Smrg
1677ec681f3Smrg   zink_resource_setup_transfer_layouts(ctx, src, dst);
1687ec681f3Smrg   if (info->dst.resource->target == PIPE_BUFFER)
1697ec681f3Smrg      util_range_add(info->dst.resource, &dst->valid_buffer_range,
1707ec681f3Smrg                     info->dst.box.x, info->dst.box.x + info->dst.box.width);
1717ec681f3Smrg   VkImageBlit region = {0};
1727ec681f3Smrg   region.srcSubresource.aspectMask = src->aspect;
1737ec681f3Smrg   region.srcSubresource.mipLevel = info->src.level;
1747ec681f3Smrg   region.srcOffsets[0].x = info->src.box.x;
1757ec681f3Smrg   region.srcOffsets[0].y = info->src.box.y;
1767ec681f3Smrg   region.srcOffsets[1].x = info->src.box.x + info->src.box.width;
1777ec681f3Smrg   region.srcOffsets[1].y = info->src.box.y + info->src.box.height;
1787ec681f3Smrg
1797ec681f3Smrg   switch (src->base.b.target) {
1807ec681f3Smrg   case PIPE_TEXTURE_CUBE:
1817ec681f3Smrg   case PIPE_TEXTURE_CUBE_ARRAY:
1827ec681f3Smrg   case PIPE_TEXTURE_2D_ARRAY:
1837ec681f3Smrg   case PIPE_TEXTURE_1D_ARRAY:
1847ec681f3Smrg      /* these use layer */
1857ec681f3Smrg      region.srcSubresource.baseArrayLayer = info->src.box.z;
1867ec681f3Smrg      region.srcSubresource.layerCount = info->src.box.depth;
1877ec681f3Smrg      region.srcOffsets[0].z = 0;
1887ec681f3Smrg      region.srcOffsets[1].z = 1;
1897ec681f3Smrg      break;
1907ec681f3Smrg   case PIPE_TEXTURE_3D:
1917ec681f3Smrg      /* this uses depth */
1927ec681f3Smrg      region.srcSubresource.baseArrayLayer = 0;
1937ec681f3Smrg      region.srcSubresource.layerCount = 1;
1947ec681f3Smrg      region.srcOffsets[0].z = info->src.box.z;
1957ec681f3Smrg      region.srcOffsets[1].z = info->src.box.z + info->src.box.depth;
1967ec681f3Smrg      break;
1977ec681f3Smrg   default:
1987ec681f3Smrg      /* these must only copy one layer */
1997ec681f3Smrg      region.srcSubresource.baseArrayLayer = 0;
2007ec681f3Smrg      region.srcSubresource.layerCount = 1;
2017ec681f3Smrg      region.srcOffsets[0].z = 0;
2027ec681f3Smrg      region.srcOffsets[1].z = 1;
2037ec681f3Smrg   }
2047ec681f3Smrg
2057ec681f3Smrg   region.dstSubresource.aspectMask = dst->aspect;
2067ec681f3Smrg   region.dstSubresource.mipLevel = info->dst.level;
2077ec681f3Smrg   region.dstOffsets[0].x = info->dst.box.x;
2087ec681f3Smrg   region.dstOffsets[0].y = info->dst.box.y;
2097ec681f3Smrg   region.dstOffsets[1].x = info->dst.box.x + info->dst.box.width;
2107ec681f3Smrg   region.dstOffsets[1].y = info->dst.box.y + info->dst.box.height;
2117ec681f3Smrg   assert(region.dstOffsets[0].x != region.dstOffsets[1].x);
2127ec681f3Smrg   assert(region.dstOffsets[0].y != region.dstOffsets[1].y);
2137ec681f3Smrg
2147ec681f3Smrg   switch (dst->base.b.target) {
2157ec681f3Smrg   case PIPE_TEXTURE_CUBE:
2167ec681f3Smrg   case PIPE_TEXTURE_CUBE_ARRAY:
2177ec681f3Smrg   case PIPE_TEXTURE_2D_ARRAY:
2187ec681f3Smrg   case PIPE_TEXTURE_1D_ARRAY:
2197ec681f3Smrg      /* these use layer */
2207ec681f3Smrg      region.dstSubresource.baseArrayLayer = info->dst.box.z;
2217ec681f3Smrg      region.dstSubresource.layerCount = info->dst.box.depth;
2227ec681f3Smrg      region.dstOffsets[0].z = 0;
2237ec681f3Smrg      region.dstOffsets[1].z = 1;
2247ec681f3Smrg      break;
2257ec681f3Smrg   case PIPE_TEXTURE_3D:
2267ec681f3Smrg      /* this uses depth */
2277ec681f3Smrg      region.dstSubresource.baseArrayLayer = 0;
2287ec681f3Smrg      region.dstSubresource.layerCount = 1;
2297ec681f3Smrg      region.dstOffsets[0].z = info->dst.box.z;
2307ec681f3Smrg      region.dstOffsets[1].z = info->dst.box.z + info->dst.box.depth;
2317ec681f3Smrg      break;
2327ec681f3Smrg   default:
2337ec681f3Smrg      /* these must only copy one layer */
2347ec681f3Smrg      region.dstSubresource.baseArrayLayer = 0;
2357ec681f3Smrg      region.dstSubresource.layerCount = 1;
2367ec681f3Smrg      region.dstOffsets[0].z = 0;
2377ec681f3Smrg      region.dstOffsets[1].z = 1;
2387ec681f3Smrg   }
2397ec681f3Smrg   assert(region.dstOffsets[0].z != region.dstOffsets[1].z);
2407ec681f3Smrg
2417ec681f3Smrg   VKCTX(CmdBlitImage)(batch->state->cmdbuf, src->obj->image, src->layout,
2427ec681f3Smrg                  dst->obj->image, dst->layout,
2437ec681f3Smrg                  1, &region,
2447ec681f3Smrg                  zink_filter(info->filter));
2457ec681f3Smrg
2467ec681f3Smrg   return true;
2477ec681f3Smrg}
2487ec681f3Smrg
2497ec681f3Smrgvoid
2507ec681f3Smrgzink_blit(struct pipe_context *pctx,
2517ec681f3Smrg          const struct pipe_blit_info *info)
2527ec681f3Smrg{
2537ec681f3Smrg   struct zink_context *ctx = zink_context(pctx);
2547ec681f3Smrg   const struct util_format_description *src_desc = util_format_description(info->src.format);
2557ec681f3Smrg   const struct util_format_description *dst_desc = util_format_description(info->dst.format);
2567ec681f3Smrg
2577ec681f3Smrg   if (info->render_condition_enable &&
2587ec681f3Smrg       unlikely(!zink_screen(pctx->screen)->info.have_EXT_conditional_rendering && !zink_check_conditional_render(ctx)))
2597ec681f3Smrg      return;
2607ec681f3Smrg
2617ec681f3Smrg   if (src_desc == dst_desc ||
2627ec681f3Smrg       src_desc->nr_channels != 4 || src_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN ||
2637ec681f3Smrg       (src_desc->nr_channels == 4 && src_desc->channel[3].type != UTIL_FORMAT_TYPE_VOID)) {
2647ec681f3Smrg      /* we can't blit RGBX -> RGBA formats directly since they're emulated
2657ec681f3Smrg       * so we have to use sampler views
2667ec681f3Smrg       */
2677ec681f3Smrg      if (info->src.resource->nr_samples > 1 &&
2687ec681f3Smrg          info->dst.resource->nr_samples <= 1) {
2697ec681f3Smrg         if (blit_resolve(ctx, info))
2707ec681f3Smrg            return;
2717ec681f3Smrg      } else {
2727ec681f3Smrg         if (blit_native(ctx, info))
2737ec681f3Smrg            return;
2747ec681f3Smrg      }
2757ec681f3Smrg   }
2767ec681f3Smrg
2777ec681f3Smrg   struct zink_resource *src = zink_resource(info->src.resource);
2787ec681f3Smrg   struct zink_resource *dst = zink_resource(info->dst.resource);
2797ec681f3Smrg   /* if we're copying between resources with matching aspects then we can probably just copy_region */
2807ec681f3Smrg   if (src->aspect == dst->aspect) {
2817ec681f3Smrg      struct pipe_blit_info new_info = *info;
2827ec681f3Smrg
2837ec681f3Smrg      if (src->aspect & VK_IMAGE_ASPECT_STENCIL_BIT &&
2847ec681f3Smrg          new_info.render_condition_enable &&
2857ec681f3Smrg          !ctx->render_condition_active)
2867ec681f3Smrg         new_info.render_condition_enable = false;
2877ec681f3Smrg
2887ec681f3Smrg      if (util_try_blit_via_copy_region(pctx, &new_info))
2897ec681f3Smrg         return;
2907ec681f3Smrg   }
2917ec681f3Smrg
2927ec681f3Smrg   if (!util_blitter_is_blit_supported(ctx->blitter, info)) {
2937ec681f3Smrg      debug_printf("blit unsupported %s -> %s\n",
2947ec681f3Smrg              util_format_short_name(info->src.resource->format),
2957ec681f3Smrg              util_format_short_name(info->dst.resource->format));
2967ec681f3Smrg      return;
2977ec681f3Smrg   }
2987ec681f3Smrg
2997ec681f3Smrg   /* this is discard_only because we're about to start a renderpass that will
3007ec681f3Smrg    * flush all pending clears anyway
3017ec681f3Smrg    */
3027ec681f3Smrg   apply_dst_clears(ctx, info, true);
3037ec681f3Smrg
3047ec681f3Smrg   if (info->dst.resource->target == PIPE_BUFFER)
3057ec681f3Smrg      util_range_add(info->dst.resource, &dst->valid_buffer_range,
3067ec681f3Smrg                     info->dst.box.x, info->dst.box.x + info->dst.box.width);
3077ec681f3Smrg   zink_blit_begin(ctx, ZINK_BLIT_SAVE_FB | ZINK_BLIT_SAVE_FS | ZINK_BLIT_SAVE_TEXTURES);
3087ec681f3Smrg
3097ec681f3Smrg   util_blitter_blit(ctx->blitter, info);
3107ec681f3Smrg}
3117ec681f3Smrg
3127ec681f3Smrg/* similar to radeonsi */
3137ec681f3Smrgvoid
3147ec681f3Smrgzink_blit_begin(struct zink_context *ctx, enum zink_blit_flags flags)
3157ec681f3Smrg{
3167ec681f3Smrg   util_blitter_save_vertex_elements(ctx->blitter, ctx->element_state);
3177ec681f3Smrg   util_blitter_save_viewport(ctx->blitter, ctx->vp_state.viewport_states);
3187ec681f3Smrg
3197ec681f3Smrg   util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vertex_buffers);
3207ec681f3Smrg   util_blitter_save_vertex_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_VERTEX]);
3217ec681f3Smrg   util_blitter_save_tessctrl_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_TESS_CTRL]);
3227ec681f3Smrg   util_blitter_save_tesseval_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_TESS_EVAL]);
3237ec681f3Smrg   util_blitter_save_geometry_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_GEOMETRY]);
3247ec681f3Smrg   util_blitter_save_rasterizer(ctx->blitter, ctx->rast_state);
3257ec681f3Smrg   util_blitter_save_so_targets(ctx->blitter, ctx->num_so_targets, ctx->so_targets);
3267ec681f3Smrg
3277ec681f3Smrg   if (flags & ZINK_BLIT_SAVE_FS) {
3287ec681f3Smrg      util_blitter_save_fragment_constant_buffer_slot(ctx->blitter, ctx->ubos[PIPE_SHADER_FRAGMENT]);
3297ec681f3Smrg      util_blitter_save_blend(ctx->blitter, ctx->gfx_pipeline_state.blend_state);
3307ec681f3Smrg      util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->dsa_state);
3317ec681f3Smrg      util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref);
3327ec681f3Smrg      util_blitter_save_sample_mask(ctx->blitter, ctx->gfx_pipeline_state.sample_mask);
3337ec681f3Smrg      util_blitter_save_scissor(ctx->blitter, ctx->vp_state.scissor_states);
3347ec681f3Smrg      /* also util_blitter_save_window_rectangles when we have that? */
3357ec681f3Smrg
3367ec681f3Smrg      util_blitter_save_fragment_shader(ctx->blitter, ctx->gfx_stages[PIPE_SHADER_FRAGMENT]);
3377ec681f3Smrg   }
3387ec681f3Smrg
3397ec681f3Smrg   if (flags & ZINK_BLIT_SAVE_FB)
3407ec681f3Smrg      util_blitter_save_framebuffer(ctx->blitter, &ctx->fb_state);
3417ec681f3Smrg
3427ec681f3Smrg
3437ec681f3Smrg   if (flags & ZINK_BLIT_SAVE_TEXTURES) {
3447ec681f3Smrg      util_blitter_save_fragment_sampler_states(ctx->blitter,
3457ec681f3Smrg                                                ctx->di.num_samplers[PIPE_SHADER_FRAGMENT],
3467ec681f3Smrg                                                (void**)ctx->sampler_states[PIPE_SHADER_FRAGMENT]);
3477ec681f3Smrg      util_blitter_save_fragment_sampler_views(ctx->blitter,
3487ec681f3Smrg                                               ctx->di.num_sampler_views[PIPE_SHADER_FRAGMENT],
3497ec681f3Smrg                                               ctx->sampler_views[PIPE_SHADER_FRAGMENT]);
3507ec681f3Smrg   }
3517ec681f3Smrg
3527ec681f3Smrg   if (flags & ZINK_BLIT_NO_COND_RENDER && ctx->render_condition_active)
3537ec681f3Smrg      zink_stop_conditional_render(ctx);
3547ec681f3Smrg}
3557ec681f3Smrg
3567ec681f3Smrgbool
3577ec681f3Smrgzink_blit_region_fills(struct u_rect region, unsigned width, unsigned height)
3587ec681f3Smrg{
3597ec681f3Smrg   struct u_rect intersect = {0, width, 0, height};
3607ec681f3Smrg   struct u_rect r = {
3617ec681f3Smrg      MIN2(region.x0, region.x1),
3627ec681f3Smrg      MAX2(region.x0, region.x1),
3637ec681f3Smrg      MIN2(region.y0, region.y1),
3647ec681f3Smrg      MAX2(region.y0, region.y1),
3657ec681f3Smrg   };
3667ec681f3Smrg
3677ec681f3Smrg   if (!u_rect_test_intersection(&r, &intersect))
3687ec681f3Smrg      /* is this even a thing? */
3697ec681f3Smrg      return false;
3707ec681f3Smrg
3717ec681f3Smrg   u_rect_find_intersection(&r, &intersect);
3727ec681f3Smrg   if (intersect.x0 != 0 || intersect.y0 != 0 ||
3737ec681f3Smrg       intersect.x1 != width || intersect.y1 != height)
3747ec681f3Smrg      return false;
3757ec681f3Smrg
3767ec681f3Smrg   return true;
3777ec681f3Smrg}
3787ec681f3Smrg
3797ec681f3Smrgbool
3807ec681f3Smrgzink_blit_region_covers(struct u_rect region, struct u_rect covers)
3817ec681f3Smrg{
3827ec681f3Smrg   struct u_rect r = {
3837ec681f3Smrg      MIN2(region.x0, region.x1),
3847ec681f3Smrg      MAX2(region.x0, region.x1),
3857ec681f3Smrg      MIN2(region.y0, region.y1),
3867ec681f3Smrg      MAX2(region.y0, region.y1),
3877ec681f3Smrg   };
3887ec681f3Smrg   struct u_rect c = {
3897ec681f3Smrg      MIN2(covers.x0, covers.x1),
3907ec681f3Smrg      MAX2(covers.x0, covers.x1),
3917ec681f3Smrg      MIN2(covers.y0, covers.y1),
3927ec681f3Smrg      MAX2(covers.y0, covers.y1),
3937ec681f3Smrg   };
3947ec681f3Smrg   struct u_rect intersect;
3957ec681f3Smrg   if (!u_rect_test_intersection(&r, &c))
3967ec681f3Smrg      return false;
3977ec681f3Smrg
3987ec681f3Smrg    u_rect_union(&intersect, &r, &c);
3997ec681f3Smrg    return intersect.x0 == c.x0 && intersect.y0 == c.y0 &&
4007ec681f3Smrg           intersect.x1 == c.x1 && intersect.y1 == c.y1;
4017ec681f3Smrg}
402