Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 1 | /* |
| 2 | * Copyright © 2015 Intel Corporation |
| 3 | * |
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 5 | * copy of this software and associated documentation files (the "Software"), |
| 6 | * to deal in the Software without restriction, including without limitation |
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| 8 | * and/or sell copies of the Software, and to permit persons to whom the |
| 9 | * Software is furnished to do so, subject to the following conditions: |
| 10 | * |
| 11 | * The above copyright notice and this permission notice (including the next |
| 12 | * paragraph) shall be included in all copies or substantial portions of the |
| 13 | * Software. |
| 14 | * |
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| 21 | * IN THE SOFTWARE. |
| 22 | * |
| 23 | */ |
| 24 | |
| 25 | #include <sys/mman.h> |
| 26 | |
| 27 | #include "igt_draw.h" |
| 28 | |
| 29 | #include "drmtest.h" |
| 30 | #include "intel_chipset.h" |
| 31 | #include "igt_core.h" |
| 32 | #include "igt_fb.h" |
| 33 | #include "ioctl_wrappers.h" |
Akash Goel | a844ccb | 2017-04-28 20:07:31 +0530 | [diff] [blame] | 34 | #include "i830_reg.h" |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 35 | |
| 36 | /** |
| 37 | * SECTION:igt_draw |
| 38 | * @short_description: drawing helpers for tests |
Damien Lespiau | 6ebd8c2 | 2015-06-26 14:28:41 +0100 | [diff] [blame] | 39 | * @title: Draw |
Thomas Wood | f0381d1 | 2015-09-07 09:26:01 +0100 | [diff] [blame] | 40 | * @include: igt.h |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 41 | * |
| 42 | * This library contains some functions for drawing rectangles on buffers using |
| 43 | * the many different drawing methods we have. It also contains some wrappers |
| 44 | * that make the process easier if you have the abstract objects in hand. |
| 45 | * |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 46 | * This library only claims support for some pixel formats, but adding support |
| 47 | * for more formats should be faily easy now that we support both 16bpp and |
| 48 | * 32bpp. If you need a new pixel format, make sure you update both this file |
| 49 | * and tests/kms_draw_crc.c. |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 50 | */ |
| 51 | |
| 52 | /* Some internal data structures to avoid having to pass tons of parameters |
| 53 | * around everything. */ |
| 54 | struct cmd_data { |
| 55 | drm_intel_bufmgr *bufmgr; |
| 56 | drm_intel_context *context; |
| 57 | }; |
| 58 | |
| 59 | struct buf_data { |
| 60 | uint32_t handle; |
| 61 | uint32_t size; |
| 62 | uint32_t stride; |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 63 | int bpp; |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 64 | }; |
| 65 | |
| 66 | struct rect { |
| 67 | int x; |
| 68 | int y; |
| 69 | int w; |
| 70 | int h; |
| 71 | }; |
| 72 | |
| 73 | /** |
| 74 | * igt_draw_get_method_name: |
Thomas Wood | 6141aa2 | 2015-05-14 16:00:25 +0100 | [diff] [blame] | 75 | * @method: draw method |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 76 | * |
| 77 | * Simple function to transform the enum into a string. Useful when naming |
| 78 | * subtests and printing debug messages. |
| 79 | */ |
| 80 | const char *igt_draw_get_method_name(enum igt_draw_method method) |
| 81 | { |
| 82 | switch (method) { |
| 83 | case IGT_DRAW_MMAP_CPU: |
| 84 | return "mmap-cpu"; |
| 85 | case IGT_DRAW_MMAP_GTT: |
| 86 | return "mmap-gtt"; |
| 87 | case IGT_DRAW_MMAP_WC: |
| 88 | return "mmap-wc"; |
| 89 | case IGT_DRAW_PWRITE: |
| 90 | return "pwrite"; |
| 91 | case IGT_DRAW_BLT: |
| 92 | return "blt"; |
| 93 | case IGT_DRAW_RENDER: |
| 94 | return "render"; |
| 95 | default: |
| 96 | igt_assert(false); |
| 97 | } |
| 98 | } |
| 99 | |
| 100 | #define BIT(num, bit) ((num >> bit) & 1) |
| 101 | |
| 102 | static int swizzle_addr(int addr, int swizzle) |
| 103 | { |
| 104 | int bit6; |
| 105 | |
| 106 | switch (swizzle) { |
| 107 | case I915_BIT_6_SWIZZLE_NONE: |
| 108 | bit6 = BIT(addr, 6); |
| 109 | break; |
| 110 | case I915_BIT_6_SWIZZLE_9: |
| 111 | bit6 = BIT(addr, 6) ^ BIT(addr, 9); |
| 112 | break; |
| 113 | case I915_BIT_6_SWIZZLE_9_10: |
| 114 | bit6 = BIT(addr, 6) ^ BIT(addr, 9) ^ BIT(addr, 10); |
| 115 | break; |
| 116 | case I915_BIT_6_SWIZZLE_9_11: |
| 117 | bit6 = BIT(addr, 6) ^ BIT(addr, 9) ^ BIT(addr, 11); |
| 118 | break; |
| 119 | case I915_BIT_6_SWIZZLE_9_10_11: |
| 120 | bit6 = BIT(addr, 6) ^ BIT(addr, 9) ^ BIT(addr, 10) ^ |
| 121 | BIT(addr, 11); |
| 122 | break; |
| 123 | case I915_BIT_6_SWIZZLE_UNKNOWN: |
| 124 | case I915_BIT_6_SWIZZLE_9_17: |
| 125 | case I915_BIT_6_SWIZZLE_9_10_17: |
| 126 | default: |
| 127 | /* If we hit this case, we need to implement support for the |
| 128 | * appropriate swizzling method. */ |
| 129 | igt_require(false); |
| 130 | break; |
| 131 | } |
| 132 | |
| 133 | addr &= ~(1 << 6); |
| 134 | addr |= (bit6 << 6); |
| 135 | return addr; |
| 136 | } |
| 137 | |
Paulo Zanoni | 10e010f | 2017-07-18 22:52:58 +0530 | [diff] [blame] | 138 | static int tile(int x, int y, uint32_t x_tile_size, uint32_t y_tile_size, |
| 139 | uint32_t line_size, bool xmajor) |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 140 | { |
Paulo Zanoni | 10e010f | 2017-07-18 22:52:58 +0530 | [diff] [blame] | 141 | int tile_size, tiles_per_line, x_tile_n, y_tile_n, tile_off, pos; |
| 142 | int tile_n, x_tile_off, y_tile_off; |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 143 | |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 144 | tiles_per_line = line_size / x_tile_size; |
Paulo Zanoni | 10e010f | 2017-07-18 22:52:58 +0530 | [diff] [blame] | 145 | tile_size = x_tile_size * y_tile_size; |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 146 | |
Paulo Zanoni | 10e010f | 2017-07-18 22:52:58 +0530 | [diff] [blame] | 147 | x_tile_n = x / x_tile_size; |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 148 | y_tile_n = y / y_tile_size; |
Paulo Zanoni | 10e010f | 2017-07-18 22:52:58 +0530 | [diff] [blame] | 149 | tile_n = y_tile_n * tiles_per_line + x_tile_n; |
| 150 | |
| 151 | x_tile_off = x % x_tile_size; |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 152 | y_tile_off = y % y_tile_size; |
| 153 | |
Paulo Zanoni | 10e010f | 2017-07-18 22:52:58 +0530 | [diff] [blame] | 154 | if (xmajor) |
| 155 | tile_off = y_tile_off * x_tile_size + x_tile_off; |
| 156 | else |
| 157 | tile_off = x_tile_off * y_tile_size + y_tile_off; |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 158 | |
Paulo Zanoni | 10e010f | 2017-07-18 22:52:58 +0530 | [diff] [blame] | 159 | pos = tile_n * tile_size + tile_off; |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 160 | |
Paulo Zanoni | 10e010f | 2017-07-18 22:52:58 +0530 | [diff] [blame] | 161 | return pos; |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 162 | } |
| 163 | |
Paulo Zanoni | 10e010f | 2017-07-18 22:52:58 +0530 | [diff] [blame] | 164 | static void untile(int tiled_pos, int x_tile_size, int y_tile_size, |
| 165 | uint32_t line_size, bool xmajor, int *x, int *y) |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 166 | { |
Paulo Zanoni | 10e010f | 2017-07-18 22:52:58 +0530 | [diff] [blame] | 167 | int tile_n, tile_off, tiles_per_line; |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 168 | int x_tile_off, y_tile_off; |
| 169 | int x_tile_n, y_tile_n; |
Paulo Zanoni | 10e010f | 2017-07-18 22:52:58 +0530 | [diff] [blame] | 170 | int tile_size; |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 171 | |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 172 | tile_size = x_tile_size * y_tile_size; |
| 173 | tiles_per_line = line_size / x_tile_size; |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 174 | |
| 175 | tile_n = tiled_pos / tile_size; |
| 176 | tile_off = tiled_pos % tile_size; |
| 177 | |
Paulo Zanoni | 10e010f | 2017-07-18 22:52:58 +0530 | [diff] [blame] | 178 | if (xmajor) { |
| 179 | y_tile_off = tile_off / x_tile_size; |
| 180 | x_tile_off = tile_off % x_tile_size; |
| 181 | } else { |
| 182 | y_tile_off = tile_off % y_tile_size; |
| 183 | x_tile_off = tile_off / y_tile_size; |
| 184 | } |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 185 | |
| 186 | x_tile_n = tile_n % tiles_per_line; |
| 187 | y_tile_n = tile_n / tiles_per_line; |
| 188 | |
Paulo Zanoni | 10e010f | 2017-07-18 22:52:58 +0530 | [diff] [blame] | 189 | *x = (x_tile_n * x_tile_size + x_tile_off); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 190 | *y = y_tile_n * y_tile_size + y_tile_off; |
| 191 | } |
| 192 | |
Paulo Zanoni | 10e010f | 2017-07-18 22:52:58 +0530 | [diff] [blame] | 193 | static int linear_x_y_to_xtiled_pos(int x, int y, uint32_t stride, int swizzle, |
| 194 | int bpp) |
| 195 | { |
| 196 | int pos; |
| 197 | int pixel_size = bpp / 8; |
| 198 | |
| 199 | x *= pixel_size; |
| 200 | pos = tile(x, y, 512, 8, stride, true); |
| 201 | pos = swizzle_addr(pos, swizzle); |
| 202 | return pos / pixel_size; |
| 203 | } |
| 204 | |
| 205 | static int linear_x_y_to_ytiled_pos(int x, int y, uint32_t stride, int swizzle, |
| 206 | int bpp) |
| 207 | { |
| 208 | int ow_tile_n, pos; |
| 209 | int ow_size = 16; |
| 210 | int pixel_size = bpp / 8; |
| 211 | |
| 212 | /* We have an Y tiling of OWords, so use the tile() function to get the |
| 213 | * OW number, then adjust to the fact that the OW may have more than one |
| 214 | * pixel. */ |
| 215 | x *= pixel_size; |
| 216 | ow_tile_n = tile(x / ow_size, y, 128 / ow_size, 32, |
| 217 | stride / ow_size, false); |
| 218 | pos = ow_tile_n * ow_size + (x % ow_size); |
| 219 | pos = swizzle_addr(pos, swizzle); |
| 220 | return pos / pixel_size; |
| 221 | } |
| 222 | |
| 223 | static void xtiled_pos_to_x_y_linear(int tiled_pos, uint32_t stride, |
| 224 | int swizzle, int bpp, int *x, int *y) |
| 225 | { |
| 226 | int pixel_size = bpp / 8; |
| 227 | |
| 228 | tiled_pos = swizzle_addr(tiled_pos, swizzle); |
| 229 | |
| 230 | untile(tiled_pos, 512, 8, stride, true, x, y); |
| 231 | *x /= pixel_size; |
| 232 | } |
| 233 | |
| 234 | static void ytiled_pos_to_x_y_linear(int tiled_pos, uint32_t stride, |
| 235 | int swizzle, int bpp, int *x, int *y) |
| 236 | { |
| 237 | int ow_tile_n; |
| 238 | int ow_size = 16; |
| 239 | int pixel_size = bpp / 8; |
| 240 | |
| 241 | tiled_pos = swizzle_addr(tiled_pos, swizzle); |
| 242 | |
| 243 | ow_tile_n = tiled_pos / ow_size; |
| 244 | untile(ow_tile_n, 128 / ow_size, 32, stride / ow_size, false, x, y); |
| 245 | *x *= ow_size; |
| 246 | *x += tiled_pos % ow_size; |
| 247 | *x /= pixel_size; |
| 248 | } |
| 249 | |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 250 | static void set_pixel(void *_ptr, int index, uint32_t color, int bpp) |
| 251 | { |
| 252 | if (bpp == 16) { |
| 253 | uint16_t *ptr = _ptr; |
| 254 | ptr[index] = color; |
| 255 | } else if (bpp == 32) { |
| 256 | uint32_t *ptr = _ptr; |
| 257 | ptr[index] = color; |
| 258 | } else { |
| 259 | igt_assert_f(false, "bpp: %d\n", bpp); |
| 260 | } |
| 261 | } |
| 262 | |
Akash Goel | a844ccb | 2017-04-28 20:07:31 +0530 | [diff] [blame] | 263 | static void switch_blt_tiling(struct intel_batchbuffer *batch, uint32_t tiling, |
| 264 | bool on) |
| 265 | { |
| 266 | uint32_t bcs_swctrl; |
| 267 | |
| 268 | /* Default is X-tile */ |
| 269 | if (tiling != I915_TILING_Y) |
| 270 | return; |
| 271 | |
| 272 | bcs_swctrl = (0x3 << 16) | (on ? 0x3 : 0x0); |
| 273 | |
| 274 | /* To change the tile register, insert an MI_FLUSH_DW followed by an |
| 275 | * MI_LOAD_REGISTER_IMM |
| 276 | */ |
| 277 | BEGIN_BATCH(4, 0); |
| 278 | OUT_BATCH(MI_FLUSH_DW | 2); |
| 279 | OUT_BATCH(0x0); |
| 280 | OUT_BATCH(0x0); |
| 281 | OUT_BATCH(0x0); |
| 282 | ADVANCE_BATCH(); |
| 283 | |
| 284 | BEGIN_BATCH(4, 0); |
| 285 | OUT_BATCH(MI_LOAD_REGISTER_IMM); |
| 286 | OUT_BATCH(0x22200); /* BCS_SWCTRL */ |
| 287 | OUT_BATCH(bcs_swctrl); |
| 288 | OUT_BATCH(MI_NOOP); |
| 289 | ADVANCE_BATCH(); |
| 290 | } |
| 291 | |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 292 | static void draw_rect_ptr_linear(void *ptr, uint32_t stride, |
| 293 | struct rect *rect, uint32_t color, int bpp) |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 294 | { |
| 295 | int x, y, line_begin; |
| 296 | |
| 297 | for (y = rect->y; y < rect->y + rect->h; y++) { |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 298 | line_begin = y * stride / (bpp / 8); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 299 | for (x = rect->x; x < rect->x + rect->w; x++) |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 300 | set_pixel(ptr, line_begin + x, color, bpp); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 301 | } |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 302 | } |
| 303 | |
Paulo Zanoni | 10e010f | 2017-07-18 22:52:58 +0530 | [diff] [blame] | 304 | static void draw_rect_ptr_tiled(void *ptr, uint32_t stride, uint32_t tiling, |
| 305 | int swizzle, struct rect *rect, uint32_t color, |
| 306 | int bpp) |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 307 | { |
| 308 | int x, y, pos; |
| 309 | |
| 310 | for (y = rect->y; y < rect->y + rect->h; y++) { |
| 311 | for (x = rect->x; x < rect->x + rect->w; x++) { |
Paulo Zanoni | 10e010f | 2017-07-18 22:52:58 +0530 | [diff] [blame] | 312 | switch (tiling) { |
| 313 | case I915_TILING_X: |
| 314 | pos = linear_x_y_to_xtiled_pos(x, y, stride, |
| 315 | swizzle, bpp); |
| 316 | break; |
| 317 | case I915_TILING_Y: |
| 318 | pos = linear_x_y_to_ytiled_pos(x, y, stride, |
| 319 | swizzle, bpp); |
| 320 | break; |
| 321 | default: |
| 322 | igt_assert(false); |
| 323 | } |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 324 | set_pixel(ptr, pos, color, bpp); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 325 | } |
| 326 | } |
| 327 | } |
| 328 | |
| 329 | static void draw_rect_mmap_cpu(int fd, struct buf_data *buf, struct rect *rect, |
| 330 | uint32_t color) |
| 331 | { |
| 332 | uint32_t *ptr; |
| 333 | uint32_t tiling, swizzle; |
| 334 | |
| 335 | gem_set_domain(fd, buf->handle, I915_GEM_DOMAIN_CPU, |
| 336 | I915_GEM_DOMAIN_CPU); |
Chris Wilson | e276268 | 2016-10-19 14:07:25 +0100 | [diff] [blame] | 337 | igt_require(gem_get_tiling(fd, buf->handle, &tiling, &swizzle)); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 338 | |
| 339 | /* We didn't implement suport for the older tiling methods yet. */ |
| 340 | if (tiling != I915_TILING_NONE) |
| 341 | igt_require(intel_gen(intel_get_drm_devid(fd)) >= 5); |
| 342 | |
Ville Syrjälä | f52e7ec | 2015-10-09 19:11:39 +0300 | [diff] [blame] | 343 | ptr = gem_mmap__cpu(fd, buf->handle, 0, buf->size, 0); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 344 | |
| 345 | switch (tiling) { |
| 346 | case I915_TILING_NONE: |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 347 | draw_rect_ptr_linear(ptr, buf->stride, rect, color, buf->bpp); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 348 | break; |
| 349 | case I915_TILING_X: |
Paulo Zanoni | 10e010f | 2017-07-18 22:52:58 +0530 | [diff] [blame] | 350 | case I915_TILING_Y: |
| 351 | draw_rect_ptr_tiled(ptr, buf->stride, tiling, swizzle, rect, |
| 352 | color, buf->bpp); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 353 | break; |
| 354 | default: |
| 355 | igt_assert(false); |
| 356 | break; |
| 357 | } |
| 358 | |
| 359 | gem_sw_finish(fd, buf->handle); |
| 360 | |
Maarten Lankhorst | d930b64 | 2017-02-09 10:42:01 +0100 | [diff] [blame] | 361 | igt_assert(gem_munmap(ptr, buf->size) == 0); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 362 | } |
| 363 | |
| 364 | static void draw_rect_mmap_gtt(int fd, struct buf_data *buf, struct rect *rect, |
| 365 | uint32_t color) |
| 366 | { |
| 367 | uint32_t *ptr; |
| 368 | |
Paulo Zanoni | e86557c | 2015-06-25 14:19:24 -0300 | [diff] [blame] | 369 | gem_set_domain(fd, buf->handle, I915_GEM_DOMAIN_GTT, |
| 370 | I915_GEM_DOMAIN_GTT); |
| 371 | |
Ville Syrjälä | f52e7ec | 2015-10-09 19:11:39 +0300 | [diff] [blame] | 372 | ptr = gem_mmap__gtt(fd, buf->handle, buf->size, PROT_READ | PROT_WRITE); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 373 | |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 374 | draw_rect_ptr_linear(ptr, buf->stride, rect, color, buf->bpp); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 375 | |
Maarten Lankhorst | d930b64 | 2017-02-09 10:42:01 +0100 | [diff] [blame] | 376 | igt_assert(gem_munmap(ptr, buf->size) == 0); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 377 | } |
| 378 | |
| 379 | static void draw_rect_mmap_wc(int fd, struct buf_data *buf, struct rect *rect, |
| 380 | uint32_t color) |
| 381 | { |
| 382 | uint32_t *ptr; |
| 383 | uint32_t tiling, swizzle; |
| 384 | |
Paulo Zanoni | e86557c | 2015-06-25 14:19:24 -0300 | [diff] [blame] | 385 | gem_set_domain(fd, buf->handle, I915_GEM_DOMAIN_GTT, |
| 386 | I915_GEM_DOMAIN_GTT); |
Chris Wilson | e276268 | 2016-10-19 14:07:25 +0100 | [diff] [blame] | 387 | igt_require(gem_get_tiling(fd, buf->handle, &tiling, &swizzle)); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 388 | |
| 389 | /* We didn't implement suport for the older tiling methods yet. */ |
| 390 | if (tiling != I915_TILING_NONE) |
| 391 | igt_require(intel_gen(intel_get_drm_devid(fd)) >= 5); |
| 392 | |
Ville Syrjälä | f52e7ec | 2015-10-09 19:11:39 +0300 | [diff] [blame] | 393 | ptr = gem_mmap__wc(fd, buf->handle, 0, buf->size, |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 394 | PROT_READ | PROT_WRITE); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 395 | |
| 396 | switch (tiling) { |
| 397 | case I915_TILING_NONE: |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 398 | draw_rect_ptr_linear(ptr, buf->stride, rect, color, buf->bpp); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 399 | break; |
| 400 | case I915_TILING_X: |
Paulo Zanoni | 10e010f | 2017-07-18 22:52:58 +0530 | [diff] [blame] | 401 | case I915_TILING_Y: |
| 402 | draw_rect_ptr_tiled(ptr, buf->stride, tiling, swizzle, rect, |
| 403 | color, buf->bpp); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 404 | break; |
| 405 | default: |
| 406 | igt_assert(false); |
| 407 | break; |
| 408 | } |
| 409 | |
Maarten Lankhorst | d930b64 | 2017-02-09 10:42:01 +0100 | [diff] [blame] | 410 | igt_assert(gem_munmap(ptr, buf->size) == 0); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 411 | } |
| 412 | |
| 413 | static void draw_rect_pwrite_untiled(int fd, struct buf_data *buf, |
| 414 | struct rect *rect, uint32_t color) |
| 415 | { |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 416 | int i, y, offset; |
| 417 | int pixel_size = buf->bpp / 8; |
| 418 | uint8_t tmp[rect->w * pixel_size]; |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 419 | |
| 420 | for (i = 0; i < rect->w; i++) |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 421 | set_pixel(tmp, i, color, buf->bpp); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 422 | |
| 423 | for (y = rect->y; y < rect->y + rect->h; y++) { |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 424 | offset = (y * buf->stride) + (rect->x * pixel_size); |
| 425 | gem_write(fd, buf->handle, offset, tmp, rect->w * pixel_size); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 426 | } |
| 427 | } |
| 428 | |
| 429 | static void draw_rect_pwrite_tiled(int fd, struct buf_data *buf, |
Paulo Zanoni | 10e010f | 2017-07-18 22:52:58 +0530 | [diff] [blame] | 430 | uint32_t tiling, struct rect *rect, |
| 431 | uint32_t color, uint32_t swizzle) |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 432 | { |
| 433 | int i; |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 434 | int tiled_pos, x, y, pixel_size; |
| 435 | uint8_t tmp[4096]; |
| 436 | int tmp_used = 0, tmp_size; |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 437 | bool flush_tmp = false; |
| 438 | int tmp_start_pos = 0; |
Paulo Zanoni | 9113c9a | 2015-08-13 17:37:06 -0300 | [diff] [blame] | 439 | int pixels_written = 0; |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 440 | |
| 441 | /* We didn't implement suport for the older tiling methods yet. */ |
| 442 | igt_require(intel_gen(intel_get_drm_devid(fd)) >= 5); |
| 443 | |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 444 | pixel_size = buf->bpp / 8; |
| 445 | tmp_size = sizeof(tmp) / pixel_size; |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 446 | |
| 447 | /* Instead of doing one pwrite per pixel, we try to group the maximum |
| 448 | * amount of consecutive pixels we can in a single pwrite: that's why we |
| 449 | * use the "tmp" variables. */ |
| 450 | for (i = 0; i < tmp_size; i++) |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 451 | set_pixel(tmp, i, color, buf->bpp); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 452 | |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 453 | for (tiled_pos = 0; tiled_pos < buf->size; tiled_pos += pixel_size) { |
Paulo Zanoni | 10e010f | 2017-07-18 22:52:58 +0530 | [diff] [blame] | 454 | switch (tiling) { |
| 455 | case I915_TILING_X: |
| 456 | xtiled_pos_to_x_y_linear(tiled_pos, buf->stride, |
| 457 | swizzle, buf->bpp, &x, &y); |
| 458 | break; |
| 459 | case I915_TILING_Y: |
| 460 | ytiled_pos_to_x_y_linear(tiled_pos, buf->stride, |
| 461 | swizzle, buf->bpp, &x, &y); |
| 462 | break; |
| 463 | default: |
| 464 | igt_assert(false); |
| 465 | } |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 466 | |
| 467 | if (x >= rect->x && x < rect->x + rect->w && |
| 468 | y >= rect->y && y < rect->y + rect->h) { |
| 469 | if (tmp_used == 0) |
| 470 | tmp_start_pos = tiled_pos; |
| 471 | tmp_used++; |
| 472 | } else { |
| 473 | flush_tmp = true; |
| 474 | } |
| 475 | |
Paulo Zanoni | 9194f4e | 2015-08-13 17:25:31 -0300 | [diff] [blame] | 476 | if (tmp_used == tmp_size || (flush_tmp && tmp_used > 0) || |
| 477 | tiled_pos + pixel_size >= buf->size) { |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 478 | gem_write(fd, buf->handle, tmp_start_pos, tmp, |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 479 | tmp_used * pixel_size); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 480 | flush_tmp = false; |
Paulo Zanoni | 9113c9a | 2015-08-13 17:37:06 -0300 | [diff] [blame] | 481 | pixels_written += tmp_used; |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 482 | tmp_used = 0; |
Paulo Zanoni | 9113c9a | 2015-08-13 17:37:06 -0300 | [diff] [blame] | 483 | |
| 484 | if (pixels_written == rect->w * rect->h) |
| 485 | break; |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 486 | } |
| 487 | } |
| 488 | } |
| 489 | |
| 490 | static void draw_rect_pwrite(int fd, struct buf_data *buf, |
| 491 | struct rect *rect, uint32_t color) |
| 492 | { |
| 493 | uint32_t tiling, swizzle; |
| 494 | |
Chris Wilson | e276268 | 2016-10-19 14:07:25 +0100 | [diff] [blame] | 495 | igt_require(gem_get_tiling(fd, buf->handle, &tiling, &swizzle)); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 496 | |
| 497 | switch (tiling) { |
| 498 | case I915_TILING_NONE: |
| 499 | draw_rect_pwrite_untiled(fd, buf, rect, color); |
| 500 | break; |
| 501 | case I915_TILING_X: |
Paulo Zanoni | 10e010f | 2017-07-18 22:52:58 +0530 | [diff] [blame] | 502 | case I915_TILING_Y: |
| 503 | draw_rect_pwrite_tiled(fd, buf, tiling, rect, color, swizzle); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 504 | break; |
| 505 | default: |
| 506 | igt_assert(false); |
| 507 | break; |
| 508 | } |
| 509 | } |
| 510 | |
| 511 | static void draw_rect_blt(int fd, struct cmd_data *cmd_data, |
| 512 | struct buf_data *buf, struct rect *rect, |
| 513 | uint32_t color) |
| 514 | { |
| 515 | drm_intel_bo *dst; |
| 516 | struct intel_batchbuffer *batch; |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 517 | int blt_cmd_len, blt_cmd_tiling, blt_cmd_depth; |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 518 | uint32_t devid = intel_get_drm_devid(fd); |
| 519 | int gen = intel_gen(devid); |
| 520 | uint32_t tiling, swizzle; |
| 521 | int pitch; |
| 522 | |
Chris Wilson | e276268 | 2016-10-19 14:07:25 +0100 | [diff] [blame] | 523 | igt_require(gem_get_tiling(fd, buf->handle, &tiling, &swizzle)); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 524 | |
| 525 | dst = gem_handle_to_libdrm_bo(cmd_data->bufmgr, fd, "", buf->handle); |
| 526 | igt_assert(dst); |
| 527 | |
| 528 | batch = intel_batchbuffer_alloc(cmd_data->bufmgr, devid); |
| 529 | igt_assert(batch); |
| 530 | |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 531 | switch (buf->bpp) { |
| 532 | case 8: |
| 533 | blt_cmd_depth = 0; |
| 534 | break; |
| 535 | case 16: /* we're assuming 565 */ |
| 536 | blt_cmd_depth = 1 << 24; |
| 537 | break; |
| 538 | case 32: |
| 539 | blt_cmd_depth = 3 << 24; |
| 540 | break; |
| 541 | default: |
| 542 | igt_assert(false); |
| 543 | } |
| 544 | |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 545 | blt_cmd_len = (gen >= 8) ? 0x5 : 0x4; |
| 546 | blt_cmd_tiling = (tiling) ? XY_COLOR_BLT_TILED : 0; |
| 547 | pitch = (tiling) ? buf->stride / 4 : buf->stride; |
| 548 | |
Akash Goel | a844ccb | 2017-04-28 20:07:31 +0530 | [diff] [blame] | 549 | switch_blt_tiling(batch, tiling, true); |
| 550 | |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 551 | BEGIN_BATCH(6, 1); |
| 552 | OUT_BATCH(XY_COLOR_BLT_CMD_NOLEN | XY_COLOR_BLT_WRITE_ALPHA | |
| 553 | XY_COLOR_BLT_WRITE_RGB | blt_cmd_tiling | blt_cmd_len); |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 554 | OUT_BATCH(blt_cmd_depth | (0xF0 << 16) | pitch); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 555 | OUT_BATCH((rect->y << 16) | rect->x); |
| 556 | OUT_BATCH(((rect->y + rect->h) << 16) | (rect->x + rect->w)); |
| 557 | OUT_RELOC_FENCED(dst, 0, I915_GEM_DOMAIN_RENDER, 0); |
| 558 | OUT_BATCH(color); |
| 559 | ADVANCE_BATCH(); |
| 560 | |
Akash Goel | a844ccb | 2017-04-28 20:07:31 +0530 | [diff] [blame] | 561 | switch_blt_tiling(batch, tiling, false); |
| 562 | |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 563 | intel_batchbuffer_flush(batch); |
| 564 | intel_batchbuffer_free(batch); |
| 565 | } |
| 566 | |
| 567 | static void draw_rect_render(int fd, struct cmd_data *cmd_data, |
| 568 | struct buf_data *buf, struct rect *rect, |
| 569 | uint32_t color) |
| 570 | { |
| 571 | drm_intel_bo *src, *dst; |
| 572 | uint32_t devid = intel_get_drm_devid(fd); |
| 573 | igt_render_copyfunc_t rendercopy = igt_get_render_copyfunc(devid); |
| 574 | struct igt_buf src_buf, dst_buf; |
| 575 | struct intel_batchbuffer *batch; |
| 576 | uint32_t tiling, swizzle; |
| 577 | struct buf_data tmp; |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 578 | int pixel_size = buf->bpp / 8; |
| 579 | unsigned adjusted_w, adjusted_dst_x; |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 580 | |
| 581 | igt_skip_on(!rendercopy); |
| 582 | |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 583 | /* Rendercopy works at 32bpp, so if you try to do copies on buffers with |
| 584 | * smaller bpps you won't succeeed if you need to copy "half" of a 32bpp |
| 585 | * pixel or something similar. */ |
| 586 | igt_skip_on(rect->x % (32 / buf->bpp) != 0 || |
| 587 | rect->y % (32 / buf->bpp) != 0 || |
| 588 | rect->w % (32 / buf->bpp) != 0 || |
| 589 | rect->h % (32 / buf->bpp) != 0); |
| 590 | |
Chris Wilson | e276268 | 2016-10-19 14:07:25 +0100 | [diff] [blame] | 591 | igt_require(gem_get_tiling(fd, buf->handle, &tiling, &swizzle)); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 592 | |
| 593 | /* We create a temporary buffer and copy from it using rendercopy. */ |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 594 | tmp.size = rect->w * rect->h * pixel_size; |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 595 | tmp.handle = gem_create(fd, tmp.size); |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 596 | tmp.stride = rect->w * pixel_size; |
| 597 | tmp.bpp = buf->bpp; |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 598 | draw_rect_mmap_cpu(fd, &tmp, &(struct rect){0, 0, rect->w, rect->h}, |
| 599 | color); |
| 600 | |
| 601 | src = gem_handle_to_libdrm_bo(cmd_data->bufmgr, fd, "", tmp.handle); |
| 602 | igt_assert(src); |
| 603 | dst = gem_handle_to_libdrm_bo(cmd_data->bufmgr, fd, "", buf->handle); |
| 604 | igt_assert(dst); |
| 605 | |
| 606 | src_buf.bo = src; |
| 607 | src_buf.stride = tmp.stride; |
| 608 | src_buf.tiling = I915_TILING_NONE; |
| 609 | src_buf.size = tmp.size; |
| 610 | dst_buf.bo = dst; |
| 611 | dst_buf.stride = buf->stride; |
| 612 | dst_buf.tiling = tiling; |
| 613 | dst_buf.size = buf->size; |
| 614 | |
| 615 | batch = intel_batchbuffer_alloc(cmd_data->bufmgr, devid); |
| 616 | igt_assert(batch); |
| 617 | |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 618 | switch (buf->bpp) { |
| 619 | case 16: |
| 620 | case 32: |
| 621 | adjusted_w = rect->w / (32 / buf->bpp); |
| 622 | adjusted_dst_x = rect->x / (32 / buf->bpp); |
| 623 | break; |
| 624 | default: |
| 625 | igt_assert(false); |
| 626 | } |
| 627 | |
| 628 | rendercopy(batch, cmd_data->context, &src_buf, 0, 0, adjusted_w, |
| 629 | rect->h, &dst_buf, adjusted_dst_x, rect->y); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 630 | |
| 631 | intel_batchbuffer_free(batch); |
| 632 | gem_close(fd, tmp.handle); |
| 633 | } |
| 634 | |
| 635 | /** |
| 636 | * igt_draw_rect: |
| 637 | * @fd: the DRM file descriptor |
| 638 | * @bufmgr: the libdrm bufmgr, only required for IGT_DRAW_BLT and |
| 639 | * IGT_DRAW_RENDER |
| 640 | * @context: the context, can be NULL if you don't want to think about it |
| 641 | * @buf_handle: the handle of the buffer where you're going to draw to |
| 642 | * @buf_size: the size of the buffer |
| 643 | * @buf_stride: the stride of the buffer |
| 644 | * @method: method you're going to use to write to the buffer |
| 645 | * @rect_x: horizontal position on the buffer where your rectangle starts |
| 646 | * @rect_y: vertical position on the buffer where your rectangle starts |
| 647 | * @rect_w: width of the rectangle |
| 648 | * @rect_h: height of the rectangle |
| 649 | * @color: color of the rectangle |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 650 | * @bpp: bits per pixel |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 651 | * |
| 652 | * This function draws a colored rectangle on the destination buffer, allowing |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 653 | * you to specify the method used to draw the rectangle. |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 654 | */ |
| 655 | void igt_draw_rect(int fd, drm_intel_bufmgr *bufmgr, drm_intel_context *context, |
| 656 | uint32_t buf_handle, uint32_t buf_size, uint32_t buf_stride, |
| 657 | enum igt_draw_method method, int rect_x, int rect_y, |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 658 | int rect_w, int rect_h, uint32_t color, int bpp) |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 659 | { |
| 660 | struct cmd_data cmd_data = { |
| 661 | .bufmgr = bufmgr, |
| 662 | .context = context, |
| 663 | }; |
| 664 | struct buf_data buf = { |
| 665 | .handle = buf_handle, |
| 666 | .size = buf_size, |
| 667 | .stride = buf_stride, |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 668 | .bpp = bpp, |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 669 | }; |
| 670 | struct rect rect = { |
| 671 | .x = rect_x, |
| 672 | .y = rect_y, |
| 673 | .w = rect_w, |
| 674 | .h = rect_h, |
| 675 | }; |
| 676 | |
| 677 | switch (method) { |
| 678 | case IGT_DRAW_MMAP_CPU: |
| 679 | draw_rect_mmap_cpu(fd, &buf, &rect, color); |
| 680 | break; |
| 681 | case IGT_DRAW_MMAP_GTT: |
| 682 | draw_rect_mmap_gtt(fd, &buf, &rect, color); |
| 683 | break; |
| 684 | case IGT_DRAW_MMAP_WC: |
| 685 | draw_rect_mmap_wc(fd, &buf, &rect, color); |
| 686 | break; |
| 687 | case IGT_DRAW_PWRITE: |
| 688 | draw_rect_pwrite(fd, &buf, &rect, color); |
| 689 | break; |
| 690 | case IGT_DRAW_BLT: |
| 691 | draw_rect_blt(fd, &cmd_data, &buf, &rect, color); |
| 692 | break; |
| 693 | case IGT_DRAW_RENDER: |
| 694 | draw_rect_render(fd, &cmd_data, &buf, &rect, color); |
| 695 | break; |
| 696 | default: |
| 697 | igt_assert(false); |
| 698 | break; |
| 699 | } |
| 700 | } |
| 701 | |
| 702 | /** |
| 703 | * igt_draw_rect_fb: |
Thomas Wood | 6141aa2 | 2015-05-14 16:00:25 +0100 | [diff] [blame] | 704 | * @fd: the DRM file descriptor |
| 705 | * @bufmgr: the libdrm bufmgr, only required for IGT_DRAW_BLT and |
| 706 | * IGT_DRAW_RENDER |
| 707 | * @context: the context, can be NULL if you don't want to think about it |
| 708 | * @fb: framebuffer |
| 709 | * @method: method you're going to use to write to the buffer |
| 710 | * @rect_x: horizontal position on the buffer where your rectangle starts |
| 711 | * @rect_y: vertical position on the buffer where your rectangle starts |
| 712 | * @rect_w: width of the rectangle |
| 713 | * @rect_h: height of the rectangle |
| 714 | * @color: color of the rectangle |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 715 | * |
| 716 | * This is exactly the same as igt_draw_rect, but you can pass an igt_fb instead |
| 717 | * of manually providing its details. See igt_draw_rect. |
| 718 | */ |
| 719 | void igt_draw_rect_fb(int fd, drm_intel_bufmgr *bufmgr, |
| 720 | drm_intel_context *context, struct igt_fb *fb, |
| 721 | enum igt_draw_method method, int rect_x, int rect_y, |
| 722 | int rect_w, int rect_h, uint32_t color) |
| 723 | { |
| 724 | igt_draw_rect(fd, bufmgr, context, fb->gem_handle, fb->size, fb->stride, |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 725 | method, rect_x, rect_y, rect_w, rect_h, color, |
Paulo Zanoni | 12c1eb6 | 2016-01-25 21:17:50 -0200 | [diff] [blame] | 726 | igt_drm_format_to_bpp(fb->drm_format)); |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 727 | } |
| 728 | |
| 729 | /** |
| 730 | * igt_draw_fill_fb: |
| 731 | * @fd: the DRM file descriptor |
| 732 | * @fb: the FB that is going to be filled |
| 733 | * @color: the color you're going to paint it |
| 734 | * |
Paulo Zanoni | caaf3b8 | 2015-08-03 14:41:35 -0300 | [diff] [blame] | 735 | * This function just paints an igt_fb using the provided color. |
Paulo Zanoni | cf9f48e | 2015-02-19 15:41:15 -0200 | [diff] [blame] | 736 | */ |
| 737 | void igt_draw_fill_fb(int fd, struct igt_fb *fb, uint32_t color) |
| 738 | { |
| 739 | igt_draw_rect_fb(fd, NULL, NULL, fb, IGT_DRAW_MMAP_GTT, |
| 740 | 0, 0, fb->width, fb->height, color); |
| 741 | } |