Merge remote-tracking branch 'origin/master' into pipe-video
[mesa.git] / src / gallium / drivers / r600 / r600_blit.c
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
28 enum r600_blitter_op /* bitmask */
29 {
30 R600_CLEAR = 1,
31 R600_CLEAR_SURFACE = 2,
32 R600_COPY = 4
33 };
34
35 static 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,
58 rctx->vbuf_mgr->nr_vertex_buffers,
59 rctx->vbuf_mgr->vertex_buffer);
60
61 if (op & (R600_CLEAR_SURFACE | R600_COPY))
62 util_blitter_save_framebuffer(rctx->blitter, &rctx->framebuffer);
63
64 if (op & R600_COPY) {
65 util_blitter_save_fragment_sampler_states(
66 rctx->blitter, rctx->ps_samplers.n_samplers,
67 (void**)rctx->ps_samplers.samplers);
68
69 util_blitter_save_fragment_sampler_views(
70 rctx->blitter, rctx->ps_samplers.n_views,
71 (struct pipe_sampler_view**)rctx->ps_samplers.views);
72 }
73
74 }
75
76 static void r600_blitter_end(struct pipe_context *ctx)
77 {
78 struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
79 r600_context_queries_resume(&rctx->ctx);
80 rctx->blit = false;
81 }
82
83 void r600_blit_uncompress_depth(struct pipe_context *ctx, struct r600_resource_texture *texture)
84 {
85 struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
86 struct pipe_surface *zsurf, *cbsurf, surf_tmpl;
87 int level = 0;
88 float depth = 1.0f;
89
90 if (!texture->dirty_db)
91 return;
92
93 surf_tmpl.format = texture->resource.b.b.b.format;
94 surf_tmpl.u.tex.level = level;
95 surf_tmpl.u.tex.first_layer = 0;
96 surf_tmpl.u.tex.last_layer = 0;
97 surf_tmpl.usage = PIPE_BIND_DEPTH_STENCIL;
98
99 zsurf = ctx->create_surface(ctx, &texture->resource.b.b.b, &surf_tmpl);
100
101 surf_tmpl.format = ((struct pipe_resource*)texture->flushed_depth_texture)->format;
102 surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
103 cbsurf = ctx->create_surface(ctx,
104 (struct pipe_resource*)texture->flushed_depth_texture, &surf_tmpl);
105
106 if (rctx->family == CHIP_RV610 || rctx->family == CHIP_RV630 ||
107 rctx->family == CHIP_RV620 || rctx->family == CHIP_RV635)
108 depth = 0.0f;
109
110 r600_blitter_begin(ctx, R600_CLEAR_SURFACE);
111 util_blitter_custom_depth_stencil(rctx->blitter, zsurf, cbsurf, rctx->custom_dsa_flush, depth);
112 r600_blitter_end(ctx);
113
114 pipe_surface_reference(&zsurf, NULL);
115 pipe_surface_reference(&cbsurf, NULL);
116
117 texture->dirty_db = FALSE;
118 }
119
120 void r600_flush_depth_textures(struct r600_pipe_context *rctx)
121 {
122 unsigned int i;
123
124 if (rctx->blit) return;
125
126 /* FIXME: This handles fragment shader textures only. */
127
128 for (i = 0; i < rctx->ps_samplers.n_views; ++i) {
129 struct r600_pipe_sampler_view *view;
130 struct r600_resource_texture *tex;
131
132 view = rctx->ps_samplers.views[i];
133 if (!view) continue;
134
135 tex = (struct r600_resource_texture *)view->base.texture;
136 if (!tex->depth)
137 continue;
138
139 if (tex->is_flushing_texture)
140 continue;
141
142 r600_blit_uncompress_depth(&rctx->context, tex);
143 }
144
145 /* also check CB here */
146 for (i = 0; i < rctx->framebuffer.nr_cbufs; i++) {
147 struct r600_resource_texture *tex;
148 tex = (struct r600_resource_texture *)rctx->framebuffer.cbufs[i]->texture;
149
150 if (!tex->depth)
151 continue;
152
153 if (tex->is_flushing_texture)
154 continue;
155
156 r600_blit_uncompress_depth(&rctx->context, tex);
157 }
158 }
159
160 static void r600_clear(struct pipe_context *ctx, unsigned buffers,
161 const float *rgba, double depth, unsigned stencil)
162 {
163 struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
164 struct pipe_framebuffer_state *fb = &rctx->framebuffer;
165
166 r600_blitter_begin(ctx, R600_CLEAR);
167 util_blitter_clear(rctx->blitter, fb->width, fb->height,
168 fb->nr_cbufs, buffers, rgba, depth,
169 stencil);
170 r600_blitter_end(ctx);
171 }
172
173 static void r600_clear_render_target(struct pipe_context *ctx,
174 struct pipe_surface *dst,
175 const float *rgba,
176 unsigned dstx, unsigned dsty,
177 unsigned width, unsigned height)
178 {
179 struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
180
181 r600_blitter_begin(ctx, R600_CLEAR_SURFACE);
182 util_blitter_clear_render_target(rctx->blitter, dst, rgba,
183 dstx, dsty, width, height);
184 r600_blitter_end(ctx);
185 }
186
187 static void r600_clear_depth_stencil(struct pipe_context *ctx,
188 struct pipe_surface *dst,
189 unsigned clear_flags,
190 double depth,
191 unsigned stencil,
192 unsigned dstx, unsigned dsty,
193 unsigned width, unsigned height)
194 {
195 struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
196
197 r600_blitter_begin(ctx, R600_CLEAR_SURFACE);
198 util_blitter_clear_depth_stencil(rctx->blitter, dst, clear_flags, depth, stencil,
199 dstx, dsty, width, height);
200 r600_blitter_end(ctx);
201 }
202
203
204
205 /* Copy a block of pixels from one surface to another using HW. */
206 static void r600_hw_copy_region(struct pipe_context *ctx,
207 struct pipe_resource *dst,
208 unsigned dst_level,
209 unsigned dstx, unsigned dsty, unsigned dstz,
210 struct pipe_resource *src,
211 unsigned src_level,
212 const struct pipe_box *src_box)
213 {
214 struct r600_pipe_context *rctx = (struct r600_pipe_context *)ctx;
215
216 r600_blitter_begin(ctx, R600_COPY);
217 util_blitter_copy_region(rctx->blitter, dst, dst_level, dstx, dsty, dstz,
218 src, src_level, src_box, TRUE);
219 r600_blitter_end(ctx);
220 }
221
222 struct texture_orig_info {
223 unsigned format;
224 unsigned width0;
225 unsigned height0;
226 };
227
228 static void r600_compressed_to_blittable(struct pipe_resource *tex,
229 unsigned level,
230 struct texture_orig_info *orig)
231 {
232 struct r600_resource_texture *rtex = (struct r600_resource_texture*)tex;
233 unsigned pixsize = util_format_get_blocksize(tex->format);
234 int new_format;
235 int new_height, new_width;
236
237 orig->format = tex->format;
238 orig->width0 = tex->width0;
239 orig->height0 = tex->height0;
240
241 if (pixsize == 8)
242 new_format = PIPE_FORMAT_R16G16B16A16_UNORM; /* 64-bit block */
243 else
244 new_format = PIPE_FORMAT_R32G32B32A32_UNORM; /* 128-bit block */
245
246 new_width = util_format_get_nblocksx(tex->format, orig->width0);
247 new_height = util_format_get_nblocksy(tex->format, orig->height0);
248
249 rtex->force_int_type = true;
250 tex->width0 = new_width;
251 tex->height0 = new_height;
252 tex->format = new_format;
253
254 }
255
256 static void r600_reset_blittable_to_compressed(struct pipe_resource *tex,
257 unsigned level,
258 struct texture_orig_info *orig)
259 {
260 struct r600_resource_texture *rtex = (struct r600_resource_texture*)tex;
261 rtex->force_int_type = false;
262
263 tex->format = orig->format;
264 tex->width0 = orig->width0;
265 tex->height0 = orig->height0;
266 }
267
268 static void r600_resource_copy_region(struct pipe_context *ctx,
269 struct pipe_resource *dst,
270 unsigned dst_level,
271 unsigned dstx, unsigned dsty, unsigned dstz,
272 struct pipe_resource *src,
273 unsigned src_level,
274 const struct pipe_box *src_box)
275 {
276 struct r600_resource_texture *rsrc = (struct r600_resource_texture*)src;
277 struct texture_orig_info orig_info[2];
278 boolean restore_orig[2];
279
280 /* Fallback for buffers. */
281 if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
282 util_resource_copy_region(ctx, dst, dst_level, dstx, dsty, dstz,
283 src, src_level, src_box);
284 return;
285 }
286
287 if (rsrc->depth && !rsrc->is_flushing_texture)
288 r600_texture_depth_flush(ctx, src, FALSE);
289
290 restore_orig[0] = restore_orig[1] = FALSE;
291
292 if (util_format_is_compressed(src->format)) {
293 r600_compressed_to_blittable(src, src_level, &orig_info[0]);
294 restore_orig[0] = TRUE;
295 }
296
297 if (util_format_is_compressed(dst->format)) {
298 r600_compressed_to_blittable(dst, dst_level, &orig_info[1]);
299 restore_orig[1] = TRUE;
300 /* translate the dst box as well */
301 dstx = util_format_get_nblocksx(orig_info[1].format, dstx);
302 dsty = util_format_get_nblocksy(orig_info[1].format, dsty);
303 }
304
305 r600_hw_copy_region(ctx, dst, dst_level, dstx, dsty, dstz,
306 src, src_level, src_box);
307
308 if (restore_orig[0])
309 r600_reset_blittable_to_compressed(src, src_level, &orig_info[0]);
310
311 if (restore_orig[1])
312 r600_reset_blittable_to_compressed(dst, dst_level, &orig_info[1]);
313 }
314
315 void r600_init_blit_functions(struct r600_pipe_context *rctx)
316 {
317 rctx->context.clear = r600_clear;
318 rctx->context.clear_render_target = r600_clear_render_target;
319 rctx->context.clear_depth_stencil = r600_clear_depth_stencil;
320 rctx->context.resource_copy_region = r600_resource_copy_region;
321 }
322
323 void r600_blit_push_depth(struct pipe_context *ctx, struct r600_resource_texture *texture)
324 {
325 struct pipe_box sbox;
326
327 sbox.x = sbox.y = sbox.z = 0;
328 sbox.width = texture->resource.b.b.b.width0;
329 sbox.height = texture->resource.b.b.b.height0;
330 /* XXX that might be wrong */
331 sbox.depth = 1;
332
333 r600_hw_copy_region(ctx, (struct pipe_resource *)texture, 0,
334 0, 0, 0,
335 (struct pipe_resource *)texture->flushed_depth_texture, 0,
336 &sbox);
337 }