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