r600_blit.c revision f67fae0e43fa0909b57b8a07858d37caecd5cbb1
1/* 2 * Copyright 2010 Jerome Glisse <glisse@freedesktop.org> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * on the rights to use, copy, modify, merge, publish, distribute, sub 8 * license, and/or sell copies of the Software, and to permit persons to whom 9 * the Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21 * USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23#include "util/u_surface.h" 24#include "util/u_blitter.h" 25#include "util/u_format.h" 26#include "radeonsi_pipe.h" 27#include "si_state.h" 28 29enum r600_blitter_op /* bitmask */ 30{ 31 R600_SAVE_TEXTURES = 1, 32 R600_SAVE_FRAMEBUFFER = 2, 33 R600_DISABLE_RENDER_COND = 4, 34 35 R600_CLEAR = 0, 36 37 R600_CLEAR_SURFACE = R600_SAVE_FRAMEBUFFER, 38 39 R600_COPY = R600_SAVE_FRAMEBUFFER | R600_SAVE_TEXTURES | 40 R600_DISABLE_RENDER_COND, 41 42 R600_DECOMPRESS = R600_SAVE_FRAMEBUFFER | R600_DISABLE_RENDER_COND, 43}; 44 45static void r600_blitter_begin(struct pipe_context *ctx, enum r600_blitter_op op) 46{ 47 struct r600_context *rctx = (struct r600_context *)ctx; 48 49 r600_context_queries_suspend(rctx); 50 51 util_blitter_save_blend(rctx->blitter, rctx->queued.named.blend); 52 util_blitter_save_depth_stencil_alpha(rctx->blitter, rctx->states[R600_PIPE_STATE_DSA]); 53 if (rctx->states[R600_PIPE_STATE_STENCIL_REF]) { 54 util_blitter_save_stencil_ref(rctx->blitter, &rctx->stencil_ref); 55 } 56 util_blitter_save_rasterizer(rctx->blitter, rctx->queued.named.rasterizer); 57 util_blitter_save_fragment_shader(rctx->blitter, rctx->ps_shader); 58 util_blitter_save_vertex_shader(rctx->blitter, rctx->vs_shader); 59 util_blitter_save_vertex_elements(rctx->blitter, rctx->vertex_elements); 60 if (rctx->queued.named.viewport) { 61 util_blitter_save_viewport(rctx->blitter, &rctx->queued.named.viewport->viewport); 62 } 63 util_blitter_save_vertex_buffers(rctx->blitter, 64 rctx->nr_vertex_buffers, 65 rctx->vertex_buffer); 66 util_blitter_save_so_targets(rctx->blitter, rctx->num_so_targets, 67 (struct pipe_stream_output_target**)rctx->so_targets); 68 69 if (op & R600_SAVE_FRAMEBUFFER) 70 util_blitter_save_framebuffer(rctx->blitter, &rctx->framebuffer); 71 72 if (op & R600_SAVE_TEXTURES) { 73 util_blitter_save_fragment_sampler_states( 74 rctx->blitter, rctx->ps_samplers.n_samplers, 75 (void**)rctx->ps_samplers.samplers); 76 77 util_blitter_save_fragment_sampler_views( 78 rctx->blitter, rctx->ps_samplers.n_views, 79 (struct pipe_sampler_view**)rctx->ps_samplers.views); 80 } 81 82 if ((op & R600_DISABLE_RENDER_COND) && rctx->current_render_cond) { 83 rctx->saved_render_cond = rctx->current_render_cond; 84 rctx->saved_render_cond_mode = rctx->current_render_cond_mode; 85 rctx->context.render_condition(&rctx->context, NULL, 0); 86 } 87 88} 89 90static void r600_blitter_end(struct pipe_context *ctx) 91{ 92 struct r600_context *rctx = (struct r600_context *)ctx; 93 if (rctx->saved_render_cond) { 94 rctx->context.render_condition(&rctx->context, 95 rctx->saved_render_cond, 96 rctx->saved_render_cond_mode); 97 rctx->saved_render_cond = NULL; 98 } 99 r600_context_queries_resume(rctx); 100} 101 102static unsigned u_num_layers(struct pipe_resource *r, unsigned level) 103{ 104 switch (r->target) { 105 case PIPE_TEXTURE_CUBE: 106 return 6; 107 case PIPE_TEXTURE_3D: 108 return u_minify(r->depth0, level); 109 case PIPE_TEXTURE_1D_ARRAY: 110 return r->array_size; 111 case PIPE_TEXTURE_2D_ARRAY: 112 return r->array_size; 113 default: 114 return 1; 115 } 116} 117 118void r600_blit_uncompress_depth(struct pipe_context *ctx, struct r600_resource_texture *texture) 119{ 120 struct r600_context *rctx = (struct r600_context *)ctx; 121 unsigned layer, level; 122 float depth = 1.0f; 123 124 if (!texture->dirty_db) 125 return; 126 127 for (level = 0; level <= texture->resource.b.b.last_level; level++) { 128 unsigned num_layers = u_num_layers(&texture->resource.b.b, level); 129 130 for (layer = 0; layer < num_layers; layer++) { 131 struct pipe_surface *zsurf, *cbsurf, surf_tmpl; 132 133 surf_tmpl.format = texture->real_format; 134 surf_tmpl.u.tex.level = level; 135 surf_tmpl.u.tex.first_layer = layer; 136 surf_tmpl.u.tex.last_layer = layer; 137 surf_tmpl.usage = PIPE_BIND_DEPTH_STENCIL; 138 139 zsurf = ctx->create_surface(ctx, &texture->resource.b.b, &surf_tmpl); 140 141 surf_tmpl.format = texture->flushed_depth_texture->real_format; 142 surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; 143 cbsurf = ctx->create_surface(ctx, 144 (struct pipe_resource*)texture->flushed_depth_texture, &surf_tmpl); 145 146 r600_blitter_begin(ctx, R600_DECOMPRESS); 147 util_blitter_custom_depth_stencil(rctx->blitter, zsurf, cbsurf, rctx->custom_dsa_flush, depth); 148 r600_blitter_end(ctx); 149 150 pipe_surface_reference(&zsurf, NULL); 151 pipe_surface_reference(&cbsurf, NULL); 152 } 153 } 154 155 texture->dirty_db = FALSE; 156} 157 158void r600_flush_depth_textures(struct r600_context *rctx) 159{ 160 unsigned int i; 161 162 /* FIXME: This handles fragment shader textures only. */ 163 164 for (i = 0; i < rctx->ps_samplers.n_views; ++i) { 165 struct si_pipe_sampler_view *view; 166 struct r600_resource_texture *tex; 167 168 view = rctx->ps_samplers.views[i]; 169 if (!view) continue; 170 171 tex = (struct r600_resource_texture *)view->base.texture; 172 if (!tex->depth) 173 continue; 174 175 if (tex->is_flushing_texture) 176 continue; 177 178 r600_blit_uncompress_depth(&rctx->context, tex); 179 } 180 181 /* also check CB here */ 182 for (i = 0; i < rctx->framebuffer.nr_cbufs; i++) { 183 struct r600_resource_texture *tex; 184 tex = (struct r600_resource_texture *)rctx->framebuffer.cbufs[i]->texture; 185 186 if (!tex->depth) 187 continue; 188 189 if (tex->is_flushing_texture) 190 continue; 191 192 r600_blit_uncompress_depth(&rctx->context, tex); 193 } 194} 195 196static void r600_clear(struct pipe_context *ctx, unsigned buffers, 197 const union pipe_color_union *color, 198 double depth, unsigned stencil) 199{ 200 struct r600_context *rctx = (struct r600_context *)ctx; 201 struct pipe_framebuffer_state *fb = &rctx->framebuffer; 202 203 r600_blitter_begin(ctx, R600_CLEAR); 204 util_blitter_clear(rctx->blitter, fb->width, fb->height, 205 fb->nr_cbufs, buffers, fb->nr_cbufs ? fb->cbufs[0]->format : PIPE_FORMAT_NONE, 206 color, depth, stencil); 207 r600_blitter_end(ctx); 208} 209 210static void r600_clear_render_target(struct pipe_context *ctx, 211 struct pipe_surface *dst, 212 const union pipe_color_union *color, 213 unsigned dstx, unsigned dsty, 214 unsigned width, unsigned height) 215{ 216 struct r600_context *rctx = (struct r600_context *)ctx; 217 218 r600_blitter_begin(ctx, R600_CLEAR_SURFACE); 219 util_blitter_clear_render_target(rctx->blitter, dst, color, 220 dstx, dsty, width, height); 221 r600_blitter_end(ctx); 222} 223 224static void r600_clear_depth_stencil(struct pipe_context *ctx, 225 struct pipe_surface *dst, 226 unsigned clear_flags, 227 double depth, 228 unsigned stencil, 229 unsigned dstx, unsigned dsty, 230 unsigned width, unsigned height) 231{ 232 struct r600_context *rctx = (struct r600_context *)ctx; 233 234 r600_blitter_begin(ctx, R600_CLEAR_SURFACE); 235 util_blitter_clear_depth_stencil(rctx->blitter, dst, clear_flags, depth, stencil, 236 dstx, dsty, width, height); 237 r600_blitter_end(ctx); 238} 239 240 241 242/* Copy a block of pixels from one surface to another using HW. */ 243static void r600_hw_copy_region(struct pipe_context *ctx, 244 struct pipe_resource *dst, 245 unsigned dst_level, 246 unsigned dstx, unsigned dsty, unsigned dstz, 247 struct pipe_resource *src, 248 unsigned src_level, 249 const struct pipe_box *src_box) 250{ 251 struct r600_context *rctx = (struct r600_context *)ctx; 252 253 r600_blitter_begin(ctx, R600_COPY); 254 util_blitter_copy_texture(rctx->blitter, dst, dst_level, dstx, dsty, dstz, 255 src, src_level, src_box, TRUE); 256 r600_blitter_end(ctx); 257} 258 259struct texture_orig_info { 260 unsigned format; 261 unsigned width0; 262 unsigned height0; 263 unsigned npix_x; 264 unsigned npix_y; 265 unsigned npix0_x; 266 unsigned npix0_y; 267}; 268 269static void r600_compressed_to_blittable(struct pipe_resource *tex, 270 unsigned level, 271 struct texture_orig_info *orig) 272{ 273 struct r600_resource_texture *rtex = (struct r600_resource_texture*)tex; 274 struct r600_screen *rscreen = (struct r600_screen *)tex->screen; 275 unsigned pixsize = util_format_get_blocksize(rtex->real_format); 276 int new_format; 277 int new_height, new_width; 278 279 orig->format = tex->format; 280 orig->width0 = tex->width0; 281 orig->height0 = tex->height0; 282 orig->npix0_x = rtex->surface.level[0].npix_x; 283 orig->npix0_y = rtex->surface.level[0].npix_y; 284 orig->npix_x = rtex->surface.level[level].npix_x; 285 orig->npix_y = rtex->surface.level[level].npix_y; 286 287 if (pixsize == 8) 288 new_format = PIPE_FORMAT_R16G16B16A16_UINT; /* 64-bit block */ 289 else 290 new_format = PIPE_FORMAT_R32G32B32A32_UINT; /* 128-bit block */ 291 292 new_width = util_format_get_nblocksx(tex->format, orig->width0); 293 new_height = util_format_get_nblocksy(tex->format, orig->height0); 294 295 tex->width0 = new_width; 296 tex->height0 = new_height; 297 tex->format = new_format; 298 rtex->surface.level[0].npix_x = util_format_get_nblocksx(orig->format, orig->npix0_x); 299 rtex->surface.level[0].npix_y = util_format_get_nblocksy(orig->format, orig->npix0_y); 300 rtex->surface.level[level].npix_x = util_format_get_nblocksx(orig->format, orig->npix_x); 301 rtex->surface.level[level].npix_y = util_format_get_nblocksy(orig->format, orig->npix_y); 302} 303 304static void r600_reset_blittable_to_compressed(struct pipe_resource *tex, 305 unsigned level, 306 struct texture_orig_info *orig) 307{ 308 struct r600_resource_texture *rtex = (struct r600_resource_texture*)tex; 309 struct r600_screen *rscreen = (struct r600_screen *)tex->screen; 310 311 tex->format = orig->format; 312 tex->width0 = orig->width0; 313 tex->height0 = orig->height0; 314 rtex->surface.level[0].npix_x = orig->npix0_x; 315 rtex->surface.level[0].npix_y = orig->npix0_y; 316 rtex->surface.level[level].npix_x = orig->npix_x; 317 rtex->surface.level[level].npix_y = orig->npix_y; 318} 319 320static void r600_resource_copy_region(struct pipe_context *ctx, 321 struct pipe_resource *dst, 322 unsigned dst_level, 323 unsigned dstx, unsigned dsty, unsigned dstz, 324 struct pipe_resource *src, 325 unsigned src_level, 326 const struct pipe_box *src_box) 327{ 328 struct r600_resource_texture *rsrc = (struct r600_resource_texture*)src; 329 struct texture_orig_info orig_info[2]; 330 struct pipe_box sbox; 331 const struct pipe_box *psbox; 332 boolean restore_orig[2]; 333 334 memset(orig_info, 0, sizeof(orig_info)); 335 336 /* Fallback for buffers. */ 337 if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { 338 util_resource_copy_region(ctx, dst, dst_level, dstx, dsty, dstz, 339 src, src_level, src_box); 340 return; 341 } 342 343 if (rsrc->depth && !rsrc->is_flushing_texture) 344 r600_texture_depth_flush(ctx, src, FALSE); 345 346 restore_orig[0] = restore_orig[1] = FALSE; 347 348 if (util_format_is_compressed(src->format)) { 349 r600_compressed_to_blittable(src, src_level, &orig_info[0]); 350 restore_orig[0] = TRUE; 351 sbox.x = util_format_get_nblocksx(orig_info[0].format, src_box->x); 352 sbox.y = util_format_get_nblocksy(orig_info[0].format, src_box->y); 353 sbox.z = src_box->z; 354 sbox.width = util_format_get_nblocksx(orig_info[0].format, src_box->width); 355 sbox.height = util_format_get_nblocksy(orig_info[0].format, src_box->height); 356 sbox.depth = src_box->depth; 357 psbox=&sbox; 358 } else 359 psbox=src_box; 360 361 if (util_format_is_compressed(dst->format)) { 362 r600_compressed_to_blittable(dst, dst_level, &orig_info[1]); 363 restore_orig[1] = TRUE; 364 /* translate the dst box as well */ 365 dstx = util_format_get_nblocksx(orig_info[1].format, dstx); 366 dsty = util_format_get_nblocksy(orig_info[1].format, dsty); 367 } 368 369 r600_hw_copy_region(ctx, dst, dst_level, dstx, dsty, dstz, 370 src, src_level, psbox); 371 372 if (restore_orig[0]) 373 r600_reset_blittable_to_compressed(src, src_level, &orig_info[0]); 374 375 if (restore_orig[1]) 376 r600_reset_blittable_to_compressed(dst, dst_level, &orig_info[1]); 377} 378 379void r600_init_blit_functions(struct r600_context *rctx) 380{ 381 rctx->context.clear = r600_clear; 382 rctx->context.clear_render_target = r600_clear_render_target; 383 rctx->context.clear_depth_stencil = r600_clear_depth_stencil; 384 rctx->context.resource_copy_region = r600_resource_copy_region; 385} 386 387void r600_blit_push_depth(struct pipe_context *ctx, struct r600_resource_texture *texture) 388{ 389 struct pipe_box sbox; 390 391 sbox.x = sbox.y = sbox.z = 0; 392 sbox.width = texture->resource.b.b.width0; 393 sbox.height = texture->resource.b.b.height0; 394 /* XXX that might be wrong */ 395 sbox.depth = 1; 396 397 r600_hw_copy_region(ctx, (struct pipe_resource *)texture, 0, 398 0, 0, 0, 399 (struct pipe_resource *)texture->flushed_depth_texture, 0, 400 &sbox); 401} 402