r600_blit.c revision 3e9bc43fbafdd497d475eaffe0deec81b446d122
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_CLEAR = 1, 31 R600_CLEAR_SURFACE = 2, 32 R600_COPY = 4 33}; 34 35static void r600_blitter_begin(struct pipe_context *ctx, enum r600_blitter_op op) 36{ 37 struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; 38 39 rctx->blit = true; 40 r600_context_queries_suspend(&rctx->ctx); 41 42 util_blitter_save_blend(rctx->blitter, rctx->states[R600_PIPE_STATE_BLEND]); 43 util_blitter_save_depth_stencil_alpha(rctx->blitter, rctx->states[R600_PIPE_STATE_DSA]); 44 if (rctx->states[R600_PIPE_STATE_STENCIL_REF]) { 45 util_blitter_save_stencil_ref(rctx->blitter, &rctx->stencil_ref); 46 } 47 util_blitter_save_rasterizer(rctx->blitter, rctx->states[R600_PIPE_STATE_RASTERIZER]); 48 util_blitter_save_fragment_shader(rctx->blitter, rctx->ps_shader); 49 util_blitter_save_vertex_shader(rctx->blitter, rctx->vs_shader); 50 util_blitter_save_vertex_elements(rctx->blitter, rctx->vertex_elements); 51 if (rctx->states[R600_PIPE_STATE_VIEWPORT]) { 52 util_blitter_save_viewport(rctx->blitter, &rctx->viewport); 53 } 54 if (rctx->states[R600_PIPE_STATE_CLIP]) { 55 util_blitter_save_clip(rctx->blitter, &rctx->clip); 56 } 57 util_blitter_save_vertex_buffers(rctx->blitter, rctx->nvertex_buffers, rctx->vertex_buffer); 58 59 if (op & (R600_CLEAR_SURFACE | R600_COPY)) 60 util_blitter_save_framebuffer(rctx->blitter, &rctx->framebuffer); 61 62 if (op & R600_COPY) { 63 util_blitter_save_fragment_sampler_states( 64 rctx->blitter, rctx->ps_samplers.n_samplers, 65 (void**)rctx->ps_samplers.samplers); 66 67 util_blitter_save_fragment_sampler_views( 68 rctx->blitter, rctx->ps_samplers.n_views, 69 (struct pipe_sampler_view**)rctx->ps_samplers.views); 70 } 71 72} 73 74static void r600_blitter_end(struct pipe_context *ctx) 75{ 76 struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; 77 r600_context_queries_resume(&rctx->ctx); 78 rctx->blit = false; 79} 80 81void r600_blit_uncompress_depth(struct pipe_context *ctx, struct r600_resource_texture *texture) 82{ 83 struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; 84 struct pipe_surface *zsurf, *cbsurf, surf_tmpl; 85 int level = 0; 86 float depth = 1.0f; 87 88 if (!texture->dirty_db) 89 return; 90 91 surf_tmpl.format = texture->resource.base.b.format; 92 surf_tmpl.u.tex.level = level; 93 surf_tmpl.u.tex.first_layer = 0; 94 surf_tmpl.u.tex.last_layer = 0; 95 surf_tmpl.usage = PIPE_BIND_DEPTH_STENCIL; 96 97 zsurf = ctx->create_surface(ctx, &texture->resource.base.b, &surf_tmpl); 98 99 surf_tmpl.format = ((struct pipe_resource*)texture->flushed_depth_texture)->format; 100 surf_tmpl.usage = PIPE_BIND_RENDER_TARGET; 101 cbsurf = ctx->create_surface(ctx, 102 (struct pipe_resource*)texture->flushed_depth_texture, &surf_tmpl); 103 104 if (rctx->family == CHIP_RV610 || rctx->family == CHIP_RV630 || 105 rctx->family == CHIP_RV620 || rctx->family == CHIP_RV635) 106 depth = 0.0f; 107 108 r600_blitter_begin(ctx, R600_CLEAR_SURFACE); 109 util_blitter_custom_depth_stencil(rctx->blitter, zsurf, cbsurf, rctx->custom_dsa_flush, depth); 110 r600_blitter_end(ctx); 111 112 pipe_surface_reference(&zsurf, NULL); 113 pipe_surface_reference(&cbsurf, NULL); 114 115 texture->dirty_db = FALSE; 116} 117 118void r600_flush_depth_textures(struct r600_pipe_context *rctx) 119{ 120 unsigned int i; 121 122 if (rctx->blit) return; 123 124 /* FIXME: This handles fragment shader textures only. */ 125 126 for (i = 0; i < rctx->ps_samplers.n_views; ++i) { 127 struct r600_pipe_sampler_view *view; 128 struct r600_resource_texture *tex; 129 130 view = rctx->ps_samplers.views[i]; 131 if (!view) continue; 132 133 tex = (struct r600_resource_texture *)view->base.texture; 134 if (!tex->depth) 135 continue; 136 137 r600_blit_uncompress_depth(&rctx->context, tex); 138 } 139 140 /* also check CB here */ 141 for (i = 0; i < rctx->framebuffer.nr_cbufs; i++) { 142 struct r600_resource_texture *tex; 143 tex = (struct r600_resource_texture *)rctx->framebuffer.cbufs[i]->texture; 144 145 if (!tex->depth) 146 continue; 147 148 r600_blit_uncompress_depth(&rctx->context, tex); 149 } 150} 151 152static void r600_clear(struct pipe_context *ctx, unsigned buffers, 153 const float *rgba, double depth, unsigned stencil) 154{ 155 struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; 156 struct pipe_framebuffer_state *fb = &rctx->framebuffer; 157 158 r600_blitter_begin(ctx, R600_CLEAR); 159 util_blitter_clear(rctx->blitter, fb->width, fb->height, 160 fb->nr_cbufs, buffers, rgba, depth, 161 stencil); 162 r600_blitter_end(ctx); 163} 164 165static void r600_clear_render_target(struct pipe_context *ctx, 166 struct pipe_surface *dst, 167 const float *rgba, 168 unsigned dstx, unsigned dsty, 169 unsigned width, unsigned height) 170{ 171 struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; 172 173 r600_blitter_begin(ctx, R600_CLEAR_SURFACE); 174 util_blitter_clear_render_target(rctx->blitter, dst, rgba, 175 dstx, dsty, width, height); 176 r600_blitter_end(ctx); 177} 178 179static void r600_clear_depth_stencil(struct pipe_context *ctx, 180 struct pipe_surface *dst, 181 unsigned clear_flags, 182 double depth, 183 unsigned stencil, 184 unsigned dstx, unsigned dsty, 185 unsigned width, unsigned height) 186{ 187 struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; 188 189 r600_blitter_begin(ctx, R600_CLEAR_SURFACE); 190 util_blitter_clear_depth_stencil(rctx->blitter, dst, clear_flags, depth, stencil, 191 dstx, dsty, width, height); 192 r600_blitter_end(ctx); 193} 194 195 196 197/* Copy a block of pixels from one surface to another using HW. */ 198static void r600_hw_copy_region(struct pipe_context *ctx, 199 struct pipe_resource *dst, 200 unsigned dst_level, 201 unsigned dstx, unsigned dsty, unsigned dstz, 202 struct pipe_resource *src, 203 unsigned src_level, 204 const struct pipe_box *src_box) 205{ 206 struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; 207 208 r600_blitter_begin(ctx, R600_COPY); 209 util_blitter_copy_region(rctx->blitter, dst, dst_level, dstx, dsty, dstz, 210 src, src_level, src_box, TRUE); 211 r600_blitter_end(ctx); 212} 213 214static void r600_resource_copy_region(struct pipe_context *ctx, 215 struct pipe_resource *dst, 216 unsigned dst_level, 217 unsigned dstx, unsigned dsty, unsigned dstz, 218 struct pipe_resource *src, 219 unsigned src_level, 220 const struct pipe_box *src_box) 221{ 222 struct r600_resource_texture *rsrc = (struct r600_resource_texture*)src; 223 224 if (rsrc->depth && !rsrc->is_flushing_texture) 225 r600_texture_depth_flush(ctx, src, FALSE); 226 227 r600_hw_copy_region(ctx, dst, dst_level, dstx, dsty, dstz, 228 src, src_level, src_box); 229 230} 231 232void r600_init_blit_functions(struct r600_pipe_context *rctx) 233{ 234 rctx->context.clear = r600_clear; 235 rctx->context.clear_render_target = r600_clear_render_target; 236 rctx->context.clear_depth_stencil = r600_clear_depth_stencil; 237 rctx->context.resource_copy_region = r600_resource_copy_region; 238} 239 240void r600_blit_push_depth(struct pipe_context *ctx, struct r600_resource_texture *texture) 241{ 242 struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx; 243 struct pipe_surface *zsurf, *cbsurf, surf_tmpl; 244 int level = 0; 245 float depth = 1.0f; 246 struct pipe_box sbox; 247 248 sbox.x = sbox.y = sbox.z = 0; 249 sbox.width = texture->resource.base.b.width0; 250 sbox.height = texture->resource.base.b.height0; 251 /* XXX that might be wrong */ 252 sbox.depth = 1; 253 254 r600_hw_copy_region(ctx, (struct pipe_resource *)texture, 0, 255 0, 0, 0, 256 (struct pipe_resource *)texture->flushed_depth_texture, 0, 257 &sbox); 258} 259