xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/llvmpipe/lp_surface.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /**************************************************************************
2  *
3  * Copyright 2007 VMware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  **************************************************************************/
27 
28 #include "util/u_rect.h"
29 #include "util/u_surface.h"
30 #include "util/u_memset.h"
31 #include "lp_context.h"
32 #include "lp_flush.h"
33 #include "lp_limits.h"
34 #include "lp_surface.h"
35 #include "lp_texture.h"
36 #include "lp_query.h"
37 #include "lp_rast.h"
38 
39 
40 static void
lp_resource_copy_ms(struct pipe_context * pipe,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)41 lp_resource_copy_ms(struct pipe_context *pipe,
42                     struct pipe_resource *dst, unsigned dst_level,
43                     unsigned dstx, unsigned dsty, unsigned dstz,
44                     struct pipe_resource *src, unsigned src_level,
45                     const struct pipe_box *src_box)
46 {
47    struct pipe_box dst_box = *src_box;
48    dst_box.x = dstx;
49    dst_box.y = dsty;
50    dst_box.z = dstz;
51 
52    enum pipe_format src_format = src->format;
53 
54    for (unsigned i = 0; i < MAX2(src->nr_samples, dst->nr_samples); i++) {
55       struct pipe_transfer *src_trans, *dst_trans;
56       const uint8_t *src_map =
57          llvmpipe_transfer_map_ms(pipe,src, 0, PIPE_MAP_READ,
58                                   MIN2(i, src->nr_samples - 1),
59                                   src_box, &src_trans);
60       if (!src_map)
61          return;
62 
63       uint8_t *dst_map = llvmpipe_transfer_map_ms(pipe,
64                                                   dst, 0, PIPE_MAP_WRITE, i,
65                                                   &dst_box,
66                                                   &dst_trans);
67       if (!dst_map) {
68          pipe->texture_unmap(pipe, src_trans);
69          return;
70       }
71 
72       util_copy_box(dst_map,
73                     src_format,
74                     dst_trans->stride, dst_trans->layer_stride,
75                     0, 0, 0,
76                     src_box->width, src_box->height, src_box->depth,
77                     src_map,
78                     src_trans->stride, src_trans->layer_stride,
79                     0, 0, 0);
80       pipe->texture_unmap(pipe, dst_trans);
81       pipe->texture_unmap(pipe, src_trans);
82    }
83 }
84 
85 
86 static void
lp_resource_copy(struct pipe_context * pipe,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)87 lp_resource_copy(struct pipe_context *pipe,
88                  struct pipe_resource *dst, unsigned dst_level,
89                  unsigned dstx, unsigned dsty, unsigned dstz,
90                  struct pipe_resource *src, unsigned src_level,
91                  const struct pipe_box *src_box)
92 {
93    llvmpipe_flush_resource(pipe,
94                            dst, dst_level,
95                            false, /* read_only */
96                            true, /* cpu_access */
97                            false, /* do_not_block */
98                            "blit dest");
99 
100    llvmpipe_flush_resource(pipe,
101                            src, src_level,
102                            true, /* read_only */
103                            true, /* cpu_access */
104                            false, /* do_not_block */
105                            "blit src");
106 
107    if (dst->nr_samples > 1 &&
108        (dst->nr_samples == src->nr_samples ||
109        (src->nr_samples == 1 && dst->nr_samples > 1))) {
110       lp_resource_copy_ms(pipe, dst, dst_level, dstx, dsty, dstz,
111                           src, src_level, src_box);
112       return;
113    }
114    util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
115                              src, src_level, src_box);
116 }
117 
118 
119 static void
lp_blit(struct pipe_context * pipe,const struct pipe_blit_info * blit_info)120 lp_blit(struct pipe_context *pipe,
121         const struct pipe_blit_info *blit_info)
122 {
123    struct llvmpipe_context *lp = llvmpipe_context(pipe);
124    struct pipe_blit_info info = *blit_info;
125 
126    if (blit_info->render_condition_enable && !llvmpipe_check_render_cond(lp))
127       return;
128 
129    if (util_try_blit_via_copy_region(pipe, &info,
130                                      lp->render_cond_query != NULL)) {
131       return; /* done */
132    }
133 
134    if (blit_info->src.resource->format == blit_info->src.format &&
135        blit_info->dst.resource->format == blit_info->dst.format &&
136        blit_info->src.format == blit_info->dst.format &&
137        blit_info->src.resource->nr_samples > 1 &&
138        blit_info->dst.resource->nr_samples < 2 &&
139        blit_info->sample0_only) {
140       util_resource_copy_region(pipe, blit_info->dst.resource,
141                                 blit_info->dst.level, blit_info->dst.box.x,
142                                 blit_info->dst.box.y, blit_info->dst.box.z,
143                                 blit_info->src.resource, blit_info->src.level,
144                                 &blit_info->src.box);
145       return;
146    }
147 
148    if (!util_blitter_is_blit_supported(lp->blitter, &info)) {
149       debug_printf("llvmpipe: blit unsupported %s -> %s\n",
150                    util_format_short_name(info.src.resource->format),
151                    util_format_short_name(info.dst.resource->format));
152       return;
153    }
154 
155    /* for 32-bit unorm depth, avoid the conversions to float and back,
156       which can introduce accuracy errors. */
157    if (blit_info->src.format == PIPE_FORMAT_Z32_UNORM &&
158        blit_info->dst.format == PIPE_FORMAT_Z32_UNORM &&
159        info.filter == PIPE_TEX_FILTER_NEAREST) {
160       info.src.format = PIPE_FORMAT_R32_UINT;
161       info.dst.format = PIPE_FORMAT_R32_UINT;
162       info.mask = PIPE_MASK_R;
163    }
164 
165    util_blitter_save_vertex_buffers(lp->blitter, lp->vertex_buffer,
166                                     lp->num_vertex_buffers);
167    util_blitter_save_vertex_elements(lp->blitter, (void*)lp->velems);
168    util_blitter_save_vertex_shader(lp->blitter, (void*)lp->vs);
169    util_blitter_save_geometry_shader(lp->blitter, (void*)lp->gs);
170    util_blitter_save_so_targets(lp->blitter, lp->num_so_targets,
171                      (struct pipe_stream_output_target**)lp->so_targets);
172    util_blitter_save_rasterizer(lp->blitter, (void*)lp->rasterizer);
173    util_blitter_save_viewport(lp->blitter, &lp->viewports[0]);
174    util_blitter_save_scissor(lp->blitter, &lp->scissors[0]);
175    util_blitter_save_fragment_shader(lp->blitter, lp->fs);
176    util_blitter_save_blend(lp->blitter, (void*)lp->blend);
177    util_blitter_save_tessctrl_shader(lp->blitter, (void*)lp->tcs);
178    util_blitter_save_tesseval_shader(lp->blitter, (void*)lp->tes);
179    util_blitter_save_depth_stencil_alpha(lp->blitter,
180                                          (void*)lp->depth_stencil);
181    util_blitter_save_stencil_ref(lp->blitter, &lp->stencil_ref);
182    util_blitter_save_sample_mask(lp->blitter, lp->sample_mask,
183                                  lp->min_samples);
184    util_blitter_save_framebuffer(lp->blitter, &lp->framebuffer);
185    util_blitter_save_fragment_sampler_states(lp->blitter,
186                      lp->num_samplers[PIPE_SHADER_FRAGMENT],
187                      (void**)lp->samplers[PIPE_SHADER_FRAGMENT]);
188    util_blitter_save_fragment_sampler_views(lp->blitter,
189                      lp->num_sampler_views[PIPE_SHADER_FRAGMENT],
190                      lp->sampler_views[PIPE_SHADER_FRAGMENT]);
191    util_blitter_save_render_condition(lp->blitter, lp->render_cond_query,
192                                       lp->render_cond_cond,
193                                       lp->render_cond_mode);
194    util_blitter_blit(lp->blitter, &info, NULL);
195 }
196 
197 
198 static void
lp_flush_resource(struct pipe_context * ctx,struct pipe_resource * resource)199 lp_flush_resource(struct pipe_context *ctx, struct pipe_resource *resource)
200 {
201    llvmpipe_flush_resource(ctx, resource, 0, true, true, false, "resource");
202 }
203 
204 
205 static struct pipe_surface *
llvmpipe_create_surface(struct pipe_context * pipe,struct pipe_resource * pt,const struct pipe_surface * surf_tmpl)206 llvmpipe_create_surface(struct pipe_context *pipe,
207                         struct pipe_resource *pt,
208                         const struct pipe_surface *surf_tmpl)
209 {
210    if (!(pt->bind & (PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_RENDER_TARGET))) {
211       debug_printf("Illegal surface creation without bind flag\n");
212       if (util_format_is_depth_or_stencil(surf_tmpl->format)) {
213          pt->bind |= PIPE_BIND_DEPTH_STENCIL;
214       }
215       else {
216          pt->bind |= PIPE_BIND_RENDER_TARGET;
217       }
218    }
219 
220    struct pipe_surface *ps = CALLOC_STRUCT(pipe_surface);
221    if (ps) {
222       pipe_reference_init(&ps->reference, 1);
223       pipe_resource_reference(&ps->texture, pt);
224       ps->context = pipe;
225       ps->format = surf_tmpl->format;
226       if (llvmpipe_resource_is_texture(pt)) {
227          assert(surf_tmpl->u.tex.level <= pt->last_level);
228          assert(surf_tmpl->u.tex.first_layer <= surf_tmpl->u.tex.last_layer);
229          ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level);
230          ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level);
231          ps->u.tex.level = surf_tmpl->u.tex.level;
232          ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
233          ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
234       } else {
235          /* setting width as number of elements should get us correct
236           * renderbuffer width
237           */
238          ps->width = surf_tmpl->u.buf.last_element
239                    - surf_tmpl->u.buf.first_element + 1;
240          ps->height = pt->height0;
241          ps->u.buf.first_element = surf_tmpl->u.buf.first_element;
242          ps->u.buf.last_element = surf_tmpl->u.buf.last_element;
243          assert(ps->u.buf.first_element <= ps->u.buf.last_element);
244          assert(util_format_get_blocksize(surf_tmpl->format) *
245                 (ps->u.buf.last_element + 1) <= pt->width0);
246       }
247    }
248    return ps;
249 }
250 
251 
252 static void
llvmpipe_surface_destroy(struct pipe_context * pipe,struct pipe_surface * surf)253 llvmpipe_surface_destroy(struct pipe_context *pipe,
254                          struct pipe_surface *surf)
255 {
256    /* Effectively do the texture_update work here - if texture images
257     * needed post-processing to put them into hardware layout, this is
258     * where it would happen.  For llvmpipe, nothing to do.
259     */
260    assert(surf->texture);
261    pipe_resource_reference(&surf->texture, NULL);
262    FREE(surf);
263 }
264 
265 
266 static void
llvmpipe_get_sample_position(struct pipe_context * pipe,unsigned sample_count,unsigned sample_index,float * out_value)267 llvmpipe_get_sample_position(struct pipe_context *pipe,
268                              unsigned sample_count,
269                              unsigned sample_index,
270                              float *out_value)
271 {
272    switch (sample_count) {
273    case 4:
274       out_value[0] = lp_sample_pos_4x[sample_index][0];
275       out_value[1] = lp_sample_pos_4x[sample_index][1];
276       break;
277    default:
278       break;
279    }
280 }
281 
282 
283 static void
lp_clear_color_texture_helper(struct pipe_transfer * dst_trans,uint8_t * dst_map,enum pipe_format format,const union pipe_color_union * color,unsigned width,unsigned height,unsigned depth)284 lp_clear_color_texture_helper(struct pipe_transfer *dst_trans,
285                               uint8_t *dst_map,
286                               enum pipe_format format,
287                               const union pipe_color_union *color,
288                               unsigned width, unsigned height,
289                               unsigned depth)
290 {
291    union util_color uc;
292 
293    assert(dst_trans->stride > 0);
294 
295    util_pack_color_union(format, &uc, color);
296 
297    util_fill_box(dst_map, format,
298                  dst_trans->stride, dst_trans->layer_stride,
299                  0, 0, 0, width, height, depth, &uc);
300 }
301 
302 
303 static void
lp_clear_color_texture_msaa(struct pipe_context * pipe,struct pipe_resource * texture,enum pipe_format format,const union pipe_color_union * color,unsigned sample,const struct pipe_box * box)304 lp_clear_color_texture_msaa(struct pipe_context *pipe,
305                             struct pipe_resource *texture,
306                             enum pipe_format format,
307                             const union pipe_color_union *color,
308                             unsigned sample,
309                             const struct pipe_box *box)
310 {
311    struct pipe_transfer *dst_trans;
312    uint8_t *dst_map;
313 
314    dst_map = llvmpipe_transfer_map_ms(pipe, texture, 0, PIPE_MAP_WRITE,
315                                       sample, box, &dst_trans);
316    if (!dst_map)
317       return;
318 
319    if (dst_trans->stride > 0) {
320       lp_clear_color_texture_helper(dst_trans, dst_map, format, color,
321                                     box->width, box->height, box->depth);
322    }
323    pipe->texture_unmap(pipe, dst_trans);
324 }
325 
326 
327 static void
llvmpipe_clear_render_target(struct pipe_context * pipe,struct pipe_surface * dst,const union pipe_color_union * color,unsigned dstx,unsigned dsty,unsigned width,unsigned height,bool render_condition_enabled)328 llvmpipe_clear_render_target(struct pipe_context *pipe,
329                              struct pipe_surface *dst,
330                              const union pipe_color_union *color,
331                              unsigned dstx, unsigned dsty,
332                              unsigned width, unsigned height,
333                              bool render_condition_enabled)
334 {
335    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
336 
337    if (render_condition_enabled && !llvmpipe_check_render_cond(llvmpipe))
338       return;
339 
340    width = MIN2(width, dst->texture->width0 - dstx);
341    height = MIN2(height, dst->texture->height0 - dsty);
342 
343    if (dst->texture->nr_samples > 1) {
344       struct pipe_box box;
345       u_box_2d(dstx, dsty, width, height, &box);
346       if (dst->texture->target != PIPE_BUFFER) {
347          box.z = dst->u.tex.first_layer;
348          box.depth = dst->u.tex.last_layer - dst->u.tex.first_layer + 1;
349       }
350       for (unsigned s = 0; s < util_res_sample_count(dst->texture); s++) {
351          lp_clear_color_texture_msaa(pipe, dst->texture, dst->format,
352                                      color, s, &box);
353       }
354    } else {
355       util_clear_render_target(pipe, dst, color,
356                                dstx, dsty, width, height);
357    }
358 }
359 
360 
361 static void
lp_clear_depth_stencil_texture_msaa(struct pipe_context * pipe,struct pipe_resource * texture,enum pipe_format format,unsigned clear_flags,uint64_t zstencil,unsigned sample,const struct pipe_box * box)362 lp_clear_depth_stencil_texture_msaa(struct pipe_context *pipe,
363                                     struct pipe_resource *texture,
364                                     enum pipe_format format,
365                                     unsigned clear_flags,
366                                     uint64_t zstencil, unsigned sample,
367                                     const struct pipe_box *box)
368 {
369    struct pipe_transfer *dst_trans;
370    bool need_rmw = false;
371 
372    if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) &&
373        ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) &&
374        util_format_is_depth_and_stencil(format)) {
375       need_rmw = true;
376    }
377 
378    uint8_t *dst_map = llvmpipe_transfer_map_ms(pipe,
379                                                texture,
380                                                0,
381                                                (need_rmw ? PIPE_MAP_READ_WRITE :
382                                                 PIPE_MAP_WRITE),
383                                                sample, box, &dst_trans);
384    assert(dst_map);
385    if (!dst_map)
386       return;
387 
388    assert(dst_trans->stride > 0);
389 
390    util_fill_zs_box(dst_map, format, need_rmw, clear_flags,
391                     dst_trans->stride, dst_trans->layer_stride,
392                     box->width, box->height, box->depth, zstencil);
393 
394    pipe->texture_unmap(pipe, dst_trans);
395 }
396 
397 
398 static void
llvmpipe_clear_depth_stencil(struct pipe_context * pipe,struct pipe_surface * dst,unsigned clear_flags,double depth,unsigned stencil,unsigned dstx,unsigned dsty,unsigned width,unsigned height,bool render_condition_enabled)399 llvmpipe_clear_depth_stencil(struct pipe_context *pipe,
400                              struct pipe_surface *dst,
401                              unsigned clear_flags,
402                              double depth,
403                              unsigned stencil,
404                              unsigned dstx, unsigned dsty,
405                              unsigned width, unsigned height,
406                              bool render_condition_enabled)
407 {
408    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
409 
410    if (render_condition_enabled && !llvmpipe_check_render_cond(llvmpipe))
411       return;
412 
413    width = MIN2(width, dst->texture->width0 - dstx);
414    height = MIN2(height, dst->texture->height0 - dsty);
415 
416    if (dst->texture->nr_samples > 1) {
417       uint64_t zstencil = util_pack64_z_stencil(dst->format, depth, stencil);
418       struct pipe_box box;
419       u_box_2d(dstx, dsty, width, height, &box);
420       if (dst->texture->target != PIPE_BUFFER) {
421          box.z = dst->u.tex.first_layer;
422          box.depth = dst->u.tex.last_layer - dst->u.tex.first_layer + 1;
423       }
424       for (unsigned s = 0; s < util_res_sample_count(dst->texture); s++)
425          lp_clear_depth_stencil_texture_msaa(pipe, dst->texture,
426                                              dst->format, clear_flags,
427                                              zstencil, s, &box);
428    } else {
429       util_clear_depth_stencil(pipe, dst, clear_flags,
430                                depth, stencil,
431                                dstx, dsty, width, height);
432    }
433 }
434 
435 
436 static void
llvmpipe_clear_texture(struct pipe_context * pipe,struct pipe_resource * tex,unsigned level,const struct pipe_box * box,const void * data)437 llvmpipe_clear_texture(struct pipe_context *pipe,
438                        struct pipe_resource *tex,
439                        unsigned level,
440                        const struct pipe_box *box,
441                        const void *data)
442 {
443    const struct util_format_description *desc =
444           util_format_description(tex->format);
445    if (tex->nr_samples <= 1) {
446       util_clear_texture_sw(pipe, tex, level, box, data);
447       return;
448    }
449    union pipe_color_union color;
450 
451    if (util_format_is_depth_or_stencil(tex->format)) {
452       unsigned clear = 0;
453       float depth = 0.0f;
454       uint8_t stencil = 0;
455       uint64_t zstencil;
456 
457       if (util_format_has_depth(desc)) {
458          clear |= PIPE_CLEAR_DEPTH;
459          util_format_unpack_z_float(tex->format, &depth, data, 1);
460       }
461 
462       if (util_format_has_stencil(desc)) {
463          clear |= PIPE_CLEAR_STENCIL;
464          util_format_unpack_s_8uint(tex->format, &stencil, data, 1);
465       }
466 
467       zstencil = util_pack64_z_stencil(tex->format, depth, stencil);
468 
469       for (unsigned s = 0; s < util_res_sample_count(tex); s++)
470          lp_clear_depth_stencil_texture_msaa(pipe, tex, tex->format, clear,
471                                              zstencil, s, box);
472    } else {
473       util_format_unpack_rgba(tex->format, color.ui, data, 1);
474 
475       for (unsigned s = 0; s < util_res_sample_count(tex); s++) {
476          lp_clear_color_texture_msaa(pipe, tex, tex->format, &color, s,
477                                      box);
478       }
479    }
480 }
481 
482 
483 static void
llvmpipe_clear_buffer(struct pipe_context * pipe,struct pipe_resource * res,unsigned offset,unsigned size,const void * clear_value,int clear_value_size)484 llvmpipe_clear_buffer(struct pipe_context *pipe,
485                       struct pipe_resource *res,
486                       unsigned offset,
487                       unsigned size,
488                       const void *clear_value,
489                       int clear_value_size)
490 {
491    struct pipe_transfer *dst_t;
492    struct pipe_box box;
493 
494    u_box_1d(offset, size, &box);
495 
496    char *dst = pipe->buffer_map(pipe, res, 0, PIPE_MAP_WRITE, &box, &dst_t);
497 
498    switch (clear_value_size) {
499    case 1:
500       memset(dst, *(uint8_t *)clear_value, size);
501       break;
502    case 4:
503       util_memset32(dst, *(uint32_t *)clear_value, size / 4);
504       break;
505    default:
506       for (unsigned i = 0; i < size; i += clear_value_size)
507          memcpy(&dst[i], clear_value, clear_value_size);
508       break;
509    }
510    pipe->buffer_unmap(pipe, dst_t);
511 }
512 
513 
514 void
llvmpipe_init_surface_functions(struct llvmpipe_context * lp)515 llvmpipe_init_surface_functions(struct llvmpipe_context *lp)
516 {
517    lp->pipe.clear_render_target = llvmpipe_clear_render_target;
518    lp->pipe.clear_depth_stencil = llvmpipe_clear_depth_stencil;
519    lp->pipe.create_surface = llvmpipe_create_surface;
520    lp->pipe.surface_destroy = llvmpipe_surface_destroy;
521    /* These are not actually functions dealing with surfaces */
522    lp->pipe.clear_texture = llvmpipe_clear_texture;
523    lp->pipe.clear_buffer = llvmpipe_clear_buffer;
524    lp->pipe.resource_copy_region = lp_resource_copy;
525    lp->pipe.blit = lp_blit;
526    lp->pipe.flush_resource = lp_flush_resource;
527    lp->pipe.get_sample_position = llvmpipe_get_sample_position;
528 }
529