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 (at) 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 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 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 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 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 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 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 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