• 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_buffer_slot(ctx->blitter, ctx->vtx.vertexbuf.vb);
83    util_blitter_save_vertex_elements(ctx->blitter, ctx->vtx.vtx);
84    util_blitter_save_vertex_shader(ctx->blitter, ctx->prog.vs);
85    util_blitter_save_tessctrl_shader(ctx->blitter, ctx->prog.hs);
86    util_blitter_save_tesseval_shader(ctx->blitter, ctx->prog.ds);
87    util_blitter_save_geometry_shader(ctx->blitter, ctx->prog.gs);
88    util_blitter_save_so_targets(ctx->blitter, ctx->streamout.num_targets,
89                                 ctx->streamout.targets);
90    util_blitter_save_rasterizer(ctx->blitter, ctx->rasterizer);
91    util_blitter_save_viewport(ctx->blitter, &ctx->viewport);
92    util_blitter_save_scissor(ctx->blitter, &ctx->scissor);
93    util_blitter_save_fragment_shader(ctx->blitter, ctx->prog.fs);
94    util_blitter_save_blend(ctx->blitter, ctx->blend);
95    util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->zsa);
96    util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref);
97    util_blitter_save_sample_mask(ctx->blitter, ctx->sample_mask);
98    util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer);
99    util_blitter_save_fragment_sampler_states(
100       ctx->blitter, ctx->tex[PIPE_SHADER_FRAGMENT].num_samplers,
101       (void **)ctx->tex[PIPE_SHADER_FRAGMENT].samplers);
102    util_blitter_save_fragment_sampler_views(
103       ctx->blitter, ctx->tex[PIPE_SHADER_FRAGMENT].num_textures,
104       ctx->tex[PIPE_SHADER_FRAGMENT].textures);
105    if (!render_cond)
106       util_blitter_save_render_condition(ctx->blitter, ctx->cond_query,
107                                          ctx->cond_cond, ctx->cond_mode);
108 
109    if (ctx->batch)
110       fd_batch_update_queries(ctx->batch);
111 }
112 
113 static void
fd_blitter_pipe_end(struct fd_context * ctx)114 fd_blitter_pipe_end(struct fd_context *ctx) assert_dt
115 {
116 }
117 
118 bool
fd_blitter_blit(struct fd_context * ctx,const struct pipe_blit_info * info)119 fd_blitter_blit(struct fd_context *ctx, const struct pipe_blit_info *info)
120 {
121    struct pipe_context *pctx = &ctx->base;
122    struct pipe_resource *dst = info->dst.resource;
123    struct pipe_resource *src = info->src.resource;
124    struct pipe_context *pipe = &ctx->base;
125    struct pipe_surface *dst_view, dst_templ;
126    struct pipe_sampler_view src_templ, *src_view;
127 
128    /* If the blit is updating the whole contents of the resource,
129     * invalidate it so we don't trigger any unnecessary tile loads in the 3D
130     * path.
131     */
132    if (util_blit_covers_whole_resource(info))
133       pctx->invalidate_resource(pctx, info->dst.resource);
134 
135    /* The blit format may not match the resource format in this path, so
136     * we need to validate that we can use the src/dst resource with the
137     * requested format (and uncompress if necessary).  Normally this would
138     * happen in ->set_sampler_view(), ->set_framebuffer_state(), etc.  But
139     * that would cause recursion back into u_blitter, which ends in tears.
140     *
141     * To avoid recursion, this needs to be done before util_blitter_save_*()
142     */
143    if (ctx->validate_format) {
144       ctx->validate_format(ctx, fd_resource(dst), info->dst.format);
145       ctx->validate_format(ctx, fd_resource(src), info->src.format);
146    }
147 
148    if (src == dst)
149       pipe->flush(pipe, NULL, 0);
150 
151    DBG_BLIT(info, NULL);
152 
153    fd_blitter_pipe_begin(ctx, info->render_condition_enable);
154 
155    /* Initialize the surface. */
156    default_dst_texture(&dst_templ, dst, info->dst.level, info->dst.box.z);
157    dst_templ.format = info->dst.format;
158    dst_view = pipe->create_surface(pipe, dst, &dst_templ);
159 
160    /* Initialize the sampler view. */
161    default_src_texture(&src_templ, src, info->src.level);
162    src_templ.format = info->src.format;
163    src_view = pipe->create_sampler_view(pipe, src, &src_templ);
164 
165    /* Copy. */
166    util_blitter_blit_generic(
167       ctx->blitter, dst_view, &info->dst.box, src_view, &info->src.box,
168       src->width0, src->height0, info->mask, info->filter,
169       info->scissor_enable ? &info->scissor : NULL, info->alpha_blend, false);
170 
171    pipe_surface_reference(&dst_view, NULL);
172    pipe_sampler_view_reference(&src_view, NULL);
173 
174    fd_blitter_pipe_end(ctx);
175 
176    /* While this shouldn't technically be necessary, it is required for
177     * dEQP-GLES31.functional.stencil_texturing.format.stencil_index8_cube and
178     * 2d_array to pass.
179     */
180    fd_bc_flush_writer(ctx, fd_resource(info->dst.resource));
181 
182    /* The fallback blitter must never fail: */
183    return true;
184 }
185 
186 /* Generic clear implementation (partially) using u_blitter: */
187 void
fd_blitter_clear(struct pipe_context * pctx,unsigned buffers,const union pipe_color_union * color,double depth,unsigned stencil)188 fd_blitter_clear(struct pipe_context *pctx, unsigned buffers,
189                  const union pipe_color_union *color, double depth,
190                  unsigned stencil)
191 {
192    struct fd_context *ctx = fd_context(pctx);
193    struct pipe_framebuffer_state *pfb = &ctx->batch->framebuffer;
194    struct blitter_context *blitter = ctx->blitter;
195 
196    /* Note: don't use discard=true, if there was something to
197     * discard, that would have been already handled in fd_clear().
198     */
199    fd_blitter_pipe_begin(ctx, false);
200 
201    util_blitter_save_fragment_constant_buffer_slot(
202       ctx->blitter, ctx->constbuf[PIPE_SHADER_FRAGMENT].cb);
203 
204    util_blitter_common_clear_setup(blitter, pfb->width, pfb->height, buffers,
205                                    NULL, NULL);
206 
207    struct pipe_stencil_ref sr = {.ref_value = {stencil & 0xff}};
208    pctx->set_stencil_ref(pctx, sr);
209 
210    struct pipe_constant_buffer cb = {
211       .buffer_size = 16,
212       .user_buffer = &color->ui,
213    };
214    pctx->set_constant_buffer(pctx, PIPE_SHADER_FRAGMENT, 0, false, &cb);
215 
216    unsigned rs_idx = pfb->samples > 1 ? 1 : 0;
217    if (!ctx->clear_rs_state[rs_idx]) {
218       const struct pipe_rasterizer_state tmpl = {
219          .cull_face = PIPE_FACE_NONE,
220          .half_pixel_center = 1,
221          .bottom_edge_rule = 1,
222          .flatshade = 1,
223          .depth_clip_near = 1,
224          .depth_clip_far = 1,
225          .multisample = pfb->samples > 1,
226       };
227       ctx->clear_rs_state[rs_idx] = pctx->create_rasterizer_state(pctx, &tmpl);
228    }
229    pctx->bind_rasterizer_state(pctx, ctx->clear_rs_state[rs_idx]);
230 
231    struct pipe_viewport_state vp = {
232       .scale = {0.5f * pfb->width, -0.5f * pfb->height, depth},
233       .translate = {0.5f * pfb->width, 0.5f * pfb->height, 0.0f},
234    };
235    pctx->set_viewport_states(pctx, 0, 1, &vp);
236 
237    pctx->bind_vertex_elements_state(pctx, ctx->solid_vbuf_state.vtx);
238    pctx->set_vertex_buffers(pctx, blitter->vb_slot, 1, 0, false,
239                             &ctx->solid_vbuf_state.vertexbuf.vb[0]);
240    pctx->set_stream_output_targets(pctx, 0, NULL, NULL);
241 
242    if (pfb->layers > 1)
243       pctx->bind_vs_state(pctx, ctx->solid_layered_prog.vs);
244    else
245       pctx->bind_vs_state(pctx, ctx->solid_prog.vs);
246 
247    pctx->bind_fs_state(pctx, ctx->solid_prog.fs);
248 
249    /* Clear geom/tess shaders, lest the draw emit code think we are
250     * trying to use use them:
251     */
252    pctx->bind_gs_state(pctx, NULL);
253    pctx->bind_tcs_state(pctx, NULL);
254    pctx->bind_tes_state(pctx, NULL);
255 
256    struct pipe_draw_info info = {
257       .mode = PIPE_PRIM_MAX, /* maps to DI_PT_RECTLIST */
258       .index_bounds_valid = true,
259       .max_index = 1,
260       .instance_count = MAX2(1, pfb->layers),
261    };
262    struct pipe_draw_start_count_bias draw = {
263       .count = 2,
264    };
265 
266    pctx->draw_vbo(pctx, &info, 0, NULL, &draw, 1);
267 
268    /* We expect that this should not have triggered a change in pfb: */
269    assert(util_framebuffer_state_equal(pfb, &ctx->framebuffer));
270 
271    util_blitter_restore_constant_buffer_state(blitter);
272    util_blitter_restore_vertex_states(blitter);
273    util_blitter_restore_fragment_states(blitter);
274    util_blitter_restore_textures(blitter);
275    util_blitter_restore_fb_state(blitter);
276    util_blitter_restore_render_cond(blitter);
277    util_blitter_unset_running_flag(blitter);
278 
279    fd_blitter_pipe_end(ctx);
280 }
281 
282 /**
283  * Optimal hardware path for blitting pixels.
284  * Scaling, format conversion, up- and downsampling (resolve) are allowed.
285  */
286 bool
fd_blit(struct pipe_context * pctx,const struct pipe_blit_info * blit_info)287 fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info)
288 {
289    struct fd_context *ctx = fd_context(pctx);
290    struct pipe_blit_info info = *blit_info;
291 
292    if (info.render_condition_enable && !fd_render_condition_check(pctx))
293       return true;
294 
295    if (ctx->blit && ctx->blit(ctx, &info))
296       return true;
297 
298    if (info.mask & PIPE_MASK_S) {
299       DBG("cannot blit stencil, skipping");
300       info.mask &= ~PIPE_MASK_S;
301    }
302 
303    if (!util_blitter_is_blit_supported(ctx->blitter, &info)) {
304       DBG("blit unsupported %s -> %s",
305           util_format_short_name(info.src.resource->format),
306           util_format_short_name(info.dst.resource->format));
307       return false;
308    }
309 
310    return fd_blitter_blit(ctx, &info);
311 }
312 
313 /**
314  * _copy_region using pipe (3d engine)
315  */
316 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)317 fd_blitter_pipe_copy_region(struct fd_context *ctx, struct pipe_resource *dst,
318                             unsigned dst_level, unsigned dstx, unsigned dsty,
319                             unsigned dstz, struct pipe_resource *src,
320                             unsigned src_level,
321                             const struct pipe_box *src_box) assert_dt
322 {
323    /* not until we allow rendertargets to be buffers */
324    if (dst->target == PIPE_BUFFER || src->target == PIPE_BUFFER)
325       return false;
326 
327    if (!util_blitter_is_copy_supported(ctx->blitter, dst, src))
328       return false;
329 
330    if (src == dst) {
331       struct pipe_context *pctx = &ctx->base;
332       pctx->flush(pctx, NULL, 0);
333    }
334 
335    /* TODO we could invalidate if dst box covers dst level fully. */
336    fd_blitter_pipe_begin(ctx, false);
337    util_blitter_copy_texture(ctx->blitter, dst, dst_level, dstx, dsty, dstz,
338                              src, src_level, src_box);
339    fd_blitter_pipe_end(ctx);
340 
341    return true;
342 }
343 
344 /**
345  * Copy a block of pixels from one resource to another.
346  * The resource must be of the same format.
347  */
348 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)349 fd_resource_copy_region(struct pipe_context *pctx, struct pipe_resource *dst,
350                         unsigned dst_level, unsigned dstx, unsigned dsty,
351                         unsigned dstz, struct pipe_resource *src,
352                         unsigned src_level, const struct pipe_box *src_box)
353 {
354    struct fd_context *ctx = fd_context(pctx);
355 
356    /* The blitter path handles compressed formats only if src and dst format
357     * match, in other cases just fall back to sw:
358     */
359    if ((src->format != dst->format) &&
360        (util_format_is_compressed(src->format) ||
361         util_format_is_compressed(dst->format))) {
362       perf_debug_ctx(ctx, "copy_region falls back to sw for {%"PRSC_FMT"} to {%"PRSC_FMT"}",
363                      PRSC_ARGS(src), PRSC_ARGS(dst));
364       goto fallback;
365    }
366 
367    if (ctx->blit) {
368       struct pipe_blit_info info;
369 
370       memset(&info, 0, sizeof info);
371       info.dst.resource = dst;
372       info.dst.level = dst_level;
373       info.dst.box.x = dstx;
374       info.dst.box.y = dsty;
375       info.dst.box.z = dstz;
376       info.dst.box.width = src_box->width;
377       info.dst.box.height = src_box->height;
378       assert(info.dst.box.width >= 0);
379       assert(info.dst.box.height >= 0);
380       info.dst.box.depth = 1;
381       info.dst.format = dst->format;
382       info.src.resource = src;
383       info.src.level = src_level;
384       info.src.box = *src_box;
385       info.src.format = src->format;
386       info.mask = util_format_get_mask(src->format);
387       info.filter = PIPE_TEX_FILTER_NEAREST;
388       info.scissor_enable = 0;
389 
390       if (ctx->blit(ctx, &info))
391          return;
392    }
393 
394    /* try blit on 3d pipe: */
395    if (fd_blitter_pipe_copy_region(ctx, dst, dst_level, dstx, dsty, dstz, src,
396                                    src_level, src_box))
397       return;
398 
399    /* else fallback to pure sw: */
400 fallback:
401    util_resource_copy_region(pctx, dst, dst_level, dstx, dsty, dstz, src,
402                              src_level, src_box);
403 }
404