ilo: replace cp hooks by cp owner and flush callback
[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_blitter.h"
29 #include "util/u_clear.h"
30 #include "util/u_pack_color.h"
31 #include "util/u_surface.h"
32 #include "intel_reg.h"
33
34 #include "ilo_context.h"
35 #include "ilo_cp.h"
36 #include "ilo_resource.h"
37 #include "ilo_screen.h"
38 #include "ilo_blit.h"
39
40 static bool
41 blitter_xy_color_blt(struct pipe_context *pipe,
42 struct pipe_resource *res,
43 int16_t x1, int16_t y1,
44 int16_t x2, int16_t y2,
45 uint32_t color)
46 {
47 const int cmd_len = 6;
48 struct ilo_context *ilo = ilo_context(pipe);
49 struct ilo_texture *tex = ilo_texture(res);
50 uint32_t cmd, br13;
51 int cpp, stride;
52 struct intel_bo *bo_check[2];
53
54 /* how to support Y-tiling? */
55 if (tex->tiling == INTEL_TILING_Y)
56 return false;
57
58 /* nothing to clear */
59 if (x1 >= x2 || y1 >= y2)
60 return true;
61
62 cmd = XY_COLOR_BLT_CMD | (cmd_len - 2);
63 br13 = 0xf0 << 16;
64
65 cpp = util_format_get_blocksize(tex->base.format);
66 switch (cpp) {
67 case 4:
68 cmd |= XY_BLT_WRITE_ALPHA | XY_BLT_WRITE_RGB;
69 br13 |= BR13_8888;
70 break;
71 case 2:
72 br13 |= BR13_565;
73 break;
74 case 1:
75 br13 |= BR13_8;
76 break;
77 default:
78 return false;
79 break;
80 }
81
82 stride = tex->bo_stride;
83 if (tex->tiling != INTEL_TILING_NONE) {
84 assert(tex->tiling == INTEL_TILING_X);
85
86 cmd |= XY_DST_TILED;
87 /* in dwords */
88 stride /= 4;
89 }
90
91 ilo_cp_set_ring(ilo->cp, ILO_CP_RING_BLT);
92 ilo_cp_set_owner(ilo->cp, NULL, 0);
93
94 /* make room if necessary */
95 bo_check[0] = ilo->cp->bo;
96 bo_check[1] = tex->bo;
97 if (ilo->winsys->check_aperture_space(ilo->winsys, bo_check, 2))
98 ilo_cp_flush(ilo->cp);
99
100 ilo_cp_begin(ilo->cp, cmd_len);
101 ilo_cp_write(ilo->cp, cmd);
102 ilo_cp_write(ilo->cp, br13 | stride);
103 ilo_cp_write(ilo->cp, (y1 << 16) | x1);
104 ilo_cp_write(ilo->cp, (y2 << 16) | x2);
105 ilo_cp_write_bo(ilo->cp, 0, tex->bo,
106 INTEL_DOMAIN_RENDER,
107 INTEL_DOMAIN_RENDER);
108 ilo_cp_write(ilo->cp, color);
109 ilo_cp_end(ilo->cp);
110
111 return true;
112 }
113
114 enum ilo_blitter_op {
115 ILO_BLITTER_CLEAR,
116 ILO_BLITTER_CLEAR_SURFACE,
117 ILO_BLITTER_BLIT,
118 };
119
120 static void
121 ilo_blitter_begin(struct ilo_context *ilo, enum ilo_blitter_op op)
122 {
123 /* as documented in util/u_blitter.h */
124 util_blitter_save_vertex_buffer_slot(ilo->blitter,
125 ilo->vertex_buffers.buffers);
126 util_blitter_save_vertex_elements(ilo->blitter, ilo->vertex_elements);
127 util_blitter_save_vertex_shader(ilo->blitter, ilo->vs);
128 util_blitter_save_geometry_shader(ilo->blitter, ilo->gs);
129 util_blitter_save_so_targets(ilo->blitter,
130 ilo->stream_output_targets.num_targets,
131 ilo->stream_output_targets.targets);
132
133 util_blitter_save_fragment_shader(ilo->blitter, ilo->fs);
134 util_blitter_save_depth_stencil_alpha(ilo->blitter,
135 ilo->depth_stencil_alpha);
136 util_blitter_save_blend(ilo->blitter, ilo->blend);
137
138 /* undocumented? */
139 util_blitter_save_viewport(ilo->blitter, &ilo->viewport);
140 util_blitter_save_stencil_ref(ilo->blitter, &ilo->stencil_ref);
141 util_blitter_save_sample_mask(ilo->blitter, ilo->sample_mask);
142
143 switch (op) {
144 case ILO_BLITTER_CLEAR:
145 util_blitter_save_rasterizer(ilo->blitter, ilo->rasterizer);
146 break;
147 case ILO_BLITTER_CLEAR_SURFACE:
148 util_blitter_save_framebuffer(ilo->blitter, &ilo->framebuffer);
149 break;
150 case ILO_BLITTER_BLIT:
151 util_blitter_save_rasterizer(ilo->blitter, ilo->rasterizer);
152 util_blitter_save_framebuffer(ilo->blitter, &ilo->framebuffer);
153
154 util_blitter_save_fragment_sampler_states(ilo->blitter,
155 ilo->samplers[PIPE_SHADER_FRAGMENT].num_samplers,
156 (void **) ilo->samplers[PIPE_SHADER_FRAGMENT].samplers);
157
158 util_blitter_save_fragment_sampler_views(ilo->blitter,
159 ilo->sampler_views[PIPE_SHADER_FRAGMENT].num_views,
160 ilo->sampler_views[PIPE_SHADER_FRAGMENT].views);
161
162 /* disable render condition? */
163 break;
164 default:
165 break;
166 }
167 }
168
169 static void
170 ilo_blitter_end(struct ilo_context *ilo)
171 {
172 }
173
174 static void
175 ilo_clear(struct pipe_context *pipe,
176 unsigned buffers,
177 const union pipe_color_union *color,
178 double depth,
179 unsigned stencil)
180 {
181 struct ilo_context *ilo = ilo_context(pipe);
182
183 /* TODO we should pause/resume some queries */
184 ilo_blitter_begin(ilo, ILO_BLITTER_CLEAR);
185
186 util_blitter_clear(ilo->blitter,
187 ilo->framebuffer.width, ilo->framebuffer.height,
188 ilo->framebuffer.nr_cbufs, buffers,
189 (ilo->framebuffer.nr_cbufs) ? ilo->framebuffer.cbufs[0]->format :
190 PIPE_FORMAT_NONE,
191 color, depth, stencil);
192
193 ilo_blitter_end(ilo);
194 }
195
196 static void
197 ilo_clear_render_target(struct pipe_context *pipe,
198 struct pipe_surface *dst,
199 const union pipe_color_union *color,
200 unsigned dstx, unsigned dsty,
201 unsigned width, unsigned height)
202 {
203 struct ilo_context *ilo = ilo_context(pipe);
204 union util_color packed;
205
206 if (!width || !height || dstx >= dst->width || dsty >= dst->height)
207 return;
208
209 if (dstx + width > dst->width)
210 width = dst->width - dstx;
211 if (dsty + height > dst->height)
212 height = dst->height - dsty;
213
214 util_pack_color(color->f, dst->format, &packed);
215
216 /* try HW blit first */
217 if (blitter_xy_color_blt(pipe, dst->texture,
218 dstx, dsty,
219 dstx + width, dsty + height,
220 packed.ui))
221 return;
222
223 ilo_blitter_begin(ilo, ILO_BLITTER_CLEAR_SURFACE);
224 util_blitter_clear_render_target(ilo->blitter,
225 dst, color, dstx, dsty, width, height);
226 ilo_blitter_end(ilo);
227 }
228
229 static void
230 ilo_clear_depth_stencil(struct pipe_context *pipe,
231 struct pipe_surface *dst,
232 unsigned clear_flags,
233 double depth,
234 unsigned stencil,
235 unsigned dstx, unsigned dsty,
236 unsigned width, unsigned height)
237 {
238 struct ilo_context *ilo = ilo_context(pipe);
239
240 /*
241 * The PRM claims that HW blit supports Y-tiling since GEN6, but it does
242 * not tell us how to program it. Since depth buffers are always Y-tiled,
243 * HW blit will not work.
244 */
245 ilo_blitter_begin(ilo, ILO_BLITTER_CLEAR_SURFACE);
246 util_blitter_clear_depth_stencil(ilo->blitter,
247 dst, clear_flags, depth, stencil, dstx, dsty, width, height);
248 ilo_blitter_end(ilo);
249 }
250
251 static void
252 ilo_blit(struct pipe_context *pipe, const struct pipe_blit_info *info)
253 {
254 struct ilo_context *ilo = ilo_context(pipe);
255 struct pipe_blit_info skip_stencil;
256
257 if (util_try_blit_via_copy_region(pipe, info))
258 return;
259
260 if (!util_blitter_is_blit_supported(ilo->blitter, info)) {
261 /* try without stencil */
262 if (info->mask & PIPE_MASK_S) {
263 skip_stencil = *info;
264 skip_stencil.mask = info->mask & ~PIPE_MASK_S;
265
266 if (util_blitter_is_blit_supported(ilo->blitter, &skip_stencil))
267 info = &skip_stencil;
268 }
269
270 if (info == &skip_stencil) {
271 ilo_warn("ignore stencil buffer blitting\n");
272 }
273 else {
274 ilo_warn("failed to blit with the generic blitter\n");
275 return;
276 }
277 }
278
279 ilo_blitter_begin(ilo, ILO_BLITTER_BLIT);
280 util_blitter_blit(ilo->blitter, info);
281 ilo_blitter_end(ilo);
282 }
283
284 /**
285 * Initialize blit-related functions.
286 */
287 void
288 ilo_init_blit_functions(struct ilo_context *ilo)
289 {
290 ilo->base.resource_copy_region = util_resource_copy_region;
291 ilo->base.blit = ilo_blit;
292
293 ilo->base.clear = ilo_clear;
294 ilo->base.clear_render_target = ilo_clear_render_target;
295 ilo->base.clear_depth_stencil = ilo_clear_depth_stencil;
296 }