1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2014 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 #ifndef ILO_BUILDER_BLT_H
29 #define ILO_BUILDER_BLT_H
30
31 #include "genhw/genhw.h"
32 #include "intel_winsys.h"
33
34 #include "ilo_core.h"
35 #include "ilo_dev.h"
36 #include "ilo_builder.h"
37
38 enum gen6_blt_mask {
39 GEN6_BLT_MASK_8,
40 GEN6_BLT_MASK_16,
41 GEN6_BLT_MASK_32,
42 GEN6_BLT_MASK_32_LO,
43 GEN6_BLT_MASK_32_HI,
44 };
45
46 struct gen6_blt_bo {
47 struct intel_bo *bo;
48 uint32_t offset;
49 int16_t pitch;
50 };
51
52 struct gen6_blt_xy_bo {
53 struct intel_bo *bo;
54 uint32_t offset;
55 int16_t pitch;
56
57 enum gen_surface_tiling tiling;
58 int16_t x, y;
59 };
60
61 /*
62 * From the Sandy Bridge PRM, volume 1 part 5, page 7:
63 *
64 * "The BLT engine is capable of transferring very large quantities of
65 * graphics data. Any graphics data read from and written to the
66 * destination is permitted to represent a number of pixels that occupies
67 * up to 65,536 scan lines and up to 32,768 bytes per scan line at the
68 * destination. The maximum number of pixels that may be represented per
69 * scan line's worth of graphics data depends on the color depth."
70 */
71 static const int gen6_blt_max_bytes_per_scanline = 32768;
72 static const int gen6_blt_max_scanlines = 65536;
73
74 static inline uint32_t
gen6_blt_translate_value_mask(enum gen6_blt_mask value_mask)75 gen6_blt_translate_value_mask(enum gen6_blt_mask value_mask)
76 {
77 switch (value_mask) {
78 case GEN6_BLT_MASK_8: return GEN6_BLITTER_BR13_FORMAT_8;
79 case GEN6_BLT_MASK_16: return GEN6_BLITTER_BR13_FORMAT_565;
80 default: return GEN6_BLITTER_BR13_FORMAT_8888;
81 }
82 }
83
84 static inline uint32_t
gen6_blt_translate_value_cpp(enum gen6_blt_mask value_mask)85 gen6_blt_translate_value_cpp(enum gen6_blt_mask value_mask)
86 {
87 switch (value_mask) {
88 case GEN6_BLT_MASK_8: return 1;
89 case GEN6_BLT_MASK_16: return 2;
90 default: return 4;
91 }
92 }
93
94 static inline uint32_t
gen6_blt_translate_write_mask(enum gen6_blt_mask write_mask)95 gen6_blt_translate_write_mask(enum gen6_blt_mask write_mask)
96 {
97 switch (write_mask) {
98 case GEN6_BLT_MASK_32: return GEN6_BLITTER_BR00_WRITE_RGB |
99 GEN6_BLITTER_BR00_WRITE_A;
100 case GEN6_BLT_MASK_32_LO: return GEN6_BLITTER_BR00_WRITE_RGB;
101 case GEN6_BLT_MASK_32_HI: return GEN6_BLITTER_BR00_WRITE_A;
102 default: return 0;
103 }
104 }
105
106 static inline void
gen6_COLOR_BLT(struct ilo_builder * builder,const struct gen6_blt_bo * dst,uint32_t pattern,uint16_t width,uint16_t height,uint8_t rop,enum gen6_blt_mask value_mask,enum gen6_blt_mask write_mask)107 gen6_COLOR_BLT(struct ilo_builder *builder,
108 const struct gen6_blt_bo *dst, uint32_t pattern,
109 uint16_t width, uint16_t height, uint8_t rop,
110 enum gen6_blt_mask value_mask,
111 enum gen6_blt_mask write_mask)
112 {
113 const uint8_t cmd_len = (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) ? 6 : 5;
114 const int cpp = gen6_blt_translate_value_cpp(value_mask);
115 uint32_t *dw;
116 unsigned pos;
117
118 ILO_DEV_ASSERT(builder->dev, 6, 8);
119
120 assert(width < gen6_blt_max_bytes_per_scanline);
121 assert(height < gen6_blt_max_scanlines);
122 /* offsets are naturally aligned and pitches are dword-aligned */
123 assert(dst->offset % cpp == 0 && dst->pitch % 4 == 0);
124
125 pos = ilo_builder_batch_pointer(builder, cmd_len, &dw);
126
127 dw[0] = GEN6_BLITTER_CMD(COLOR_BLT) |
128 gen6_blt_translate_write_mask(write_mask) |
129 (cmd_len - 2);
130 dw[1] = rop << GEN6_BLITTER_BR13_ROP__SHIFT |
131 gen6_blt_translate_value_mask(value_mask) |
132 dst->pitch;
133 dw[2] = height << 16 | width;
134
135 if (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) {
136 dw[5] = pattern;
137
138 ilo_builder_batch_reloc64(builder, pos + 3,
139 dst->bo, dst->offset, INTEL_RELOC_WRITE);
140 } else {
141 dw[4] = pattern;
142
143 ilo_builder_batch_reloc(builder, pos + 3,
144 dst->bo, dst->offset, INTEL_RELOC_WRITE);
145 }
146 }
147
148 static inline void
gen6_XY_COLOR_BLT(struct ilo_builder * builder,const struct gen6_blt_xy_bo * dst,uint32_t pattern,uint16_t width,uint16_t height,uint8_t rop,enum gen6_blt_mask value_mask,enum gen6_blt_mask write_mask)149 gen6_XY_COLOR_BLT(struct ilo_builder *builder,
150 const struct gen6_blt_xy_bo *dst, uint32_t pattern,
151 uint16_t width, uint16_t height, uint8_t rop,
152 enum gen6_blt_mask value_mask,
153 enum gen6_blt_mask write_mask)
154 {
155 const uint8_t cmd_len = (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) ? 7 : 6;
156 const int cpp = gen6_blt_translate_value_cpp(value_mask);
157 int dst_align = 4, dst_pitch_shift = 0;
158 uint32_t *dw;
159 unsigned pos;
160
161 ILO_DEV_ASSERT(builder->dev, 6, 8);
162
163 assert(width * cpp < gen6_blt_max_bytes_per_scanline);
164 assert(height < gen6_blt_max_scanlines);
165 /* INT16_MAX */
166 assert(dst->x + width <= 32767 && dst->y + height <= 32767);
167
168 pos = ilo_builder_batch_pointer(builder, cmd_len, &dw);
169
170 dw[0] = GEN6_BLITTER_CMD(XY_COLOR_BLT) |
171 gen6_blt_translate_write_mask(write_mask) |
172 (cmd_len - 2);
173
174 if (dst->tiling != GEN6_TILING_NONE) {
175 dw[0] |= GEN6_BLITTER_BR00_DST_TILED;
176
177 assert(dst->tiling == GEN6_TILING_X || dst->tiling == GEN6_TILING_Y);
178 dst_align = (dst->tiling == GEN6_TILING_Y) ? 128 : 512;
179 /* in dwords when tiled */
180 dst_pitch_shift = 2;
181 }
182
183 assert(dst->offset % dst_align == 0 && dst->pitch % dst_align == 0);
184
185 dw[1] = rop << GEN6_BLITTER_BR13_ROP__SHIFT |
186 gen6_blt_translate_value_mask(value_mask) |
187 dst->pitch >> dst_pitch_shift;
188 dw[2] = dst->y << 16 | dst->x;
189 dw[3] = (dst->y + height) << 16 | (dst->x + width);
190
191 if (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) {
192 dw[6] = pattern;
193
194 ilo_builder_batch_reloc64(builder, pos + 4,
195 dst->bo, dst->offset, INTEL_RELOC_WRITE);
196 } else {
197 dw[5] = pattern;
198
199 ilo_builder_batch_reloc(builder, pos + 4,
200 dst->bo, dst->offset, INTEL_RELOC_WRITE);
201 }
202 }
203
204 static inline void
gen6_SRC_COPY_BLT(struct ilo_builder * builder,const struct gen6_blt_bo * dst,const struct gen6_blt_bo * src,uint16_t width,uint16_t height,uint8_t rop,enum gen6_blt_mask value_mask,enum gen6_blt_mask write_mask)205 gen6_SRC_COPY_BLT(struct ilo_builder *builder,
206 const struct gen6_blt_bo *dst,
207 const struct gen6_blt_bo *src,
208 uint16_t width, uint16_t height, uint8_t rop,
209 enum gen6_blt_mask value_mask,
210 enum gen6_blt_mask write_mask)
211 {
212 const uint8_t cmd_len = (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) ? 8 : 6;
213 const int cpp = gen6_blt_translate_value_cpp(value_mask);
214 uint32_t *dw;
215 unsigned pos;
216
217 ILO_DEV_ASSERT(builder->dev, 6, 8);
218
219 assert(width < gen6_blt_max_bytes_per_scanline);
220 assert(height < gen6_blt_max_scanlines);
221 /* offsets are naturally aligned and pitches are dword-aligned */
222 assert(dst->offset % cpp == 0 && dst->pitch % 4 == 0);
223 assert(src->offset % cpp == 0 && src->pitch % 4 == 0);
224
225 pos = ilo_builder_batch_pointer(builder, cmd_len, &dw);
226
227 dw[0] = GEN6_BLITTER_CMD(SRC_COPY_BLT) |
228 gen6_blt_translate_write_mask(write_mask) |
229 (cmd_len - 2);
230 dw[1] = rop << GEN6_BLITTER_BR13_ROP__SHIFT |
231 gen6_blt_translate_value_mask(value_mask) |
232 dst->pitch;
233 dw[2] = height << 16 | width;
234
235 if (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) {
236 dw[5] = src->pitch;
237
238 ilo_builder_batch_reloc64(builder, pos + 3,
239 dst->bo, dst->offset, INTEL_RELOC_WRITE);
240 ilo_builder_batch_reloc64(builder, pos + 6, src->bo, src->offset, 0);
241 } else {
242 dw[4] = src->pitch;
243
244 ilo_builder_batch_reloc(builder, pos + 3,
245 dst->bo, dst->offset, INTEL_RELOC_WRITE);
246 ilo_builder_batch_reloc(builder, pos + 5, src->bo, src->offset, 0);
247 }
248 }
249
250 static inline void
gen6_XY_SRC_COPY_BLT(struct ilo_builder * builder,const struct gen6_blt_xy_bo * dst,const struct gen6_blt_xy_bo * src,uint16_t width,uint16_t height,uint8_t rop,enum gen6_blt_mask value_mask,enum gen6_blt_mask write_mask)251 gen6_XY_SRC_COPY_BLT(struct ilo_builder *builder,
252 const struct gen6_blt_xy_bo *dst,
253 const struct gen6_blt_xy_bo *src,
254 uint16_t width, uint16_t height, uint8_t rop,
255 enum gen6_blt_mask value_mask,
256 enum gen6_blt_mask write_mask)
257 {
258 const uint8_t cmd_len = (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) ? 10 : 8;
259 const int cpp = gen6_blt_translate_value_cpp(value_mask);
260 int dst_align = 4, dst_pitch_shift = 0;
261 int src_align = 4, src_pitch_shift = 0;
262 uint32_t *dw;
263 unsigned pos;
264
265 ILO_DEV_ASSERT(builder->dev, 6, 8);
266
267 assert(width * cpp < gen6_blt_max_bytes_per_scanline);
268 assert(height < gen6_blt_max_scanlines);
269 /* INT16_MAX */
270 assert(dst->x + width <= 32767 && dst->y + height <= 32767);
271
272 pos = ilo_builder_batch_pointer(builder, cmd_len, &dw);
273
274 dw[0] = GEN6_BLITTER_CMD(XY_SRC_COPY_BLT) |
275 gen6_blt_translate_write_mask(write_mask) |
276 (cmd_len - 2);
277
278 if (dst->tiling != GEN6_TILING_NONE) {
279 dw[0] |= GEN6_BLITTER_BR00_DST_TILED;
280
281 assert(dst->tiling == GEN6_TILING_X || dst->tiling == GEN6_TILING_Y);
282 dst_align = (dst->tiling == GEN6_TILING_Y) ? 128 : 512;
283 /* in dwords when tiled */
284 dst_pitch_shift = 2;
285 }
286
287 if (src->tiling != GEN6_TILING_NONE) {
288 dw[0] |= GEN6_BLITTER_BR00_SRC_TILED;
289
290 assert(src->tiling == GEN6_TILING_X || src->tiling == GEN6_TILING_Y);
291 src_align = (src->tiling == GEN6_TILING_Y) ? 128 : 512;
292 /* in dwords when tiled */
293 src_pitch_shift = 2;
294 }
295
296 assert(dst->offset % dst_align == 0 && dst->pitch % dst_align == 0);
297 assert(src->offset % src_align == 0 && src->pitch % src_align == 0);
298
299 dw[1] = rop << GEN6_BLITTER_BR13_ROP__SHIFT |
300 gen6_blt_translate_value_mask(value_mask) |
301 dst->pitch >> dst_pitch_shift;
302 dw[2] = dst->y << 16 | dst->x;
303 dw[3] = (dst->y + height) << 16 | (dst->x + width);
304
305 if (ilo_dev_gen(builder->dev) >= ILO_GEN(8)) {
306 dw[6] = src->y << 16 | src->x;
307 dw[7] = src->pitch >> src_pitch_shift;
308
309 ilo_builder_batch_reloc64(builder, pos + 4,
310 dst->bo, dst->offset, INTEL_RELOC_WRITE);
311 ilo_builder_batch_reloc64(builder, pos + 8, src->bo, src->offset, 0);
312 } else {
313 dw[5] = src->y << 16 | src->x;
314 dw[6] = src->pitch >> src_pitch_shift;
315
316 ilo_builder_batch_reloc(builder, pos + 4,
317 dst->bo, dst->offset, INTEL_RELOC_WRITE);
318 ilo_builder_batch_reloc(builder, pos + 7, src->bo, src->offset, 0);
319 }
320 }
321
322 #endif /* ILO_BUILDER_BLT_H */
323