Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | /* |
2 | * Copyright 2010 Jerome Glisse |
||
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 | |||
28 | enum 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_BLIT = R600_SAVE_FRAGMENT_STATE | R600_SAVE_FRAMEBUFFER | R600_SAVE_TEXTURES | |
||
45 | R600_DISABLE_RENDER_COND, |
||
46 | |||
47 | R600_DECOMPRESS = R600_SAVE_FRAGMENT_STATE | R600_SAVE_FRAMEBUFFER | R600_DISABLE_RENDER_COND, |
||
48 | |||
49 | R600_COLOR_RESOLVE = R600_SAVE_FRAGMENT_STATE | R600_SAVE_FRAMEBUFFER | R600_DISABLE_RENDER_COND |
||
50 | }; |
||
51 | |||
52 | static void r600_blitter_begin(struct pipe_context *ctx, enum r600_blitter_op op) |
||
53 | { |
||
54 | struct r600_context *rctx = (struct r600_context *)ctx; |
||
55 | |||
56 | r600_suspend_nontimer_queries(rctx); |
||
57 | |||
58 | util_blitter_save_vertex_buffer_slot(rctx->blitter, rctx->vertex_buffer_state.vb); |
||
59 | util_blitter_save_vertex_elements(rctx->blitter, rctx->vertex_fetch_shader.cso); |
||
60 | util_blitter_save_vertex_shader(rctx->blitter, rctx->vs_shader); |
||
61 | util_blitter_save_so_targets(rctx->blitter, rctx->streamout.num_targets, |
||
62 | (struct pipe_stream_output_target**)rctx->streamout.targets); |
||
63 | util_blitter_save_rasterizer(rctx->blitter, rctx->rasterizer_state.cso); |
||
64 | |||
65 | if (op & R600_SAVE_FRAGMENT_STATE) { |
||
66 | util_blitter_save_viewport(rctx->blitter, &rctx->viewport.state); |
||
67 | util_blitter_save_scissor(rctx->blitter, &rctx->scissor.scissor); |
||
68 | util_blitter_save_fragment_shader(rctx->blitter, rctx->ps_shader); |
||
69 | util_blitter_save_blend(rctx->blitter, rctx->blend_state.cso); |
||
70 | util_blitter_save_depth_stencil_alpha(rctx->blitter, rctx->dsa_state.cso); |
||
71 | util_blitter_save_stencil_ref(rctx->blitter, &rctx->stencil_ref.pipe_state); |
||
72 | util_blitter_save_sample_mask(rctx->blitter, rctx->sample_mask.sample_mask); |
||
73 | } |
||
74 | |||
75 | if (op & R600_SAVE_FRAMEBUFFER) |
||
76 | util_blitter_save_framebuffer(rctx->blitter, &rctx->framebuffer.state); |
||
77 | |||
78 | if (op & R600_SAVE_TEXTURES) { |
||
79 | util_blitter_save_fragment_sampler_states( |
||
80 | rctx->blitter, util_last_bit(rctx->samplers[PIPE_SHADER_FRAGMENT].states.enabled_mask), |
||
81 | (void**)rctx->samplers[PIPE_SHADER_FRAGMENT].states.states); |
||
82 | |||
83 | util_blitter_save_fragment_sampler_views( |
||
84 | rctx->blitter, util_last_bit(rctx->samplers[PIPE_SHADER_FRAGMENT].views.enabled_mask), |
||
85 | (struct pipe_sampler_view**)rctx->samplers[PIPE_SHADER_FRAGMENT].views.views); |
||
86 | } |
||
87 | |||
88 | if ((op & R600_DISABLE_RENDER_COND) && rctx->current_render_cond) { |
||
89 | util_blitter_save_render_condition(rctx->blitter, |
||
90 | rctx->current_render_cond, |
||
91 | rctx->current_render_cond_cond, |
||
92 | rctx->current_render_cond_mode); |
||
93 | } |
||
94 | } |
||
95 | |||
96 | static void r600_blitter_end(struct pipe_context *ctx) |
||
97 | { |
||
98 | struct r600_context *rctx = (struct r600_context *)ctx; |
||
99 | r600_resume_nontimer_queries(rctx); |
||
100 | } |
||
101 | |||
102 | static unsigned u_max_sample(struct pipe_resource *r) |
||
103 | { |
||
104 | return r->nr_samples ? r->nr_samples - 1 : 0; |
||
105 | } |
||
106 | |||
107 | void r600_blit_decompress_depth(struct pipe_context *ctx, |
||
108 | struct r600_texture *texture, |
||
109 | struct r600_texture *staging, |
||
110 | unsigned first_level, unsigned last_level, |
||
111 | unsigned first_layer, unsigned last_layer, |
||
112 | unsigned first_sample, unsigned last_sample) |
||
113 | { |
||
114 | struct r600_context *rctx = (struct r600_context *)ctx; |
||
115 | unsigned layer, level, sample, checked_last_layer, max_layer, max_sample; |
||
116 | struct r600_texture *flushed_depth_texture = staging ? |
||
117 | staging : texture->flushed_depth_texture; |
||
118 | const struct util_format_description *desc = |
||
119 | util_format_description(texture->resource.b.b.format); |
||
120 | float depth; |
||
121 | |||
122 | if (!staging && !texture->dirty_level_mask) |
||
123 | return; |
||
124 | |||
125 | max_sample = u_max_sample(&texture->resource.b.b); |
||
126 | |||
127 | /* XXX Decompressing MSAA depth textures is broken on R6xx. |
||
128 | * There is also a hardlock if CMASK and FMASK are not present. |
||
129 | * Just skip this until we find out how to fix it. */ |
||
130 | if (rctx->chip_class == R600 && max_sample > 0) { |
||
131 | texture->dirty_level_mask = 0; |
||
132 | return; |
||
133 | } |
||
134 | |||
135 | if (rctx->family == CHIP_RV610 || rctx->family == CHIP_RV630 || |
||
136 | rctx->family == CHIP_RV620 || rctx->family == CHIP_RV635) |
||
137 | depth = 0.0f; |
||
138 | else |
||
139 | depth = 1.0f; |
||
140 | |||
141 | /* Enable decompression in DB_RENDER_CONTROL */ |
||
142 | rctx->db_misc_state.flush_depthstencil_through_cb = true; |
||
143 | rctx->db_misc_state.copy_depth = util_format_has_depth(desc); |
||
144 | rctx->db_misc_state.copy_stencil = util_format_has_stencil(desc); |
||
145 | rctx->db_misc_state.copy_sample = first_sample; |
||
146 | rctx->db_misc_state.atom.dirty = true; |
||
147 | |||
148 | for (level = first_level; level <= last_level; level++) { |
||
149 | if (!staging && !(texture->dirty_level_mask & (1 << level))) |
||
150 | continue; |
||
151 | |||
152 | /* The smaller the mipmap level, the less layers there are |
||
153 | * as far as 3D textures are concerned. */ |
||
154 | max_layer = util_max_layer(&texture->resource.b.b, level); |
||
155 | checked_last_layer = last_layer < max_layer ? last_layer : max_layer; |
||
156 | |||
157 | for (layer = first_layer; layer <= checked_last_layer; layer++) { |
||
158 | for (sample = first_sample; sample <= last_sample; sample++) { |
||
159 | struct pipe_surface *zsurf, *cbsurf, surf_tmpl; |
||
160 | |||
161 | if (sample != rctx->db_misc_state.copy_sample) { |
||
162 | rctx->db_misc_state.copy_sample = sample; |
||
163 | rctx->db_misc_state.atom.dirty = true; |
||
164 | } |
||
165 | |||
166 | surf_tmpl.format = texture->resource.b.b.format; |
||
167 | surf_tmpl.u.tex.level = level; |
||
168 | surf_tmpl.u.tex.first_layer = layer; |
||
169 | surf_tmpl.u.tex.last_layer = layer; |
||
170 | |||
171 | zsurf = ctx->create_surface(ctx, &texture->resource.b.b, &surf_tmpl); |
||
172 | |||
173 | surf_tmpl.format = flushed_depth_texture->resource.b.b.format; |
||
174 | surf_tmpl.u.tex.level = level; |
||
175 | surf_tmpl.u.tex.first_layer = layer; |
||
176 | surf_tmpl.u.tex.last_layer = layer; |
||
177 | cbsurf = ctx->create_surface(ctx, |
||
178 | &flushed_depth_texture->resource.b.b, &surf_tmpl); |
||
179 | |||
180 | r600_blitter_begin(ctx, R600_DECOMPRESS); |
||
181 | util_blitter_custom_depth_stencil(rctx->blitter, zsurf, cbsurf, 1 << sample, |
||
182 | rctx->custom_dsa_flush, depth); |
||
183 | r600_blitter_end(ctx); |
||
184 | |||
185 | pipe_surface_reference(&zsurf, NULL); |
||
186 | pipe_surface_reference(&cbsurf, NULL); |
||
187 | } |
||
188 | } |
||
189 | |||
190 | /* The texture will always be dirty if some layers or samples aren't flushed. |
||
191 | * I don't think this case occurs often though. */ |
||
192 | if (!staging && |
||
193 | first_layer == 0 && last_layer == max_layer && |
||
194 | first_sample == 0 && last_sample == max_sample) { |
||
195 | texture->dirty_level_mask &= ~(1 << level); |
||
196 | } |
||
197 | } |
||
198 | |||
199 | /* reenable compression in DB_RENDER_CONTROL */ |
||
200 | rctx->db_misc_state.flush_depthstencil_through_cb = false; |
||
201 | rctx->db_misc_state.atom.dirty = true; |
||
202 | } |
||
203 | |||
204 | static void r600_blit_decompress_depth_in_place(struct r600_context *rctx, |
||
205 | struct r600_texture *texture, |
||
206 | unsigned first_level, unsigned last_level, |
||
207 | unsigned first_layer, unsigned last_layer) |
||
208 | { |
||
209 | struct pipe_surface *zsurf, surf_tmpl = {{0}}; |
||
210 | unsigned layer, max_layer, checked_last_layer, level; |
||
211 | |||
212 | /* Enable decompression in DB_RENDER_CONTROL */ |
||
213 | rctx->db_misc_state.flush_depthstencil_in_place = true; |
||
214 | rctx->db_misc_state.atom.dirty = true; |
||
215 | |||
216 | surf_tmpl.format = texture->resource.b.b.format; |
||
217 | |||
218 | for (level = first_level; level <= last_level; level++) { |
||
219 | if (!(texture->dirty_level_mask & (1 << level))) |
||
220 | continue; |
||
221 | |||
222 | surf_tmpl.u.tex.level = level; |
||
223 | |||
224 | /* The smaller the mipmap level, the less layers there are |
||
225 | * as far as 3D textures are concerned. */ |
||
226 | max_layer = util_max_layer(&texture->resource.b.b, level); |
||
227 | checked_last_layer = last_layer < max_layer ? last_layer : max_layer; |
||
228 | |||
229 | for (layer = first_layer; layer <= checked_last_layer; layer++) { |
||
230 | surf_tmpl.u.tex.first_layer = layer; |
||
231 | surf_tmpl.u.tex.last_layer = layer; |
||
232 | |||
233 | zsurf = rctx->context.create_surface(&rctx->context, &texture->resource.b.b, &surf_tmpl); |
||
234 | |||
235 | r600_blitter_begin(&rctx->context, R600_DECOMPRESS); |
||
236 | util_blitter_custom_depth_stencil(rctx->blitter, zsurf, NULL, ~0, |
||
237 | rctx->custom_dsa_flush, 1.0f); |
||
238 | r600_blitter_end(&rctx->context); |
||
239 | |||
240 | pipe_surface_reference(&zsurf, NULL); |
||
241 | } |
||
242 | |||
243 | /* The texture will always be dirty if some layers or samples aren't flushed. |
||
244 | * I don't think this case occurs often though. */ |
||
245 | if (first_layer == 0 && last_layer == max_layer) { |
||
246 | texture->dirty_level_mask &= ~(1 << level); |
||
247 | } |
||
248 | } |
||
249 | |||
250 | /* Disable decompression in DB_RENDER_CONTROL */ |
||
251 | rctx->db_misc_state.flush_depthstencil_in_place = false; |
||
252 | rctx->db_misc_state.atom.dirty = true; |
||
253 | } |
||
254 | |||
255 | void r600_decompress_depth_textures(struct r600_context *rctx, |
||
256 | struct r600_samplerview_state *textures) |
||
257 | { |
||
258 | unsigned i; |
||
259 | unsigned depth_texture_mask = textures->compressed_depthtex_mask; |
||
260 | |||
261 | while (depth_texture_mask) { |
||
262 | struct pipe_sampler_view *view; |
||
263 | struct r600_texture *tex; |
||
264 | |||
265 | i = u_bit_scan(&depth_texture_mask); |
||
266 | |||
267 | view = &textures->views[i]->base; |
||
268 | assert(view); |
||
269 | |||
270 | tex = (struct r600_texture *)view->texture; |
||
271 | assert(tex->is_depth && !tex->is_flushing_texture); |
||
272 | |||
273 | if (rctx->chip_class >= EVERGREEN || |
||
274 | r600_can_read_depth(tex)) { |
||
275 | r600_blit_decompress_depth_in_place(rctx, tex, |
||
276 | view->u.tex.first_level, view->u.tex.last_level, |
||
277 | 0, util_max_layer(&tex->resource.b.b, view->u.tex.first_level)); |
||
278 | } else { |
||
279 | r600_blit_decompress_depth(&rctx->context, tex, NULL, |
||
280 | view->u.tex.first_level, view->u.tex.last_level, |
||
281 | 0, util_max_layer(&tex->resource.b.b, view->u.tex.first_level), |
||
282 | 0, u_max_sample(&tex->resource.b.b)); |
||
283 | } |
||
284 | } |
||
285 | } |
||
286 | |||
287 | static void r600_blit_decompress_color(struct pipe_context *ctx, |
||
288 | struct r600_texture *rtex, |
||
289 | unsigned first_level, unsigned last_level, |
||
290 | unsigned first_layer, unsigned last_layer) |
||
291 | { |
||
292 | struct r600_context *rctx = (struct r600_context *)ctx; |
||
293 | unsigned layer, level, checked_last_layer, max_layer; |
||
294 | |||
295 | if (!rtex->dirty_level_mask) |
||
296 | return; |
||
297 | |||
298 | for (level = first_level; level <= last_level; level++) { |
||
299 | if (!(rtex->dirty_level_mask & (1 << level))) |
||
300 | continue; |
||
301 | |||
302 | /* The smaller the mipmap level, the less layers there are |
||
303 | * as far as 3D textures are concerned. */ |
||
304 | max_layer = util_max_layer(&rtex->resource.b.b, level); |
||
305 | checked_last_layer = last_layer < max_layer ? last_layer : max_layer; |
||
306 | |||
307 | for (layer = first_layer; layer <= checked_last_layer; layer++) { |
||
308 | struct pipe_surface *cbsurf, surf_tmpl; |
||
309 | |||
310 | surf_tmpl.format = rtex->resource.b.b.format; |
||
311 | surf_tmpl.u.tex.level = level; |
||
312 | surf_tmpl.u.tex.first_layer = layer; |
||
313 | surf_tmpl.u.tex.last_layer = layer; |
||
314 | cbsurf = ctx->create_surface(ctx, &rtex->resource.b.b, &surf_tmpl); |
||
315 | |||
316 | r600_blitter_begin(ctx, R600_DECOMPRESS); |
||
317 | util_blitter_custom_color(rctx->blitter, cbsurf, rctx->custom_blend_decompress); |
||
318 | r600_blitter_end(ctx); |
||
319 | |||
320 | pipe_surface_reference(&cbsurf, NULL); |
||
321 | } |
||
322 | |||
323 | /* The texture will always be dirty if some layers aren't flushed. |
||
324 | * I don't think this case occurs often though. */ |
||
325 | if (first_layer == 0 && last_layer == max_layer) { |
||
326 | rtex->dirty_level_mask &= ~(1 << level); |
||
327 | } |
||
328 | } |
||
329 | } |
||
330 | |||
331 | void r600_decompress_color_textures(struct r600_context *rctx, |
||
332 | struct r600_samplerview_state *textures) |
||
333 | { |
||
334 | unsigned i; |
||
335 | unsigned mask = textures->compressed_colortex_mask; |
||
336 | |||
337 | while (mask) { |
||
338 | struct pipe_sampler_view *view; |
||
339 | struct r600_texture *tex; |
||
340 | |||
341 | i = u_bit_scan(&mask); |
||
342 | |||
343 | view = &textures->views[i]->base; |
||
344 | assert(view); |
||
345 | |||
346 | tex = (struct r600_texture *)view->texture; |
||
347 | assert(tex->cmask_size && tex->fmask_size); |
||
348 | |||
349 | r600_blit_decompress_color(&rctx->context, tex, |
||
350 | view->u.tex.first_level, view->u.tex.last_level, |
||
351 | 0, util_max_layer(&tex->resource.b.b, view->u.tex.first_level)); |
||
352 | } |
||
353 | } |
||
354 | |||
355 | /* Helper for decompressing a portion of a color or depth resource before |
||
356 | * blitting if any decompression is needed. |
||
357 | * The driver doesn't decompress resources automatically while u_blitter is |
||
358 | * rendering. */ |
||
359 | static bool r600_decompress_subresource(struct pipe_context *ctx, |
||
360 | struct pipe_resource *tex, |
||
361 | unsigned level, |
||
362 | unsigned first_layer, unsigned last_layer) |
||
363 | { |
||
364 | struct r600_context *rctx = (struct r600_context *)ctx; |
||
365 | struct r600_texture *rtex = (struct r600_texture*)tex; |
||
366 | |||
367 | if (rtex->is_depth && !rtex->is_flushing_texture) { |
||
368 | if (rctx->chip_class >= EVERGREEN || |
||
369 | r600_can_read_depth(rtex)) { |
||
370 | r600_blit_decompress_depth_in_place(rctx, rtex, |
||
371 | level, level, |
||
372 | first_layer, last_layer); |
||
373 | } else { |
||
374 | if (!r600_init_flushed_depth_texture(ctx, tex, NULL)) |
||
375 | return false; /* error */ |
||
376 | |||
377 | r600_blit_decompress_depth(ctx, rtex, NULL, |
||
378 | level, level, |
||
379 | first_layer, last_layer, |
||
380 | 0, u_max_sample(tex)); |
||
381 | } |
||
382 | } else if (rtex->fmask_size && rtex->cmask_size) { |
||
383 | r600_blit_decompress_color(ctx, rtex, level, level, |
||
384 | first_layer, last_layer); |
||
385 | } |
||
386 | return true; |
||
387 | } |
||
388 | |||
389 | static boolean is_simple_msaa_resolve(const struct pipe_blit_info *info) |
||
390 | { |
||
391 | unsigned dst_width = u_minify(info->dst.resource->width0, info->dst.level); |
||
392 | unsigned dst_height = u_minify(info->dst.resource->height0, info->dst.level); |
||
393 | struct r600_texture *dst = (struct r600_texture*)info->dst.resource; |
||
394 | unsigned dst_tile_mode = dst->surface.level[info->dst.level].mode; |
||
395 | |||
396 | return info->dst.resource->format == info->src.resource->format && |
||
397 | info->dst.resource->format == info->dst.format && |
||
398 | info->src.resource->format == info->src.format && |
||
399 | !info->scissor_enable && |
||
400 | info->mask == PIPE_MASK_RGBA && |
||
401 | dst_width == info->src.resource->width0 && |
||
402 | dst_height == info->src.resource->height0 && |
||
403 | info->dst.box.x == 0 && |
||
404 | info->dst.box.y == 0 && |
||
405 | info->dst.box.width == dst_width && |
||
406 | info->dst.box.height == dst_height && |
||
407 | info->src.box.x == 0 && |
||
408 | info->src.box.y == 0 && |
||
409 | info->src.box.width == dst_width && |
||
410 | info->src.box.height == dst_height && |
||
411 | /* Dst must be tiled. If it's not, we have to use a temporary |
||
412 | * resource which is tiled. */ |
||
413 | dst_tile_mode >= RADEON_SURF_MODE_1D; |
||
414 | } |
||
415 | |||
416 | static void r600_clear_buffer(struct pipe_context *ctx, struct pipe_resource *dst, |
||
417 | unsigned offset, unsigned size, unsigned char value); |
||
418 | |||
419 | static void evergreen_set_clear_color(struct pipe_surface *cbuf, |
||
420 | const union pipe_color_union *color) |
||
421 | { |
||
422 | unsigned *clear_value = ((struct r600_texture *)cbuf->texture)->color_clear_value; |
||
423 | union util_color uc; |
||
424 | |||
425 | memset(&uc, 0, sizeof(uc)); |
||
426 | |||
427 | if (util_format_is_pure_uint(cbuf->format)) { |
||
428 | util_format_write_4ui(cbuf->format, color->ui, 0, &uc, 0, 0, 0, 1, 1); |
||
429 | } else if (util_format_is_pure_sint(cbuf->format)) { |
||
430 | util_format_write_4i(cbuf->format, color->i, 0, &uc, 0, 0, 0, 1, 1); |
||
431 | } else { |
||
432 | util_pack_color(color->f, cbuf->format, &uc); |
||
433 | } |
||
434 | |||
435 | memcpy(clear_value, &uc, 2 * sizeof(uint32_t)); |
||
436 | } |
||
437 | |||
438 | static bool can_fast_clear_color(struct pipe_context *ctx) |
||
439 | { |
||
440 | struct r600_context *rctx = (struct r600_context *)ctx; |
||
441 | struct pipe_framebuffer_state *fb = &rctx->framebuffer.state; |
||
442 | int i; |
||
443 | |||
444 | if (rctx->chip_class < EVERGREEN) { |
||
445 | return false; |
||
446 | } |
||
447 | |||
448 | for (i = 0; i < fb->nr_cbufs; i++) { |
||
449 | struct r600_texture *tex = (struct r600_texture *)fb->cbufs[i]->texture; |
||
450 | |||
451 | if (tex->cmask_size == 0) { |
||
452 | return false; |
||
453 | } |
||
454 | |||
455 | /* 128-bit formats are unuspported */ |
||
456 | if (util_format_get_blocksizebits(fb->cbufs[i]->format) > 64) { |
||
457 | return false; |
||
458 | } |
||
459 | |||
460 | /* the clear is allowed if all layers are bound */ |
||
461 | if (fb->cbufs[i]->u.tex.first_layer != 0 || |
||
462 | fb->cbufs[i]->u.tex.last_layer != util_max_layer(&tex->resource.b.b, 0)) { |
||
463 | return false; |
||
464 | } |
||
465 | } |
||
466 | |||
467 | return true; |
||
468 | } |
||
469 | |||
470 | static void r600_clear(struct pipe_context *ctx, unsigned buffers, |
||
471 | const union pipe_color_union *color, |
||
472 | double depth, unsigned stencil) |
||
473 | { |
||
474 | struct r600_context *rctx = (struct r600_context *)ctx; |
||
475 | struct pipe_framebuffer_state *fb = &rctx->framebuffer.state; |
||
476 | |||
477 | /* fast color clear on AA framebuffers (EG+) */ |
||
478 | if ((buffers & PIPE_CLEAR_COLOR) && can_fast_clear_color(ctx)) { |
||
479 | int i; |
||
480 | |||
481 | for (i = 0; i < fb->nr_cbufs; i++) { |
||
482 | struct r600_texture *tex = (struct r600_texture *)fb->cbufs[i]->texture; |
||
483 | |||
484 | evergreen_set_clear_color(fb->cbufs[i], color); |
||
485 | r600_clear_buffer(ctx, fb->cbufs[i]->texture, |
||
486 | tex->cmask_offset, tex->cmask_size, 0); |
||
487 | tex->dirty_level_mask |= 1 << fb->cbufs[i]->u.tex.level; |
||
488 | } |
||
489 | |||
490 | rctx->framebuffer.atom.dirty = true; |
||
491 | |||
492 | buffers &= ~PIPE_CLEAR_COLOR; |
||
493 | if (!buffers) |
||
494 | return; |
||
495 | } |
||
496 | |||
497 | /* if hyperz enabled just clear hyperz */ |
||
498 | if (fb->zsbuf && (buffers & PIPE_CLEAR_DEPTH)) { |
||
499 | struct r600_texture *rtex; |
||
500 | unsigned level = fb->zsbuf->u.tex.level; |
||
501 | |||
502 | rtex = (struct r600_texture*)fb->zsbuf->texture; |
||
503 | |||
504 | /* We can't use hyperz fast clear if each slice of a texture |
||
505 | * array are clear to different value. To simplify code just |
||
506 | * disable fast clear for texture array. |
||
507 | */ |
||
508 | /* Only use htile for first level */ |
||
509 | if (rtex->htile && !level && rtex->surface.array_size == 1) { |
||
510 | if (rtex->depth_clear != depth) { |
||
511 | rtex->depth_clear = depth; |
||
512 | rctx->db_state.atom.dirty = true; |
||
513 | } |
||
514 | rctx->db_misc_state.htile_clear = true; |
||
515 | rctx->db_misc_state.atom.dirty = true; |
||
516 | } |
||
517 | } |
||
518 | |||
519 | r600_blitter_begin(ctx, R600_CLEAR); |
||
520 | util_blitter_clear(rctx->blitter, fb->width, fb->height, |
||
521 | buffers, color, depth, stencil); |
||
522 | r600_blitter_end(ctx); |
||
523 | |||
524 | /* disable fast clear */ |
||
525 | if (rctx->db_misc_state.htile_clear) { |
||
526 | rctx->db_misc_state.htile_clear = false; |
||
527 | rctx->db_misc_state.atom.dirty = true; |
||
528 | } |
||
529 | } |
||
530 | |||
531 | static void r600_clear_render_target(struct pipe_context *ctx, |
||
532 | struct pipe_surface *dst, |
||
533 | const union pipe_color_union *color, |
||
534 | unsigned dstx, unsigned dsty, |
||
535 | unsigned width, unsigned height) |
||
536 | { |
||
537 | struct r600_context *rctx = (struct r600_context *)ctx; |
||
538 | |||
539 | r600_blitter_begin(ctx, R600_CLEAR_SURFACE); |
||
540 | util_blitter_clear_render_target(rctx->blitter, dst, color, |
||
541 | dstx, dsty, width, height); |
||
542 | r600_blitter_end(ctx); |
||
543 | } |
||
544 | |||
545 | static void r600_clear_depth_stencil(struct pipe_context *ctx, |
||
546 | struct pipe_surface *dst, |
||
547 | unsigned clear_flags, |
||
548 | double depth, |
||
549 | unsigned stencil, |
||
550 | unsigned dstx, unsigned dsty, |
||
551 | unsigned width, unsigned height) |
||
552 | { |
||
553 | struct r600_context *rctx = (struct r600_context *)ctx; |
||
554 | |||
555 | r600_blitter_begin(ctx, R600_CLEAR_SURFACE); |
||
556 | util_blitter_clear_depth_stencil(rctx->blitter, dst, clear_flags, depth, stencil, |
||
557 | dstx, dsty, width, height); |
||
558 | r600_blitter_end(ctx); |
||
559 | } |
||
560 | |||
561 | void r600_copy_buffer(struct pipe_context *ctx, struct pipe_resource *dst, unsigned dstx, |
||
562 | struct pipe_resource *src, const struct pipe_box *src_box) |
||
563 | { |
||
564 | struct r600_context *rctx = (struct r600_context*)ctx; |
||
565 | |||
566 | if (rctx->screen->has_cp_dma) { |
||
567 | r600_cp_dma_copy_buffer(rctx, dst, dstx, src, src_box->x, src_box->width); |
||
568 | } |
||
569 | else if (rctx->screen->has_streamout && |
||
570 | /* Require 4-byte alignment. */ |
||
571 | dstx % 4 == 0 && src_box->x % 4 == 0 && src_box->width % 4 == 0) { |
||
572 | |||
573 | /* Flush both resources. */ |
||
574 | r600_flag_resource_cache_flush(rctx, src); |
||
575 | r600_flag_resource_cache_flush(rctx, dst); |
||
576 | |||
577 | r600_blitter_begin(ctx, R600_COPY_BUFFER); |
||
578 | util_blitter_copy_buffer(rctx->blitter, dst, dstx, src, src_box->x, src_box->width); |
||
579 | r600_blitter_end(ctx); |
||
580 | |||
581 | /* Flush the dst in case the 3D engine has been prefetching the resource. */ |
||
582 | r600_flag_resource_cache_flush(rctx, dst); |
||
583 | } else { |
||
584 | util_resource_copy_region(ctx, dst, 0, dstx, 0, 0, src, 0, src_box); |
||
585 | } |
||
586 | } |
||
587 | |||
588 | static void r600_clear_buffer(struct pipe_context *ctx, struct pipe_resource *dst, |
||
589 | unsigned offset, unsigned size, unsigned char value) |
||
590 | { |
||
591 | struct r600_context *rctx = (struct r600_context*)ctx; |
||
592 | uint32_t v = value; |
||
593 | |||
594 | if (rctx->screen->has_cp_dma && |
||
595 | rctx->chip_class >= EVERGREEN && |
||
596 | offset % 4 == 0 && size % 4 == 0) { |
||
597 | uint32_t clear_value = v | (v << 8) | (v << 16) | (v << 24); |
||
598 | |||
599 | evergreen_cp_dma_clear_buffer(rctx, dst, offset, size, clear_value); |
||
600 | } else if (rctx->screen->has_streamout && offset % 4 == 0 && size % 4 == 0) { |
||
601 | union pipe_color_union clear_value; |
||
602 | |||
603 | clear_value.ui[0] = v | (v << 8) | (v << 16) | (v << 24); |
||
604 | |||
605 | r600_flag_resource_cache_flush(rctx, dst); |
||
606 | |||
607 | r600_blitter_begin(ctx, R600_DISABLE_RENDER_COND); |
||
608 | util_blitter_clear_buffer(rctx->blitter, dst, offset, size, |
||
609 | 1, &clear_value); |
||
610 | r600_blitter_end(ctx); |
||
611 | |||
612 | /* Flush again in case the 3D engine has been prefetching the resource. */ |
||
613 | r600_flag_resource_cache_flush(rctx, dst); |
||
614 | } else { |
||
615 | char *map = r600_buffer_mmap_sync_with_rings(rctx, r600_resource(dst), |
||
616 | PIPE_TRANSFER_WRITE); |
||
617 | memset(map + offset, value, size); |
||
618 | } |
||
619 | } |
||
620 | |||
621 | void r600_screen_clear_buffer(struct r600_screen *rscreen, struct pipe_resource *dst, |
||
622 | unsigned offset, unsigned size, unsigned char value) |
||
623 | { |
||
624 | pipe_mutex_lock(rscreen->aux_context_lock); |
||
625 | r600_clear_buffer(rscreen->aux_context, dst, offset, size, value); |
||
626 | rscreen->aux_context->flush(rscreen->aux_context, NULL, 0); |
||
627 | pipe_mutex_unlock(rscreen->aux_context_lock); |
||
628 | } |
||
629 | |||
630 | static bool util_format_is_subsampled_2x1_32bpp(enum pipe_format format) |
||
631 | { |
||
632 | const struct util_format_description *desc = util_format_description(format); |
||
633 | |||
634 | return desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED && |
||
635 | desc->block.width == 2 && |
||
636 | desc->block.height == 1 && |
||
637 | desc->block.bits == 32; |
||
638 | } |
||
639 | |||
640 | static void r600_resource_copy_region(struct pipe_context *ctx, |
||
641 | struct pipe_resource *dst, |
||
642 | unsigned dst_level, |
||
643 | unsigned dstx, unsigned dsty, unsigned dstz, |
||
644 | struct pipe_resource *src, |
||
645 | unsigned src_level, |
||
646 | const struct pipe_box *src_box) |
||
647 | { |
||
648 | struct r600_context *rctx = (struct r600_context *)ctx; |
||
649 | struct pipe_surface *dst_view, dst_templ; |
||
650 | struct pipe_sampler_view src_templ, *src_view; |
||
651 | unsigned dst_width, dst_height, src_width0, src_height0, src_widthFL, src_heightFL; |
||
652 | struct pipe_box sbox, dstbox; |
||
653 | |||
654 | /* Handle buffers first. */ |
||
655 | if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { |
||
656 | r600_copy_buffer(ctx, dst, dstx, src, src_box); |
||
657 | return; |
||
658 | } |
||
659 | |||
660 | assert(u_max_sample(dst) == u_max_sample(src)); |
||
661 | |||
662 | /* The driver doesn't decompress resources automatically while |
||
663 | * u_blitter is rendering. */ |
||
664 | if (!r600_decompress_subresource(ctx, src, src_level, |
||
665 | src_box->z, src_box->z + src_box->depth - 1)) { |
||
666 | return; /* error */ |
||
667 | } |
||
668 | |||
669 | dst_width = u_minify(dst->width0, dst_level); |
||
670 | dst_height = u_minify(dst->height0, dst_level); |
||
671 | src_width0 = src->width0; |
||
672 | src_height0 = src->height0; |
||
673 | src_widthFL = u_minify(src->width0, src_level); |
||
674 | src_heightFL = u_minify(src->height0, src_level); |
||
675 | |||
676 | util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz); |
||
677 | util_blitter_default_src_texture(&src_templ, src, src_level); |
||
678 | |||
679 | if (util_format_is_compressed(src->format)) { |
||
680 | unsigned blocksize = util_format_get_blocksize(src->format); |
||
681 | |||
682 | if (blocksize == 8) |
||
683 | src_templ.format = PIPE_FORMAT_R16G16B16A16_UINT; /* 64-bit block */ |
||
684 | else |
||
685 | src_templ.format = PIPE_FORMAT_R32G32B32A32_UINT; /* 128-bit block */ |
||
686 | dst_templ.format = src_templ.format; |
||
687 | |||
688 | dst_width = util_format_get_nblocksx(dst->format, dst_width); |
||
689 | dst_height = util_format_get_nblocksy(dst->format, dst_height); |
||
690 | src_width0 = util_format_get_nblocksx(src->format, src_width0); |
||
691 | src_height0 = util_format_get_nblocksy(src->format, src_height0); |
||
692 | src_widthFL = util_format_get_nblocksx(src->format, src_widthFL); |
||
693 | src_heightFL = util_format_get_nblocksy(src->format, src_heightFL); |
||
694 | |||
695 | dstx = util_format_get_nblocksx(dst->format, dstx); |
||
696 | dsty = util_format_get_nblocksy(dst->format, dsty); |
||
697 | |||
698 | sbox.x = util_format_get_nblocksx(src->format, src_box->x); |
||
699 | sbox.y = util_format_get_nblocksy(src->format, src_box->y); |
||
700 | sbox.z = src_box->z; |
||
701 | sbox.width = util_format_get_nblocksx(src->format, src_box->width); |
||
702 | sbox.height = util_format_get_nblocksy(src->format, src_box->height); |
||
703 | sbox.depth = src_box->depth; |
||
704 | src_box = &sbox; |
||
705 | } else if (!util_blitter_is_copy_supported(rctx->blitter, dst, src, |
||
706 | PIPE_MASK_RGBAZS)) { |
||
707 | if (util_format_is_subsampled_2x1_32bpp(src->format)) { |
||
708 | |||
709 | src_templ.format = PIPE_FORMAT_R8G8B8A8_UINT; |
||
710 | dst_templ.format = PIPE_FORMAT_R8G8B8A8_UINT; |
||
711 | |||
712 | dst_width = util_format_get_nblocksx(dst->format, dst_width); |
||
713 | src_width0 = util_format_get_nblocksx(src->format, src_width0); |
||
714 | src_widthFL = util_format_get_nblocksx(src->format, src_widthFL); |
||
715 | |||
716 | dstx = util_format_get_nblocksx(dst->format, dstx); |
||
717 | |||
718 | sbox = *src_box; |
||
719 | sbox.x = util_format_get_nblocksx(src->format, src_box->x); |
||
720 | sbox.width = util_format_get_nblocksx(src->format, src_box->width); |
||
721 | src_box = &sbox; |
||
722 | } else { |
||
723 | unsigned blocksize = util_format_get_blocksize(src->format); |
||
724 | |||
725 | switch (blocksize) { |
||
726 | case 1: |
||
727 | dst_templ.format = PIPE_FORMAT_R8_UNORM; |
||
728 | src_templ.format = PIPE_FORMAT_R8_UNORM; |
||
729 | break; |
||
730 | case 2: |
||
731 | dst_templ.format = PIPE_FORMAT_R8G8_UNORM; |
||
732 | src_templ.format = PIPE_FORMAT_R8G8_UNORM; |
||
733 | break; |
||
734 | case 4: |
||
735 | dst_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM; |
||
736 | src_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM; |
||
737 | break; |
||
738 | case 8: |
||
739 | dst_templ.format = PIPE_FORMAT_R16G16B16A16_UINT; |
||
740 | src_templ.format = PIPE_FORMAT_R16G16B16A16_UINT; |
||
741 | break; |
||
742 | case 16: |
||
743 | dst_templ.format = PIPE_FORMAT_R32G32B32A32_UINT; |
||
744 | src_templ.format = PIPE_FORMAT_R32G32B32A32_UINT; |
||
745 | break; |
||
746 | default: |
||
747 | fprintf(stderr, "Unhandled format %s with blocksize %u\n", |
||
748 | util_format_short_name(src->format), blocksize); |
||
749 | assert(0); |
||
750 | } |
||
751 | } |
||
752 | } |
||
753 | |||
754 | dst_view = r600_create_surface_custom(ctx, dst, &dst_templ, dst_width, dst_height); |
||
755 | |||
756 | if (rctx->chip_class >= EVERGREEN) { |
||
757 | src_view = evergreen_create_sampler_view_custom(ctx, src, &src_templ, |
||
758 | src_width0, src_height0); |
||
759 | } else { |
||
760 | src_view = r600_create_sampler_view_custom(ctx, src, &src_templ, |
||
761 | src_widthFL, src_heightFL); |
||
762 | } |
||
763 | |||
764 | u_box_3d(dstx, dsty, dstz, abs(src_box->width), abs(src_box->height), |
||
765 | abs(src_box->depth), &dstbox); |
||
766 | |||
767 | /* Copy. */ |
||
768 | r600_blitter_begin(ctx, R600_COPY_TEXTURE); |
||
769 | util_blitter_blit_generic(rctx->blitter, dst_view, &dstbox, |
||
770 | src_view, src_box, src_width0, src_height0, |
||
771 | PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL, |
||
772 | TRUE); |
||
773 | r600_blitter_end(ctx); |
||
774 | |||
775 | pipe_surface_reference(&dst_view, NULL); |
||
776 | pipe_sampler_view_reference(&src_view, NULL); |
||
777 | } |
||
778 | |||
779 | /* For MSAA integer resolving to work, we change the format to NORM using this function. */ |
||
780 | static enum pipe_format int_to_norm_format(enum pipe_format format) |
||
781 | { |
||
782 | switch (format) { |
||
783 | #define REPLACE_FORMAT_SIGN(format,sign) \ |
||
784 | case PIPE_FORMAT_##format##_##sign##INT: \ |
||
785 | return PIPE_FORMAT_##format##_##sign##NORM |
||
786 | #define REPLACE_FORMAT(format) \ |
||
787 | REPLACE_FORMAT_SIGN(format, U); \ |
||
788 | REPLACE_FORMAT_SIGN(format, S) |
||
789 | |||
790 | REPLACE_FORMAT_SIGN(B10G10R10A2, U); |
||
791 | REPLACE_FORMAT(R8); |
||
792 | REPLACE_FORMAT(R8G8); |
||
793 | REPLACE_FORMAT(R8G8B8X8); |
||
794 | REPLACE_FORMAT(R8G8B8A8); |
||
795 | REPLACE_FORMAT(A8); |
||
796 | REPLACE_FORMAT(I8); |
||
797 | REPLACE_FORMAT(L8); |
||
798 | REPLACE_FORMAT(L8A8); |
||
799 | REPLACE_FORMAT(R16); |
||
800 | REPLACE_FORMAT(R16G16); |
||
801 | REPLACE_FORMAT(R16G16B16X16); |
||
802 | REPLACE_FORMAT(R16G16B16A16); |
||
803 | REPLACE_FORMAT(A16); |
||
804 | REPLACE_FORMAT(I16); |
||
805 | REPLACE_FORMAT(L16); |
||
806 | REPLACE_FORMAT(L16A16); |
||
807 | |||
808 | #undef REPLACE_FORMAT |
||
809 | #undef REPLACE_FORMAT_SIGN |
||
810 | default: |
||
811 | return format; |
||
812 | } |
||
813 | } |
||
814 | |||
815 | static void r600_msaa_color_resolve(struct pipe_context *ctx, |
||
816 | const struct pipe_blit_info *info) |
||
817 | { |
||
818 | struct r600_context *rctx = (struct r600_context *)ctx; |
||
819 | struct pipe_screen *screen = ctx->screen; |
||
820 | struct pipe_resource *tmp, templ; |
||
821 | struct pipe_blit_info blit; |
||
822 | unsigned sample_mask = |
||
823 | rctx->chip_class == CAYMAN ? ~0 : |
||
824 | ((1ull << MAX2(1, info->src.resource->nr_samples)) - 1); |
||
825 | |||
826 | assert(info->src.level == 0); |
||
827 | assert(info->src.box.depth == 1); |
||
828 | assert(info->dst.box.depth == 1); |
||
829 | |||
830 | if (is_simple_msaa_resolve(info)) { |
||
831 | r600_blitter_begin(ctx, R600_COLOR_RESOLVE); |
||
832 | util_blitter_custom_resolve_color(rctx->blitter, |
||
833 | info->dst.resource, info->dst.level, |
||
834 | info->dst.box.z, |
||
835 | info->src.resource, info->src.box.z, |
||
836 | sample_mask, rctx->custom_blend_resolve, |
||
837 | int_to_norm_format(info->dst.format)); |
||
838 | r600_blitter_end(ctx); |
||
839 | return; |
||
840 | } |
||
841 | |||
842 | /* resolve into a temporary texture, then blit */ |
||
843 | templ.target = PIPE_TEXTURE_2D; |
||
844 | templ.format = info->src.resource->format; |
||
845 | templ.width0 = info->src.resource->width0; |
||
846 | templ.height0 = info->src.resource->height0; |
||
847 | templ.depth0 = 1; |
||
848 | templ.array_size = 1; |
||
849 | templ.last_level = 0; |
||
850 | templ.nr_samples = 0; |
||
851 | templ.usage = PIPE_USAGE_STATIC; |
||
852 | templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; |
||
853 | templ.flags = R600_RESOURCE_FLAG_FORCE_TILING; /* dst must not have a linear layout */ |
||
854 | |||
855 | tmp = screen->resource_create(screen, &templ); |
||
856 | |||
857 | /* resolve */ |
||
858 | r600_blitter_begin(ctx, R600_COLOR_RESOLVE); |
||
859 | util_blitter_custom_resolve_color(rctx->blitter, |
||
860 | tmp, 0, 0, |
||
861 | info->src.resource, info->src.box.z, |
||
862 | sample_mask, rctx->custom_blend_resolve, |
||
863 | int_to_norm_format(tmp->format)); |
||
864 | r600_blitter_end(ctx); |
||
865 | |||
866 | /* blit */ |
||
867 | blit = *info; |
||
868 | blit.src.resource = tmp; |
||
869 | blit.src.box.z = 0; |
||
870 | |||
871 | r600_blitter_begin(ctx, R600_BLIT); |
||
872 | util_blitter_blit(rctx->blitter, &blit); |
||
873 | r600_blitter_end(ctx); |
||
874 | |||
875 | pipe_resource_reference(&tmp, NULL); |
||
876 | } |
||
877 | |||
878 | static void r600_blit(struct pipe_context *ctx, |
||
879 | const struct pipe_blit_info *info) |
||
880 | { |
||
881 | struct r600_context *rctx = (struct r600_context*)ctx; |
||
882 | |||
883 | assert(util_blitter_is_blit_supported(rctx->blitter, info)); |
||
884 | |||
885 | if (info->src.resource->nr_samples > 1 && |
||
886 | info->dst.resource->nr_samples <= 1 && |
||
887 | !util_format_is_depth_or_stencil(info->src.resource->format) && |
||
888 | !util_format_is_pure_integer(int_to_norm_format(info->src.resource->format))) { |
||
889 | r600_msaa_color_resolve(ctx, info); |
||
890 | return; |
||
891 | } |
||
892 | |||
893 | /* The driver doesn't decompress resources automatically while |
||
894 | * u_blitter is rendering. */ |
||
895 | if (!r600_decompress_subresource(ctx, info->src.resource, info->src.level, |
||
896 | info->src.box.z, |
||
897 | info->src.box.z + info->src.box.depth - 1)) { |
||
898 | return; /* error */ |
||
899 | } |
||
900 | |||
901 | r600_blitter_begin(ctx, R600_BLIT); |
||
902 | util_blitter_blit(rctx->blitter, info); |
||
903 | r600_blitter_end(ctx); |
||
904 | } |
||
905 | |||
906 | void r600_init_blit_functions(struct r600_context *rctx) |
||
907 | { |
||
908 | rctx->context.clear = r600_clear; |
||
909 | rctx->context.clear_render_target = r600_clear_render_target; |
||
910 | rctx->context.clear_depth_stencil = r600_clear_depth_stencil; |
||
911 | rctx->context.resource_copy_region = r600_resource_copy_region; |
||
912 | rctx->context.blit = r600_blit; |
||
913 | }=>><>><>><>><>><>><>><>><>>>>><>=>>><>=>><>=>>><>=>><>><>=>=>>><>=> |