static void svga_blit(struct pipe_context *pipe, const struct pipe_blit_info *blit_info) { struct svga_context *svga = svga_context(pipe); struct pipe_blit_info info = *blit_info; if (info.src.resource->nr_samples > 1 && info.dst.resource->nr_samples <= 1 && !util_format_is_depth_or_stencil(info.src.resource->format) && !util_format_is_pure_integer(info.src.resource->format)) { debug_printf("svga: color resolve unimplemented\n"); return; } if (util_try_blit_via_copy_region(pipe, &info)) { return; /* done */ } if (info.mask & PIPE_MASK_S) { debug_printf("svga: cannot blit stencil, skipping\n"); info.mask &= ~PIPE_MASK_S; } if (!util_blitter_is_blit_supported(svga->blitter, &info)) { debug_printf("svga: blit unsupported %s -> %s\n", util_format_short_name(info.src.resource->format), util_format_short_name(info.dst.resource->format)); return; } /* XXX turn off occlusion and streamout queries */ util_blitter_save_vertex_buffers(svga->blitter, svga->curr.num_vertex_buffers, svga->curr.vb); util_blitter_save_vertex_elements(svga->blitter, (void*)svga->curr.velems); util_blitter_save_vertex_shader(svga->blitter, svga->curr.vs); /*util_blitter_save_geometry_shader(svga->blitter, svga->curr.gs);*/ /*util_blitter_save_so_targets(svga->blitter, svga->num_so_targets, (struct pipe_stream_output_target**)svga->so_targets);*/ util_blitter_save_rasterizer(svga->blitter, (void*)svga->curr.rast); util_blitter_save_viewport(svga->blitter, &svga->curr.viewport); util_blitter_save_scissor(svga->blitter, &svga->curr.scissor); util_blitter_save_fragment_shader(svga->blitter, svga->curr.fs); util_blitter_save_blend(svga->blitter, (void*)svga->curr.blend); util_blitter_save_depth_stencil_alpha(svga->blitter, (void*)svga->curr.depth); util_blitter_save_stencil_ref(svga->blitter, &svga->curr.stencil_ref); /*util_blitter_save_sample_mask(svga->blitter, svga->sample_mask);*/ util_blitter_save_framebuffer(svga->blitter, &svga->curr.framebuffer); util_blitter_save_fragment_sampler_states(svga->blitter, svga->curr.num_samplers, (void**)svga->curr.sampler); util_blitter_save_fragment_sampler_views(svga->blitter, svga->curr.num_sampler_views, svga->curr.sampler_views); /*util_blitter_save_render_condition(svga->blitter, svga->render_cond_query, svga->render_cond_mode);*/ util_blitter_blit(svga->blitter, &info); }
static void r600_blit(struct pipe_context *ctx, const struct pipe_blit_info *info) { struct r600_context *rctx = (struct r600_context*)ctx; if (do_hardware_msaa_resolve(ctx, info)) { return; } assert(util_blitter_is_blit_supported(rctx->blitter, info)); /* The driver doesn't decompress resources automatically while * u_blitter is rendering. */ if (!r600_decompress_subresource(ctx, info->src.resource, info->src.level, info->src.box.z, info->src.box.z + info->src.box.depth - 1)) { return; /* error */ } if (rctx->screen->b.debug_flags & DBG_FORCE_DMA && util_try_blit_via_copy_region(ctx, info)) return; r600_blitter_begin(ctx, R600_BLIT | (info->render_condition_enable ? 0 : R600_DISABLE_RENDER_COND)); util_blitter_blit(rctx->blitter, info); r600_blitter_end(ctx); }
static void i915_blit(struct pipe_context *pipe, const struct pipe_blit_info *blit_info) { struct i915_context *i915 = i915_context(pipe); struct pipe_blit_info info = *blit_info; if (util_try_blit_via_copy_region(pipe, &info)) { return; /* done */ } if (info.mask & PIPE_MASK_S) { debug_printf("i915: cannot blit stencil, skipping\n"); info.mask &= ~PIPE_MASK_S; } if (!util_blitter_is_blit_supported(i915->blitter, &info)) { debug_printf("i915: blit unsupported %s -> %s\n", util_format_short_name(info.src.resource->format), util_format_short_name(info.dst.resource->format)); return; } i915_util_blitter_save_states(i915); util_blitter_blit(i915->blitter, &info); }
/** * Optimal hardware path for blitting pixels. * Scaling, format conversion, up- and downsampling (resolve) are allowed. */ static void fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) { struct fd_context *ctx = fd_context(pctx); struct pipe_blit_info info = *blit_info; if (info.src.resource->nr_samples > 1 && info.dst.resource->nr_samples <= 1 && !util_format_is_depth_or_stencil(info.src.resource->format) && !util_format_is_pure_integer(info.src.resource->format)) { DBG("color resolve unimplemented"); return; } if (util_try_blit_via_copy_region(pctx, &info)) { return; /* done */ } if (info.mask & PIPE_MASK_S) { DBG("cannot blit stencil, skipping"); info.mask &= ~PIPE_MASK_S; } if (!util_blitter_is_blit_supported(ctx->blitter, &info)) { DBG("blit unsupported %s -> %s", util_format_short_name(info.src.resource->format), util_format_short_name(info.dst.resource->format)); return; } fd_blitter_pipe_begin(ctx); util_blitter_blit(ctx->blitter, &info); fd_blitter_pipe_end(ctx); }
static void lp_blit(struct pipe_context *pipe, const struct pipe_blit_info *blit_info) { struct llvmpipe_context *lp = llvmpipe_context(pipe); struct pipe_blit_info info = *blit_info; if (info.src.resource->nr_samples > 1 && info.dst.resource->nr_samples <= 1 && !util_format_is_depth_or_stencil(info.src.resource->format) && !util_format_is_pure_integer(info.src.resource->format)) { debug_printf("llvmpipe: color resolve unimplemented\n"); return; } if (util_try_blit_via_copy_region(pipe, &info)) { return; /* done */ } if (info.mask & PIPE_MASK_S) { debug_printf("llvmpipe: cannot blit stencil, skipping\n"); info.mask &= ~PIPE_MASK_S; } if (!util_blitter_is_blit_supported(lp->blitter, &info)) { debug_printf("llvmpipe: blit unsupported %s -> %s\n", util_format_short_name(info.src.resource->format), util_format_short_name(info.dst.resource->format)); return; } /* XXX turn off occlusion and streamout queries */ util_blitter_save_vertex_buffers(lp->blitter, lp->num_vertex_buffers, lp->vertex_buffer); util_blitter_save_vertex_elements(lp->blitter, (void*)lp->velems); util_blitter_save_vertex_shader(lp->blitter, (void*)lp->vs); util_blitter_save_geometry_shader(lp->blitter, (void*)lp->gs); /*util_blitter_save_so_targets(lp->blitter, lp->num_so_targets, (struct pipe_stream_output_target**)lp->so_targets);*/ util_blitter_save_rasterizer(lp->blitter, (void*)lp->rasterizer); util_blitter_save_viewport(lp->blitter, &lp->viewport); util_blitter_save_scissor(lp->blitter, &lp->scissor); util_blitter_save_fragment_shader(lp->blitter, lp->fs); util_blitter_save_blend(lp->blitter, (void*)lp->blend); util_blitter_save_depth_stencil_alpha(lp->blitter, (void*)lp->depth_stencil); util_blitter_save_stencil_ref(lp->blitter, &lp->stencil_ref); /*util_blitter_save_sample_mask(sp->blitter, lp->sample_mask);*/ util_blitter_save_framebuffer(lp->blitter, &lp->framebuffer); util_blitter_save_fragment_sampler_states(lp->blitter, lp->num_samplers[PIPE_SHADER_FRAGMENT], (void**)lp->samplers[PIPE_SHADER_FRAGMENT]); util_blitter_save_fragment_sampler_views(lp->blitter, lp->num_sampler_views[PIPE_SHADER_FRAGMENT], lp->sampler_views[PIPE_SHADER_FRAGMENT]); util_blitter_save_render_condition(lp->blitter, lp->render_cond_query, lp->render_cond_mode); util_blitter_blit(lp->blitter, &info); }
void nv30_blit(struct pipe_context *pipe, const struct pipe_blit_info *blit_info) { struct nv30_context *nv30 = nv30_context(pipe); struct pipe_blit_info info = *blit_info; if (info.src.resource->nr_samples > 1 && info.dst.resource->nr_samples <= 1 && !util_format_is_depth_or_stencil(info.src.resource->format) && !util_format_is_pure_integer(info.src.resource->format)) { debug_printf("nv30: color resolve unimplemented\n"); return; } if (util_try_blit_via_copy_region(pipe, &info)) { return; /* done */ } if (info.mask & PIPE_MASK_S) { debug_printf("nv30: cannot blit stencil, skipping\n"); info.mask &= ~PIPE_MASK_S; } if (!util_blitter_is_blit_supported(nv30->blitter, &info)) { debug_printf("nv30: blit unsupported %s -> %s\n", util_format_short_name(info.src.resource->format), util_format_short_name(info.dst.resource->format)); return; } /* XXX turn off occlusion queries */ util_blitter_save_vertex_buffer_slot(nv30->blitter, nv30->vtxbuf); util_blitter_save_vertex_elements(nv30->blitter, nv30->vertex); util_blitter_save_vertex_shader(nv30->blitter, nv30->vertprog.program); util_blitter_save_rasterizer(nv30->blitter, nv30->rast); util_blitter_save_viewport(nv30->blitter, &nv30->viewport); util_blitter_save_scissor(nv30->blitter, &nv30->scissor); util_blitter_save_fragment_shader(nv30->blitter, nv30->fragprog.program); util_blitter_save_blend(nv30->blitter, nv30->blend); util_blitter_save_depth_stencil_alpha(nv30->blitter, nv30->zsa); util_blitter_save_stencil_ref(nv30->blitter, &nv30->stencil_ref); util_blitter_save_sample_mask(nv30->blitter, nv30->sample_mask); util_blitter_save_framebuffer(nv30->blitter, &nv30->framebuffer); util_blitter_save_fragment_sampler_states(nv30->blitter, nv30->fragprog.num_samplers, (void**)nv30->fragprog.samplers); util_blitter_save_fragment_sampler_views(nv30->blitter, nv30->fragprog.num_textures, nv30->fragprog.textures); util_blitter_save_render_condition(nv30->blitter, nv30->render_cond_query, nv30->render_cond_mode); util_blitter_blit(nv30->blitter, &info); }
static void sp_blit(struct pipe_context *pipe, const struct pipe_blit_info *info) { struct softpipe_context *sp = softpipe_context(pipe); if (info->render_condition_enable && !softpipe_check_render_cond(sp)) return; if (info->src.resource->nr_samples > 1 && info->dst.resource->nr_samples <= 1 && !util_format_is_depth_or_stencil(info->src.resource->format) && !util_format_is_pure_integer(info->src.resource->format)) { debug_printf("softpipe: color resolve unimplemented\n"); return; } if (util_try_blit_via_copy_region(pipe, info)) { return; /* done */ } if (!util_blitter_is_blit_supported(sp->blitter, info)) { debug_printf("softpipe: blit unsupported %s -> %s\n", util_format_short_name(info->src.resource->format), util_format_short_name(info->dst.resource->format)); return; } /* XXX turn off occlusion and streamout queries */ util_blitter_save_vertex_buffer_slot(sp->blitter, sp->vertex_buffer); util_blitter_save_vertex_elements(sp->blitter, sp->velems); util_blitter_save_vertex_shader(sp->blitter, sp->vs); util_blitter_save_geometry_shader(sp->blitter, sp->gs); util_blitter_save_so_targets(sp->blitter, sp->num_so_targets, (struct pipe_stream_output_target**)sp->so_targets); util_blitter_save_rasterizer(sp->blitter, sp->rasterizer); util_blitter_save_viewport(sp->blitter, &sp->viewports[0]); util_blitter_save_scissor(sp->blitter, &sp->scissors[0]); util_blitter_save_fragment_shader(sp->blitter, sp->fs); util_blitter_save_blend(sp->blitter, sp->blend); util_blitter_save_depth_stencil_alpha(sp->blitter, sp->depth_stencil); util_blitter_save_stencil_ref(sp->blitter, &sp->stencil_ref); /*util_blitter_save_sample_mask(sp->blitter, sp->sample_mask);*/ util_blitter_save_framebuffer(sp->blitter, &sp->framebuffer); util_blitter_save_fragment_sampler_states(sp->blitter, sp->num_samplers[PIPE_SHADER_FRAGMENT], (void**)sp->samplers[PIPE_SHADER_FRAGMENT]); util_blitter_save_fragment_sampler_views(sp->blitter, sp->num_sampler_views[PIPE_SHADER_FRAGMENT], sp->sampler_views[PIPE_SHADER_FRAGMENT]); util_blitter_save_render_condition(sp->blitter, sp->render_cond_query, sp->render_cond_cond, sp->render_cond_mode); util_blitter_blit(sp->blitter, info); }
/* Optimal hardware path for blitting pixels. * Scaling, format conversion, up- and downsampling (resolve) are allowed. */ static void fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) { struct fd_context *ctx = fd_context(pctx); struct pipe_blit_info info = *blit_info; if (info.src.resource->nr_samples > 1 && info.dst.resource->nr_samples <= 1 && !util_format_is_depth_or_stencil(info.src.resource->format) && !util_format_is_pure_integer(info.src.resource->format)) { DBG("color resolve unimplemented"); return; } if (util_try_blit_via_copy_region(pctx, &info)) { return; /* done */ } if (info.mask & PIPE_MASK_S) { DBG("cannot blit stencil, skipping"); info.mask &= ~PIPE_MASK_S; } if (!util_blitter_is_blit_supported(ctx->blitter, &info)) { DBG("blit unsupported %s -> %s", util_format_short_name(info.src.resource->format), util_format_short_name(info.dst.resource->format)); return; } util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vertexbuf.vb); util_blitter_save_vertex_elements(ctx->blitter, ctx->vtx); util_blitter_save_vertex_shader(ctx->blitter, ctx->prog.vp); util_blitter_save_rasterizer(ctx->blitter, ctx->rasterizer); util_blitter_save_viewport(ctx->blitter, &ctx->viewport); util_blitter_save_scissor(ctx->blitter, &ctx->scissor); util_blitter_save_fragment_shader(ctx->blitter, ctx->prog.fp); util_blitter_save_blend(ctx->blitter, ctx->blend); util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->zsa); util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref); util_blitter_save_sample_mask(ctx->blitter, ctx->sample_mask); util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer.base); util_blitter_save_fragment_sampler_states(ctx->blitter, ctx->fragtex.num_samplers, (void **)ctx->fragtex.samplers); util_blitter_save_fragment_sampler_views(ctx->blitter, ctx->fragtex.num_textures, ctx->fragtex.textures); util_blitter_blit(ctx->blitter, &info); }
/* Optimal hardware path for blitting pixels. * Scaling, format conversion, up- and downsampling (resolve) are allowed. */ void vc4_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) { struct pipe_blit_info info = *blit_info; if (vc4_tile_blit(pctx, blit_info)) return; if (info.mask & PIPE_MASK_S) { if (util_try_blit_via_copy_region(pctx, &info)) return; info.mask &= ~PIPE_MASK_S; fprintf(stderr, "cannot blit stencil, skipping\n"); } if (vc4_render_blit(pctx, &info)) return; fprintf(stderr, "Unsupported blit\n"); }
bool ilo_blitter_pipe_blit(struct ilo_blitter *blitter, const struct pipe_blit_info *info) { struct blitter_context *b = blitter->pipe_blitter; struct pipe_blit_info skip_stencil; if (util_try_blit_via_copy_region(&blitter->ilo->base, info)) return true; if (!util_blitter_is_blit_supported(b, info)) { /* try without stencil */ if (info->mask & PIPE_MASK_S) { skip_stencil = *info; skip_stencil.mask = info->mask & ~PIPE_MASK_S; if (util_blitter_is_blit_supported(blitter->pipe_blitter, &skip_stencil)) { ilo_warn("ignore stencil buffer blitting\n"); info = &skip_stencil; } } if (info != &skip_stencil) { ilo_warn("failed to blit with pipe blitter\n"); return false; } } ilo_blitter_pipe_begin(blitter, ILO_BLITTER_PIPE_BLIT, info->scissor_enable); util_blitter_blit(b, info); ilo_blitter_pipe_end(blitter); return true; }
/* Optimal hardware path for blitting pixels. * Scaling, format conversion, up- and downsampling (resolve) are allowed. */ static void vc4_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) { struct pipe_blit_info info = *blit_info; if (info.src.resource->nr_samples > 1 && info.dst.resource->nr_samples <= 1 && !util_format_is_depth_or_stencil(info.src.resource->format) && !util_format_is_pure_integer(info.src.resource->format)) { fprintf(stderr, "color resolve unimplemented"); return; } if (util_try_blit_via_copy_region(pctx, &info)) { return; /* done */ } if (info.mask & PIPE_MASK_S) { fprintf(stderr, "cannot blit stencil, skipping"); info.mask &= ~PIPE_MASK_S; } render_blit(pctx, &info); }
static void swr_blit(struct pipe_context *pipe, const struct pipe_blit_info *blit_info) { struct swr_context *ctx = swr_context(pipe); /* Make a copy of the const blit_info, so we can modify it */ struct pipe_blit_info info = *blit_info; if (info.render_condition_enable && !swr_check_render_cond(pipe)) return; if (info.src.resource->nr_samples > 1 && info.dst.resource->nr_samples <= 1 && !util_format_is_depth_or_stencil(info.src.resource->format) && !util_format_is_pure_integer(info.src.resource->format)) { debug_printf("swr_blit: color resolve : %d -> %d\n", info.src.resource->nr_samples, info.dst.resource->nr_samples); /* Resolve is done as part of the surface store. */ swr_store_dirty_resource(pipe, info.src.resource, SWR_TILE_RESOLVED); struct pipe_resource *src_resource = info.src.resource; struct pipe_resource *resolve_target = swr_resource(src_resource)->resolve_target; /* The resolve target becomes the new source for the blit. */ info.src.resource = resolve_target; } if (util_try_blit_via_copy_region(pipe, &info)) { return; /* done */ } if (info.mask & PIPE_MASK_S) { debug_printf("swr: cannot blit stencil, skipping\n"); info.mask &= ~PIPE_MASK_S; } if (!util_blitter_is_blit_supported(ctx->blitter, &info)) { debug_printf("swr: blit unsupported %s -> %s\n", util_format_short_name(info.src.resource->format), util_format_short_name(info.dst.resource->format)); return; } if (ctx->active_queries) { ctx->api.pfnSwrEnableStatsFE(ctx->swrContext, FALSE); ctx->api.pfnSwrEnableStatsBE(ctx->swrContext, FALSE); } util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vertex_buffer); util_blitter_save_vertex_elements(ctx->blitter, (void *)ctx->velems); util_blitter_save_vertex_shader(ctx->blitter, (void *)ctx->vs); util_blitter_save_geometry_shader(ctx->blitter, (void*)ctx->gs); util_blitter_save_so_targets( ctx->blitter, ctx->num_so_targets, (struct pipe_stream_output_target **)ctx->so_targets); util_blitter_save_rasterizer(ctx->blitter, (void *)ctx->rasterizer); util_blitter_save_viewport(ctx->blitter, &ctx->viewport); util_blitter_save_scissor(ctx->blitter, &ctx->scissor); util_blitter_save_fragment_shader(ctx->blitter, ctx->fs); util_blitter_save_blend(ctx->blitter, (void *)ctx->blend); util_blitter_save_depth_stencil_alpha(ctx->blitter, (void *)ctx->depth_stencil); util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref); util_blitter_save_sample_mask(ctx->blitter, ctx->sample_mask); util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer); util_blitter_save_fragment_sampler_states( ctx->blitter, ctx->num_samplers[PIPE_SHADER_FRAGMENT], (void **)ctx->samplers[PIPE_SHADER_FRAGMENT]); util_blitter_save_fragment_sampler_views( ctx->blitter, ctx->num_sampler_views[PIPE_SHADER_FRAGMENT], ctx->sampler_views[PIPE_SHADER_FRAGMENT]); util_blitter_save_render_condition(ctx->blitter, ctx->render_cond_query, ctx->render_cond_cond, ctx->render_cond_mode); util_blitter_blit(ctx->blitter, &info); if (ctx->active_queries) { ctx->api.pfnSwrEnableStatsFE(ctx->swrContext, TRUE); ctx->api.pfnSwrEnableStatsBE(ctx->swrContext, TRUE); } }
static void *vc4_get_yuv_vs(struct pipe_context *pctx) { struct vc4_context *vc4 = vc4_context(pctx); struct pipe_screen *pscreen = pctx->screen; if (vc4->yuv_linear_blit_vs) return vc4->yuv_linear_blit_vs; const struct nir_shader_compiler_options *options = pscreen->get_compiler_options(pscreen, PIPE_SHADER_IR_NIR, PIPE_SHADER_VERTEX); nir_builder b; nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_VERTEX, options); b.shader->info.name = ralloc_strdup(b.shader, "linear_blit_vs"); const struct glsl_type *vec4 = glsl_vec4_type(); nir_variable *pos_in = nir_variable_create(b.shader, nir_var_shader_in, vec4, "pos"); nir_variable *pos_out = nir_variable_create(b.shader, nir_var_shader_out, vec4, "gl_Position"); pos_out->data.location = VARYING_SLOT_POS; nir_store_var(&b, pos_out, nir_load_var(&b, pos_in), 0xf); struct pipe_shader_state shader_tmpl = { .type = PIPE_SHADER_IR_NIR, .ir.nir = b.shader, }; vc4->yuv_linear_blit_vs = pctx->create_vs_state(pctx, &shader_tmpl); return vc4->yuv_linear_blit_vs; } static void *vc4_get_yuv_fs(struct pipe_context *pctx, int cpp) { struct vc4_context *vc4 = vc4_context(pctx); struct pipe_screen *pscreen = pctx->screen; struct pipe_shader_state **cached_shader; const char *name; if (cpp == 1) { cached_shader = &vc4->yuv_linear_blit_fs_8bit; name = "linear_blit_8bit_fs"; } else { cached_shader = &vc4->yuv_linear_blit_fs_16bit; name = "linear_blit_16bit_fs"; } if (*cached_shader) return *cached_shader; const struct nir_shader_compiler_options *options = pscreen->get_compiler_options(pscreen, PIPE_SHADER_IR_NIR, PIPE_SHADER_FRAGMENT); nir_builder b; nir_builder_init_simple_shader(&b, NULL, MESA_SHADER_FRAGMENT, options); b.shader->info.name = ralloc_strdup(b.shader, name); const struct glsl_type *vec4 = glsl_vec4_type(); const struct glsl_type *glsl_int = glsl_int_type(); nir_variable *color_out = nir_variable_create(b.shader, nir_var_shader_out, vec4, "f_color"); color_out->data.location = FRAG_RESULT_COLOR; nir_variable *pos_in = nir_variable_create(b.shader, nir_var_shader_in, vec4, "pos"); pos_in->data.location = VARYING_SLOT_POS; nir_ssa_def *pos = nir_load_var(&b, pos_in); nir_ssa_def *one = nir_imm_int(&b, 1); nir_ssa_def *two = nir_imm_int(&b, 2); nir_ssa_def *x = nir_f2i32(&b, nir_channel(&b, pos, 0)); nir_ssa_def *y = nir_f2i32(&b, nir_channel(&b, pos, 1)); nir_variable *stride_in = nir_variable_create(b.shader, nir_var_uniform, glsl_int, "stride"); nir_ssa_def *stride = nir_load_var(&b, stride_in); nir_ssa_def *x_offset; nir_ssa_def *y_offset; if (cpp == 1) { nir_ssa_def *intra_utile_x_offset = nir_ishl(&b, nir_iand(&b, x, one), two); nir_ssa_def *inter_utile_x_offset = nir_ishl(&b, nir_iand(&b, x, nir_imm_int(&b, ~3)), one); x_offset = nir_iadd(&b, intra_utile_x_offset, inter_utile_x_offset); y_offset = nir_imul(&b, nir_iadd(&b, nir_ishl(&b, y, one), nir_ushr(&b, nir_iand(&b, x, two), one)), stride); } else { x_offset = nir_ishl(&b, x, two); y_offset = nir_imul(&b, y, stride); } nir_intrinsic_instr *load = nir_intrinsic_instr_create(b.shader, nir_intrinsic_load_ubo); load->num_components = 1; nir_ssa_dest_init(&load->instr, &load->dest, load->num_components, 32, NULL); load->src[0] = nir_src_for_ssa(one); load->src[1] = nir_src_for_ssa(nir_iadd(&b, x_offset, y_offset)); nir_builder_instr_insert(&b, &load->instr); nir_store_var(&b, color_out, nir_unpack_unorm_4x8(&b, &load->dest.ssa), 0xf); struct pipe_shader_state shader_tmpl = { .type = PIPE_SHADER_IR_NIR, .ir.nir = b.shader, }; *cached_shader = pctx->create_fs_state(pctx, &shader_tmpl); return *cached_shader; } static bool vc4_yuv_blit(struct pipe_context *pctx, const struct pipe_blit_info *info) { struct vc4_context *vc4 = vc4_context(pctx); struct vc4_resource *src = vc4_resource(info->src.resource); struct vc4_resource *dst = vc4_resource(info->dst.resource); bool ok; if (src->tiled) return false; if (src->base.format != PIPE_FORMAT_R8_UNORM && src->base.format != PIPE_FORMAT_R8G8_UNORM) return false; /* YUV blits always turn raster-order to tiled */ assert(dst->base.format == src->base.format); assert(dst->tiled); /* Always 1:1 and at the origin */ assert(info->src.box.x == 0 && info->dst.box.x == 0); assert(info->src.box.y == 0 && info->dst.box.y == 0); assert(info->src.box.width == info->dst.box.width); assert(info->src.box.height == info->dst.box.height); if ((src->slices[info->src.level].offset & 3) || (src->slices[info->src.level].stride & 3)) { perf_debug("YUV-blit src texture offset/stride misaligned: 0x%08x/%d\n", src->slices[info->src.level].offset, src->slices[info->src.level].stride); goto fallback; } vc4_blitter_save(vc4); /* Create a renderable surface mapping the T-tiled shadow buffer. */ struct pipe_surface dst_tmpl; util_blitter_default_dst_texture(&dst_tmpl, info->dst.resource, info->dst.level, info->dst.box.z); dst_tmpl.format = PIPE_FORMAT_RGBA8888_UNORM; struct pipe_surface *dst_surf = pctx->create_surface(pctx, info->dst.resource, &dst_tmpl); if (!dst_surf) { fprintf(stderr, "Failed to create YUV dst surface\n"); util_blitter_unset_running_flag(vc4->blitter); return false; } dst_surf->width /= 2; if (dst->cpp == 1) dst_surf->height /= 2; /* Set the constant buffer. */ uint32_t stride = src->slices[info->src.level].stride; struct pipe_constant_buffer cb_uniforms = { .user_buffer = &stride, .buffer_size = sizeof(stride), }; pctx->set_constant_buffer(pctx, PIPE_SHADER_FRAGMENT, 0, &cb_uniforms); struct pipe_constant_buffer cb_src = { .buffer = info->src.resource, .buffer_offset = src->slices[info->src.level].offset, .buffer_size = (src->bo->size - src->slices[info->src.level].offset), }; pctx->set_constant_buffer(pctx, PIPE_SHADER_FRAGMENT, 1, &cb_src); /* Unbind the textures, to make sure we don't try to recurse into the * shadow blit. */ pctx->set_sampler_views(pctx, PIPE_SHADER_FRAGMENT, 0, 0, NULL); pctx->bind_sampler_states(pctx, PIPE_SHADER_FRAGMENT, 0, 0, NULL); util_blitter_custom_shader(vc4->blitter, dst_surf, vc4_get_yuv_vs(pctx), vc4_get_yuv_fs(pctx, src->cpp)); util_blitter_restore_textures(vc4->blitter); util_blitter_restore_constant_buffer_state(vc4->blitter); /* Restore cb1 (util_blitter doesn't handle this one). */ struct pipe_constant_buffer cb_disabled = { 0 }; pctx->set_constant_buffer(pctx, PIPE_SHADER_FRAGMENT, 1, &cb_disabled); pipe_surface_reference(&dst_surf, NULL); return true; fallback: /* Do an immediate SW fallback, since the render blit path * would just recurse. */ ok = util_try_blit_via_copy_region(pctx, info); assert(ok); (void)ok; return true; } static bool vc4_render_blit(struct pipe_context *ctx, struct pipe_blit_info *info) { struct vc4_context *vc4 = vc4_context(ctx); if (!util_blitter_is_blit_supported(vc4->blitter, info)) { fprintf(stderr, "blit unsupported %s -> %s\n", util_format_short_name(info->src.resource->format), util_format_short_name(info->dst.resource->format)); return false; } /* Enable the scissor, so we get a minimal set of tiles rendered. */ if (!info->scissor_enable) { info->scissor_enable = true; info->scissor.minx = info->dst.box.x; info->scissor.miny = info->dst.box.y; info->scissor.maxx = info->dst.box.x + info->dst.box.width; info->scissor.maxy = info->dst.box.y + info->dst.box.height; } vc4_blitter_save(vc4); util_blitter_blit(vc4->blitter, info); return true; } /* Optimal hardware path for blitting pixels. * Scaling, format conversion, up- and downsampling (resolve) are allowed. */ void vc4_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) { struct pipe_blit_info info = *blit_info; if (vc4_yuv_blit(pctx, blit_info)) return; if (vc4_tile_blit(pctx, blit_info)) return; if (info.mask & PIPE_MASK_S) { if (util_try_blit_via_copy_region(pctx, &info)) return; info.mask &= ~PIPE_MASK_S; fprintf(stderr, "cannot blit stencil, skipping\n"); } if (vc4_render_blit(pctx, &info)) return; fprintf(stderr, "Unsupported blit\n"); }