ilo: resolve Z/HiZ correctly
[mesa.git] / src / gallium / drivers / ilo / ilo_blit.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2012-2013 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Chia-I Wu <olv@lunarg.com>
26 */
27
28 #include "util/u_surface.h"
29
30 #include "ilo_blitter.h"
31 #include "ilo_context.h"
32 #include "ilo_blit.h"
33
34 static void
35 ilo_resource_copy_region(struct pipe_context *pipe,
36 struct pipe_resource *dst,
37 unsigned dst_level,
38 unsigned dstx, unsigned dsty, unsigned dstz,
39 struct pipe_resource *src,
40 unsigned src_level,
41 const struct pipe_box *src_box)
42 {
43 struct ilo_context *ilo = ilo_context(pipe);
44
45 if (ilo_blitter_blt_copy_resource(ilo->blitter,
46 dst, dst_level, dstx, dsty, dstz,
47 src, src_level, src_box))
48 return;
49
50 if (ilo_blitter_pipe_copy_resource(ilo->blitter,
51 dst, dst_level, dstx, dsty, dstz,
52 src, src_level, src_box))
53 return;
54
55 util_resource_copy_region(&ilo->base, dst, dst_level,
56 dstx, dsty, dstz, src, src_level, src_box);
57 }
58
59 static void
60 ilo_clear(struct pipe_context *pipe,
61 unsigned buffers,
62 const union pipe_color_union *color,
63 double depth,
64 unsigned stencil)
65 {
66 struct ilo_context *ilo = ilo_context(pipe);
67
68 ilo_blitter_pipe_clear_fb(ilo->blitter, buffers, color, depth, stencil);
69 }
70
71 static void
72 ilo_clear_render_target(struct pipe_context *pipe,
73 struct pipe_surface *dst,
74 const union pipe_color_union *color,
75 unsigned dstx, unsigned dsty,
76 unsigned width, unsigned height)
77 {
78 struct ilo_context *ilo = ilo_context(pipe);
79
80 if (!width || !height || dstx >= dst->width || dsty >= dst->height)
81 return;
82
83 if (dstx + width > dst->width)
84 width = dst->width - dstx;
85 if (dsty + height > dst->height)
86 height = dst->height - dsty;
87
88 if (ilo_blitter_blt_clear_rt(ilo->blitter,
89 dst, color, dstx, dsty, width, height))
90 return;
91
92 ilo_blitter_pipe_clear_rt(ilo->blitter,
93 dst, color, dstx, dsty, width, height);
94 }
95
96 static void
97 ilo_clear_depth_stencil(struct pipe_context *pipe,
98 struct pipe_surface *dst,
99 unsigned clear_flags,
100 double depth,
101 unsigned stencil,
102 unsigned dstx, unsigned dsty,
103 unsigned width, unsigned height)
104 {
105 struct ilo_context *ilo = ilo_context(pipe);
106
107 if (!width || !height || dstx >= dst->width || dsty >= dst->height)
108 return;
109
110 if (dstx + width > dst->width)
111 width = dst->width - dstx;
112 if (dsty + height > dst->height)
113 height = dst->height - dsty;
114
115 if (ilo_blitter_blt_clear_zs(ilo->blitter,
116 dst, clear_flags, depth, stencil, dstx, dsty, width, height))
117 return;
118
119 ilo_blitter_pipe_clear_zs(ilo->blitter,
120 dst, clear_flags, depth, stencil, dstx, dsty, width, height);
121 }
122
123 static void
124 ilo_blit(struct pipe_context *pipe, const struct pipe_blit_info *info)
125 {
126 struct ilo_context *ilo = ilo_context(pipe);
127
128 ilo_blitter_pipe_blit(ilo->blitter, info);
129 }
130
131 static void
132 ilo_flush_resource(struct pipe_context *pipe, struct pipe_resource *res)
133 {
134 struct ilo_context *ilo = ilo_context(pipe);
135 const unsigned flags = ILO_TEXTURE_CPU_READ |
136 ILO_TEXTURE_BLT_READ |
137 ILO_TEXTURE_RENDER_READ;
138
139 ilo_blit_resolve_resource(ilo, res, flags);
140 }
141
142 void
143 ilo_blit_resolve_slices_for_hiz(struct ilo_context *ilo,
144 struct pipe_resource *res, unsigned level,
145 unsigned first_slice, unsigned num_slices,
146 unsigned flags)
147 {
148 struct ilo_texture *tex = ilo_texture(res);
149 const unsigned any_reader =
150 ILO_TEXTURE_RENDER_READ |
151 ILO_TEXTURE_BLT_READ |
152 ILO_TEXTURE_CPU_READ;
153 const unsigned other_writers =
154 ILO_TEXTURE_BLT_WRITE |
155 ILO_TEXTURE_CPU_WRITE;
156 unsigned i;
157
158 assert(tex->base.target != PIPE_BUFFER && tex->hiz.bo);
159
160 if (flags & ILO_TEXTURE_RENDER_WRITE) {
161 /*
162 * When ILO_TEXTURE_RENDER_WRITE is set, there can be no reader. We
163 * need to perform a HiZ Buffer Resolve in case the resource was
164 * previously written by another writer, unless this is a clear.
165 */
166 assert(!(flags & (other_writers | any_reader)));
167
168 if (!(flags & ILO_TEXTURE_CLEAR)) {
169 for (i = 0; i < num_slices; i++) {
170 const struct ilo_texture_slice *slice =
171 ilo_texture_get_slice(tex, level, first_slice + i);
172
173 if (slice->flags & other_writers) {
174 ilo_blitter_rectlist_resolve_hiz(ilo->blitter,
175 res, level, first_slice + i);
176 }
177 }
178 }
179 }
180 else if ((flags & any_reader) ||
181 ((flags & other_writers) && !(flags & ILO_TEXTURE_CLEAR))) {
182 /*
183 * When there is at least a reader or writer, we need to perform a
184 * Depth Buffer Resolve in case the resource was previously written
185 * by ILO_TEXTURE_RENDER_WRITE.
186 */
187 for (i = 0; i < num_slices; i++) {
188 const struct ilo_texture_slice *slice =
189 ilo_texture_get_slice(tex, level, first_slice + i);
190
191 if (slice->flags & ILO_TEXTURE_RENDER_WRITE) {
192 ilo_blitter_rectlist_resolve_z(ilo->blitter,
193 &tex->base, level, first_slice + i);
194 }
195 }
196 }
197 }
198
199 /**
200 * Initialize blit-related functions.
201 */
202 void
203 ilo_init_blit_functions(struct ilo_context *ilo)
204 {
205 ilo->base.resource_copy_region = ilo_resource_copy_region;
206 ilo->base.blit = ilo_blit;
207 ilo->base.flush_resource = ilo_flush_resource;
208
209 ilo->base.clear = ilo_clear;
210 ilo->base.clear_render_target = ilo_clear_render_target;
211 ilo->base.clear_depth_stencil = ilo_clear_depth_stencil;
212 }