1 /* basic set of prime tests between intel and nouveau */
4 1. share buffer from intel -> nouveau.
5 2. share buffer from nouveau -> intel
6 3. share intel->nouveau, map on both, write intel, read nouveau
7 4. share intel->nouveau, blit intel fill, readback on nouveau
8 test 1 + map buffer, read/write, map other size.
9 do some hw actions on the buffer
10 some illegal operations -
11 close prime fd try and map
13 TODO add some nouveau rendering tests
23 #include <sys/ioctl.h>
26 #include "ioctl_wrappers.h"
27 #include "intel_bufmgr.h"
30 #include "intel_batchbuffer.h"
31 #include "intel_chipset.h"
34 static int intel_fd = -1, nouveau_fd = -1;
35 static drm_intel_bufmgr *bufmgr;
36 static struct nouveau_device *ndev;
37 static struct nouveau_client *nclient;
38 static uint32_t devid;
39 static struct intel_batchbuffer *batch;
40 static struct nouveau_object *nchannel, *pcopy;
41 static struct nouveau_bufctx *nbufctx;
42 static struct nouveau_pushbuf *npush;
44 static struct nouveau_bo *query_bo;
45 static uint32_t query_counter;
46 static volatile uint32_t *query;
47 static uint32_t memtype_intel, tile_intel_y, tile_intel_x;
49 #define SUBC_COPY(x) 6, (x)
50 #define NV01_SUBCHAN_OBJECT 0
52 #define NV01_SUBC(subc, mthd) SUBC_##subc((NV01_SUBCHAN_##mthd))
56 uint32_t pitch, lines;
59 static void nv_bo_alloc(struct nouveau_bo **bo, rect *r,
60 uint32_t w, uint32_t h, uint32_t tile_mode,
61 int handle, uint32_t dom)
64 uint32_t dx = 1, dy = 1, memtype = 0;
72 if ((tile_mode & 0xf) == 0xe)
73 /* but the internal layout is different */
76 tile_x = 6 + (tile_mode & 0xf);
77 if (ndev->chipset < 0xc0) {
84 if ((tile_mode & 0xf) == 0xe)
85 memtype = memtype_intel;
86 tile_y += ((tile_mode & 0xf0)>>4);
90 igt_debug("Tiling requirements: x y %u %u\n", dx, dy);
96 r->pitch = w = (w + dx-1) & ~(dx-1);
97 r->lines = h = (h + dy-1) & ~(dy-1);
101 union nouveau_bo_config cfg;
102 cfg.nv50.memtype = memtype;
103 cfg.nv50.tile_mode = tile_mode;
104 if (dom == NOUVEAU_BO_GART)
105 dom |= NOUVEAU_BO_MAP;
106 igt_assert(nouveau_bo_new(ndev, dom, 4096, size, &cfg, bo) == 0);
107 igt_assert(nouveau_bo_map(*bo, NOUVEAU_BO_RDWR, nclient) == 0);
109 igt_debug("new flags %08x memtype %08x tile %08x\n",
110 (*bo)->flags, (*bo)->config.nv50.memtype,
111 (*bo)->config.nv50.tile_mode);
112 if (tile_mode == tile_intel_y || tile_mode == tile_intel_x) {
113 igt_debug("tile mode was: %02x, now: %02x\n",
114 (*bo)->config.nv50.tile_mode, tile_mode);
115 /* Doesn't like intel tiling much.. */
116 (*bo)->config.nv50.tile_mode = tile_mode;
119 igt_assert(nouveau_bo_prime_handle_ref(ndev, handle, bo) == 0);
121 igt_assert_f((*bo)->size >= size,
122 "expected bo size to be at least %u,"
123 "but received %"PRIu64"\n", size, (*bo)->size);
124 igt_debug("prime flags %08x memtype %08x tile %08x\n",
125 (*bo)->flags, (*bo)->config.nv50.memtype,
126 (*bo)->config.nv50.tile_mode);
127 (*bo)->config.nv50.memtype = memtype;
128 (*bo)->config.nv50.tile_mode = tile_mode;
130 igt_debug("size: %"PRIu64"\n", (*bo)->size);
134 PUSH_DATA(struct nouveau_pushbuf *push, uint32_t data)
140 BEGIN_NV04(struct nouveau_pushbuf *push, int subc, int mthd, int size)
142 PUSH_DATA (push, 0x00000000 | (size << 18) | (subc << 13) | mthd);
146 BEGIN_NI04(struct nouveau_pushbuf *push, int subc, int mthd, int size)
148 PUSH_DATA (push, 0x40000000 | (size << 18) | (subc << 13) | mthd);
152 BEGIN_NVC0(struct nouveau_pushbuf *push, int subc, int mthd, int size)
154 PUSH_DATA (push, 0x20000000 | (size << 16) | (subc << 13) | (mthd / 4));
158 BEGIN_NVXX(struct nouveau_pushbuf *push, int subc, int mthd, int size)
160 if (ndev->chipset < 0xc0)
161 BEGIN_NV04(push, subc, mthd, size);
163 BEGIN_NVC0(push, subc, mthd, size);
167 noop_intel(drm_intel_bo *bo)
171 OUT_BATCH(MI_BATCH_BUFFER_END);
172 OUT_RELOC(bo, I915_GEM_DOMAIN_RENDER,
173 I915_GEM_DOMAIN_RENDER, 0);
176 intel_batchbuffer_flush(batch);
179 static void find_and_open_devices(void)
182 char path[80], *unused;
185 char vendor_id[8] = {};
187 for (i = 0; i < 9; i++) {
188 sprintf(path, "/sys/class/drm/card%d/device/vendor", i);
189 if (stat(path, &buf))
192 fl = fopen(path, "r");
196 unused = fgets(vendor_id, sizeof(vendor_id)-1, fl);
200 venid = strtoul(vendor_id, NULL, 16);
201 sprintf(path, "/dev/dri/card%d", i);
202 if (venid == 0x8086) {
203 intel_fd = open(path, O_RDWR);
204 igt_assert(intel_fd);
205 } else if (venid == 0x10de) {
206 nouveau_fd = open(path, O_RDWR);
207 igt_assert(nouveau_fd);
212 static void init_nouveau(void)
214 struct nv04_fifo nv04_data = { .vram = 0xbeef0201,
215 .gart = 0xbeef0202 };
216 struct nvc0_fifo nvc0_data = { };
217 struct nouveau_fifo *fifo;
222 igt_assert(nouveau_device_wrap(nouveau_fd, 0, &ndev) == 0);
224 igt_assert(nouveau_client_new(ndev, &nclient) == 0);
226 igt_skip_on_f(ndev->chipset < 0xa3 || ndev->chipset == 0xaa || ndev->chipset == 0xac,
227 "Your card doesn't support PCOPY\n");
229 // TODO: Get a kepler and add support for it
230 igt_skip_on_f(ndev->chipset >= 0xe0,
231 "Unsure how kepler works!\n");
232 igt_assert(nouveau_bo_new(ndev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP,
233 4096, 4096, NULL, &query_bo) == 0);
234 igt_assert(nouveau_bo_map(query_bo, NOUVEAU_BO_RDWR, nclient) == 0);
235 query = query_bo->map;
236 *query = query_counter;
238 if (ndev->chipset < 0xc0) {
241 size = sizeof(nv04_data);
243 class = ndev->chipset < 0xe0 ? 0x490b5 : 0xa0b5;
245 size = sizeof(nvc0_data);
248 igt_assert(nouveau_object_new(&ndev->object, 0, NOUVEAU_FIFO_CHANNEL_CLASS,
249 data, size, &nchannel) == 0);
251 fifo = nchannel->data;
253 igt_assert(nouveau_pushbuf_new(nclient, nchannel, 4, 32 * 1024,
256 igt_assert(nouveau_bufctx_new(nclient, 1, &nbufctx) == 0);
258 npush->user_priv = nbufctx;
260 /* Hope this is enough init for PCOPY */
261 igt_assert(nouveau_object_new(nchannel, class, class & 0xffff, NULL, 0, &pcopy) == 0);
262 igt_assert(nouveau_pushbuf_space(npush, 512, 0, 0) == 0);
264 if (ndev->chipset < 0xc0) {
265 struct nv04_fifo *nv04_fifo = (struct nv04_fifo*)fifo;
269 BEGIN_NV04(npush, NV01_SUBC(COPY, OBJECT), 1);
270 PUSH_DATA(npush, pcopy->handle);
271 BEGIN_NV04(npush, SUBC_COPY(0x0180), 3);
272 PUSH_DATA(npush, nv04_fifo->vram);
273 PUSH_DATA(npush, nv04_fifo->vram);
274 PUSH_DATA(npush, nv04_fifo->vram);
278 BEGIN_NVC0(npush, NV01_SUBC(COPY, OBJECT), 1);
279 PUSH_DATA(npush, pcopy->handle);
281 nouveau_pushbuf_kick(npush, npush->channel);
284 static void fill16(void *ptr, uint32_t val)
287 val = (val) | (val << 8) | (val << 16) | (val << 24);
288 p[0] = p[1] = p[2] = p[3] = val;
291 #define TILE_SIZE 4096
293 static void swtile_y(uint8_t *out, const uint8_t *in, int w, int h)
295 uint32_t x, y, dx, dy;
296 uint8_t *endptr = out + w * h;
297 igt_assert(!(w % 128));
298 igt_assert(!(h % 32));
300 for (y = 0; y < h; y += 32) {
301 for (x = 0; x < w; x += 128, out += TILE_SIZE) {
302 for (dx = 0; dx < 8; ++dx) {
303 for (dy = 0; dy < 32; ++dy) {
304 uint32_t out_ofs = (dx * 32 + dy) * 16;
305 uint32_t in_ofs = (y + dy) * w + (x + 16 * dx);
306 igt_assert(out_ofs < TILE_SIZE);
307 igt_assert(in_ofs < w*h);
309 // To do the Y tiling quirk:
310 // out_ofs = out_ofs ^ (((out_ofs >> 9) & 1) << 6);
311 memcpy(&out[out_ofs], &in[in_ofs], 16);
316 igt_assert(out == endptr);
319 static void swtile_x(uint8_t *out, const uint8_t *in, int w, int h)
322 uint8_t *endptr = out + w * h;
323 igt_assert(!(w % 512));
324 igt_assert(!(h % 8));
326 for (y = 0; y < h; y += 8) {
327 for (x = 0; x < w; x += 512, out += TILE_SIZE) {
328 for (dy = 0; dy < 8; ++dy) {
329 uint32_t out_ofs = 512 * dy;
330 uint32_t in_ofs = (y + dy) * w + x;
331 igt_assert(out_ofs < TILE_SIZE);
332 igt_assert(in_ofs < w*h);
333 memcpy(&out[out_ofs], &in[in_ofs], 512);
337 igt_assert(out == endptr);
340 static void perform_copy(struct nouveau_bo *nvbo, const rect *dst,
341 uint32_t dst_x, uint32_t dst_y,
342 struct nouveau_bo *nvbi, const rect *src,
343 uint32_t src_x, uint32_t src_y,
344 uint32_t w, uint32_t h)
346 struct nouveau_pushbuf_refn refs[] = {
347 { nvbi, (nvbi->flags & NOUVEAU_BO_APER) | NOUVEAU_BO_RD },
348 { nvbo, (nvbo->flags & NOUVEAU_BO_APER) | NOUVEAU_BO_WR },
349 { query_bo, NOUVEAU_BO_GART | NOUVEAU_BO_RDWR }
351 uint32_t cpp = 1, exec = 0x00003000; /* QUERY|QUERY_SHORT|FORMAT */
352 uint32_t src_off = 0, dst_off = 0;
353 struct nouveau_pushbuf *push = npush;
356 if (nvbi->config.nv50.tile_mode == tile_intel_y)
357 igt_debug("src is y-tiled\n");
358 if (nvbo->config.nv50.tile_mode == tile_intel_y)
359 igt_debug("dst is y-tiled\n");
361 igt_assert(nouveau_pushbuf_space(push, 64, 0, 0) == 0);
362 igt_assert(nouveau_pushbuf_refn(push, refs, 3) == 0);
364 if (!nvbi->config.nv50.tile_mode) {
365 src_off = src_y * src->pitch + src_x;
369 if (!nvbo->config.nv50.tile_mode) {
370 dst_off = dst_y * dst->pitch + dst_x;
374 BEGIN_NVXX(push, SUBC_COPY(0x0200), 7);
375 PUSH_DATA (push, nvbi->config.nv50.tile_mode);
376 PUSH_DATA (push, src->pitch / cpp);
377 PUSH_DATA (push, src->h);
380 PUSH_DATA (push, src_x / cpp);
381 PUSH_DATA (push, src_y);
383 BEGIN_NVXX(push, SUBC_COPY(0x0220), 7);
384 PUSH_DATA (push, nvbo->config.nv50.tile_mode);
385 PUSH_DATA (push, dst->pitch / cpp);
386 PUSH_DATA (push, dst->h);
389 PUSH_DATA (push, dst_x / cpp);
390 PUSH_DATA (push, dst_y);
392 BEGIN_NVXX(push, SUBC_COPY(0x030c), 9);
393 PUSH_DATA (push, (nvbi->offset + src_off) >> 32);
394 PUSH_DATA (push, (nvbi->offset + src_off));
395 PUSH_DATA (push, (nvbo->offset + dst_off) >> 32);
396 PUSH_DATA (push, (nvbo->offset + dst_off));
397 PUSH_DATA (push, src->pitch);
398 PUSH_DATA (push, dst->pitch);
399 PUSH_DATA (push, w / cpp);
401 PUSH_DATA (push, 0x03333120);
403 BEGIN_NVXX(push, SUBC_COPY(0x0338), 3);
404 PUSH_DATA (push, (query_bo->offset) >> 32);
405 PUSH_DATA (push, (query_bo->offset));
406 PUSH_DATA (push, ++query_counter);
408 BEGIN_NVXX(push, SUBC_COPY(0x0300), 1);
409 PUSH_DATA (push, exec);
411 ret = nouveau_pushbuf_kick(push, push->channel);
412 while (!ret && *query < query_counter) { usleep(1000); }
414 igt_assert(ret == 0);
417 static void check1_macro(uint32_t *p, uint32_t w, uint32_t h)
421 for (i = 0; i < 256; ++i, p += 4) {
422 val = (i) | (i << 8) | (i << 16) | (i << 24);
423 igt_assert_f(p[0] == val && p[1] == val && p[2] == val && p[3] == val,
424 "Retile check failed in first tile!\n"
425 "%08x %08x %08x %08x instead of %08x\n",
426 p[0], p[1], p[2], p[3], val);
430 for (i = 0; i < 256 * (w-1); ++i, p += 4) {
431 igt_assert_f(p[0] == val && p[1] == val && p[2] == val && p[3] == val,
432 "Retile check failed in second tile!\n"
433 "%08x %08x %08x %08x instead of %08x\n",
434 p[0], p[1], p[2], p[3], val);
437 for (j = 1; j < h; ++j) {
439 for (i = 0; i < 256; ++i, p += 4) {
440 igt_assert_f(p[0] == val && p[1] == val && p[2] == val && p[3] == val,
441 "Retile check failed in third tile!\n"
442 "%08x %08x %08x %08x instead of %08x\n",
443 p[0], p[1], p[2], p[3], val);
447 for (i = 0; i < 256 * (w-1); ++i, p += 4) {
448 igt_assert_f(p[0] == val && p[1] == val && p[2] == val && p[3] == val,
449 "Retile check failed in fourth tile!\n"
450 "%08x %08x %08x %08x instead of %08x\n",
451 p[0], p[1], p[2], p[3], val);
456 /* test 1, see if we can copy from linear to intel Y format safely */
457 static void test1_macro(void)
460 struct nouveau_bo *nvbo = NULL, *nvbi = NULL;
463 uint32_t w = 2 * 128, h = 2 * 32, x, y;
465 nv_bo_alloc(&nvbi, &src, w, h, 0, -1, NOUVEAU_BO_GART);
466 nv_bo_alloc(&nvbo, &dst, w, h, tile_intel_y, -1, NOUVEAU_BO_GART);
468 nouveau_bo_set_prime(nvbo, &prime_fd);
470 /* Set up something for our tile that should map into the first
471 * y-major tile, assuming my understanding of documentation is
475 /* First tile should be read out in groups of 16 bytes that
476 * are all set to a linear increasing value..
479 for (x = 0; x < 128; x += 16)
480 for (y = 0; y < 32; ++y)
481 fill16(&ptr[y * w + x], x * 2 + y);
484 for (x = 128; x < w; x += 16)
485 for (y = 0; y < 32; ++y)
486 fill16(&ptr[y * w + x], 0x3e);
489 for (x = 0; x < 128; x += 16)
490 for (y = 32; y < h; ++y)
491 fill16(&ptr[y * w + x], 0x7e);
494 for (x = 128; x < w; x += 16)
495 for (y = 32; y < h; ++y)
496 fill16(&ptr[y * w + x], 0xce);
497 memset(nvbo->map, 0xfc, w * h);
500 perform_copy(nvbo, &dst, 0, 0, nvbi, &src, 0, 0, w, h);
502 swtile_y(nvbo->map, nvbi->map, w, h);
503 check1_macro(nvbo->map, w/128, h/32);
505 nouveau_bo_ref(NULL, &nvbo);
506 nouveau_bo_ref(NULL, &nvbi);
510 static void dump_line(uint8_t *map)
513 igt_debug("Dumping sub-tile:\n");
514 for (dy = 0; dy < 32; ++dy) {
515 for (dx = 0; dx < 15; ++dx, ++map) {
516 igt_debug("%02x ", *map);
518 igt_debug("%02x\n", *(map++));
522 static void check1_micro(void *map, uint32_t pitch, uint32_t lines,
523 uint32_t dst_x, uint32_t dst_y, uint32_t w, uint32_t h)
527 /* check only the relevant subrectangle [0..w) [0...h) */
529 for (y = 0; y < h; ++y, m += pitch) {
530 for (x = 0; x < w; ++x) {
531 uint8_t expected = ((y & 3) << 6) | (x & 0x3f);
533 if (expected != m[x])
536 igt_assert_f(expected == m[x],
537 "failed check at x=%u y=%u, expected %02x got %02x\n",
538 x, y, expected, m[x]);
543 /* test 1, but check micro format, should be unaffected by bit9 swizzling */
544 static void test1_micro(void)
546 struct nouveau_bo *bo_intel = NULL, *bo_nvidia = NULL, *bo_linear = NULL;
547 rect intel, nvidia, linear;
548 uint32_t tiling = I915_TILING_Y;
550 uint32_t src_x = 0, src_y = 0;
551 uint32_t dst_x = 0, dst_y = 0;
552 uint32_t x, y, w = 256, h = 64;
554 drm_intel_bo *test_intel_bo;
557 test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", w * h, 4096);
558 igt_assert(test_intel_bo);
559 drm_intel_bo_set_tiling(test_intel_bo, &tiling, w);
560 igt_assert(tiling == I915_TILING_Y);
561 igt_assert(drm_intel_gem_bo_map_gtt(test_intel_bo) == 0);
563 drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd);
564 igt_assert(prime_fd >= 0);
565 noop_intel(test_intel_bo);
567 nv_bo_alloc(&bo_intel, &intel, w, h, tile_intel_y, prime_fd, 0);
568 nv_bo_alloc(&bo_nvidia, &nvidia, w, h, 0x10, -1, NOUVEAU_BO_VRAM);
569 nv_bo_alloc(&bo_linear, &linear, w, h, 0, -1, NOUVEAU_BO_GART);
571 for (y = 0; y < linear.h; ++y) {
572 uint8_t *map = bo_linear->map;
573 map += y * linear.pitch;
574 for (x = 0; x < linear.pitch; ++x) {
575 uint8_t pos = x & 0x3f;
576 /* low 4 bits: micro tile pos */
577 /* 2 bits: x pos in tile (wraps) */
578 /* 2 bits: y pos in tile (wraps) */
584 perform_copy(bo_nvidia, &nvidia, 0, 0, bo_linear, &linear, 0, 0, nvidia.pitch, nvidia.h);
586 /* Perform the actual sub rectangle copy */
588 perform_copy(bo_intel, &intel, dst_x, dst_y, bo_nvidia, &nvidia, src_x, src_y, w, h);
590 swtile_y(test_intel_bo->virtual, bo_linear->map, w, h);
592 noop_intel(test_intel_bo);
593 check1_micro(test_intel_bo->virtual, intel.pitch, intel.h, dst_x, dst_y, w, h);
595 nouveau_bo_ref(NULL, &bo_linear);
596 nouveau_bo_ref(NULL, &bo_nvidia);
597 nouveau_bo_ref(NULL, &bo_intel);
598 drm_intel_bo_unreference(test_intel_bo);
601 /* test 2, see if we can copy from linear to intel X format safely
602 * Seems nvidia lacks a method to do it, so just keep this test
603 * as a reference for potential future tests. Software tiling is
606 static void test2(void)
608 struct nouveau_bo *nvbo = NULL, *nvbi = NULL;
611 uint32_t w = 1024, h = 16, x, y;
613 nv_bo_alloc(&nvbi, &src, w, h, 0, -1, NOUVEAU_BO_GART);
614 nv_bo_alloc(&nvbo, &dst, w, h, tile_intel_x, -1, NOUVEAU_BO_GART);
616 /* Set up something for our tile that should map into the first
617 * y-major tile, assuming my understanding of documentation is
621 /* First tile should be read out in groups of 16 bytes that
622 * are all set to a linear increasing value..
625 for (y = 0; y < 8; ++y)
626 for (x = 0; x < 512; x += 16)
627 fill16(&ptr[y * w + x], (y * 512 + x)/16);
629 for (y = 0; y < 8; ++y)
630 for (x = 512; x < w; x += 16)
631 fill16(&ptr[y * w + x], 0x3e);
633 for (y = 8; y < h; ++y)
634 for (x = 0; x < 512; x += 16)
635 fill16(&ptr[y * w + x], 0x7e);
637 for (y = 8; y < h; ++y)
638 for (x = 512; x < w; x += 16)
639 fill16(&ptr[y * w + x], 0xce);
640 memset(nvbo->map, 0xfc, w * h);
642 /* do this in software, there is no X major tiling in PCOPY (yet?) */
644 perform_copy(nvbo, &dst, 0, 0, nvbi, &src, 0, 0, w, h);
646 swtile_x(nvbo->map, nvbi->map, w, h);
647 check1_macro(nvbo->map, w/512, h/8);
649 nouveau_bo_ref(NULL, &nvbo);
650 nouveau_bo_ref(NULL, &nvbi);
653 static void check3(const uint32_t *p, uint32_t pitch, uint32_t lines,
654 uint32_t sub_x, uint32_t sub_y,
655 uint32_t sub_w, uint32_t sub_h)
662 igt_assert_f(p[pitch * lines / 4 - 1] != 0x03030303,
663 "copy failed: Not all lines have been copied back!\n");
665 for (y = 0; y < lines; ++y) {
666 for (x = 0; x < pitch; x += 4, ++p) {
668 if ((x < sub_x || x >= sub_w) ||
669 (y < sub_y || y >= sub_h))
670 expected = 0x80808080;
672 expected = 0x04040404;
673 igt_assert_f(*p == expected,
674 "%u,%u should be %08x, but is %08x\n",
680 /* copy from nvidia bo to intel bo and copy to a linear bo to check if tiling went succesful */
681 static void test3_base(int tile_src, int tile_dst)
683 struct nouveau_bo *bo_intel = NULL, *bo_nvidia = NULL, *bo_linear = NULL;
684 rect intel, nvidia, linear;
687 uint32_t src_x = 1 * cpp, src_y = 1;
688 uint32_t dst_x = 2 * cpp, dst_y = 26;
689 uint32_t w = 298 * cpp, h = 298;
691 drm_intel_bo *test_intel_bo;
694 test_intel_bo = drm_intel_bo_alloc(bufmgr, "test bo", 2048 * cpp * 768, 4096);
695 igt_assert(test_intel_bo);
697 drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd);
698 igt_assert(prime_fd >= 0);
700 nv_bo_alloc(&bo_intel, &intel, 2048 * cpp, 768, tile_dst, prime_fd, 0);
701 nv_bo_alloc(&bo_nvidia, &nvidia, 300 * cpp, 300, tile_src, -1, NOUVEAU_BO_VRAM);
702 nv_bo_alloc(&bo_linear, &linear, 2048 * cpp, 768, 0, -1, NOUVEAU_BO_GART);
704 noop_intel(test_intel_bo);
705 memset(bo_linear->map, 0x80, bo_linear->size);
706 perform_copy(bo_intel, &intel, 0, 0, bo_linear, &linear, 0, 0, linear.pitch, linear.h);
707 noop_intel(test_intel_bo);
709 memset(bo_linear->map, 0x04, bo_linear->size);
710 perform_copy(bo_nvidia, &nvidia, 0, 0, bo_linear, &linear, 0, 0, nvidia.pitch, nvidia.h);
712 /* Perform the actual sub rectangle copy */
713 noop_intel(test_intel_bo);
714 perform_copy(bo_intel, &intel, dst_x, dst_y, bo_nvidia, &nvidia, src_x, src_y, w, h);
715 noop_intel(test_intel_bo);
717 memset(bo_linear->map, 0x3, bo_linear->size);
718 noop_intel(test_intel_bo);
719 perform_copy(bo_linear, &linear, 0, 0, bo_intel, &intel, 0, 0, intel.pitch, intel.h);
720 noop_intel(test_intel_bo);
722 check3(bo_linear->map, linear.pitch, linear.h, dst_x, dst_y, w, h);
724 nouveau_bo_ref(NULL, &bo_linear);
725 nouveau_bo_ref(NULL, &bo_nvidia);
726 nouveau_bo_ref(NULL, &bo_intel);
727 drm_intel_bo_unreference(test_intel_bo);
730 static void test3_1(void)
732 /* nvidia tiling to intel */
733 test3_base(0x40, tile_intel_y);
736 static void test3_2(void)
738 /* intel tiling to nvidia */
739 test3_base(tile_intel_y, 0x40);
742 static void test3_3(void)
744 /* intel tiling to linear */
745 test3_base(tile_intel_y, 0);
748 static void test3_4(void)
750 /* linear tiling to intel */
751 test3_base(0, tile_intel_y);
754 static void test3_5(void)
756 /* linear to linear */
760 /* Acquire when == SEQUENCE */
761 #define SEMA_ACQUIRE_EQUAL 1
763 /* Release, and write a 16 byte query structure to sema:
764 * { (uint32)seq, (uint32)0, (uint64)timestamp } */
765 #define SEMA_WRITE_LONG 2
767 /* Acquire when >= SEQUENCE */
768 #define SEMA_ACQUIRE_GEQUAL 4
770 /* Test only new style semaphores, old ones are AWFUL */
771 static void test_semaphore(void)
773 drm_intel_bo *test_intel_bo = NULL;
774 struct nouveau_bo *sema_bo = NULL;
777 struct nouveau_pushbuf *push = npush;
779 igt_skip_on(ndev->chipset < 0x84);
781 /* Should probably be kept in sysmem */
782 test_intel_bo = drm_intel_bo_alloc(bufmgr, "semaphore bo", 4096, 4096);
783 igt_assert(test_intel_bo);
785 drm_intel_bo_gem_export_to_prime(test_intel_bo, &prime_fd);
786 igt_assert(prime_fd >= 0);
787 igt_assert(nouveau_bo_prime_handle_ref(ndev, prime_fd, &sema_bo) == 0);
790 igt_assert(drm_intel_gem_bo_map_gtt(test_intel_bo) == 0);
791 sema = test_intel_bo->virtual;
795 igt_assert(nouveau_pushbuf_space(push, 64, 0, 0) == 0);
796 igt_assert(nouveau_pushbuf_refn(push, &(struct nouveau_pushbuf_refn)
797 { sema_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR }, 1) == 0);
799 if (ndev->chipset < 0xc0) {
800 struct nv04_fifo *nv04_fifo = nchannel->data;
801 /* kernel binds it's own dma object here and overwrites old one,
802 * so just rebind vram every time we submit
804 BEGIN_NV04(npush, SUBC_COPY(0x0060), 1);
805 PUSH_DATA(npush, nv04_fifo->vram);
807 BEGIN_NVXX(push, SUBC_COPY(0x0010), 4);
808 PUSH_DATA(push, sema_bo->offset >> 32);
809 PUSH_DATA(push, sema_bo->offset + 4);
810 PUSH_DATA(push, 2); // SEQUENCE
811 PUSH_DATA(push, SEMA_WRITE_LONG); // TRIGGER
813 BEGIN_NVXX(push, SUBC_COPY(0x0018), 2);
815 PUSH_DATA(push, SEMA_ACQUIRE_EQUAL);
816 BEGIN_NVXX(push, SUBC_COPY(0x0018), 2);
818 PUSH_DATA(push, SEMA_WRITE_LONG);
820 BEGIN_NVXX(push, SUBC_COPY(0x0018), 2);
822 PUSH_DATA(push, SEMA_ACQUIRE_GEQUAL);
823 BEGIN_NVXX(push, SUBC_COPY(0x0018), 2);
825 PUSH_DATA(push, SEMA_WRITE_LONG);
827 BEGIN_NVXX(push, SUBC_COPY(0x0018), 2);
829 PUSH_DATA(push, SEMA_ACQUIRE_GEQUAL);
830 BEGIN_NVXX(push, SUBC_COPY(0x0018), 2);
832 PUSH_DATA(push, SEMA_WRITE_LONG);
833 nouveau_pushbuf_kick(push, push->channel);
836 igt_assert(*sema == 2);
840 igt_assert(*sema == 4);
844 igt_assert(*sema == 6);
848 igt_assert(*sema == 9);
850 nouveau_bo_ref(NULL, &sema_bo);
851 drm_intel_bo_unreference(test_intel_bo);
857 find_and_open_devices();
859 igt_require(nouveau_fd != -1);
860 igt_require(intel_fd != -1);
862 /* set up intel bufmgr */
863 bufmgr = drm_intel_bufmgr_gem_init(intel_fd, 4096);
865 /* Do not enable reuse, we share (almost) all buffers. */
866 //drm_intel_bufmgr_gem_enable_reuse(bufmgr);
868 /* set up nouveau bufmgr */
871 /* set up an intel batch buffer */
872 devid = intel_get_drm_devid(intel_fd);
873 batch = intel_batchbuffer_alloc(bufmgr, devid);
877 #define xtest(x, args...) \
883 //xtest(test1_swizzle);
890 xtest(test_semaphore);
893 nouveau_bo_ref(NULL, &query_bo);
894 nouveau_object_del(&pcopy);
895 nouveau_bufctx_del(&nbufctx);
896 nouveau_pushbuf_del(&npush);
897 nouveau_object_del(&nchannel);
899 intel_batchbuffer_free(batch);
901 nouveau_client_del(&nclient);
902 nouveau_device_del(&ndev);
903 drm_intel_bufmgr_destroy(bufmgr);