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