r600_blit.c revision 7684808f9ce2da944be3ca9cc1ac4661d9b167fb
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 "r600_pipe.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_pipe_context *rctx = (struct r600_pipe_context *)ctx; 47 48 r600_context_queries_suspend(&rctx->ctx); 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 if (rctx->states[R600_PIPE_STATE_CLIP]) { 63 util_blitter_save_clip(rctx->blitter, &rctx->clip); 64 } 65 util_blitter_save_vertex_buffers(rctx->blitter, 66 rctx->vbuf_mgr->nr_vertex_buffers, 67 rctx->vbuf_mgr->vertex_buffer); 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_pipe_context *rctx = (struct r600_pipe_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->ctx); 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_pipe_context *rctx = (struct r600_pipe_context *)ctx; 121 unsigned layer, level; 122 float depth = 1.0f; 123 124 if (!texture->dirty_db) 125 return; 126 127 if (rctx->family == CHIP_RV610 || rctx->family == CHIP_RV630 || 128 rctx->family == CHIP_RV620 || rctx->family == CHIP_RV635) 129 depth = 0.0f; 130 131 for (level = 0; level <= texture->resource.b.b.b.last_level; level++) { 132 unsigned num_layers = u_num_layers(&texture->resource.b.b.b, level); 133 134 for (layer = 0; layer < num_layers; layer++) { 135 struct pipe_surface *zsurf, *cbsurf, surf_tmpl; 136 137 surf_tmpl.format = texture->real_format; 138 surf_tmpl.u.tex.level = level; 139 surf_tmpl.u.tex.first_layer = layer; 140 surf_tmpl.u.tex.last_layer = layer; 141 surf_tmpl.usage = PIPE_BIND_DEPTH_STENCIL; 142 143 zsurf = ctx->create_surface(ctx, &texture->resource.b.b.b, &surf_tmpl); 144 145 surf_tmpl.format = texture->flushed_depth_texture->real_format; 146 surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; 147 cbsurf = ctx->create_surface(ctx, 148 (struct pipe_resource*)texture->flushed_depth_texture, &surf_tmpl); 149 150 r600_blitter_begin(ctx, R600_DECOMPRESS); 151 util_blitter_custom_depth_stencil(rctx->blitter, zsurf, cbsurf, rctx->custom_dsa_flush, depth); 152 r600_blitter_end(ctx); 153 154 pipe_surface_reference(&zsurf, NULL); 155 pipe_surface_reference(&cbsurf, NULL); 156 } 157 } 158 159 texture->dirty_db = FALSE; 160} 161 162void r600_flush_depth_textures(struct r600_pipe_context *rctx) 163{ 164 unsigned int i; 165 166 /* FIXME: This handles fragment shader textures only. */ 167 168 for (i = 0; i < rctx->ps_samplers.n_views; ++i) { 169 struct r600_pipe_sampler_view *view; 170 struct r600_resource_texture *tex; 171 172 view = rctx->ps_samplers.views[i]; 173 if (!view) continue; 174 175 tex = (struct r600_resource_texture *)view->base.texture; 176 if (!tex->depth) 177 continue; 178 179 if (tex->is_flushing_texture) 180 continue; 181 182 r600_blit_uncompress_depth(&rctx->context, tex); 183 } 184 185 /* also check CB here */ 186 for (i = 0; i < rctx->framebuffer.nr_cbufs; i++) { 187 struct r600_resource_texture *tex; 188 tex = (struct r600_resource_texture *)rctx->framebuffer.cbufs[i]->texture; 189 190 if (!tex->depth) 191 continue; 192 193 if (tex->is_flushing_texture) 194 continue; 195 196 r600_blit_uncompress_depth(&rctx->context, tex); 197 } 198} 199 200static void r600_clear(struct pipe_context *ctx, unsigned buffers, 201 const union pipe_color_union *color, 202 double depth, unsigned stencil) 203{ 204 struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; 205 struct pipe_framebuffer_state *fb = &rctx->framebuffer; 206 207 r600_blitter_begin(ctx, R600_CLEAR); 208 util_blitter_clear(rctx->blitter, fb->width, fb->height, 209 fb->nr_cbufs, buffers, fb->nr_cbufs ? fb->cbufs[0]->format : PIPE_FORMAT_NONE, 210 color, depth, stencil); 211 r600_blitter_end(ctx); 212} 213 214static void r600_clear_render_target(struct pipe_context *ctx, 215 struct pipe_surface *dst, 216 const union pipe_color_union *color, 217 unsigned dstx, unsigned dsty, 218 unsigned width, unsigned height) 219{ 220 struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; 221 222 r600_blitter_begin(ctx, R600_CLEAR_SURFACE); 223 util_blitter_clear_render_target(rctx->blitter, dst, color, 224 dstx, dsty, width, height); 225 r600_blitter_end(ctx); 226} 227 228static void r600_clear_depth_stencil(struct pipe_context *ctx, 229 struct pipe_surface *dst, 230 unsigned clear_flags, 231 double depth, 232 unsigned stencil, 233 unsigned dstx, unsigned dsty, 234 unsigned width, unsigned height) 235{ 236 struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; 237 238 r600_blitter_begin(ctx, R600_CLEAR_SURFACE); 239 util_blitter_clear_depth_stencil(rctx->blitter, dst, clear_flags, depth, stencil, 240 dstx, dsty, width, height); 241 r600_blitter_end(ctx); 242} 243 244 245 246/* Copy a block of pixels from one surface to another using HW. */ 247static void r600_hw_copy_region(struct pipe_context *ctx, 248 struct pipe_resource *dst, 249 unsigned dst_level, 250 unsigned dstx, unsigned dsty, unsigned dstz, 251 struct pipe_resource *src, 252 unsigned src_level, 253 const struct pipe_box *src_box) 254{ 255 struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; 256 257 r600_blitter_begin(ctx, R600_COPY); 258 util_blitter_copy_texture(rctx->blitter, dst, dst_level, dstx, dsty, dstz, 259 src, src_level, src_box, TRUE); 260 r600_blitter_end(ctx); 261} 262 263struct texture_orig_info { 264 unsigned format; 265 unsigned width0; 266 unsigned height0; 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 unsigned pixsize = util_format_get_blocksize(rtex->real_format); 275 int new_format; 276 int new_height, new_width; 277 278 orig->format = tex->format; 279 orig->width0 = tex->width0; 280 orig->height0 = tex->height0; 281 282 if (pixsize == 8) 283 new_format = PIPE_FORMAT_R16G16B16A16_UINT; /* 64-bit block */ 284 else 285 new_format = PIPE_FORMAT_R32G32B32A32_UINT; /* 128-bit block */ 286 287 new_width = util_format_get_nblocksx(tex->format, orig->width0); 288 new_height = util_format_get_nblocksy(tex->format, orig->height0); 289 290 tex->width0 = new_width; 291 tex->height0 = new_height; 292 tex->format = new_format; 293} 294 295static void r600_reset_blittable_to_compressed(struct pipe_resource *tex, 296 struct texture_orig_info *orig) 297{ 298 tex->format = orig->format; 299 tex->width0 = orig->width0; 300 tex->height0 = orig->height0; 301} 302 303static void r600_resource_copy_region(struct pipe_context *ctx, 304 struct pipe_resource *dst, 305 unsigned dst_level, 306 unsigned dstx, unsigned dsty, unsigned dstz, 307 struct pipe_resource *src, 308 unsigned src_level, 309 const struct pipe_box *src_box) 310{ 311 struct r600_resource_texture *rsrc = (struct r600_resource_texture*)src; 312 struct texture_orig_info orig_info[2]; 313 struct pipe_box sbox; 314 const struct pipe_box *psbox; 315 boolean restore_orig[2]; 316 317 /* Fallback for buffers. */ 318 if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { 319 util_resource_copy_region(ctx, dst, dst_level, dstx, dsty, dstz, 320 src, src_level, src_box); 321 return; 322 } 323 324 if (rsrc->depth && !rsrc->is_flushing_texture) 325 r600_texture_depth_flush(ctx, src, FALSE); 326 327 restore_orig[0] = restore_orig[1] = FALSE; 328 329 if (util_format_is_compressed(src->format)) { 330 r600_compressed_to_blittable(src, src_level, &orig_info[0]); 331 restore_orig[0] = TRUE; 332 sbox.x = util_format_get_nblocksx(orig_info[0].format, src_box->x); 333 sbox.y = util_format_get_nblocksy(orig_info[0].format, src_box->y); 334 sbox.z = src_box->z; 335 sbox.width = util_format_get_nblocksx(orig_info[0].format, src_box->width); 336 sbox.height = util_format_get_nblocksy(orig_info[0].format, src_box->height); 337 sbox.depth = src_box->depth; 338 psbox=&sbox; 339 } else 340 psbox=src_box; 341 342 if (util_format_is_compressed(dst->format)) { 343 r600_compressed_to_blittable(dst, dst_level, &orig_info[1]); 344 restore_orig[1] = TRUE; 345 /* translate the dst box as well */ 346 dstx = util_format_get_nblocksx(orig_info[1].format, dstx); 347 dsty = util_format_get_nblocksy(orig_info[1].format, dsty); 348 } 349 350 r600_hw_copy_region(ctx, dst, dst_level, dstx, dsty, dstz, 351 src, src_level, psbox); 352 353 if (restore_orig[0]) 354 r600_reset_blittable_to_compressed(src, &orig_info[0]); 355 356 if (restore_orig[1]) 357 r600_reset_blittable_to_compressed(dst, &orig_info[1]); 358} 359 360void r600_init_blit_functions(struct r600_pipe_context *rctx) 361{ 362 rctx->context.clear = r600_clear; 363 rctx->context.clear_render_target = r600_clear_render_target; 364 rctx->context.clear_depth_stencil = r600_clear_depth_stencil; 365 rctx->context.resource_copy_region = r600_resource_copy_region; 366} 367 368void r600_blit_push_depth(struct pipe_context *ctx, struct r600_resource_texture *texture) 369{ 370 struct pipe_box sbox; 371 372 sbox.x = sbox.y = sbox.z = 0; 373 sbox.width = texture->resource.b.b.b.width0; 374 sbox.height = texture->resource.b.b.b.height0; 375 /* XXX that might be wrong */ 376 sbox.depth = 1; 377 378 r600_hw_copy_region(ctx, (struct pipe_resource *)texture, 0, 379 0, 0, 0, 380 (struct pipe_resource *)texture->flushed_depth_texture, 0, 381 &sbox); 382} 383