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