/** * Clear the given buffers to the specified values. * No masking, no scissor (clear entire buffer). */ void softpipe_clear(struct pipe_context *pipe, unsigned buffers, const union pipe_color_union *color, double depth, unsigned stencil) { struct softpipe_context *softpipe = softpipe_context(pipe); uint64_t cv; uint i; if (softpipe->no_rast) return; if (!softpipe_check_render_cond(softpipe)) return; #if 0 softpipe_update_derived(softpipe, PIPE_PRIM_TRIANGLES); /* not needed?? */ #endif if (buffers & PIPE_CLEAR_COLOR) { for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++) { sp_tile_cache_clear(softpipe->cbuf_cache[i], color, 0); } } if (buffers & PIPE_CLEAR_DEPTHSTENCIL) { static const union pipe_color_union zero; struct pipe_surface *ps = softpipe->framebuffer.zsbuf; cv = util_pack64_z_stencil(ps->format, depth, stencil); sp_tile_cache_clear(softpipe->zsbuf_cache, &zero, cv); } softpipe->dirty_render_cache = TRUE; }
static boolean lp_setup_try_clear_zs(struct lp_setup_context *setup, double depth, unsigned stencil, unsigned flags) { uint64_t zsmask = 0; uint64_t zsvalue = 0; uint32_t zmask32; uint8_t smask8; LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); zmask32 = (flags & PIPE_CLEAR_DEPTH) ? ~0 : 0; smask8 = (flags & PIPE_CLEAR_STENCIL) ? ~0 : 0; zsvalue = util_pack64_z_stencil(setup->fb.zsbuf->format, depth, stencil); zsmask = util_pack64_mask_z_stencil(setup->fb.zsbuf->format, zmask32, smask8); zsvalue &= zsmask; if (setup->state == SETUP_ACTIVE) { struct lp_scene *scene = setup->scene; /* Add the clear to existing scene. In the unusual case where * both color and depth-stencil are being cleared when there's * already been some rendering, we could discard the currently * binned scene and start again, but I don't see that as being * a common usage. */ if (!lp_scene_bin_everywhere(scene, LP_RAST_OP_CLEAR_ZSTENCIL, lp_rast_arg_clearzs(zsvalue, zsmask))) return FALSE; } else { /* Put ourselves into the 'pre-clear' state, specifically to try * and accumulate multiple clears to color and depth_stencil * buffers which the app or state-tracker might issue * separately. */ set_scene_state( setup, SETUP_CLEARED, __FUNCTION__ ); setup->clear.flags |= flags; setup->clear.zsmask |= zsmask; setup->clear.zsvalue = (setup->clear.zsvalue & ~zsmask) | (zsvalue & zsmask); } return TRUE; }
/** * Clear the given buffers to the specified values. * No masking, no scissor (clear entire buffer). */ void softpipe_clear(struct pipe_context *pipe, unsigned buffers, const union pipe_color_union *color, double depth, unsigned stencil) { struct softpipe_context *softpipe = softpipe_context(pipe); struct pipe_surface *zsbuf = softpipe->framebuffer.zsbuf; unsigned zs_buffers = buffers & PIPE_CLEAR_DEPTHSTENCIL; uint64_t cv; uint i; if (softpipe->no_rast) return; if (!softpipe_check_render_cond(softpipe)) return; #if 0 softpipe_update_derived(softpipe, PIPE_PRIM_TRIANGLES); /* not needed?? */ #endif if (buffers & PIPE_CLEAR_COLOR) { for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++) { sp_tile_cache_clear(softpipe->cbuf_cache[i], color, 0); } } if (zs_buffers && util_format_is_depth_and_stencil(zsbuf->texture->format) && zs_buffers != PIPE_CLEAR_DEPTHSTENCIL) { /* Clearing only depth or stencil in a combined depth-stencil buffer. */ util_clear_depth_stencil(pipe, zsbuf, zs_buffers, depth, stencil, 0, 0, zsbuf->width, zsbuf->height); } else if (zs_buffers) { static const union pipe_color_union zero; cv = util_pack64_z_stencil(zsbuf->format, depth, stencil); sp_tile_cache_clear(softpipe->zsbuf_cache, &zero, cv); } softpipe->dirty_render_cache = TRUE; }
/** * Fallback for pipe->clear_stencil() function. * sw fallback doesn't look terribly useful here. * Plus can't use these transfer fallbacks when clearing * multisampled surfaces for instance. */ void util_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) { struct pipe_transfer *dst_trans; ubyte *dst_map; boolean need_rmw = FALSE; if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) && ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && util_format_is_depth_and_stencil(dst->format)) need_rmw = TRUE; assert(dst->texture); if (!dst->texture) return; dst_map = pipe_transfer_map(pipe, dst->texture, dst->u.tex.level, dst->u.tex.first_layer, (need_rmw ? PIPE_TRANSFER_READ_WRITE : PIPE_TRANSFER_WRITE), dstx, dsty, width, height, &dst_trans); assert(dst_map); if (dst_map) { unsigned dst_stride = dst_trans->stride; uint64_t zstencil = util_pack64_z_stencil(dst->texture->format, depth, stencil); unsigned i, j; assert(dst_trans->stride > 0); switch (util_format_get_blocksize(dst->format)) { case 1: assert(dst->format == PIPE_FORMAT_S8_UINT); if(dst_stride == width) memset(dst_map, (uint8_t) zstencil, height * width); else { for (i = 0; i < height; i++) { memset(dst_map, (uint8_t) zstencil, width); dst_map += dst_stride; } } break; case 2: assert(dst->format == PIPE_FORMAT_Z16_UNORM); for (i = 0; i < height; i++) { uint16_t *row = (uint16_t *)dst_map; for (j = 0; j < width; j++) *row++ = (uint16_t) zstencil; dst_map += dst_stride; } break; case 4: if (!need_rmw) { for (i = 0; i < height; i++) { uint32_t *row = (uint32_t *)dst_map; for (j = 0; j < width; j++) *row++ = (uint32_t) zstencil; dst_map += dst_stride; } } else { uint32_t dst_mask; if (dst->format == PIPE_FORMAT_Z24_UNORM_S8_UINT) dst_mask = 0xffffff00; else { assert(dst->format == PIPE_FORMAT_S8_UINT_Z24_UNORM); dst_mask = 0xffffff; } if (clear_flags & PIPE_CLEAR_DEPTH) dst_mask = ~dst_mask; for (i = 0; i < height; i++) { uint32_t *row = (uint32_t *)dst_map; for (j = 0; j < width; j++) { uint32_t tmp = *row & dst_mask; *row++ = tmp | ((uint32_t) zstencil & ~dst_mask); } dst_map += dst_stride; } } break; case 8: if (!need_rmw) { for (i = 0; i < height; i++) { uint64_t *row = (uint64_t *)dst_map; for (j = 0; j < width; j++) *row++ = zstencil; dst_map += dst_stride; } } else { uint64_t src_mask; if (clear_flags & PIPE_CLEAR_DEPTH) src_mask = 0x00000000ffffffffull; else src_mask = 0x000000ff00000000ull; for (i = 0; i < height; i++) { uint64_t *row = (uint64_t *)dst_map; for (j = 0; j < width; j++) { uint64_t tmp = *row & ~src_mask; *row++ = tmp | (zstencil & src_mask); } dst_map += dst_stride; } } break; default: assert(0); break; } pipe->transfer_unmap(pipe, dst_trans); } }