Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | /* |
2 | * Mesa 3-D graphics library |
||
3 | * |
||
4 | * Copyright (C) 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 |
||
26 | */ |
||
27 | |||
28 | #include "util/u_pack_color.h" |
||
29 | #include "intel_reg.h" |
||
30 | |||
31 | #include "ilo_3d.h" |
||
32 | #include "ilo_context.h" |
||
33 | #include "ilo_cp.h" |
||
34 | #include "ilo_resource.h" |
||
35 | #include "ilo_blitter.h" |
||
36 | |||
37 | #ifndef COLOR_BLT_CMD |
||
38 | #define COLOR_BLT_CMD (CMD_2D | (0x40 << 22)) |
||
39 | #endif |
||
40 | |||
41 | #ifndef SRC_COPY_BLT_CMD |
||
42 | #define SRC_COPY_BLT_CMD (CMD_2D | (0x43 << 22)) |
||
43 | #endif |
||
44 | |||
45 | enum gen6_blt_mask { |
||
46 | GEN6_BLT_MASK_8, |
||
47 | GEN6_BLT_MASK_16, |
||
48 | GEN6_BLT_MASK_32, |
||
49 | GEN6_BLT_MASK_32_LO, |
||
50 | GEN6_BLT_MASK_32_HI, |
||
51 | }; |
||
52 | |||
53 | /* |
||
54 | * From the Sandy Bridge PRM, volume 1 part 5, page 7: |
||
55 | * |
||
56 | * "The BLT engine is capable of transferring very large quantities of |
||
57 | * graphics data. Any graphics data read from and written to the |
||
58 | * destination is permitted to represent a number of pixels that occupies |
||
59 | * up to 65,536 scan lines and up to 32,768 bytes per scan line at the |
||
60 | * destination. The maximum number of pixels that may be represented per |
||
61 | * scan line's worth of graphics data depends on the color depth." |
||
62 | */ |
||
63 | static const int gen6_max_bytes_per_scanline = 32768; |
||
64 | static const int gen6_max_scanlines = 65536; |
||
65 | |||
66 | static void |
||
67 | gen6_emit_MI_FLUSH_DW(struct ilo_dev_info *dev, struct ilo_cp *cp) |
||
68 | { |
||
69 | const uint8_t cmd_len = 4; |
||
70 | |||
71 | ilo_cp_begin(cp, cmd_len); |
||
72 | ilo_cp_write(cp, MI_FLUSH_DW | (cmd_len - 2)); |
||
73 | ilo_cp_write(cp, 0); |
||
74 | ilo_cp_write(cp, 0); |
||
75 | ilo_cp_write(cp, 0); |
||
76 | ilo_cp_end(cp); |
||
77 | } |
||
78 | |||
79 | static void |
||
80 | gen6_emit_MI_LOAD_REGISTER_IMM(struct ilo_dev_info *dev, |
||
81 | uint32_t reg, uint32_t val, |
||
82 | struct ilo_cp *cp) |
||
83 | { |
||
84 | const uint8_t cmd_len = 3; |
||
85 | |||
86 | ilo_cp_begin(cp, cmd_len); |
||
87 | ilo_cp_write(cp, MI_LOAD_REGISTER_IMM | (cmd_len - 2)); |
||
88 | ilo_cp_write(cp, reg); |
||
89 | ilo_cp_write(cp, val); |
||
90 | ilo_cp_end(cp); |
||
91 | } |
||
92 | |||
93 | static uint32_t |
||
94 | gen6_translate_blt_value_mask(enum gen6_blt_mask value_mask) |
||
95 | { |
||
96 | switch (value_mask) { |
||
97 | case GEN6_BLT_MASK_8: return BR13_8; |
||
98 | case GEN6_BLT_MASK_16: return BR13_565; |
||
99 | default: return BR13_8888; |
||
100 | } |
||
101 | } |
||
102 | |||
103 | static uint32_t |
||
104 | gen6_translate_blt_write_mask(enum gen6_blt_mask write_mask) |
||
105 | { |
||
106 | switch (write_mask) { |
||
107 | case GEN6_BLT_MASK_32: return XY_BLT_WRITE_RGB | |
||
108 | XY_BLT_WRITE_ALPHA; |
||
109 | case GEN6_BLT_MASK_32_LO: return XY_BLT_WRITE_RGB; |
||
110 | case GEN6_BLT_MASK_32_HI: return XY_BLT_WRITE_ALPHA; |
||
111 | default: return 0; |
||
112 | } |
||
113 | } |
||
114 | |||
115 | static uint32_t |
||
116 | gen6_translate_blt_cpp(enum gen6_blt_mask mask) |
||
117 | { |
||
118 | switch (mask) { |
||
119 | case GEN6_BLT_MASK_8: return 1; |
||
120 | case GEN6_BLT_MASK_16: return 2; |
||
121 | default: return 4; |
||
122 | } |
||
123 | } |
||
124 | |||
125 | static void |
||
126 | gen6_emit_COLOR_BLT(struct ilo_dev_info *dev, |
||
127 | struct intel_bo *dst_bo, |
||
128 | int16_t dst_pitch, uint32_t dst_offset, |
||
129 | uint16_t width, uint16_t height, |
||
130 | uint32_t pattern, uint8_t rop, |
||
131 | enum gen6_blt_mask value_mask, |
||
132 | enum gen6_blt_mask write_mask, |
||
133 | struct ilo_cp *cp) |
||
134 | { |
||
135 | const uint8_t cmd_len = 5; |
||
136 | const int cpp = gen6_translate_blt_cpp(value_mask); |
||
137 | uint32_t dw0, dw1; |
||
138 | |||
139 | dw0 = COLOR_BLT_CMD | |
||
140 | gen6_translate_blt_write_mask(write_mask) | |
||
141 | (cmd_len - 2); |
||
142 | |||
143 | assert(width < gen6_max_bytes_per_scanline); |
||
144 | assert(height < gen6_max_scanlines); |
||
145 | /* offsets are naturally aligned and pitches are dword-aligned */ |
||
146 | assert(dst_offset % cpp == 0 && dst_pitch % 4 == 0); |
||
147 | |||
148 | dw1 = rop << 16 | |
||
149 | gen6_translate_blt_value_mask(value_mask) | |
||
150 | dst_pitch; |
||
151 | |||
152 | ilo_cp_begin(cp, cmd_len); |
||
153 | ilo_cp_write(cp, dw0); |
||
154 | ilo_cp_write(cp, dw1); |
||
155 | ilo_cp_write(cp, height << 16 | width); |
||
156 | ilo_cp_write_bo(cp, dst_offset, dst_bo, INTEL_DOMAIN_RENDER, |
||
157 | INTEL_DOMAIN_RENDER); |
||
158 | ilo_cp_write(cp, pattern); |
||
159 | ilo_cp_end(cp); |
||
160 | } |
||
161 | |||
162 | static void |
||
163 | gen6_emit_XY_COLOR_BLT(struct ilo_dev_info *dev, |
||
164 | struct intel_bo *dst_bo, |
||
165 | enum intel_tiling_mode dst_tiling, |
||
166 | int16_t dst_pitch, uint32_t dst_offset, |
||
167 | int16_t x1, int16_t y1, int16_t x2, int16_t y2, |
||
168 | uint32_t pattern, uint8_t rop, |
||
169 | enum gen6_blt_mask value_mask, |
||
170 | enum gen6_blt_mask write_mask, |
||
171 | struct ilo_cp *cp) |
||
172 | { |
||
173 | const uint8_t cmd_len = 6; |
||
174 | const int cpp = gen6_translate_blt_cpp(value_mask); |
||
175 | int dst_align, dst_pitch_shift; |
||
176 | uint32_t dw0, dw1; |
||
177 | |||
178 | dw0 = XY_COLOR_BLT_CMD | |
||
179 | gen6_translate_blt_write_mask(write_mask) | |
||
180 | (cmd_len - 2); |
||
181 | |||
182 | if (dst_tiling == INTEL_TILING_NONE) { |
||
183 | dst_align = 4; |
||
184 | dst_pitch_shift = 0; |
||
185 | } |
||
186 | else { |
||
187 | dw0 |= XY_DST_TILED; |
||
188 | |||
189 | dst_align = (dst_tiling == INTEL_TILING_Y) ? 128 : 512; |
||
190 | /* in dwords when tiled */ |
||
191 | dst_pitch_shift = 2; |
||
192 | } |
||
193 | |||
194 | assert((x2 - x1) * cpp < gen6_max_bytes_per_scanline); |
||
195 | assert(y2 - y1 < gen6_max_scanlines); |
||
196 | assert(dst_offset % dst_align == 0 && dst_pitch % dst_align == 0); |
||
197 | |||
198 | dw1 = rop << 16 | |
||
199 | gen6_translate_blt_value_mask(value_mask) | |
||
200 | dst_pitch >> dst_pitch_shift; |
||
201 | |||
202 | ilo_cp_begin(cp, cmd_len); |
||
203 | ilo_cp_write(cp, dw0); |
||
204 | ilo_cp_write(cp, dw1); |
||
205 | ilo_cp_write(cp, y1 << 16 | x1); |
||
206 | ilo_cp_write(cp, y2 << 16 | x2); |
||
207 | ilo_cp_write_bo(cp, dst_offset, dst_bo, |
||
208 | INTEL_DOMAIN_RENDER, INTEL_DOMAIN_RENDER); |
||
209 | ilo_cp_write(cp, pattern); |
||
210 | ilo_cp_end(cp); |
||
211 | } |
||
212 | |||
213 | static void |
||
214 | gen6_emit_SRC_COPY_BLT(struct ilo_dev_info *dev, |
||
215 | struct intel_bo *dst_bo, |
||
216 | int16_t dst_pitch, uint32_t dst_offset, |
||
217 | uint16_t width, uint16_t height, |
||
218 | struct intel_bo *src_bo, |
||
219 | int16_t src_pitch, uint32_t src_offset, |
||
220 | bool dir_rtl, uint8_t rop, |
||
221 | enum gen6_blt_mask value_mask, |
||
222 | enum gen6_blt_mask write_mask, |
||
223 | struct ilo_cp *cp) |
||
224 | { |
||
225 | const uint8_t cmd_len = 6; |
||
226 | const int cpp = gen6_translate_blt_cpp(value_mask); |
||
227 | uint32_t dw0, dw1; |
||
228 | |||
229 | dw0 = SRC_COPY_BLT_CMD | |
||
230 | gen6_translate_blt_write_mask(write_mask) | |
||
231 | (cmd_len - 2); |
||
232 | |||
233 | assert(width < gen6_max_bytes_per_scanline); |
||
234 | assert(height < gen6_max_scanlines); |
||
235 | /* offsets are naturally aligned and pitches are dword-aligned */ |
||
236 | assert(dst_offset % cpp == 0 && dst_pitch % 4 == 0); |
||
237 | assert(src_offset % cpp == 0 && src_pitch % 4 == 0); |
||
238 | |||
239 | dw1 = rop << 16 | |
||
240 | gen6_translate_blt_value_mask(value_mask) | |
||
241 | dst_pitch; |
||
242 | |||
243 | if (dir_rtl) |
||
244 | dw1 |= 1 << 30; |
||
245 | |||
246 | ilo_cp_begin(cp, cmd_len); |
||
247 | ilo_cp_write(cp, dw0); |
||
248 | ilo_cp_write(cp, dw1); |
||
249 | ilo_cp_write(cp, height << 16 | width); |
||
250 | ilo_cp_write_bo(cp, dst_offset, dst_bo, INTEL_DOMAIN_RENDER, |
||
251 | INTEL_DOMAIN_RENDER); |
||
252 | ilo_cp_write(cp, src_pitch); |
||
253 | ilo_cp_write_bo(cp, src_offset, src_bo, INTEL_DOMAIN_RENDER, 0); |
||
254 | ilo_cp_end(cp); |
||
255 | } |
||
256 | |||
257 | static void |
||
258 | gen6_emit_XY_SRC_COPY_BLT(struct ilo_dev_info *dev, |
||
259 | struct intel_bo *dst_bo, |
||
260 | enum intel_tiling_mode dst_tiling, |
||
261 | int16_t dst_pitch, uint32_t dst_offset, |
||
262 | int16_t x1, int16_t y1, int16_t x2, int16_t y2, |
||
263 | struct intel_bo *src_bo, |
||
264 | enum intel_tiling_mode src_tiling, |
||
265 | int16_t src_pitch, uint32_t src_offset, |
||
266 | int16_t src_x, int16_t src_y, uint8_t rop, |
||
267 | enum gen6_blt_mask value_mask, |
||
268 | enum gen6_blt_mask write_mask, |
||
269 | struct ilo_cp *cp) |
||
270 | { |
||
271 | const uint8_t cmd_len = 8; |
||
272 | const int cpp = gen6_translate_blt_cpp(value_mask); |
||
273 | int dst_align, dst_pitch_shift; |
||
274 | int src_align, src_pitch_shift; |
||
275 | uint32_t dw0, dw1; |
||
276 | |||
277 | dw0 = XY_SRC_COPY_BLT_CMD | |
||
278 | gen6_translate_blt_write_mask(write_mask) | |
||
279 | (cmd_len - 2); |
||
280 | |||
281 | if (dst_tiling == INTEL_TILING_NONE) { |
||
282 | dst_align = 4; |
||
283 | dst_pitch_shift = 0; |
||
284 | } |
||
285 | else { |
||
286 | dw0 |= XY_DST_TILED; |
||
287 | |||
288 | dst_align = (dst_tiling == INTEL_TILING_Y) ? 128 : 512; |
||
289 | /* in dwords when tiled */ |
||
290 | dst_pitch_shift = 2; |
||
291 | } |
||
292 | |||
293 | if (src_tiling == INTEL_TILING_NONE) { |
||
294 | src_align = 4; |
||
295 | src_pitch_shift = 0; |
||
296 | } |
||
297 | else { |
||
298 | dw0 |= XY_SRC_TILED; |
||
299 | |||
300 | src_align = (src_tiling == INTEL_TILING_Y) ? 128 : 512; |
||
301 | /* in dwords when tiled */ |
||
302 | src_pitch_shift = 2; |
||
303 | } |
||
304 | |||
305 | assert((x2 - x1) * cpp < gen6_max_bytes_per_scanline); |
||
306 | assert(y2 - y1 < gen6_max_scanlines); |
||
307 | assert(dst_offset % dst_align == 0 && dst_pitch % dst_align == 0); |
||
308 | assert(src_offset % src_align == 0 && src_pitch % src_align == 0); |
||
309 | |||
310 | dw1 = rop << 16 | |
||
311 | gen6_translate_blt_value_mask(value_mask) | |
||
312 | dst_pitch >> dst_pitch_shift; |
||
313 | |||
314 | ilo_cp_begin(cp, cmd_len); |
||
315 | ilo_cp_write(cp, dw0); |
||
316 | ilo_cp_write(cp, dw1); |
||
317 | ilo_cp_write(cp, y1 << 16 | x1); |
||
318 | ilo_cp_write(cp, y2 << 16 | x2); |
||
319 | ilo_cp_write_bo(cp, dst_offset, dst_bo, INTEL_DOMAIN_RENDER, |
||
320 | INTEL_DOMAIN_RENDER); |
||
321 | ilo_cp_write(cp, src_y << 16 | src_x); |
||
322 | ilo_cp_write(cp, src_pitch >> src_pitch_shift); |
||
323 | ilo_cp_write_bo(cp, src_offset, src_bo, INTEL_DOMAIN_RENDER, 0); |
||
324 | ilo_cp_end(cp); |
||
325 | } |
||
326 | |||
327 | static uint32_t |
||
328 | ilo_blitter_blt_begin(struct ilo_blitter *blitter, int max_cmd_size, |
||
329 | struct intel_bo *dst, enum intel_tiling_mode dst_tiling, |
||
330 | struct intel_bo *src, enum intel_tiling_mode src_tiling) |
||
331 | { |
||
332 | struct ilo_context *ilo = blitter->ilo; |
||
333 | struct intel_bo *aper_check[3]; |
||
334 | int count; |
||
335 | uint32_t swctrl; |
||
336 | |||
337 | /* change ring */ |
||
338 | ilo_cp_set_ring(ilo->cp, ILO_CP_RING_BLT); |
||
339 | ilo_cp_set_owner(ilo->cp, NULL, 0); |
||
340 | |||
341 | /* check aperture space */ |
||
342 | aper_check[0] = ilo->cp->bo; |
||
343 | aper_check[1] = dst; |
||
344 | count = 2; |
||
345 | |||
346 | if (src) { |
||
347 | aper_check[2] = src; |
||
348 | count++; |
||
349 | } |
||
350 | |||
351 | if (intel_winsys_check_aperture_space(ilo->winsys, aper_check, count)) |
||
352 | ilo_cp_flush(ilo->cp); |
||
353 | |||
354 | /* set BCS_SWCTRL */ |
||
355 | swctrl = 0x0; |
||
356 | |||
357 | if (dst_tiling == INTEL_TILING_Y) { |
||
358 | swctrl |= BCS_SWCTRL_DST_Y << 16 | |
||
359 | BCS_SWCTRL_DST_Y; |
||
360 | } |
||
361 | |||
362 | if (src && src_tiling == INTEL_TILING_Y) { |
||
363 | swctrl |= BCS_SWCTRL_SRC_Y << 16 | |
||
364 | BCS_SWCTRL_SRC_Y; |
||
365 | } |
||
366 | |||
367 | if (swctrl) { |
||
368 | /* |
||
369 | * Most clients expect BLT engine to be stateless. If we have to set |
||
370 | * BCS_SWCTRL to a non-default value, we have to set it back in the same |
||
371 | * batch buffer. |
||
372 | */ |
||
373 | if (ilo_cp_space(ilo->cp) < (4 + 3) * 2 + max_cmd_size) |
||
374 | ilo_cp_flush(ilo->cp); |
||
375 | |||
376 | ilo_cp_assert_no_implicit_flush(ilo->cp, true); |
||
377 | |||
378 | /* |
||
379 | * From the Ivy Bridge PRM, volume 1 part 4, page 133: |
||
380 | * |
||
381 | * "SW is required to flush the HW before changing the polarity of |
||
382 | * this bit (Tile Y Destination/Source)." |
||
383 | */ |
||
384 | gen6_emit_MI_FLUSH_DW(ilo->dev, ilo->cp); |
||
385 | gen6_emit_MI_LOAD_REGISTER_IMM(ilo->dev, BCS_SWCTRL, swctrl, ilo->cp); |
||
386 | |||
387 | swctrl &= ~(BCS_SWCTRL_DST_Y | BCS_SWCTRL_SRC_Y); |
||
388 | } |
||
389 | |||
390 | return swctrl; |
||
391 | } |
||
392 | |||
393 | static void |
||
394 | ilo_blitter_blt_end(struct ilo_blitter *blitter, uint32_t swctrl) |
||
395 | { |
||
396 | struct ilo_context *ilo = blitter->ilo; |
||
397 | |||
398 | /* set BCS_SWCTRL back */ |
||
399 | if (swctrl) { |
||
400 | gen6_emit_MI_FLUSH_DW(ilo->dev, ilo->cp); |
||
401 | gen6_emit_MI_LOAD_REGISTER_IMM(ilo->dev, BCS_SWCTRL, swctrl, ilo->cp); |
||
402 | |||
403 | ilo_cp_assert_no_implicit_flush(ilo->cp, false); |
||
404 | } |
||
405 | } |
||
406 | |||
407 | static bool |
||
408 | buf_clear_region(struct ilo_blitter *blitter, |
||
409 | struct ilo_buffer *dst, |
||
410 | unsigned dst_offset, unsigned dst_size, |
||
411 | uint32_t val, |
||
412 | enum gen6_blt_mask value_mask, |
||
413 | enum gen6_blt_mask write_mask) |
||
414 | { |
||
415 | const uint8_t rop = 0xf0; /* PATCOPY */ |
||
416 | const int cpp = gen6_translate_blt_cpp(value_mask); |
||
417 | struct ilo_context *ilo = blitter->ilo; |
||
418 | unsigned offset = 0; |
||
419 | |||
420 | if (dst_offset % cpp || dst_size % cpp) |
||
421 | return false; |
||
422 | |||
423 | ilo_blitter_blt_begin(blitter, 0, |
||
424 | dst->bo, INTEL_TILING_NONE, NULL, INTEL_TILING_NONE); |
||
425 | |||
426 | while (dst_size) { |
||
427 | unsigned width, height; |
||
428 | int16_t pitch; |
||
429 | |||
430 | width = dst_size; |
||
431 | height = 1; |
||
432 | pitch = 0; |
||
433 | |||
434 | if (width > gen6_max_bytes_per_scanline) { |
||
435 | /* less than INT16_MAX and dword-aligned */ |
||
436 | pitch = 32764; |
||
437 | |||
438 | width = pitch; |
||
439 | height = dst_size / width; |
||
440 | if (height > gen6_max_scanlines) |
||
441 | height = gen6_max_scanlines; |
||
442 | } |
||
443 | |||
444 | gen6_emit_COLOR_BLT(ilo->dev, dst->bo, pitch, dst_offset + offset, |
||
445 | width, height, val, rop, value_mask, write_mask, ilo->cp); |
||
446 | |||
447 | offset += pitch * height; |
||
448 | dst_size -= width * height; |
||
449 | } |
||
450 | |||
451 | ilo_blitter_blt_end(blitter, 0); |
||
452 | |||
453 | return true; |
||
454 | } |
||
455 | |||
456 | static bool |
||
457 | buf_copy_region(struct ilo_blitter *blitter, |
||
458 | struct ilo_buffer *dst, unsigned dst_offset, |
||
459 | struct ilo_buffer *src, unsigned src_offset, |
||
460 | unsigned size) |
||
461 | { |
||
462 | const uint8_t rop = 0xcc; /* SRCCOPY */ |
||
463 | struct ilo_context *ilo = blitter->ilo; |
||
464 | unsigned offset = 0; |
||
465 | |||
466 | ilo_blitter_blt_begin(blitter, 0, |
||
467 | dst->bo, INTEL_TILING_NONE, src->bo, INTEL_TILING_NONE); |
||
468 | |||
469 | while (size) { |
||
470 | unsigned width, height; |
||
471 | int16_t pitch; |
||
472 | |||
473 | width = size; |
||
474 | height = 1; |
||
475 | pitch = 0; |
||
476 | |||
477 | if (width > gen6_max_bytes_per_scanline) { |
||
478 | /* less than INT16_MAX and dword-aligned */ |
||
479 | pitch = 32764; |
||
480 | |||
481 | width = pitch; |
||
482 | height = size / width; |
||
483 | if (height > gen6_max_scanlines) |
||
484 | height = gen6_max_scanlines; |
||
485 | } |
||
486 | |||
487 | gen6_emit_SRC_COPY_BLT(ilo->dev, |
||
488 | dst->bo, pitch, dst_offset + offset, |
||
489 | width, height, |
||
490 | src->bo, pitch, src_offset + offset, |
||
491 | false, rop, GEN6_BLT_MASK_8, GEN6_BLT_MASK_8, |
||
492 | ilo->cp); |
||
493 | |||
494 | offset += pitch * height; |
||
495 | size -= width * height; |
||
496 | } |
||
497 | |||
498 | ilo_blitter_blt_end(blitter, 0); |
||
499 | |||
500 | return true; |
||
501 | } |
||
502 | |||
503 | static bool |
||
504 | tex_clear_region(struct ilo_blitter *blitter, |
||
505 | struct ilo_texture *dst, unsigned dst_level, |
||
506 | const struct pipe_box *dst_box, |
||
507 | uint32_t val, |
||
508 | enum gen6_blt_mask value_mask, |
||
509 | enum gen6_blt_mask write_mask) |
||
510 | { |
||
511 | const int cpp = gen6_translate_blt_cpp(value_mask); |
||
512 | const unsigned max_extent = 32767; /* INT16_MAX */ |
||
513 | const uint8_t rop = 0xf0; /* PATCOPY */ |
||
514 | struct ilo_context *ilo = blitter->ilo; |
||
515 | uint32_t swctrl; |
||
516 | int slice; |
||
517 | |||
518 | /* no W-tiling support */ |
||
519 | if (dst->separate_s8) |
||
520 | return false; |
||
521 | |||
522 | if (dst->bo_stride > max_extent) |
||
523 | return false; |
||
524 | |||
525 | swctrl = ilo_blitter_blt_begin(blitter, dst_box->depth * 6, |
||
526 | dst->bo, dst->tiling, NULL, INTEL_TILING_NONE); |
||
527 | |||
528 | for (slice = 0; slice < dst_box->depth; slice++) { |
||
529 | const struct ilo_texture_slice *dst_slice = |
||
530 | &dst->slice_offsets[dst_level][dst_box->z + slice]; |
||
531 | unsigned x1, y1, x2, y2; |
||
532 | |||
533 | x1 = dst_slice->x + dst_box->x; |
||
534 | y1 = dst_slice->y + dst_box->y; |
||
535 | x2 = x1 + dst_box->width; |
||
536 | y2 = y1 + dst_box->height; |
||
537 | |||
538 | if (x2 > max_extent || y2 > max_extent || |
||
539 | (x2 - x1) * cpp > gen6_max_bytes_per_scanline) |
||
540 | break; |
||
541 | |||
542 | gen6_emit_XY_COLOR_BLT(ilo->dev, |
||
543 | dst->bo, dst->tiling, dst->bo_stride, 0, |
||
544 | x1, y1, x2, y2, val, rop, value_mask, write_mask, |
||
545 | ilo->cp); |
||
546 | } |
||
547 | |||
548 | ilo_blitter_blt_end(blitter, swctrl); |
||
549 | |||
550 | return (slice == dst_box->depth); |
||
551 | } |
||
552 | |||
553 | static bool |
||
554 | tex_copy_region(struct ilo_blitter *blitter, |
||
555 | struct ilo_texture *dst, |
||
556 | unsigned dst_level, |
||
557 | unsigned dst_x, unsigned dst_y, unsigned dst_z, |
||
558 | struct ilo_texture *src, |
||
559 | unsigned src_level, |
||
560 | const struct pipe_box *src_box) |
||
561 | { |
||
562 | const struct util_format_description *desc = |
||
563 | util_format_description(dst->bo_format); |
||
564 | const unsigned max_extent = 32767; /* INT16_MAX */ |
||
565 | const uint8_t rop = 0xcc; /* SRCCOPY */ |
||
566 | struct ilo_context *ilo = blitter->ilo; |
||
567 | enum gen6_blt_mask mask; |
||
568 | uint32_t swctrl; |
||
569 | int cpp, xscale, slice; |
||
570 | |||
571 | /* no W-tiling support */ |
||
572 | if (dst->separate_s8 || src->separate_s8) |
||
573 | return false; |
||
574 | |||
575 | if (dst->bo_stride > max_extent || src->bo_stride > max_extent) |
||
576 | return false; |
||
577 | |||
578 | cpp = desc->block.bits / 8; |
||
579 | xscale = 1; |
||
580 | |||
581 | /* accommodate for larger cpp */ |
||
582 | if (cpp > 4) { |
||
583 | if (cpp % 2 == 1) |
||
584 | return false; |
||
585 | |||
586 | cpp = (cpp % 4 == 0) ? 4 : 2; |
||
587 | xscale = (desc->block.bits / 8) / cpp; |
||
588 | } |
||
589 | |||
590 | switch (cpp) { |
||
591 | case 1: |
||
592 | mask = GEN6_BLT_MASK_8; |
||
593 | break; |
||
594 | case 2: |
||
595 | mask = GEN6_BLT_MASK_16; |
||
596 | break; |
||
597 | case 4: |
||
598 | mask = GEN6_BLT_MASK_32; |
||
599 | break; |
||
600 | default: |
||
601 | return false; |
||
602 | break; |
||
603 | } |
||
604 | |||
605 | swctrl = ilo_blitter_blt_begin(blitter, src_box->depth * 8, |
||
606 | dst->bo, dst->tiling, src->bo, src->tiling); |
||
607 | |||
608 | for (slice = 0; slice < src_box->depth; slice++) { |
||
609 | const struct ilo_texture_slice *dst_slice = |
||
610 | &dst->slice_offsets[dst_level][dst_z + slice]; |
||
611 | const struct ilo_texture_slice *src_slice = |
||
612 | &src->slice_offsets[src_level][src_box->z + slice]; |
||
613 | unsigned x1, y1, x2, y2, src_x, src_y; |
||
614 | |||
615 | x1 = (dst_slice->x + dst_x) * xscale; |
||
616 | y1 = dst_slice->y + dst_y; |
||
617 | x2 = (x1 + src_box->width) * xscale; |
||
618 | y2 = y1 + src_box->height; |
||
619 | src_x = (src_slice->x + src_box->x) * xscale; |
||
620 | src_y = src_slice->y + src_box->y; |
||
621 | |||
622 | /* in blocks */ |
||
623 | x1 /= desc->block.width; |
||
624 | y1 /= desc->block.height; |
||
625 | x2 = (x2 + desc->block.width - 1) / desc->block.width; |
||
626 | y2 = (y2 + desc->block.height - 1) / desc->block.height; |
||
627 | src_x /= desc->block.width; |
||
628 | src_y /= desc->block.height; |
||
629 | |||
630 | if (x2 > max_extent || y2 > max_extent || |
||
631 | src_x > max_extent || src_y > max_extent || |
||
632 | (x2 - x1) * cpp > gen6_max_bytes_per_scanline) |
||
633 | break; |
||
634 | |||
635 | gen6_emit_XY_SRC_COPY_BLT(ilo->dev, |
||
636 | dst->bo, dst->tiling, dst->bo_stride, 0, |
||
637 | x1, y1, x2, y2, |
||
638 | src->bo, src->tiling, src->bo_stride, 0, |
||
639 | src_x, src_y, rop, mask, mask, |
||
640 | ilo->cp); |
||
641 | } |
||
642 | |||
643 | ilo_blitter_blt_end(blitter, swctrl); |
||
644 | |||
645 | return (slice == src_box->depth); |
||
646 | } |
||
647 | |||
648 | bool |
||
649 | ilo_blitter_blt_copy_resource(struct ilo_blitter *blitter, |
||
650 | struct pipe_resource *dst, unsigned dst_level, |
||
651 | unsigned dst_x, unsigned dst_y, unsigned dst_z, |
||
652 | struct pipe_resource *src, unsigned src_level, |
||
653 | const struct pipe_box *src_box) |
||
654 | { |
||
655 | bool success; |
||
656 | |||
657 | if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) { |
||
658 | const unsigned dst_offset = dst_x; |
||
659 | const unsigned src_offset = src_box->x; |
||
660 | const unsigned size = src_box->width; |
||
661 | |||
662 | assert(dst_level == 0 && dst_y == 0 && dst_z == 0); |
||
663 | assert(src_level == 0 && |
||
664 | src_box->y == 0 && |
||
665 | src_box->z == 0 && |
||
666 | src_box->height == 1 && |
||
667 | src_box->depth == 1); |
||
668 | |||
669 | success = buf_copy_region(blitter, |
||
670 | ilo_buffer(dst), dst_offset, ilo_buffer(src), src_offset, size); |
||
671 | } |
||
672 | else if (dst->target != PIPE_BUFFER && src->target != PIPE_BUFFER) { |
||
673 | success = tex_copy_region(blitter, |
||
674 | ilo_texture(dst), dst_level, dst_x, dst_y, dst_z, |
||
675 | ilo_texture(src), src_level, src_box); |
||
676 | } |
||
677 | else { |
||
678 | success = false; |
||
679 | } |
||
680 | |||
681 | return success; |
||
682 | } |
||
683 | |||
684 | bool |
||
685 | ilo_blitter_blt_clear_rt(struct ilo_blitter *blitter, |
||
686 | struct pipe_surface *rt, |
||
687 | const union pipe_color_union *color, |
||
688 | unsigned x, unsigned y, |
||
689 | unsigned width, unsigned height) |
||
690 | { |
||
691 | const int cpp = util_format_get_blocksize(rt->format); |
||
692 | enum gen6_blt_mask mask; |
||
693 | union util_color packed; |
||
694 | bool success; |
||
695 | |||
696 | if (!ilo_3d_pass_render_condition(blitter->ilo)) |
||
697 | return true; |
||
698 | |||
699 | switch (cpp) { |
||
700 | case 1: |
||
701 | mask = GEN6_BLT_MASK_8; |
||
702 | break; |
||
703 | case 2: |
||
704 | mask = GEN6_BLT_MASK_16; |
||
705 | break; |
||
706 | case 4: |
||
707 | mask = GEN6_BLT_MASK_32; |
||
708 | break; |
||
709 | default: |
||
710 | return false; |
||
711 | break; |
||
712 | } |
||
713 | |||
714 | if (util_format_is_pure_integer(rt->format) || |
||
715 | util_format_is_compressed(rt->format)) |
||
716 | return false; |
||
717 | |||
718 | util_pack_color(color->f, rt->format, &packed); |
||
719 | |||
720 | if (rt->texture->target == PIPE_BUFFER) { |
||
721 | unsigned offset, end, size; |
||
722 | |||
723 | assert(y == 0 && height == 1); |
||
724 | |||
725 | offset = (rt->u.buf.first_element + x) * cpp; |
||
726 | end = (rt->u.buf.last_element + 1) * cpp; |
||
727 | |||
728 | size = width * cpp; |
||
729 | if (offset + size > end) |
||
730 | size = end - offset; |
||
731 | |||
732 | success = buf_clear_region(blitter, ilo_buffer(rt->texture), |
||
733 | offset, size, packed.ui, mask, mask); |
||
734 | } |
||
735 | else { |
||
736 | struct pipe_box box; |
||
737 | |||
738 | u_box_3d(x, y, rt->u.tex.first_layer, width, height, |
||
739 | rt->u.tex.last_layer - rt->u.tex.first_layer + 1, &box); |
||
740 | |||
741 | success = tex_clear_region(blitter, ilo_texture(rt->texture), |
||
742 | rt->u.tex.level, &box, packed.ui, mask, mask); |
||
743 | } |
||
744 | |||
745 | return success; |
||
746 | } |
||
747 | |||
748 | bool |
||
749 | ilo_blitter_blt_clear_zs(struct ilo_blitter *blitter, |
||
750 | struct pipe_surface *zs, |
||
751 | unsigned clear_flags, |
||
752 | double depth, unsigned stencil, |
||
753 | unsigned x, unsigned y, |
||
754 | unsigned width, unsigned height) |
||
755 | { |
||
756 | enum gen6_blt_mask value_mask, write_mask; |
||
757 | struct pipe_box box; |
||
758 | uint32_t val; |
||
759 | |||
760 | if (!ilo_3d_pass_render_condition(blitter->ilo)) |
||
761 | return true; |
||
762 | |||
763 | switch (zs->format) { |
||
764 | case PIPE_FORMAT_Z16_UNORM: |
||
765 | if (!(clear_flags & PIPE_CLEAR_DEPTH)) |
||
766 | return true; |
||
767 | |||
768 | value_mask = GEN6_BLT_MASK_16; |
||
769 | write_mask = GEN6_BLT_MASK_16; |
||
770 | break; |
||
771 | case PIPE_FORMAT_Z32_FLOAT: |
||
772 | if (!(clear_flags & PIPE_CLEAR_DEPTH)) |
||
773 | return true; |
||
774 | |||
775 | value_mask = GEN6_BLT_MASK_32; |
||
776 | write_mask = GEN6_BLT_MASK_32; |
||
777 | break; |
||
778 | case PIPE_FORMAT_Z24X8_UNORM: |
||
779 | if (!(clear_flags & PIPE_CLEAR_DEPTH)) |
||
780 | return true; |
||
781 | |||
782 | value_mask = GEN6_BLT_MASK_32; |
||
783 | write_mask = GEN6_BLT_MASK_32_LO; |
||
784 | break; |
||
785 | case PIPE_FORMAT_Z24_UNORM_S8_UINT: |
||
786 | if (!(clear_flags & PIPE_CLEAR_DEPTHSTENCIL)) |
||
787 | return true; |
||
788 | |||
789 | value_mask = GEN6_BLT_MASK_32; |
||
790 | |||
791 | if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) |
||
792 | write_mask = GEN6_BLT_MASK_32; |
||
793 | else if (clear_flags & PIPE_CLEAR_DEPTH) |
||
794 | write_mask = GEN6_BLT_MASK_32_LO; |
||
795 | else |
||
796 | write_mask = GEN6_BLT_MASK_32_HI; |
||
797 | break; |
||
798 | default: |
||
799 | return false; |
||
800 | break; |
||
801 | } |
||
802 | |||
803 | val = util_pack_z_stencil(zs->format, depth, stencil); |
||
804 | |||
805 | u_box_3d(x, y, zs->u.tex.first_layer, width, height, |
||
806 | zs->u.tex.last_layer - zs->u.tex.first_layer + 1, &box); |
||
807 | |||
808 | assert(zs->texture->target != PIPE_BUFFER); |
||
809 | |||
810 | return tex_clear_region(blitter, ilo_texture(zs->texture), |
||
811 | zs->u.tex.level, &box, val, value_mask, write_mask); |
||
812 | }>>>><>><>><>><>><>><>>>><>><>><>>>><>><>><>>>><>><>>>><>><> |