r600_blit.c revision 8ac9801669c68c33d9dd35a57baf985a4be49eff
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 134 if (!staging && !texture->dirty_db_mask) 135 return; 136 137 if (rctx->family == CHIP_RV610 || rctx->family == CHIP_RV630 || 138 rctx->family == CHIP_RV620 || rctx->family == CHIP_RV635) 139 depth = 0.0f; 140 141 if (!rctx->db_misc_state.flush_depthstencil_through_cb) { 142 /* Enable decompression in DB_RENDER_CONTROL */ 143 rctx->db_misc_state.flush_depthstencil_through_cb = true; 144 r600_atom_dirty(rctx, &rctx->db_misc_state.atom); 145 } 146 147 for (level = first_level; level <= last_level; level++) { 148 if (!staging && !(texture->dirty_db_mask & (1 << level))) 149 continue; 150 151 /* The smaller the mipmap level, the less layers there are 152 * as far as 3D textures are concerned. */ 153 max_layer = u_max_layer(&texture->resource.b.b, level); 154 checked_last_layer = last_layer < max_layer ? last_layer : max_layer; 155 156 for (layer = first_layer; layer <= checked_last_layer; layer++) { 157 struct pipe_surface *zsurf, *cbsurf, surf_tmpl; 158 159 surf_tmpl.format = texture->real_format; 160 surf_tmpl.u.tex.level = level; 161 surf_tmpl.u.tex.first_layer = layer; 162 surf_tmpl.u.tex.last_layer = layer; 163 surf_tmpl.usage = PIPE_BIND_DEPTH_STENCIL; 164 165 zsurf = ctx->create_surface(ctx, &texture->resource.b.b, &surf_tmpl); 166 167 surf_tmpl.format = flushed_depth_texture->real_format; 168 surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; 169 cbsurf = ctx->create_surface(ctx, 170 (struct pipe_resource*)flushed_depth_texture, &surf_tmpl); 171 172 r600_blitter_begin(ctx, R600_DECOMPRESS); 173 util_blitter_custom_depth_stencil(rctx->blitter, zsurf, cbsurf, rctx->custom_dsa_flush, depth); 174 r600_blitter_end(ctx); 175 176 pipe_surface_reference(&zsurf, NULL); 177 pipe_surface_reference(&cbsurf, NULL); 178 } 179 180 /* The texture will always be dirty if some layers aren't flushed. 181 * I don't think this case can occur though. */ 182 if (!staging && first_layer == 0 && last_layer == max_layer) { 183 texture->dirty_db_mask &= ~(1 << level); 184 } 185 } 186 187 /* reenable compression in DB_RENDER_CONTROL */ 188 rctx->db_misc_state.flush_depthstencil_through_cb = false; 189 r600_atom_dirty(rctx, &rctx->db_misc_state.atom); 190} 191 192void r600_flush_depth_textures(struct r600_context *rctx, 193 struct r600_samplerview_state *textures) 194{ 195 unsigned i; 196 unsigned depth_texture_mask = textures->depth_texture_mask; 197 198 while (depth_texture_mask) { 199 struct pipe_sampler_view *view; 200 struct r600_resource_texture *tex; 201 202 i = u_bit_scan(&depth_texture_mask); 203 204 view = &textures->views[i]->base; 205 assert(view); 206 207 tex = (struct r600_resource_texture *)view->texture; 208 assert(tex->is_depth && !tex->is_flushing_texture); 209 210 r600_blit_uncompress_depth(&rctx->context, tex, NULL, 211 view->u.tex.first_level, 212 view->u.tex.last_level, 213 0, 214 u_max_layer(&tex->resource.b.b, view->u.tex.first_level)); 215 } 216} 217 218static void r600_clear(struct pipe_context *ctx, unsigned buffers, 219 const union pipe_color_union *color, 220 double depth, unsigned stencil) 221{ 222 struct r600_context *rctx = (struct r600_context *)ctx; 223 struct pipe_framebuffer_state *fb = &rctx->framebuffer; 224 225 r600_blitter_begin(ctx, R600_CLEAR); 226 util_blitter_clear(rctx->blitter, fb->width, fb->height, 227 fb->nr_cbufs, buffers, fb->nr_cbufs ? fb->cbufs[0]->format : PIPE_FORMAT_NONE, 228 color, depth, stencil); 229 r600_blitter_end(ctx); 230} 231 232static void r600_clear_render_target(struct pipe_context *ctx, 233 struct pipe_surface *dst, 234 const union pipe_color_union *color, 235 unsigned dstx, unsigned dsty, 236 unsigned width, unsigned height) 237{ 238 struct r600_context *rctx = (struct r600_context *)ctx; 239 240 r600_blitter_begin(ctx, R600_CLEAR_SURFACE); 241 util_blitter_clear_render_target(rctx->blitter, dst, color, 242 dstx, dsty, width, height); 243 r600_blitter_end(ctx); 244} 245 246static void r600_clear_depth_stencil(struct pipe_context *ctx, 247 struct pipe_surface *dst, 248 unsigned clear_flags, 249 double depth, 250 unsigned stencil, 251 unsigned dstx, unsigned dsty, 252 unsigned width, unsigned height) 253{ 254 struct r600_context *rctx = (struct r600_context *)ctx; 255 256 r600_blitter_begin(ctx, R600_CLEAR_SURFACE); 257 util_blitter_clear_depth_stencil(rctx->blitter, dst, clear_flags, depth, stencil, 258 dstx, dsty, width, height); 259 r600_blitter_end(ctx); 260} 261 262static void r600_copy_buffer(struct pipe_context *ctx, 263 struct pipe_resource *dst, 264 unsigned dstx, 265 struct pipe_resource *src, 266 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_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 /* Handle buffers first. */ 358 if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { 359 r600_copy_buffer(ctx, dst, dstx, src, src_box); 360 return; 361 } 362 363 /* This must be done before entering u_blitter to avoid recursion. */ 364 if (rsrc->is_depth && !rsrc->is_flushing_texture) { 365 if (!r600_init_flushed_depth_texture(ctx, src, NULL)) 366 return; /* error */ 367 368 r600_blit_uncompress_depth(ctx, rsrc, NULL, 369 src_level, src_level, 370 src_box->z, src_box->z + src_box->depth - 1); 371 } 372 373 restore_orig[0] = restore_orig[1] = FALSE; 374 375 if (util_format_is_compressed(src->format)) { 376 r600_compressed_to_blittable(src, src_level, &orig_info[0]); 377 restore_orig[0] = TRUE; 378 sbox.x = util_format_get_nblocksx(orig_info[0].format, src_box->x); 379 sbox.y = util_format_get_nblocksy(orig_info[0].format, src_box->y); 380 sbox.z = src_box->z; 381 sbox.width = util_format_get_nblocksx(orig_info[0].format, src_box->width); 382 sbox.height = util_format_get_nblocksy(orig_info[0].format, src_box->height); 383 sbox.depth = src_box->depth; 384 psbox=&sbox; 385 } else 386 psbox=src_box; 387 388 if (util_format_is_compressed(dst->format)) { 389 r600_compressed_to_blittable(dst, dst_level, &orig_info[1]); 390 restore_orig[1] = TRUE; 391 /* translate the dst box as well */ 392 dstx = util_format_get_nblocksx(orig_info[1].format, dstx); 393 dsty = util_format_get_nblocksy(orig_info[1].format, dsty); 394 } 395 396 r600_blitter_begin(ctx, R600_COPY_TEXTURE); 397 util_blitter_copy_texture(rctx->blitter, dst, dst_level, dstx, dsty, dstz, 398 src, src_level, psbox, TRUE); 399 r600_blitter_end(ctx); 400 401 if (restore_orig[0]) 402 r600_reset_blittable_to_compressed(src, src_level, &orig_info[0]); 403 404 if (restore_orig[1]) 405 r600_reset_blittable_to_compressed(dst, dst_level, &orig_info[1]); 406} 407 408void r600_init_blit_functions(struct r600_context *rctx) 409{ 410 rctx->context.clear = r600_clear; 411 rctx->context.clear_render_target = r600_clear_render_target; 412 rctx->context.clear_depth_stencil = r600_clear_depth_stencil; 413 rctx->context.resource_copy_region = r600_resource_copy_region; 414} 415