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 39static void 40lp_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->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} 84static void 85lp_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 116static 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 176static void 177lp_flush_resource(struct pipe_context *ctx, struct pipe_resource *resource) 178{ 179} 180 181 182static struct pipe_surface * 183llvmpipe_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 229static void 230llvmpipe_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 244static void 245llvmpipe_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 260static void 261lp_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 278static void 279lp_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->texture_unmap(pipe, dst_trans); 299} 300 301static void 302llvmpipe_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 331static void 332lp_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->texture_unmap(pipe, dst_trans); 365} 366 367static void 368llvmpipe_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 400static void 401llvmpipe_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 446static void 447llvmpipe_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->buffer_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->buffer_unmap(pipe, dst_t); 479} 480 481void 482llvmpipe_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