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