• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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