• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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)40 lp_resource_copy_ms(struct pipe_context *pipe,
41                     struct pipe_resource *dst, unsigned dst_level,
42                     unsigned dstx, unsigned dsty, unsigned dstz,
43                     struct pipe_resource *src, unsigned src_level,
44                     const struct pipe_box *src_box)
45 {
46    struct pipe_box dst_box = *src_box;
47    enum pipe_format src_format;
48    dst_box.x = dstx;
49    dst_box.y = dsty;
50    dst_box.z = dstz;
51 
52    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 = llvmpipe_transfer_map_ms(pipe,
57                                                         src, 0, PIPE_MAP_READ, MIN2(i, src->nr_samples - 1),
58                                                         src_box,
59                                                         &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 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)85 lp_resource_copy(struct pipe_context *pipe,
86                  struct pipe_resource *dst, unsigned dst_level,
87                  unsigned dstx, unsigned dsty, unsigned dstz,
88                  struct pipe_resource *src, unsigned src_level,
89                  const struct pipe_box *src_box)
90 {
91    llvmpipe_flush_resource(pipe,
92                            dst, dst_level,
93                            FALSE, /* read_only */
94                            TRUE, /* cpu_access */
95                            FALSE, /* do_not_block */
96                            "blit dest");
97 
98    llvmpipe_flush_resource(pipe,
99                            src, src_level,
100                            TRUE, /* read_only */
101                            TRUE, /* cpu_access */
102                            FALSE, /* do_not_block */
103                            "blit src");
104 
105    if (dst->nr_samples > 1 &&
106        (dst->nr_samples == src->nr_samples ||
107        (src->nr_samples == 1 && dst->nr_samples > 1))) {
108       lp_resource_copy_ms(pipe, dst, dst_level, dstx, dsty, dstz,
109                           src, src_level, src_box);
110       return;
111    }
112    util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
113                              src, src_level, src_box);
114 }
115 
116 
lp_blit(struct pipe_context * pipe,const struct pipe_blit_info * blit_info)117 static void lp_blit(struct pipe_context *pipe,
118                     const struct pipe_blit_info *blit_info)
119 {
120    struct llvmpipe_context *lp = llvmpipe_context(pipe);
121    struct pipe_blit_info info = *blit_info;
122 
123    if (blit_info->render_condition_enable && !llvmpipe_check_render_cond(lp))
124       return;
125 
126    if (util_try_blit_via_copy_region(pipe, &info, lp->render_cond_query != NULL)) {
127       return; /* done */
128    }
129 
130    if (blit_info->src.resource->format == blit_info->src.format &&
131        blit_info->dst.resource->format == blit_info->dst.format &&
132        blit_info->src.format == blit_info->dst.format &&
133        blit_info->src.resource->nr_samples > 1 &&
134        blit_info->dst.resource->nr_samples < 2 &&
135        blit_info->sample0_only) {
136       util_resource_copy_region(pipe, blit_info->dst.resource, blit_info->dst.level, blit_info->dst.box.x, blit_info->dst.box.y, blit_info->dst.box.z,
137                                 blit_info->src.resource, blit_info->src.level, &blit_info->src.box);
138       return;
139    }
140 
141    if (!util_blitter_is_blit_supported(lp->blitter, &info)) {
142       debug_printf("llvmpipe: blit unsupported %s -> %s\n",
143                    util_format_short_name(info.src.resource->format),
144                    util_format_short_name(info.dst.resource->format));
145       return;
146    }
147 
148    /* for 32-bit unorm depth, avoid the conversions to float and back,
149       which can introduce accuracy errors. */
150    if (blit_info->src.format == PIPE_FORMAT_Z32_UNORM &&
151        blit_info->dst.format == PIPE_FORMAT_Z32_UNORM && info.filter == PIPE_TEX_FILTER_NEAREST) {
152       info.src.format = PIPE_FORMAT_R32_UINT;
153       info.dst.format = PIPE_FORMAT_R32_UINT;
154       info.mask = PIPE_MASK_R;
155    }
156 
157    util_blitter_save_vertex_buffer_slot(lp->blitter, lp->vertex_buffer);
158    util_blitter_save_vertex_elements(lp->blitter, (void*)lp->velems);
159    util_blitter_save_vertex_shader(lp->blitter, (void*)lp->vs);
160    util_blitter_save_geometry_shader(lp->blitter, (void*)lp->gs);
161    util_blitter_save_so_targets(lp->blitter, lp->num_so_targets,
162                                 (struct pipe_stream_output_target**)lp->so_targets);
163    util_blitter_save_rasterizer(lp->blitter, (void*)lp->rasterizer);
164    util_blitter_save_viewport(lp->blitter, &lp->viewports[0]);
165    util_blitter_save_scissor(lp->blitter, &lp->scissors[0]);
166    util_blitter_save_fragment_shader(lp->blitter, lp->fs);
167    util_blitter_save_blend(lp->blitter, (void*)lp->blend);
168    util_blitter_save_tessctrl_shader(lp->blitter, (void*)lp->tcs);
169    util_blitter_save_tesseval_shader(lp->blitter, (void*)lp->tes);
170    util_blitter_save_depth_stencil_alpha(lp->blitter, (void*)lp->depth_stencil);
171    util_blitter_save_stencil_ref(lp->blitter, &lp->stencil_ref);
172    util_blitter_save_sample_mask(lp->blitter, lp->sample_mask, lp->min_samples);
173    util_blitter_save_framebuffer(lp->blitter, &lp->framebuffer);
174    util_blitter_save_fragment_sampler_states(lp->blitter,
175                      lp->num_samplers[PIPE_SHADER_FRAGMENT],
176                      (void**)lp->samplers[PIPE_SHADER_FRAGMENT]);
177    util_blitter_save_fragment_sampler_views(lp->blitter,
178                      lp->num_sampler_views[PIPE_SHADER_FRAGMENT],
179                      lp->sampler_views[PIPE_SHADER_FRAGMENT]);
180    util_blitter_save_render_condition(lp->blitter, lp->render_cond_query,
181                                       lp->render_cond_cond, lp->render_cond_mode);
182    util_blitter_blit(lp->blitter, &info);
183 }
184 
185 
186 static void
lp_flush_resource(struct pipe_context * ctx,struct pipe_resource * resource)187 lp_flush_resource(struct pipe_context *ctx, struct pipe_resource *resource)
188 {
189    llvmpipe_flush_resource(ctx, resource, 0, true, true, false, "resource");
190 }
191 
192 
193 static struct pipe_surface *
llvmpipe_create_surface(struct pipe_context * pipe,struct pipe_resource * pt,const struct pipe_surface * surf_tmpl)194 llvmpipe_create_surface(struct pipe_context *pipe,
195                         struct pipe_resource *pt,
196                         const struct pipe_surface *surf_tmpl)
197 {
198    struct pipe_surface *ps;
199 
200    if (!(pt->bind & (PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_RENDER_TARGET))) {
201       debug_printf("Illegal surface creation without bind flag\n");
202       if (util_format_is_depth_or_stencil(surf_tmpl->format)) {
203          pt->bind |= PIPE_BIND_DEPTH_STENCIL;
204       }
205       else {
206          pt->bind |= PIPE_BIND_RENDER_TARGET;
207       }
208    }
209 
210    ps = CALLOC_STRUCT(pipe_surface);
211    if (ps) {
212       pipe_reference_init(&ps->reference, 1);
213       pipe_resource_reference(&ps->texture, pt);
214       ps->context = pipe;
215       ps->format = surf_tmpl->format;
216       if (llvmpipe_resource_is_texture(pt)) {
217          assert(surf_tmpl->u.tex.level <= pt->last_level);
218          assert(surf_tmpl->u.tex.first_layer <= surf_tmpl->u.tex.last_layer);
219          ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level);
220          ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level);
221          ps->u.tex.level = surf_tmpl->u.tex.level;
222          ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
223          ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
224       }
225       else {
226          /* setting width as number of elements should get us correct renderbuffer width */
227          ps->width = surf_tmpl->u.buf.last_element - surf_tmpl->u.buf.first_element + 1;
228          ps->height = pt->height0;
229          ps->u.buf.first_element = surf_tmpl->u.buf.first_element;
230          ps->u.buf.last_element = surf_tmpl->u.buf.last_element;
231          assert(ps->u.buf.first_element <= ps->u.buf.last_element);
232          assert(util_format_get_blocksize(surf_tmpl->format) *
233                 (ps->u.buf.last_element + 1) <= pt->width0);
234       }
235    }
236    return ps;
237 }
238 
239 
240 static void
llvmpipe_surface_destroy(struct pipe_context * pipe,struct pipe_surface * surf)241 llvmpipe_surface_destroy(struct pipe_context *pipe,
242                          struct pipe_surface *surf)
243 {
244    /* Effectively do the texture_update work here - if texture images
245     * needed post-processing to put them into hardware layout, this is
246     * where it would happen.  For llvmpipe, nothing to do.
247     */
248    assert(surf->texture);
249    pipe_resource_reference(&surf->texture, NULL);
250    FREE(surf);
251 }
252 
253 
254 
255 static void
llvmpipe_get_sample_position(struct pipe_context * pipe,unsigned sample_count,unsigned sample_index,float * out_value)256 llvmpipe_get_sample_position(struct pipe_context *pipe,
257                              unsigned sample_count,
258                              unsigned sample_index,
259                              float *out_value)
260 {
261    switch (sample_count) {
262    case 4:
263       out_value[0] = lp_sample_pos_4x[sample_index][0];
264       out_value[1] = lp_sample_pos_4x[sample_index][1];
265       break;
266    default:
267       break;
268    }
269 }
270 
271 static void
lp_clear_color_texture_helper(struct pipe_transfer * dst_trans,ubyte * dst_map,enum pipe_format format,const union pipe_color_union * color,unsigned width,unsigned height,unsigned depth)272 lp_clear_color_texture_helper(struct pipe_transfer *dst_trans,
273                                 ubyte *dst_map,
274                                 enum pipe_format format,
275                                 const union pipe_color_union *color,
276                                 unsigned width, unsigned height, unsigned depth)
277 {
278    union util_color uc;
279 
280    assert(dst_trans->stride > 0);
281 
282    util_pack_color_union(format, &uc, color);
283 
284    util_fill_box(dst_map, format,
285                  dst_trans->stride, dst_trans->layer_stride,
286                  0, 0, 0, width, height, depth, &uc);
287 }
288 
289 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)290 lp_clear_color_texture_msaa(struct pipe_context *pipe,
291                             struct pipe_resource *texture,
292                             enum pipe_format format,
293                             const union pipe_color_union *color,
294                             unsigned sample,
295                             const struct pipe_box *box)
296 {
297    struct pipe_transfer *dst_trans;
298    ubyte *dst_map;
299 
300    dst_map = llvmpipe_transfer_map_ms(pipe, texture, 0, PIPE_MAP_WRITE,
301                                       sample, box, &dst_trans);
302    if (!dst_map)
303       return;
304 
305    if (dst_trans->stride > 0) {
306       lp_clear_color_texture_helper(dst_trans, dst_map, format, color,
307                                     box->width, box->height, box->depth);
308    }
309    pipe->texture_unmap(pipe, dst_trans);
310 }
311 
312 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)313 llvmpipe_clear_render_target(struct pipe_context *pipe,
314                              struct pipe_surface *dst,
315                              const union pipe_color_union *color,
316                              unsigned dstx, unsigned dsty,
317                              unsigned width, unsigned height,
318                              bool render_condition_enabled)
319 {
320    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
321 
322    if (render_condition_enabled && !llvmpipe_check_render_cond(llvmpipe))
323       return;
324 
325    width = MIN2(width, dst->texture->width0 - dstx);
326    height = MIN2(height, dst->texture->height0 - dsty);
327 
328    if (dst->texture->nr_samples > 1) {
329       struct pipe_box box;
330       u_box_2d(dstx, dsty, width, height, &box);
331       if (dst->texture->target != PIPE_BUFFER) {
332          box.z = dst->u.tex.first_layer;
333          box.depth = dst->u.tex.last_layer - dst->u.tex.first_layer + 1;
334       }
335       for (unsigned s = 0; s < util_res_sample_count(dst->texture); s++) {
336          lp_clear_color_texture_msaa(pipe, dst->texture, dst->format,
337                                      color, s, &box);
338       }
339    } else
340       util_clear_render_target(pipe, dst, color,
341                                dstx, dsty, width, height);
342 }
343 
344 
345 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)346 lp_clear_depth_stencil_texture_msaa(struct pipe_context *pipe,
347                                     struct pipe_resource *texture,
348                                     enum pipe_format format,
349                                     unsigned clear_flags,
350                                     uint64_t zstencil, unsigned sample,
351                                     const struct pipe_box *box)
352 {
353    struct pipe_transfer *dst_trans;
354    ubyte *dst_map;
355    boolean need_rmw = FALSE;
356 
357    if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) &&
358        ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) &&
359        util_format_is_depth_and_stencil(format))
360       need_rmw = TRUE;
361 
362    dst_map = llvmpipe_transfer_map_ms(pipe,
363                                       texture,
364                                       0,
365                                       (need_rmw ? PIPE_MAP_READ_WRITE :
366                                        PIPE_MAP_WRITE),
367                                       sample, box, &dst_trans);
368    assert(dst_map);
369    if (!dst_map)
370       return;
371 
372    assert(dst_trans->stride > 0);
373 
374    util_fill_zs_box(dst_map, format, need_rmw, clear_flags,
375 		    dst_trans->stride, dst_trans->layer_stride,
376 		    box->width, box->height, box->depth, zstencil);
377 
378    pipe->texture_unmap(pipe, dst_trans);
379 }
380 
381 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)382 llvmpipe_clear_depth_stencil(struct pipe_context *pipe,
383                              struct pipe_surface *dst,
384                              unsigned clear_flags,
385                              double depth,
386                              unsigned stencil,
387                              unsigned dstx, unsigned dsty,
388                              unsigned width, unsigned height,
389                              bool render_condition_enabled)
390 {
391    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
392 
393    if (render_condition_enabled && !llvmpipe_check_render_cond(llvmpipe))
394       return;
395 
396    width = MIN2(width, dst->texture->width0 - dstx);
397    height = MIN2(height, dst->texture->height0 - dsty);
398 
399    if (dst->texture->nr_samples > 1) {
400       uint64_t zstencil = util_pack64_z_stencil(dst->format, depth, stencil);
401       struct pipe_box box;
402       u_box_2d(dstx, dsty, width, height, &box);
403       if (dst->texture->target != PIPE_BUFFER) {
404          box.z = dst->u.tex.first_layer;
405          box.depth = dst->u.tex.last_layer - dst->u.tex.first_layer + 1;
406       }
407       for (unsigned s = 0; s < util_res_sample_count(dst->texture); s++)
408          lp_clear_depth_stencil_texture_msaa(pipe, dst->texture,
409                                              dst->format, clear_flags,
410                                              zstencil, s, &box);
411    } else
412       util_clear_depth_stencil(pipe, dst, clear_flags,
413                                depth, stencil,
414                                dstx, dsty, width, height);
415 }
416 
417 static void
llvmpipe_clear_texture(struct pipe_context * pipe,struct pipe_resource * tex,unsigned level,const struct pipe_box * box,const void * data)418 llvmpipe_clear_texture(struct pipe_context *pipe,
419                        struct pipe_resource *tex,
420                        unsigned level,
421                        const struct pipe_box *box,
422                        const void *data)
423 {
424    const struct util_format_description *desc =
425           util_format_description(tex->format);
426    if (tex->nr_samples <= 1) {
427       util_clear_texture(pipe, tex, level, box, data);
428       return;
429    }
430    union pipe_color_union color;
431 
432    if (util_format_is_depth_or_stencil(tex->format)) {
433       unsigned clear = 0;
434       float depth = 0.0f;
435       uint8_t stencil = 0;
436       uint64_t zstencil;
437 
438       if (util_format_has_depth(desc)) {
439          clear |= PIPE_CLEAR_DEPTH;
440          util_format_unpack_z_float(tex->format, &depth, data, 1);
441       }
442 
443       if (util_format_has_stencil(desc)) {
444          clear |= PIPE_CLEAR_STENCIL;
445          util_format_unpack_s_8uint(tex->format, &stencil, data, 1);
446       }
447 
448       zstencil = util_pack64_z_stencil(tex->format, depth, stencil);
449 
450       for (unsigned s = 0; s < util_res_sample_count(tex); s++)
451          lp_clear_depth_stencil_texture_msaa(pipe, tex, tex->format, clear, zstencil,
452                                              s, box);
453    } else {
454       util_format_unpack_rgba(tex->format, color.ui, data, 1);
455 
456       for (unsigned s = 0; s < util_res_sample_count(tex); s++) {
457          lp_clear_color_texture_msaa(pipe, tex, tex->format, &color, s,
458                                      box);
459       }
460    }
461 }
462 
463 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)464 llvmpipe_clear_buffer(struct pipe_context *pipe,
465                       struct pipe_resource *res,
466                       unsigned offset,
467                       unsigned size,
468                       const void *clear_value,
469                       int clear_value_size)
470 {
471    struct pipe_transfer *dst_t;
472    struct pipe_box box;
473    char *dst;
474    u_box_1d(offset, size, &box);
475 
476    dst = pipe->buffer_map(pipe,
477                             res,
478                             0,
479                             PIPE_MAP_WRITE,
480                             &box,
481                             &dst_t);
482 
483    switch (clear_value_size) {
484    case 1:
485       memset(dst, *(uint8_t *)clear_value, size);
486       break;
487    case 4:
488       util_memset32(dst, *(uint32_t *)clear_value, size / 4);
489       break;
490    default:
491       for (unsigned i = 0; i < size; i += clear_value_size)
492          memcpy(&dst[i], clear_value, clear_value_size);
493       break;
494    }
495    pipe->buffer_unmap(pipe, dst_t);
496 }
497 
498 void
llvmpipe_init_surface_functions(struct llvmpipe_context * lp)499 llvmpipe_init_surface_functions(struct llvmpipe_context *lp)
500 {
501    lp->pipe.clear_render_target = llvmpipe_clear_render_target;
502    lp->pipe.clear_depth_stencil = llvmpipe_clear_depth_stencil;
503    lp->pipe.create_surface = llvmpipe_create_surface;
504    lp->pipe.surface_destroy = llvmpipe_surface_destroy;
505    /* These are not actually functions dealing with surfaces */
506    lp->pipe.clear_texture = llvmpipe_clear_texture;
507    lp->pipe.clear_buffer = llvmpipe_clear_buffer;
508    lp->pipe.resource_copy_region = lp_resource_copy;
509    lp->pipe.blit = lp_blit;
510    lp->pipe.flush_resource = lp_flush_resource;
511    lp->pipe.get_sample_position = llvmpipe_get_sample_position;
512 }
513