• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 Rob Clark <robclark@freedesktop.org>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  *
23  * Authors:
24  *    Rob Clark <robclark@freedesktop.org>
25  */
26 
27 #include "util/u_blitter.h"
28 #include "util/u_surface.h"
29 
30 #include "freedreno_blitter.h"
31 #include "freedreno_context.h"
32 #include "freedreno_fence.h"
33 #include "freedreno_resource.h"
34 
35 /* generic blit using u_blitter.. slightly modified version of util_blitter_blit
36  * which also handles PIPE_BUFFER:
37  */
38 
39 static void
default_dst_texture(struct pipe_surface * dst_templ,struct pipe_resource * dst,unsigned dstlevel,unsigned dstz)40 default_dst_texture(struct pipe_surface *dst_templ, struct pipe_resource *dst,
41                     unsigned dstlevel, unsigned dstz)
42 {
43    memset(dst_templ, 0, sizeof(*dst_templ));
44    dst_templ->u.tex.level = dstlevel;
45    dst_templ->u.tex.first_layer = dstz;
46    dst_templ->u.tex.last_layer = dstz;
47 }
48 
49 static void
default_src_texture(struct pipe_sampler_view * src_templ,struct pipe_resource * src,unsigned srclevel)50 default_src_texture(struct pipe_sampler_view *src_templ,
51                     struct pipe_resource *src, unsigned srclevel)
52 {
53    bool cube_as_2darray =
54       src->screen->get_param(src->screen, PIPE_CAP_SAMPLER_VIEW_TARGET);
55 
56    memset(src_templ, 0, sizeof(*src_templ));
57 
58    if (cube_as_2darray && (src->target == PIPE_TEXTURE_CUBE ||
59                            src->target == PIPE_TEXTURE_CUBE_ARRAY))
60       src_templ->target = PIPE_TEXTURE_2D_ARRAY;
61    else
62       src_templ->target = src->target;
63 
64    if (src->target == PIPE_BUFFER) {
65       src_templ->target = PIPE_TEXTURE_1D;
66    }
67    src_templ->u.tex.first_level = srclevel;
68    src_templ->u.tex.last_level = srclevel;
69    src_templ->u.tex.first_layer = 0;
70    src_templ->u.tex.last_layer = src->target == PIPE_TEXTURE_3D
71                                     ? u_minify(src->depth0, srclevel) - 1
72                                     : (unsigned)(src->array_size - 1);
73    src_templ->swizzle_r = PIPE_SWIZZLE_X;
74    src_templ->swizzle_g = PIPE_SWIZZLE_Y;
75    src_templ->swizzle_b = PIPE_SWIZZLE_Z;
76    src_templ->swizzle_a = PIPE_SWIZZLE_W;
77 }
78 
79 static void
fd_blitter_pipe_begin(struct fd_context * ctx,bool render_cond)80 fd_blitter_pipe_begin(struct fd_context *ctx, bool render_cond) assert_dt
81 {
82    util_blitter_save_vertex_buffers(
83       ctx->blitter, ctx->vtx.vertexbuf.vb,
84       util_last_bit(ctx->vtx.vertexbuf.enabled_mask));
85    util_blitter_save_vertex_elements(ctx->blitter, ctx->vtx.vtx);
86    util_blitter_save_vertex_shader(ctx->blitter, ctx->prog.vs);
87    util_blitter_save_tessctrl_shader(ctx->blitter, ctx->prog.hs);
88    util_blitter_save_tesseval_shader(ctx->blitter, ctx->prog.ds);
89    util_blitter_save_geometry_shader(ctx->blitter, ctx->prog.gs);
90    util_blitter_save_so_targets(ctx->blitter, ctx->streamout.num_targets,
91                                 ctx->streamout.targets);
92    util_blitter_save_rasterizer(ctx->blitter, ctx->rasterizer);
93    util_blitter_save_viewport(ctx->blitter, &ctx->viewport[0]);
94    util_blitter_save_scissor(ctx->blitter, &ctx->scissor[0]);
95    util_blitter_save_fragment_shader(ctx->blitter, ctx->prog.fs);
96    util_blitter_save_blend(ctx->blitter, ctx->blend);
97    util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->zsa);
98    util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref);
99    util_blitter_save_sample_mask(ctx->blitter, ctx->sample_mask, ctx->min_samples);
100    util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer);
101    util_blitter_save_fragment_sampler_states(
102       ctx->blitter, ctx->tex[PIPE_SHADER_FRAGMENT].num_samplers,
103       (void **)ctx->tex[PIPE_SHADER_FRAGMENT].samplers);
104    util_blitter_save_fragment_sampler_views(
105       ctx->blitter, ctx->tex[PIPE_SHADER_FRAGMENT].num_textures,
106       ctx->tex[PIPE_SHADER_FRAGMENT].textures);
107    if (!render_cond)
108       util_blitter_save_render_condition(ctx->blitter, ctx->cond_query,
109                                          ctx->cond_cond, ctx->cond_mode);
110 
111    if (ctx->batch)
112       fd_batch_update_queries(ctx->batch);
113 }
114 
115 static void
fd_blitter_pipe_end(struct fd_context * ctx)116 fd_blitter_pipe_end(struct fd_context *ctx) assert_dt
117 {
118 }
119 
120 bool
fd_blitter_blit(struct fd_context * ctx,const struct pipe_blit_info * info)121 fd_blitter_blit(struct fd_context *ctx, const struct pipe_blit_info *info)
122 {
123    struct pipe_context *pctx = &ctx->base;
124    struct pipe_resource *dst = info->dst.resource;
125    struct pipe_resource *src = info->src.resource;
126    struct pipe_context *pipe = &ctx->base;
127    struct pipe_surface *dst_view, dst_templ;
128    struct pipe_sampler_view src_templ, *src_view;
129 
130    /* If the blit is updating the whole contents of the resource,
131     * invalidate it so we don't trigger any unnecessary tile loads in the 3D
132     * path.
133     */
134    if (util_blit_covers_whole_resource(info))
135       pctx->invalidate_resource(pctx, info->dst.resource);
136 
137    /* The blit format may not match the resource format in this path, so
138     * we need to validate that we can use the src/dst resource with the
139     * requested format (and uncompress if necessary).  Normally this would
140     * happen in ->set_sampler_view(), ->set_framebuffer_state(), etc.  But
141     * that would cause recursion back into u_blitter, which ends in tears.
142     *
143     * To avoid recursion, this needs to be done before util_blitter_save_*()
144     */
145    if (ctx->validate_format) {
146       ctx->validate_format(ctx, fd_resource(dst), info->dst.format);
147       ctx->validate_format(ctx, fd_resource(src), info->src.format);
148    }
149 
150    if (src == dst)
151       pipe->flush(pipe, NULL, 0);
152 
153    DBG_BLIT(info, NULL);
154 
155    fd_blitter_pipe_begin(ctx, info->render_condition_enable);
156 
157    /* Initialize the surface. */
158    default_dst_texture(&dst_templ, dst, info->dst.level, info->dst.box.z);
159    dst_templ.format = info->dst.format;
160    dst_view = pipe->create_surface(pipe, dst, &dst_templ);
161 
162    /* Initialize the sampler view. */
163    default_src_texture(&src_templ, src, info->src.level);
164    src_templ.format = info->src.format;
165    src_view = pipe->create_sampler_view(pipe, src, &src_templ);
166 
167    /* Copy. */
168    util_blitter_blit_generic(
169       ctx->blitter, dst_view, &info->dst.box, src_view, &info->src.box,
170       src->width0, src->height0, info->mask, info->filter,
171       info->scissor_enable ? &info->scissor : NULL, info->alpha_blend, false, 0);
172 
173    pipe_surface_reference(&dst_view, NULL);
174    pipe_sampler_view_reference(&src_view, NULL);
175 
176    fd_blitter_pipe_end(ctx);
177 
178    /* While this shouldn't technically be necessary, it is required for
179     * dEQP-GLES31.functional.stencil_texturing.format.stencil_index8_cube and
180     * 2d_array to pass.
181     */
182    fd_bc_flush_writer(ctx, fd_resource(info->dst.resource));
183 
184    /* The fallback blitter must never fail: */
185    return true;
186 }
187 
188 /* Generic clear implementation (partially) using u_blitter: */
189 void
fd_blitter_clear(struct pipe_context * pctx,unsigned buffers,const union pipe_color_union * color,double depth,unsigned stencil)190 fd_blitter_clear(struct pipe_context *pctx, unsigned buffers,
191                  const union pipe_color_union *color, double depth,
192                  unsigned stencil)
193 {
194    struct fd_context *ctx = fd_context(pctx);
195    struct pipe_framebuffer_state *pfb = &ctx->batch->framebuffer;
196    struct blitter_context *blitter = ctx->blitter;
197 
198    /* Note: don't use discard=true, if there was something to
199     * discard, that would have been already handled in fd_clear().
200     */
201    fd_blitter_pipe_begin(ctx, false);
202 
203    util_blitter_save_fragment_constant_buffer_slot(
204       ctx->blitter, ctx->constbuf[PIPE_SHADER_FRAGMENT].cb);
205 
206    util_blitter_common_clear_setup(blitter, pfb->width, pfb->height, buffers,
207                                    NULL, NULL);
208 
209    struct pipe_stencil_ref sr = {.ref_value = {stencil & 0xff}};
210    pctx->set_stencil_ref(pctx, sr);
211 
212    struct pipe_constant_buffer cb = {
213       .buffer_size = 16,
214       .user_buffer = &color->ui,
215    };
216    pctx->set_constant_buffer(pctx, PIPE_SHADER_FRAGMENT, 0, false, &cb);
217 
218    unsigned rs_idx = pfb->samples > 1 ? 1 : 0;
219    if (!ctx->clear_rs_state[rs_idx]) {
220       const struct pipe_rasterizer_state tmpl = {
221          .cull_face = PIPE_FACE_NONE,
222          .half_pixel_center = 1,
223          .bottom_edge_rule = 1,
224          .flatshade = 1,
225          .depth_clip_near = 1,
226          .depth_clip_far = 1,
227          .multisample = pfb->samples > 1,
228       };
229       ctx->clear_rs_state[rs_idx] = pctx->create_rasterizer_state(pctx, &tmpl);
230    }
231    pctx->bind_rasterizer_state(pctx, ctx->clear_rs_state[rs_idx]);
232 
233    struct pipe_viewport_state vp = {
234       .scale = {0.5f * pfb->width, -0.5f * pfb->height, depth},
235       .translate = {0.5f * pfb->width, 0.5f * pfb->height, 0.0f},
236    };
237    pctx->set_viewport_states(pctx, 0, 1, &vp);
238 
239    pctx->bind_vertex_elements_state(pctx, ctx->solid_vbuf_state.vtx);
240    util_set_vertex_buffers(pctx, 1, false,
241                            &ctx->solid_vbuf_state.vertexbuf.vb[0]);
242    pctx->set_stream_output_targets(pctx, 0, NULL, NULL);
243 
244    if (pfb->layers > 1)
245       pctx->bind_vs_state(pctx, ctx->solid_layered_prog.vs);
246    else
247       pctx->bind_vs_state(pctx, ctx->solid_prog.vs);
248 
249    pctx->bind_fs_state(pctx, ctx->solid_prog.fs);
250 
251    /* Clear geom/tess shaders, lest the draw emit code think we are
252     * trying to use use them:
253     */
254    pctx->bind_gs_state(pctx, NULL);
255    pctx->bind_tcs_state(pctx, NULL);
256    pctx->bind_tes_state(pctx, NULL);
257 
258    struct pipe_draw_info info = {
259       .mode = MESA_PRIM_COUNT, /* maps to DI_PT_RECTLIST */
260       .index_bounds_valid = true,
261       .max_index = 1,
262       .instance_count = MAX2(1, pfb->layers),
263    };
264    struct pipe_draw_start_count_bias draw = {
265       .count = 2,
266    };
267 
268    pctx->draw_vbo(pctx, &info, 0, NULL, &draw, 1);
269 
270    /* We expect that this should not have triggered a change in pfb: */
271    assert(util_framebuffer_state_equal(pfb, &ctx->framebuffer));
272 
273    util_blitter_restore_constant_buffer_state(blitter);
274    util_blitter_restore_vertex_states(blitter);
275    util_blitter_restore_fragment_states(blitter);
276    util_blitter_restore_textures(blitter);
277    util_blitter_restore_fb_state(blitter);
278    util_blitter_restore_render_cond(blitter);
279    util_blitter_unset_running_flag(blitter);
280 
281    fd_blitter_pipe_end(ctx);
282 }
283 
284 /* Partially generic clear_render_target implementation using u_blitter */
285 void
fd_blitter_clear_render_target(struct pipe_context * pctx,struct pipe_surface * ps,const union pipe_color_union * color,unsigned x,unsigned y,unsigned w,unsigned h,bool render_condition_enabled)286 fd_blitter_clear_render_target(struct pipe_context *pctx, struct pipe_surface *ps,
287                                const union pipe_color_union *color, unsigned x,
288                                unsigned y, unsigned w, unsigned h,
289                                bool render_condition_enabled)
290 {
291    struct fd_context *ctx = fd_context(pctx);
292 
293    fd_blitter_pipe_begin(ctx, render_condition_enabled);
294    util_blitter_clear_render_target(ctx->blitter, ps, color, x, y, w, h);
295    fd_blitter_pipe_end(ctx);
296 }
297 
298 /* Partially generic clear_depth_stencil implementation using u_blitter */
299 void
fd_blitter_clear_depth_stencil(struct pipe_context * pctx,struct pipe_surface * ps,unsigned buffers,double depth,unsigned stencil,unsigned x,unsigned y,unsigned w,unsigned h,bool render_condition_enabled)300 fd_blitter_clear_depth_stencil(struct pipe_context *pctx, struct pipe_surface *ps,
301                                unsigned buffers, double depth, unsigned stencil,
302                                unsigned x, unsigned y, unsigned w, unsigned h,
303                                bool render_condition_enabled)
304 {
305    struct fd_context *ctx = fd_context(pctx);
306 
307    fd_blitter_pipe_begin(ctx, render_condition_enabled);
308    util_blitter_clear_depth_stencil(ctx->blitter, ps, buffers, depth,
309                                     stencil, x, y, w, h);
310    fd_blitter_pipe_end(ctx);
311 }
312 
313 /**
314  * Optimal hardware path for blitting pixels.
315  * Scaling, format conversion, up- and downsampling (resolve) are allowed.
316  */
317 bool
fd_blit(struct pipe_context * pctx,const struct pipe_blit_info * blit_info)318 fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info)
319 {
320    struct fd_context *ctx = fd_context(pctx);
321    struct pipe_blit_info info = *blit_info;
322 
323    if (info.render_condition_enable && !fd_render_condition_check(pctx))
324       return true;
325 
326    if (ctx->blit && ctx->blit(ctx, &info))
327       return true;
328 
329    if (info.mask & PIPE_MASK_S) {
330       DBG("cannot blit stencil, skipping");
331       info.mask &= ~PIPE_MASK_S;
332    }
333 
334    if (!util_blitter_is_blit_supported(ctx->blitter, &info)) {
335       DBG("blit unsupported %s -> %s",
336           util_format_short_name(info.src.resource->format),
337           util_format_short_name(info.dst.resource->format));
338       return false;
339    }
340 
341    return fd_blitter_blit(ctx, &info);
342 }
343 
344 /**
345  * _copy_region using pipe (3d engine)
346  */
347 static bool
fd_blitter_pipe_copy_region(struct fd_context * ctx,struct pipe_resource * dst,unsigned dst_level,unsigned dstx,unsigned dsty,unsigned dstz,struct pipe_resource * src,unsigned src_level,const struct pipe_box * src_box)348 fd_blitter_pipe_copy_region(struct fd_context *ctx, struct pipe_resource *dst,
349                             unsigned dst_level, unsigned dstx, unsigned dsty,
350                             unsigned dstz, struct pipe_resource *src,
351                             unsigned src_level,
352                             const struct pipe_box *src_box) assert_dt
353 {
354    /* not until we allow rendertargets to be buffers */
355    if (dst->target == PIPE_BUFFER || src->target == PIPE_BUFFER)
356       return false;
357 
358    if (!util_blitter_is_copy_supported(ctx->blitter, dst, src))
359       return false;
360 
361    if (src == dst) {
362       struct pipe_context *pctx = &ctx->base;
363       pctx->flush(pctx, NULL, 0);
364    }
365 
366    /* TODO we could invalidate if dst box covers dst level fully. */
367    fd_blitter_pipe_begin(ctx, false);
368    util_blitter_copy_texture(ctx->blitter, dst, dst_level, dstx, dsty, dstz,
369                              src, src_level, src_box);
370    fd_blitter_pipe_end(ctx);
371 
372    return true;
373 }
374 
375 /**
376  * Copy a block of pixels from one resource to another.
377  * The resource must be of the same format.
378  */
379 void
fd_resource_copy_region(struct pipe_context * pctx,struct pipe_resource * dst,unsigned dst_level,unsigned dstx,unsigned dsty,unsigned dstz,struct pipe_resource * src,unsigned src_level,const struct pipe_box * src_box)380 fd_resource_copy_region(struct pipe_context *pctx, struct pipe_resource *dst,
381                         unsigned dst_level, unsigned dstx, unsigned dsty,
382                         unsigned dstz, struct pipe_resource *src,
383                         unsigned src_level, const struct pipe_box *src_box)
384 {
385    struct fd_context *ctx = fd_context(pctx);
386 
387    /* The blitter path handles compressed formats only if src and dst format
388     * match, in other cases just fall back to sw:
389     */
390    if ((src->format != dst->format) &&
391        (util_format_is_compressed(src->format) ||
392         util_format_is_compressed(dst->format))) {
393       perf_debug_ctx(ctx, "copy_region falls back to sw for {%"PRSC_FMT"} to {%"PRSC_FMT"}",
394                      PRSC_ARGS(src), PRSC_ARGS(dst));
395       goto fallback;
396    }
397 
398    if (ctx->blit) {
399       struct pipe_blit_info info;
400 
401       memset(&info, 0, sizeof info);
402       info.dst.resource = dst;
403       info.dst.level = dst_level;
404       info.dst.box.x = dstx;
405       info.dst.box.y = dsty;
406       info.dst.box.z = dstz;
407       info.dst.box.width = src_box->width;
408       info.dst.box.height = src_box->height;
409       assert(info.dst.box.width >= 0);
410       assert(info.dst.box.height >= 0);
411       info.dst.box.depth = 1;
412       info.dst.format = dst->format;
413       info.src.resource = src;
414       info.src.level = src_level;
415       info.src.box = *src_box;
416       info.src.format = src->format;
417       info.mask = util_format_get_mask(src->format);
418       info.filter = PIPE_TEX_FILTER_NEAREST;
419       info.scissor_enable = 0;
420 
421       if (ctx->blit(ctx, &info))
422          return;
423    }
424 
425    /* try blit on 3d pipe: */
426    if (fd_blitter_pipe_copy_region(ctx, dst, dst_level, dstx, dsty, dstz, src,
427                                    src_level, src_box))
428       return;
429 
430    /* else fallback to pure sw: */
431 fallback:
432    util_resource_copy_region(pctx, dst, dst_level, dstx, dsty, dstz, src,
433                              src_level, src_box);
434 }
435