1/* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 2012-2013 LunarG, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Chia-I Wu <olv@lunarg.com> 26 */ 27 28#include "util/u_surface.h" 29 30#include "ilo_blitter.h" 31#include "ilo_context.h" 32#include "ilo_blit.h" 33 34static void 35ilo_resource_copy_region(struct pipe_context *pipe, 36 struct pipe_resource *dst, 37 unsigned dst_level, 38 unsigned dstx, unsigned dsty, unsigned dstz, 39 struct pipe_resource *src, 40 unsigned src_level, 41 const struct pipe_box *src_box) 42{ 43 struct ilo_context *ilo = ilo_context(pipe); 44 45 if (ilo_blitter_blt_copy_resource(ilo->blitter, 46 dst, dst_level, dstx, dsty, dstz, 47 src, src_level, src_box)) 48 return; 49 50 if (ilo_blitter_pipe_copy_resource(ilo->blitter, 51 dst, dst_level, dstx, dsty, dstz, 52 src, src_level, src_box)) 53 return; 54 55 util_resource_copy_region(&ilo->base, dst, dst_level, 56 dstx, dsty, dstz, src, src_level, src_box); 57} 58 59static void 60ilo_clear(struct pipe_context *pipe, 61 unsigned buffers, 62 const union pipe_color_union *color, 63 double depth, 64 unsigned stencil) 65{ 66 struct ilo_context *ilo = ilo_context(pipe); 67 struct ilo_state_vector *vec = &ilo->state_vector; 68 69 if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && vec->fb.state.zsbuf) { 70 if (ilo_blitter_rectlist_clear_zs(ilo->blitter, vec->fb.state.zsbuf, 71 buffers & PIPE_CLEAR_DEPTHSTENCIL, depth, stencil)) 72 buffers &= ~PIPE_CLEAR_DEPTHSTENCIL; 73 74 if (!buffers) 75 return; 76 } 77 78 ilo_blitter_pipe_clear_fb(ilo->blitter, buffers, color, depth, stencil); 79} 80 81static void 82ilo_clear_render_target(struct pipe_context *pipe, 83 struct pipe_surface *dst, 84 const union pipe_color_union *color, 85 unsigned dstx, unsigned dsty, 86 unsigned width, unsigned height, 87 bool render_condition_enabled) 88{ 89 struct ilo_context *ilo = ilo_context(pipe); 90 91 if (!width || !height || dstx >= dst->width || dsty >= dst->height) 92 return; 93 94 if (dstx + width > dst->width) 95 width = dst->width - dstx; 96 if (dsty + height > dst->height) 97 height = dst->height - dsty; 98 99 if (ilo_blitter_blt_clear_rt(ilo->blitter, 100 dst, color, dstx, dsty, width, height)) 101 return; 102 103 ilo_blitter_pipe_clear_rt(ilo->blitter, 104 dst, color, dstx, dsty, width, height); 105} 106 107static void 108ilo_clear_depth_stencil(struct pipe_context *pipe, 109 struct pipe_surface *dst, 110 unsigned clear_flags, 111 double depth, 112 unsigned stencil, 113 unsigned dstx, unsigned dsty, 114 unsigned width, unsigned height, 115 bool render_condition_enabled) 116{ 117 struct ilo_context *ilo = ilo_context(pipe); 118 119 if (!width || !height || dstx >= dst->width || dsty >= dst->height) 120 return; 121 122 if (dstx + width > dst->width) 123 width = dst->width - dstx; 124 if (dsty + height > dst->height) 125 height = dst->height - dsty; 126 127 if (ilo_blitter_blt_clear_zs(ilo->blitter, 128 dst, clear_flags, depth, stencil, dstx, dsty, width, height)) 129 return; 130 131 ilo_blitter_pipe_clear_zs(ilo->blitter, 132 dst, clear_flags, depth, stencil, dstx, dsty, width, height); 133} 134 135static void 136ilo_blit(struct pipe_context *pipe, const struct pipe_blit_info *info) 137{ 138 struct ilo_context *ilo = ilo_context(pipe); 139 140 ilo_blitter_pipe_blit(ilo->blitter, info); 141} 142 143static void 144ilo_flush_resource(struct pipe_context *pipe, struct pipe_resource *res) 145{ 146 struct ilo_context *ilo = ilo_context(pipe); 147 const unsigned flags = ILO_TEXTURE_CPU_READ | 148 ILO_TEXTURE_BLT_READ | 149 ILO_TEXTURE_RENDER_READ; 150 151 ilo_blit_resolve_resource(ilo, res, flags); 152} 153 154void 155ilo_blit_resolve_slices_for_hiz(struct ilo_context *ilo, 156 struct pipe_resource *res, unsigned level, 157 unsigned first_slice, unsigned num_slices, 158 unsigned resolve_flags) 159{ 160 struct ilo_texture *tex = ilo_texture(res); 161 const unsigned any_reader = 162 ILO_TEXTURE_RENDER_READ | 163 ILO_TEXTURE_BLT_READ | 164 ILO_TEXTURE_CPU_READ; 165 const unsigned other_writers = 166 ILO_TEXTURE_BLT_WRITE | 167 ILO_TEXTURE_CPU_WRITE; 168 unsigned i; 169 170 assert(tex->base.target != PIPE_BUFFER && 171 ilo_image_can_enable_aux(&tex->image, level)); 172 173 if (resolve_flags & ILO_TEXTURE_RENDER_WRITE) { 174 /* 175 * When ILO_TEXTURE_RENDER_WRITE is set, there can be no reader. We 176 * need to perform a HiZ Buffer Resolve in case the resource was 177 * previously written by another writer, unless this is a clear. 178 * 179 * When slices have different clear values, we perform a Depth Buffer 180 * Resolve on all slices not sharing the clear value of the first slice. 181 * After resolving, those slices do not use 3DSTATE_CLEAR_PARAMS and can 182 * be made to have the same clear value as the first slice does. This 183 * way, 184 * 185 * - 3DSTATE_CLEAR_PARAMS can be set to the clear value of any slice 186 * - we will not resolve unnecessarily next time this function is 187 * called 188 * 189 * Since slice clear value is the value the slice is cleared to when 190 * ILO_TEXTURE_CLEAR is set, the bit needs to be unset. 191 */ 192 assert(!(resolve_flags & (other_writers | any_reader))); 193 194 if (!(resolve_flags & ILO_TEXTURE_CLEAR)) { 195 const uint32_t first_clear_value = ilo_texture_get_slice(tex, 196 level, first_slice)->clear_value; 197 bool set_clear_value = false; 198 199 for (i = 0; i < num_slices; i++) { 200 const struct ilo_texture_slice *slice = 201 ilo_texture_get_slice(tex, level, first_slice + i); 202 203 if (slice->flags & other_writers) { 204 ilo_blitter_rectlist_resolve_hiz(ilo->blitter, 205 res, level, first_slice + i); 206 } else if (slice->clear_value != first_clear_value && 207 (slice->flags & ILO_TEXTURE_RENDER_WRITE)) { 208 ilo_blitter_rectlist_resolve_z(ilo->blitter, 209 res, level, first_slice + i); 210 set_clear_value = true; 211 } 212 } 213 214 if (set_clear_value) { 215 /* ILO_TEXTURE_CLEAR will be cleared later */ 216 ilo_texture_set_slice_clear_value(tex, level, 217 first_slice, num_slices, first_clear_value); 218 } 219 } 220 } 221 else if ((resolve_flags & any_reader) || 222 ((resolve_flags & other_writers) && 223 !(resolve_flags & ILO_TEXTURE_CLEAR))) { 224 /* 225 * When there is at least a reader or writer, we need to perform a 226 * Depth Buffer Resolve in case the resource was previously written 227 * by ILO_TEXTURE_RENDER_WRITE. 228 */ 229 for (i = 0; i < num_slices; i++) { 230 const struct ilo_texture_slice *slice = 231 ilo_texture_get_slice(tex, level, first_slice + i); 232 233 if (slice->flags & ILO_TEXTURE_RENDER_WRITE) { 234 ilo_blitter_rectlist_resolve_z(ilo->blitter, 235 &tex->base, level, first_slice + i); 236 } 237 } 238 } 239} 240 241/** 242 * Initialize blit-related functions. 243 */ 244void 245ilo_init_blit_functions(struct ilo_context *ilo) 246{ 247 ilo->base.resource_copy_region = ilo_resource_copy_region; 248 ilo->base.blit = ilo_blit; 249 ilo->base.flush_resource = ilo_flush_resource; 250 251 ilo->base.clear = ilo_clear; 252 ilo->base.clear_render_target = ilo_clear_render_target; 253 ilo->base.clear_depth_stencil = ilo_clear_depth_stencil; 254} 255