r600_blit.c revision 5a17d8318ec2c20bf86275044dc8f715105a88e7
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 "r600_pipe.h" 24#include "util/u_surface.h" 25#include "util/u_blitter.h" 26#include "util/u_format.h" 27 28enum r600_blitter_op /* bitmask */ 29{ 30 R600_SAVE_TEXTURES = 1, 31 R600_SAVE_FRAMEBUFFER = 2, 32 R600_DISABLE_RENDER_COND = 4, 33 34 R600_CLEAR = 0, 35 36 R600_CLEAR_SURFACE = R600_SAVE_FRAMEBUFFER, 37 38 R600_COPY = R600_SAVE_FRAMEBUFFER | R600_SAVE_TEXTURES | 39 R600_DISABLE_RENDER_COND, 40 41 R600_DECOMPRESS = R600_SAVE_FRAMEBUFFER | R600_DISABLE_RENDER_COND, 42}; 43 44static void r600_blitter_begin(struct pipe_context *ctx, enum r600_blitter_op op) 45{ 46 struct r600_context *rctx = (struct r600_context *)ctx; 47 48 r600_suspend_nontimer_queries(rctx); 49 50 util_blitter_save_blend(rctx->blitter, rctx->states[R600_PIPE_STATE_BLEND]); 51 util_blitter_save_depth_stencil_alpha(rctx->blitter, rctx->states[R600_PIPE_STATE_DSA]); 52 if (rctx->states[R600_PIPE_STATE_STENCIL_REF]) { 53 util_blitter_save_stencil_ref(rctx->blitter, &rctx->stencil_ref); 54 } 55 util_blitter_save_rasterizer(rctx->blitter, rctx->states[R600_PIPE_STATE_RASTERIZER]); 56 util_blitter_save_fragment_shader(rctx->blitter, rctx->ps_shader); 57 util_blitter_save_vertex_shader(rctx->blitter, rctx->vs_shader); 58 util_blitter_save_vertex_elements(rctx->blitter, rctx->vertex_elements); 59 if (rctx->states[R600_PIPE_STATE_VIEWPORT]) { 60 util_blitter_save_viewport(rctx->blitter, &rctx->viewport); 61 } 62 util_blitter_save_vertex_buffers(rctx->blitter, 63 rctx->nr_vertex_buffers, 64 rctx->vertex_buffer); 65 util_blitter_save_so_targets(rctx->blitter, rctx->num_so_targets, 66 (struct pipe_stream_output_target**)rctx->so_targets); 67 68 if (op & R600_SAVE_FRAMEBUFFER) 69 util_blitter_save_framebuffer(rctx->blitter, &rctx->framebuffer); 70 71 if (op & R600_SAVE_TEXTURES) { 72 util_blitter_save_fragment_sampler_states( 73 rctx->blitter, rctx->ps_samplers.n_samplers, 74 (void**)rctx->ps_samplers.samplers); 75 76 util_blitter_save_fragment_sampler_views( 77 rctx->blitter, rctx->ps_samplers.n_views, 78 (struct pipe_sampler_view**)rctx->ps_samplers.views); 79 } 80 81 if ((op & R600_DISABLE_RENDER_COND) && rctx->current_render_cond) { 82 rctx->saved_render_cond = rctx->current_render_cond; 83 rctx->saved_render_cond_mode = rctx->current_render_cond_mode; 84 rctx->context.render_condition(&rctx->context, NULL, 0); 85 } 86 87} 88 89static void r600_blitter_end(struct pipe_context *ctx) 90{ 91 struct r600_context *rctx = (struct r600_context *)ctx; 92 if (rctx->saved_render_cond) { 93 rctx->context.render_condition(&rctx->context, 94 rctx->saved_render_cond, 95 rctx->saved_render_cond_mode); 96 rctx->saved_render_cond = NULL; 97 } 98 r600_resume_nontimer_queries(rctx); 99} 100 101static unsigned u_max_layer(struct pipe_resource *r, unsigned level) 102{ 103 switch (r->target) { 104 case PIPE_TEXTURE_CUBE: 105 return 6 - 1; 106 case PIPE_TEXTURE_3D: 107 return u_minify(r->depth0, level) - 1; 108 case PIPE_TEXTURE_1D_ARRAY: 109 case PIPE_TEXTURE_2D_ARRAY: 110 return r->array_size - 1; 111 default: 112 return 0; 113 } 114} 115 116void r600_blit_uncompress_depth(struct pipe_context *ctx, 117 struct r600_resource_texture *texture, 118 struct r600_resource_texture *staging, 119 unsigned first_level, unsigned last_level, 120 unsigned first_layer, unsigned last_layer) 121{ 122 struct r600_context *rctx = (struct r600_context *)ctx; 123 unsigned layer, level, checked_last_layer, max_layer; 124 float depth = 1.0f; 125 struct r600_resource_texture *flushed_depth_texture = staging ? 126 staging : texture->flushed_depth_texture; 127 128 if (!staging && !texture->dirty_db_mask) 129 return; 130 131 if (rctx->family == CHIP_RV610 || rctx->family == CHIP_RV630 || 132 rctx->family == CHIP_RV620 || rctx->family == CHIP_RV635) 133 depth = 0.0f; 134 135 if (rctx->chip_class <= R700 && 136 !rctx->db_misc_state.flush_depthstencil_through_cb) { 137 /* Enable decompression in DB_RENDER_CONTROL */ 138 rctx->db_misc_state.flush_depthstencil_through_cb = true; 139 r600_atom_dirty(rctx, &rctx->db_misc_state.atom); 140 } 141 142 for (level = first_level; level <= last_level; level++) { 143 if (!staging && !(texture->dirty_db_mask & (1 << level))) 144 continue; 145 146 /* The smaller the mipmap level, the less layers there are 147 * as far as 3D textures are concerned. */ 148 max_layer = u_max_layer(&texture->resource.b.b, level); 149 checked_last_layer = last_layer < max_layer ? last_layer : max_layer; 150 151 for (layer = first_layer; layer <= checked_last_layer; layer++) { 152 struct pipe_surface *zsurf, *cbsurf, surf_tmpl; 153 154 surf_tmpl.format = texture->real_format; 155 surf_tmpl.u.tex.level = level; 156 surf_tmpl.u.tex.first_layer = layer; 157 surf_tmpl.u.tex.last_layer = layer; 158 surf_tmpl.usage = PIPE_BIND_DEPTH_STENCIL; 159 160 zsurf = ctx->create_surface(ctx, &texture->resource.b.b, &surf_tmpl); 161 162 surf_tmpl.format = flushed_depth_texture->real_format; 163 surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; 164 cbsurf = ctx->create_surface(ctx, 165 (struct pipe_resource*)flushed_depth_texture, &surf_tmpl); 166 167 r600_blitter_begin(ctx, R600_DECOMPRESS); 168 util_blitter_custom_depth_stencil(rctx->blitter, zsurf, cbsurf, rctx->custom_dsa_flush, depth); 169 r600_blitter_end(ctx); 170 171 pipe_surface_reference(&zsurf, NULL); 172 pipe_surface_reference(&cbsurf, NULL); 173 } 174 175 /* The texture will always be dirty if some layers aren't flushed. 176 * I don't think this case can occur though. */ 177 if (!staging && first_layer == 0 && last_layer == max_layer) { 178 texture->dirty_db_mask &= ~(1 << level); 179 } 180 } 181 182 if (rctx->chip_class <= R700) { 183 /* Disable decompression in DB_RENDER_CONTROL */ 184 rctx->db_misc_state.flush_depthstencil_through_cb = false; 185 r600_atom_dirty(rctx, &rctx->db_misc_state.atom); 186 } 187} 188 189static void r600_flush_depth_textures(struct r600_context *rctx, 190 struct r600_textures_info *textures) 191{ 192 unsigned i; 193 194 for (i = 0; i < textures->n_views; ++i) { 195 struct pipe_sampler_view *view; 196 struct r600_resource_texture *tex; 197 198 view = &textures->views[i]->base; 199 if (!view) continue; 200 201 tex = (struct r600_resource_texture *)view->texture; 202 if (!tex->is_depth || tex->is_flushing_texture) 203 continue; 204 205 r600_blit_uncompress_depth(&rctx->context, tex, NULL, 206 view->u.tex.first_level, 207 view->u.tex.last_level, 208 0, 209 u_max_layer(&tex->resource.b.b, view->u.tex.first_level)); 210 } 211} 212 213void r600_flush_all_depth_textures(struct r600_context *rctx) 214{ 215 unsigned i; 216 217 r600_flush_depth_textures(rctx, &rctx->ps_samplers); 218 r600_flush_depth_textures(rctx, &rctx->vs_samplers); 219 220 /* also check CB here */ 221 for (i = 0; i < rctx->framebuffer.nr_cbufs; i++) { 222 struct r600_resource_texture *tex; 223 struct pipe_surface *surf = rctx->framebuffer.cbufs[i]; 224 tex = (struct r600_resource_texture *)surf->texture; 225 226 if (!tex->is_depth || tex->is_flushing_texture) 227 continue; 228 229 r600_blit_uncompress_depth(&rctx->context, tex, NULL, 230 surf->u.tex.level, 231 surf->u.tex.level, 232 surf->u.tex.first_layer, 233 surf->u.tex.last_layer); 234 } 235} 236 237static void r600_clear(struct pipe_context *ctx, unsigned buffers, 238 const union pipe_color_union *color, 239 double depth, unsigned stencil) 240{ 241 struct r600_context *rctx = (struct r600_context *)ctx; 242 struct pipe_framebuffer_state *fb = &rctx->framebuffer; 243 244 r600_blitter_begin(ctx, R600_CLEAR); 245 util_blitter_clear(rctx->blitter, fb->width, fb->height, 246 fb->nr_cbufs, buffers, fb->nr_cbufs ? fb->cbufs[0]->format : PIPE_FORMAT_NONE, 247 color, depth, stencil); 248 r600_blitter_end(ctx); 249} 250 251static void r600_clear_render_target(struct pipe_context *ctx, 252 struct pipe_surface *dst, 253 const union pipe_color_union *color, 254 unsigned dstx, unsigned dsty, 255 unsigned width, unsigned height) 256{ 257 struct r600_context *rctx = (struct r600_context *)ctx; 258 259 r600_blitter_begin(ctx, R600_CLEAR_SURFACE); 260 util_blitter_clear_render_target(rctx->blitter, dst, color, 261 dstx, dsty, width, height); 262 r600_blitter_end(ctx); 263} 264 265static void r600_clear_depth_stencil(struct pipe_context *ctx, 266 struct pipe_surface *dst, 267 unsigned clear_flags, 268 double depth, 269 unsigned stencil, 270 unsigned dstx, unsigned dsty, 271 unsigned width, unsigned height) 272{ 273 struct r600_context *rctx = (struct r600_context *)ctx; 274 275 r600_blitter_begin(ctx, R600_CLEAR_SURFACE); 276 util_blitter_clear_depth_stencil(rctx->blitter, dst, clear_flags, depth, stencil, 277 dstx, dsty, width, height); 278 r600_blitter_end(ctx); 279} 280 281struct texture_orig_info { 282 unsigned format; 283 unsigned width0; 284 unsigned height0; 285 unsigned npix_x; 286 unsigned npix_y; 287 unsigned npix0_x; 288 unsigned npix0_y; 289}; 290 291static void r600_compressed_to_blittable(struct pipe_resource *tex, 292 unsigned level, 293 struct texture_orig_info *orig) 294{ 295 struct r600_resource_texture *rtex = (struct r600_resource_texture*)tex; 296 unsigned pixsize = util_format_get_blocksize(rtex->real_format); 297 int new_format; 298 int new_height, new_width; 299 300 orig->format = tex->format; 301 orig->width0 = tex->width0; 302 orig->height0 = tex->height0; 303 orig->npix0_x = rtex->surface.level[0].npix_x; 304 orig->npix0_y = rtex->surface.level[0].npix_y; 305 orig->npix_x = rtex->surface.level[level].npix_x; 306 orig->npix_y = rtex->surface.level[level].npix_y; 307 308 if (pixsize == 8) 309 new_format = PIPE_FORMAT_R16G16B16A16_UINT; /* 64-bit block */ 310 else 311 new_format = PIPE_FORMAT_R32G32B32A32_UINT; /* 128-bit block */ 312 313 new_width = util_format_get_nblocksx(tex->format, orig->width0); 314 new_height = util_format_get_nblocksy(tex->format, orig->height0); 315 316 tex->width0 = new_width; 317 tex->height0 = new_height; 318 tex->format = new_format; 319 rtex->surface.level[0].npix_x = util_format_get_nblocksx(orig->format, orig->npix0_x); 320 rtex->surface.level[0].npix_y = util_format_get_nblocksy(orig->format, orig->npix0_y); 321 rtex->surface.level[level].npix_x = util_format_get_nblocksx(orig->format, orig->npix_x); 322 rtex->surface.level[level].npix_y = util_format_get_nblocksy(orig->format, orig->npix_y); 323} 324 325static void r600_reset_blittable_to_compressed(struct pipe_resource *tex, 326 unsigned level, 327 struct texture_orig_info *orig) 328{ 329 struct r600_resource_texture *rtex = (struct r600_resource_texture*)tex; 330 331 tex->format = orig->format; 332 tex->width0 = orig->width0; 333 tex->height0 = orig->height0; 334 rtex->surface.level[0].npix_x = orig->npix0_x; 335 rtex->surface.level[0].npix_y = orig->npix0_y; 336 rtex->surface.level[level].npix_x = orig->npix_x; 337 rtex->surface.level[level].npix_y = orig->npix_y; 338} 339 340static void r600_resource_copy_region(struct pipe_context *ctx, 341 struct pipe_resource *dst, 342 unsigned dst_level, 343 unsigned dstx, unsigned dsty, unsigned dstz, 344 struct pipe_resource *src, 345 unsigned src_level, 346 const struct pipe_box *src_box) 347{ 348 struct r600_context *rctx = (struct r600_context *)ctx; 349 struct r600_resource_texture *rsrc = (struct r600_resource_texture*)src; 350 struct texture_orig_info orig_info[2]; 351 struct pipe_box sbox; 352 const struct pipe_box *psbox; 353 boolean restore_orig[2]; 354 355 memset(orig_info, 0, sizeof(orig_info)); 356 357 /* Fallback for buffers. */ 358 if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { 359 util_resource_copy_region(ctx, dst, dst_level, dstx, dsty, dstz, 360 src, src_level, src_box); 361 return; 362 } 363 364 if (rsrc->is_depth && !rsrc->is_flushing_texture) 365 r600_texture_depth_flush(ctx, src, NULL, 366 src_level, src_level, 367 src_box->z, src_box->z + src_box->depth - 1); 368 369 restore_orig[0] = restore_orig[1] = FALSE; 370 371 if (util_format_is_compressed(src->format)) { 372 r600_compressed_to_blittable(src, src_level, &orig_info[0]); 373 restore_orig[0] = TRUE; 374 sbox.x = util_format_get_nblocksx(orig_info[0].format, src_box->x); 375 sbox.y = util_format_get_nblocksy(orig_info[0].format, src_box->y); 376 sbox.z = src_box->z; 377 sbox.width = util_format_get_nblocksx(orig_info[0].format, src_box->width); 378 sbox.height = util_format_get_nblocksy(orig_info[0].format, src_box->height); 379 sbox.depth = src_box->depth; 380 psbox=&sbox; 381 } else 382 psbox=src_box; 383 384 if (util_format_is_compressed(dst->format)) { 385 r600_compressed_to_blittable(dst, dst_level, &orig_info[1]); 386 restore_orig[1] = TRUE; 387 /* translate the dst box as well */ 388 dstx = util_format_get_nblocksx(orig_info[1].format, dstx); 389 dsty = util_format_get_nblocksy(orig_info[1].format, dsty); 390 } 391 392 r600_blitter_begin(ctx, R600_COPY); 393 util_blitter_copy_texture(rctx->blitter, dst, dst_level, dstx, dsty, dstz, 394 src, src_level, psbox, TRUE); 395 r600_blitter_end(ctx); 396 397 if (restore_orig[0]) 398 r600_reset_blittable_to_compressed(src, src_level, &orig_info[0]); 399 400 if (restore_orig[1]) 401 r600_reset_blittable_to_compressed(dst, dst_level, &orig_info[1]); 402} 403 404void r600_init_blit_functions(struct r600_context *rctx) 405{ 406 rctx->context.clear = r600_clear; 407 rctx->context.clear_render_target = r600_clear_render_target; 408 rctx->context.clear_depth_stencil = r600_clear_depth_stencil; 409 rctx->context.resource_copy_region = r600_resource_copy_region; 410} 411