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