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, ®ion); 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, ®ion, 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