r600_blit.c revision 7c371f46958910dd2ca9487c89af1b72bbfdada9
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_FRAGMENT_STATE = 1, 31 R600_SAVE_TEXTURES = 2, 32 R600_SAVE_FRAMEBUFFER = 4, 33 R600_DISABLE_RENDER_COND = 8, 34 35 R600_CLEAR = R600_SAVE_FRAGMENT_STATE, 36 37 R600_CLEAR_SURFACE = R600_SAVE_FRAGMENT_STATE | R600_SAVE_FRAMEBUFFER, 38 39 R600_COPY_BUFFER = R600_DISABLE_RENDER_COND, 40 41 R600_COPY_TEXTURE = R600_SAVE_FRAGMENT_STATE | R600_SAVE_FRAMEBUFFER | R600_SAVE_TEXTURES | 42 R600_DISABLE_RENDER_COND, 43 44 R600_DECOMPRESS = R600_SAVE_FRAGMENT_STATE | R600_SAVE_FRAMEBUFFER | R600_DISABLE_RENDER_COND, 45}; 46 47static void r600_blitter_begin(struct pipe_context *ctx, enum r600_blitter_op op) 48{ 49 struct r600_context *rctx = (struct r600_context *)ctx; 50 51 r600_suspend_nontimer_queries(rctx); 52 53 util_blitter_save_vertex_buffers(rctx->blitter, 54 util_last_bit(rctx->vertex_buffer_state.enabled_mask), 55 rctx->vertex_buffer_state.vb); 56 util_blitter_save_vertex_elements(rctx->blitter, rctx->vertex_elements); 57 util_blitter_save_vertex_shader(rctx->blitter, rctx->vs_shader); 58 util_blitter_save_so_targets(rctx->blitter, rctx->num_so_targets, 59 (struct pipe_stream_output_target**)rctx->so_targets); 60 util_blitter_save_rasterizer(rctx->blitter, rctx->states[R600_PIPE_STATE_RASTERIZER]); 61 62 if (op & R600_SAVE_FRAGMENT_STATE) { 63 if (rctx->states[R600_PIPE_STATE_VIEWPORT]) { 64 util_blitter_save_viewport(rctx->blitter, &rctx->viewport); 65 } 66 util_blitter_save_fragment_shader(rctx->blitter, rctx->ps_shader); 67 util_blitter_save_blend(rctx->blitter, rctx->states[R600_PIPE_STATE_BLEND]); 68 util_blitter_save_depth_stencil_alpha(rctx->blitter, rctx->states[R600_PIPE_STATE_DSA]); 69 if (rctx->states[R600_PIPE_STATE_STENCIL_REF]) { 70 util_blitter_save_stencil_ref(rctx->blitter, &rctx->stencil_ref); 71 } 72 } 73 74 if (op & R600_SAVE_FRAMEBUFFER) 75 util_blitter_save_framebuffer(rctx->blitter, &rctx->framebuffer); 76 77 if (op & R600_SAVE_TEXTURES) { 78 util_blitter_save_fragment_sampler_states( 79 rctx->blitter, rctx->ps_samplers.n_samplers, 80 (void**)rctx->ps_samplers.samplers); 81 82 util_blitter_save_fragment_sampler_views( 83 rctx->blitter, util_last_bit(rctx->ps_samplers.views.enabled_mask), 84 (struct pipe_sampler_view**)rctx->ps_samplers.views.views); 85 } 86 87 if ((op & R600_DISABLE_RENDER_COND) && rctx->current_render_cond) { 88 rctx->saved_render_cond = rctx->current_render_cond; 89 rctx->saved_render_cond_mode = rctx->current_render_cond_mode; 90 rctx->context.render_condition(&rctx->context, NULL, 0); 91 } 92 93} 94 95static void r600_blitter_end(struct pipe_context *ctx) 96{ 97 struct r600_context *rctx = (struct r600_context *)ctx; 98 if (rctx->saved_render_cond) { 99 rctx->context.render_condition(&rctx->context, 100 rctx->saved_render_cond, 101 rctx->saved_render_cond_mode); 102 rctx->saved_render_cond = NULL; 103 } 104 r600_resume_nontimer_queries(rctx); 105} 106 107static unsigned u_max_layer(struct pipe_resource *r, unsigned level) 108{ 109 switch (r->target) { 110 case PIPE_TEXTURE_CUBE: 111 return 6 - 1; 112 case PIPE_TEXTURE_3D: 113 return u_minify(r->depth0, level) - 1; 114 case PIPE_TEXTURE_1D_ARRAY: 115 case PIPE_TEXTURE_2D_ARRAY: 116 return r->array_size - 1; 117 default: 118 return 0; 119 } 120} 121 122void r600_blit_uncompress_depth(struct pipe_context *ctx, 123 struct r600_resource_texture *texture, 124 struct r600_resource_texture *staging, 125 unsigned first_level, unsigned last_level, 126 unsigned first_layer, unsigned last_layer) 127{ 128 struct r600_context *rctx = (struct r600_context *)ctx; 129 unsigned layer, level, checked_last_layer, max_layer; 130 float depth = 1.0f; 131 struct r600_resource_texture *flushed_depth_texture = staging ? 132 staging : texture->flushed_depth_texture; 133 const struct util_format_description *desc = 134 util_format_description(texture->resource.b.b.format); 135 136 if (!staging && !texture->dirty_db_mask) 137 return; 138 139 if (rctx->family == CHIP_RV610 || rctx->family == CHIP_RV630 || 140 rctx->family == CHIP_RV620 || rctx->family == CHIP_RV635) 141 depth = 0.0f; 142 143 /* Enable decompression in DB_RENDER_CONTROL */ 144 rctx->db_misc_state.flush_depthstencil_through_cb = true; 145 rctx->db_misc_state.copy_depth = util_format_has_depth(desc); 146 rctx->db_misc_state.copy_stencil = util_format_has_stencil(desc); 147 r600_atom_dirty(rctx, &rctx->db_misc_state.atom); 148 149 for (level = first_level; level <= last_level; level++) { 150 if (!staging && !(texture->dirty_db_mask & (1 << level))) 151 continue; 152 153 /* The smaller the mipmap level, the less layers there are 154 * as far as 3D textures are concerned. */ 155 max_layer = u_max_layer(&texture->resource.b.b, level); 156 checked_last_layer = last_layer < max_layer ? last_layer : max_layer; 157 158 for (layer = first_layer; layer <= checked_last_layer; layer++) { 159 struct pipe_surface *zsurf, *cbsurf, surf_tmpl; 160 161 surf_tmpl.format = texture->real_format; 162 surf_tmpl.u.tex.level = level; 163 surf_tmpl.u.tex.first_layer = layer; 164 surf_tmpl.u.tex.last_layer = layer; 165 surf_tmpl.usage = PIPE_BIND_DEPTH_STENCIL; 166 167 zsurf = ctx->create_surface(ctx, &texture->resource.b.b, &surf_tmpl); 168 169 surf_tmpl.format = flushed_depth_texture->real_format; 170 surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; 171 cbsurf = ctx->create_surface(ctx, 172 (struct pipe_resource*)flushed_depth_texture, &surf_tmpl); 173 174 r600_blitter_begin(ctx, R600_DECOMPRESS); 175 util_blitter_custom_depth_stencil(rctx->blitter, zsurf, cbsurf, rctx->custom_dsa_flush, depth); 176 r600_blitter_end(ctx); 177 178 pipe_surface_reference(&zsurf, NULL); 179 pipe_surface_reference(&cbsurf, NULL); 180 } 181 182 /* The texture will always be dirty if some layers aren't flushed. 183 * I don't think this case can occur though. */ 184 if (!staging && first_layer == 0 && last_layer == max_layer) { 185 texture->dirty_db_mask &= ~(1 << level); 186 } 187 } 188 189 /* reenable compression in DB_RENDER_CONTROL */ 190 rctx->db_misc_state.flush_depthstencil_through_cb = false; 191 r600_atom_dirty(rctx, &rctx->db_misc_state.atom); 192} 193 194void r600_flush_depth_textures(struct r600_context *rctx, 195 struct r600_samplerview_state *textures) 196{ 197 unsigned i; 198 unsigned depth_texture_mask = textures->depth_texture_mask; 199 200 while (depth_texture_mask) { 201 struct pipe_sampler_view *view; 202 struct r600_resource_texture *tex; 203 204 i = u_bit_scan(&depth_texture_mask); 205 206 view = &textures->views[i]->base; 207 assert(view); 208 209 tex = (struct r600_resource_texture *)view->texture; 210 assert(tex->is_depth && !tex->is_flushing_texture); 211 212 r600_blit_uncompress_depth(&rctx->context, tex, NULL, 213 view->u.tex.first_level, 214 view->u.tex.last_level, 215 0, 216 u_max_layer(&tex->resource.b.b, view->u.tex.first_level)); 217 } 218} 219 220static void r600_clear(struct pipe_context *ctx, unsigned buffers, 221 const union pipe_color_union *color, 222 double depth, unsigned stencil) 223{ 224 struct r600_context *rctx = (struct r600_context *)ctx; 225 struct pipe_framebuffer_state *fb = &rctx->framebuffer; 226 227 r600_blitter_begin(ctx, R600_CLEAR); 228 util_blitter_clear(rctx->blitter, fb->width, fb->height, 229 fb->nr_cbufs, buffers, fb->nr_cbufs ? fb->cbufs[0]->format : PIPE_FORMAT_NONE, 230 color, depth, stencil); 231 r600_blitter_end(ctx); 232} 233 234static void r600_clear_render_target(struct pipe_context *ctx, 235 struct pipe_surface *dst, 236 const union pipe_color_union *color, 237 unsigned dstx, unsigned dsty, 238 unsigned width, unsigned height) 239{ 240 struct r600_context *rctx = (struct r600_context *)ctx; 241 242 r600_blitter_begin(ctx, R600_CLEAR_SURFACE); 243 util_blitter_clear_render_target(rctx->blitter, dst, color, 244 dstx, dsty, width, height); 245 r600_blitter_end(ctx); 246} 247 248static void r600_clear_depth_stencil(struct pipe_context *ctx, 249 struct pipe_surface *dst, 250 unsigned clear_flags, 251 double depth, 252 unsigned stencil, 253 unsigned dstx, unsigned dsty, 254 unsigned width, unsigned height) 255{ 256 struct r600_context *rctx = (struct r600_context *)ctx; 257 258 r600_blitter_begin(ctx, R600_CLEAR_SURFACE); 259 util_blitter_clear_depth_stencil(rctx->blitter, dst, clear_flags, depth, stencil, 260 dstx, dsty, width, height); 261 r600_blitter_end(ctx); 262} 263 264void r600_copy_buffer(struct pipe_context *ctx, struct 265 pipe_resource *dst, unsigned dstx, 266 struct pipe_resource *src, const struct pipe_box *src_box) 267{ 268 struct r600_context *rctx = (struct r600_context*)ctx; 269 270 if (rctx->screen->has_streamout && 271 /* Require dword alignment. */ 272 dstx % 4 == 0 && src_box->x % 4 == 0 && src_box->width % 4 == 0) { 273 r600_blitter_begin(ctx, R600_COPY_BUFFER); 274 util_blitter_copy_buffer(rctx->blitter, dst, dstx, src, src_box->x, src_box->width); 275 r600_blitter_end(ctx); 276 } else { 277 util_resource_copy_region(ctx, dst, 0, dstx, 0, 0, src, 0, src_box); 278 } 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_change_format(struct pipe_resource *tex, 326 unsigned level, 327 struct texture_orig_info *orig, 328 enum pipe_format format) 329{ 330 struct r600_resource_texture *rtex = (struct r600_resource_texture*)tex; 331 332 orig->format = tex->format; 333 orig->width0 = tex->width0; 334 orig->height0 = tex->height0; 335 orig->npix0_x = rtex->surface.level[0].npix_x; 336 orig->npix0_y = rtex->surface.level[0].npix_y; 337 orig->npix_x = rtex->surface.level[level].npix_x; 338 orig->npix_y = rtex->surface.level[level].npix_y; 339 340 tex->format = format; 341} 342 343static void r600_reset_blittable_to_orig(struct pipe_resource *tex, 344 unsigned level, 345 struct texture_orig_info *orig) 346{ 347 struct r600_resource_texture *rtex = (struct r600_resource_texture*)tex; 348 349 tex->format = orig->format; 350 tex->width0 = orig->width0; 351 tex->height0 = orig->height0; 352 rtex->surface.level[0].npix_x = orig->npix0_x; 353 rtex->surface.level[0].npix_y = orig->npix0_y; 354 rtex->surface.level[level].npix_x = orig->npix_x; 355 rtex->surface.level[level].npix_y = orig->npix_y; 356} 357 358static void r600_resource_copy_region(struct pipe_context *ctx, 359 struct pipe_resource *dst, 360 unsigned dst_level, 361 unsigned dstx, unsigned dsty, unsigned dstz, 362 struct pipe_resource *src, 363 unsigned src_level, 364 const struct pipe_box *src_box) 365{ 366 struct r600_context *rctx = (struct r600_context *)ctx; 367 struct r600_resource_texture *rsrc = (struct r600_resource_texture*)src; 368 struct texture_orig_info orig_info[2]; 369 struct pipe_box sbox; 370 const struct pipe_box *psbox = src_box; 371 boolean restore_orig[2]; 372 373 memset(orig_info, 0, sizeof(orig_info)); 374 375 /* Handle buffers first. */ 376 if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { 377 r600_copy_buffer(ctx, dst, dstx, src, src_box); 378 return; 379 } 380 381 /* This must be done before entering u_blitter to avoid recursion. */ 382 if (rsrc->is_depth && !rsrc->is_flushing_texture) { 383 if (!r600_init_flushed_depth_texture(ctx, src, NULL)) 384 return; /* error */ 385 386 r600_blit_uncompress_depth(ctx, rsrc, NULL, 387 src_level, src_level, 388 src_box->z, src_box->z + src_box->depth - 1); 389 } 390 391 restore_orig[0] = restore_orig[1] = FALSE; 392 393 if (util_format_is_compressed(src->format) && 394 util_format_is_compressed(dst->format)) { 395 r600_compressed_to_blittable(src, src_level, &orig_info[0]); 396 restore_orig[0] = TRUE; 397 sbox.x = util_format_get_nblocksx(orig_info[0].format, src_box->x); 398 sbox.y = util_format_get_nblocksy(orig_info[0].format, src_box->y); 399 sbox.z = src_box->z; 400 sbox.width = util_format_get_nblocksx(orig_info[0].format, src_box->width); 401 sbox.height = util_format_get_nblocksy(orig_info[0].format, src_box->height); 402 sbox.depth = src_box->depth; 403 psbox=&sbox; 404 405 r600_compressed_to_blittable(dst, dst_level, &orig_info[1]); 406 restore_orig[1] = TRUE; 407 /* translate the dst box as well */ 408 dstx = util_format_get_nblocksx(orig_info[1].format, dstx); 409 dsty = util_format_get_nblocksy(orig_info[1].format, dsty); 410 } else if (!util_blitter_is_copy_supported(rctx->blitter, dst, src, 411 PIPE_MASK_RGBAZS)) { 412 unsigned blocksize = util_format_get_blocksize(src->format); 413 414 switch (blocksize) { 415 case 1: 416 r600_change_format(src, src_level, &orig_info[0], 417 PIPE_FORMAT_R8_UNORM); 418 r600_change_format(dst, dst_level, &orig_info[1], 419 PIPE_FORMAT_R8_UNORM); 420 break; 421 case 4: 422 r600_change_format(src, src_level, &orig_info[0], 423 PIPE_FORMAT_R8G8B8A8_UNORM); 424 r600_change_format(dst, dst_level, &orig_info[1], 425 PIPE_FORMAT_R8G8B8A8_UNORM); 426 break; 427 default: 428 fprintf(stderr, "Unhandled format %s with blocksize %u\n", 429 util_format_short_name(src->format), blocksize); 430 assert(0); 431 } 432 restore_orig[0] = TRUE; 433 restore_orig[1] = TRUE; 434 } 435 436 r600_blitter_begin(ctx, R600_COPY_TEXTURE); 437 util_blitter_copy_texture(rctx->blitter, dst, dst_level, dstx, dsty, dstz, 438 src, src_level, psbox); 439 r600_blitter_end(ctx); 440 441 if (restore_orig[0]) 442 r600_reset_blittable_to_orig(src, src_level, &orig_info[0]); 443 444 if (restore_orig[1]) 445 r600_reset_blittable_to_orig(dst, dst_level, &orig_info[1]); 446} 447 448void r600_init_blit_functions(struct r600_context *rctx) 449{ 450 rctx->context.clear = r600_clear; 451 rctx->context.clear_render_target = r600_clear_render_target; 452 rctx->context.clear_depth_stencil = r600_clear_depth_stencil; 453 rctx->context.resource_copy_region = r600_resource_copy_region; 454} 455