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