142542f5fSchristos/* 242542f5fSchristos * Copyright (c) 2014 Intel Corporation 342542f5fSchristos * 442542f5fSchristos * Permission is hereby granted, free of charge, to any person obtaining a 542542f5fSchristos * copy of this software and associated documentation files (the "Software"), 642542f5fSchristos * to deal in the Software without restriction, including without limitation 742542f5fSchristos * the rights to use, copy, modify, merge, publish, distribute, sublicense, 842542f5fSchristos * and/or sell copies of the Software, and to permit persons to whom the 942542f5fSchristos * Software is furnished to do so, subject to the following conditions: 1042542f5fSchristos * 1142542f5fSchristos * The above copyright notice and this permission notice (including the next 1242542f5fSchristos * paragraph) shall be included in all copies or substantial portions of the 1342542f5fSchristos * Software. 1442542f5fSchristos * 1542542f5fSchristos * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1642542f5fSchristos * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1742542f5fSchristos * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1842542f5fSchristos * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1942542f5fSchristos * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2042542f5fSchristos * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2142542f5fSchristos * SOFTWARE. 2242542f5fSchristos * 2342542f5fSchristos */ 2442542f5fSchristos 2542542f5fSchristos#ifdef HAVE_CONFIG_H 2642542f5fSchristos#include "config.h" 2742542f5fSchristos#endif 2842542f5fSchristos 2942542f5fSchristos#include <X11/Xlib.h> 3042542f5fSchristos#include <X11/Xutil.h> 3142542f5fSchristos#include <X11/Xlibint.h> 3242542f5fSchristos#include <X11/extensions/Xrender.h> 3342542f5fSchristos#include <X11/extensions/XShm.h> 3442542f5fSchristos#if HAVE_X11_EXTENSIONS_SHMPROTO_H 3542542f5fSchristos#include <X11/extensions/shmproto.h> 3642542f5fSchristos#elif HAVE_X11_EXTENSIONS_SHMSTR_H 3742542f5fSchristos#include <X11/extensions/shmstr.h> 3842542f5fSchristos#else 3942542f5fSchristos#error Failed to find the right header for X11 MIT-SHM protocol definitions 4042542f5fSchristos#endif 4142542f5fSchristos#include <xf86drm.h> 4242542f5fSchristos#include <i915_drm.h> 4342542f5fSchristos 4442542f5fSchristos#include <stdio.h> 4542542f5fSchristos#include <string.h> 4642542f5fSchristos#include <fcntl.h> 4742542f5fSchristos#include <unistd.h> 4842542f5fSchristos#include <assert.h> 4942542f5fSchristos#include <errno.h> 5042542f5fSchristos 5142542f5fSchristos#include <sys/mman.h> 5242542f5fSchristos#include <sys/ipc.h> 5342542f5fSchristos#include <sys/shm.h> 5442542f5fSchristos#include <pciaccess.h> 5542542f5fSchristos 5642542f5fSchristos#include "dri3.h" 5742542f5fSchristos#include "../src/i915_pciids.h" 5842542f5fSchristos 5942542f5fSchristos#define ALIGN(x, y) (((x) + (y) - 1) & -(y)) 6042542f5fSchristos#define PAGE_ALIGN(x) ALIGN(x, 4096) 6142542f5fSchristos 6242542f5fSchristos#define GTT I915_GEM_DOMAIN_GTT 6342542f5fSchristos#define CPU I915_GEM_DOMAIN_CPU 6442542f5fSchristos 6542542f5fSchristosstatic int _x_error_occurred; 6642542f5fSchristos 6742542f5fSchristosstatic const struct pci_id_match ids[] = { 6842542f5fSchristos INTEL_I830_IDS(020), 6942542f5fSchristos INTEL_I845G_IDS(021), 7042542f5fSchristos INTEL_I85X_IDS(022), 7142542f5fSchristos INTEL_I865G_IDS(023), 7242542f5fSchristos 7342542f5fSchristos INTEL_I915G_IDS(030), 7442542f5fSchristos INTEL_I915GM_IDS(030), 7542542f5fSchristos INTEL_I945G_IDS(031), 7642542f5fSchristos INTEL_I945GM_IDS(031), 7742542f5fSchristos 7842542f5fSchristos INTEL_G33_IDS(033), 7942542f5fSchristos INTEL_PINEVIEW_IDS(033), 8042542f5fSchristos 8142542f5fSchristos INTEL_I965G_IDS(040), 8242542f5fSchristos INTEL_I965GM_IDS(040), 8342542f5fSchristos 8442542f5fSchristos INTEL_G45_IDS(045), 8542542f5fSchristos INTEL_GM45_IDS(045), 8642542f5fSchristos 8742542f5fSchristos INTEL_IRONLAKE_D_IDS(050), 8842542f5fSchristos INTEL_IRONLAKE_M_IDS(050), 8942542f5fSchristos 9042542f5fSchristos INTEL_SNB_D_IDS(060), 9142542f5fSchristos INTEL_SNB_M_IDS(060), 9242542f5fSchristos 9342542f5fSchristos INTEL_IVB_D_IDS(070), 9442542f5fSchristos INTEL_IVB_M_IDS(070), 9542542f5fSchristos 96fe8aea9eSmrg INTEL_HSW_IDS(075), 97fe8aea9eSmrg INTEL_VLV_IDS(071), 98fe8aea9eSmrg INTEL_BDW_IDS(0100), 9942542f5fSchristos}; 10042542f5fSchristos 10142542f5fSchristosstatic int i915_gen(int device) 10242542f5fSchristos{ 10342542f5fSchristos struct drm_i915_getparam gp; 10442542f5fSchristos int devid = 0; 10542542f5fSchristos int n; 10642542f5fSchristos 10742542f5fSchristos gp.param = I915_PARAM_CHIPSET_ID; 10842542f5fSchristos gp.value = &devid; 10942542f5fSchristos 11042542f5fSchristos if (drmIoctl(device, DRM_IOCTL_I915_GETPARAM, &gp)) 11142542f5fSchristos return 0; 11242542f5fSchristos 11342542f5fSchristos for (n = 0; n < sizeof(ids)/sizeof(ids[0]); n++) { 11442542f5fSchristos if (devid == ids[n].device_id) 11542542f5fSchristos return ids[n].match_data; 11642542f5fSchristos } 11742542f5fSchristos 11842542f5fSchristos return 0; 11942542f5fSchristos} 12042542f5fSchristos 12142542f5fSchristosstatic int is_i915_device(int fd) 12242542f5fSchristos{ 12342542f5fSchristos drm_version_t version; 12442542f5fSchristos char name[5] = ""; 12542542f5fSchristos 12642542f5fSchristos memset(&version, 0, sizeof(version)); 12742542f5fSchristos version.name_len = 4; 12842542f5fSchristos version.name = name; 12942542f5fSchristos 13042542f5fSchristos if (drmIoctl(fd, DRM_IOCTL_VERSION, &version)) 13142542f5fSchristos return 0; 13242542f5fSchristos 13342542f5fSchristos return strcmp("i915", name) == 0; 13442542f5fSchristos} 13542542f5fSchristos 13642542f5fSchristosstatic int is_intel(int fd) 13742542f5fSchristos{ 13842542f5fSchristos struct drm_i915_getparam gp; 13942542f5fSchristos int ret; 14042542f5fSchristos 14142542f5fSchristos /* Confirm that this is a i915.ko device with GEM/KMS enabled */ 14242542f5fSchristos ret = is_i915_device(fd); 14342542f5fSchristos if (ret) { 14442542f5fSchristos gp.param = I915_PARAM_HAS_GEM; 14542542f5fSchristos gp.value = &ret; 14642542f5fSchristos if (drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp)) 14742542f5fSchristos ret = 0; 14842542f5fSchristos } 14942542f5fSchristos return ret; 15042542f5fSchristos} 15142542f5fSchristos 15242542f5fSchristosstatic uint32_t gem_create(int fd, int size) 15342542f5fSchristos{ 15442542f5fSchristos struct drm_i915_gem_create create; 15542542f5fSchristos 15642542f5fSchristos create.handle = 0; 15742542f5fSchristos create.size = size; 15842542f5fSchristos (void)drmIoctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create); 15942542f5fSchristos 16042542f5fSchristos return create.handle; 16142542f5fSchristos} 16242542f5fSchristos 16342542f5fSchristosstruct local_i915_gem_caching { 16442542f5fSchristos uint32_t handle; 16542542f5fSchristos uint32_t caching; 16642542f5fSchristos}; 16742542f5fSchristos 16842542f5fSchristos#define LOCAL_I915_GEM_SET_CACHING 0x2f 16942542f5fSchristos#define LOCAL_IOCTL_I915_GEM_SET_CACHING DRM_IOW(DRM_COMMAND_BASE + LOCAL_I915_GEM_SET_CACHING, struct local_i915_gem_caching) 17042542f5fSchristos 17142542f5fSchristosstatic int gem_set_caching(int fd, uint32_t handle, int caching) 17242542f5fSchristos{ 17342542f5fSchristos struct local_i915_gem_caching arg; 17442542f5fSchristos 17542542f5fSchristos arg.handle = handle; 17642542f5fSchristos arg.caching = caching; 17742542f5fSchristos 17842542f5fSchristos return drmIoctl(fd, LOCAL_IOCTL_I915_GEM_SET_CACHING, &arg) == 0; 17942542f5fSchristos} 18042542f5fSchristos 18142542f5fSchristosstatic int gem_export(int fd, uint32_t handle) 18242542f5fSchristos{ 18342542f5fSchristos struct drm_prime_handle args; 18442542f5fSchristos 18542542f5fSchristos args.handle = handle; 18642542f5fSchristos args.flags = O_CLOEXEC; 18742542f5fSchristos 18842542f5fSchristos if (drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args)) 18942542f5fSchristos return -1; 19042542f5fSchristos 19142542f5fSchristos return args.fd; 19242542f5fSchristos} 19342542f5fSchristos 19442542f5fSchristosstatic uint32_t gem_import(int fd, int name) 19542542f5fSchristos{ 19642542f5fSchristos struct drm_prime_handle args; 19742542f5fSchristos 19842542f5fSchristos args.fd = name; 19942542f5fSchristos args.flags = 0; 20042542f5fSchristos if (drmIoctl(fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &args)) 20142542f5fSchristos return 0; 20242542f5fSchristos 20342542f5fSchristos return args.handle; 20442542f5fSchristos} 20542542f5fSchristos 20642542f5fSchristosstatic int gem_write(int fd, uint32_t handle, int offset, void *data, int len) 20742542f5fSchristos{ 20842542f5fSchristos struct drm_i915_gem_pwrite gem_pwrite; 20942542f5fSchristos 21042542f5fSchristos gem_pwrite.handle = handle; 21142542f5fSchristos gem_pwrite.offset = offset; 21242542f5fSchristos gem_pwrite.size = len; 21342542f5fSchristos gem_pwrite.data_ptr = (uintptr_t)data; 21442542f5fSchristos return drmIoctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &gem_pwrite); 21542542f5fSchristos} 21642542f5fSchristos 21742542f5fSchristosstatic void *gem_mmap(int fd, uint32_t handle, int size, unsigned prot, int domain) 21842542f5fSchristos{ 21942542f5fSchristos struct drm_i915_gem_set_domain set_domain; 22042542f5fSchristos void *ptr; 22142542f5fSchristos 22242542f5fSchristos if (domain == CPU) { 22342542f5fSchristos struct drm_i915_gem_mmap mmap_arg; 22442542f5fSchristos 22542542f5fSchristos mmap_arg.handle = handle; 22642542f5fSchristos mmap_arg.offset = 0; 22742542f5fSchristos mmap_arg.size = size; 22842542f5fSchristos if (drmIoctl(fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg)) 22942542f5fSchristos return NULL; 23042542f5fSchristos 23142542f5fSchristos ptr = (void *)(uintptr_t)mmap_arg.addr_ptr; 23242542f5fSchristos } else { 23342542f5fSchristos struct drm_i915_gem_mmap_gtt mmap_arg; 23442542f5fSchristos 23542542f5fSchristos mmap_arg.handle = handle; 23642542f5fSchristos if (drmIoctl(fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_arg)) 23742542f5fSchristos return NULL; 23842542f5fSchristos 23942542f5fSchristos ptr = mmap(0, size, prot, MAP_SHARED, fd, mmap_arg.offset); 24042542f5fSchristos if (ptr == MAP_FAILED) 24142542f5fSchristos return NULL; 24242542f5fSchristos } 24342542f5fSchristos 24442542f5fSchristos set_domain.handle = handle; 24542542f5fSchristos set_domain.read_domains = domain; 24642542f5fSchristos set_domain.write_domain = prot & PROT_WRITE ? set_domain.read_domains : 0; 24742542f5fSchristos if (drmIoctl(fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain)) { 24842542f5fSchristos munmap(ptr, size); 24942542f5fSchristos return NULL; 25042542f5fSchristos } 25142542f5fSchristos 25242542f5fSchristos return ptr; 25342542f5fSchristos} 25442542f5fSchristos 25542542f5fSchristosstatic void gem_sync(int fd, uint32_t handle, int read) 25642542f5fSchristos{ 25742542f5fSchristos struct drm_i915_gem_set_domain set_domain; 25842542f5fSchristos 25942542f5fSchristos set_domain.handle = handle; 26042542f5fSchristos set_domain.read_domains = read; 26142542f5fSchristos set_domain.write_domain = 0; 26242542f5fSchristos drmIoctl(fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain); 26342542f5fSchristos} 26442542f5fSchristos 26542542f5fSchristosstatic int gem_get_tiling(int fd, uint32_t handle) 26642542f5fSchristos{ 26742542f5fSchristos struct drm_i915_gem_get_tiling tiling; 26842542f5fSchristos 26942542f5fSchristos tiling.handle = handle; 27042542f5fSchristos tiling.tiling_mode = -1; 27142542f5fSchristos (void)drmIoctl(fd, DRM_IOCTL_I915_GEM_GET_TILING, &tiling); 27242542f5fSchristos return tiling.tiling_mode; 27342542f5fSchristos} 27442542f5fSchristos 27542542f5fSchristosstatic void gem_close(int fd, uint32_t handle) 27642542f5fSchristos{ 27742542f5fSchristos struct drm_gem_close close; 27842542f5fSchristos 27942542f5fSchristos close.handle = handle; 28042542f5fSchristos (void)drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &close); 28142542f5fSchristos} 28242542f5fSchristos 28342542f5fSchristosstatic void gem_fill(int fd, uint32_t handle, uint32_t pixel, uint32_t size, int domain) 28442542f5fSchristos{ 28542542f5fSchristos uint32_t *ptr, s; 28642542f5fSchristos 28742542f5fSchristos ptr = gem_mmap(fd, handle, size, PROT_READ | PROT_WRITE, domain); 28842542f5fSchristos if (ptr == NULL) 28942542f5fSchristos return; 29042542f5fSchristos 29142542f5fSchristos for (s = 0; s < size; s += 4) 29242542f5fSchristos ptr[s/4] = pixel; 29342542f5fSchristos munmap(ptr, size); 29442542f5fSchristos} 29542542f5fSchristos 29642542f5fSchristosstatic int check_pixmap(Display *dpy, Pixmap pix, 29742542f5fSchristos int x, int y, uint32_t expected, int bpp) 29842542f5fSchristos{ 29942542f5fSchristos XImage *image; 30042542f5fSchristos int w = 32 / bpp; 30142542f5fSchristos 30242542f5fSchristos image = XGetImage(dpy, pix, x - (x % w), y, w, 1, AllPlanes, ZPixmap); 30342542f5fSchristos if (image == NULL) 30442542f5fSchristos return 0; 30542542f5fSchristos 30642542f5fSchristos if (*(uint32_t *)image->data != expected) { 30742542f5fSchristos printf("pixmap[%d, %d]:%d = %08x\n", x, y, bpp, *(uint32_t *)image->data); 30842542f5fSchristos return 0; 30942542f5fSchristos } 31042542f5fSchristos XDestroyImage(image); 31142542f5fSchristos 31242542f5fSchristos return 1; 31342542f5fSchristos} 31442542f5fSchristos 31542542f5fSchristosstatic int check_pixel(int fd, uint32_t handle, uint32_t stride, uint32_t size, 31642542f5fSchristos int x, int y, uint32_t expected, int bpp, int domain) 31742542f5fSchristos{ 31842542f5fSchristos uint32_t *ptr; 31942542f5fSchristos int w = 32 / bpp; 32042542f5fSchristos 32142542f5fSchristos assert((stride & 3) == 0); 32242542f5fSchristos 32342542f5fSchristos ptr = gem_mmap(fd, handle, size, PROT_READ, domain); 32442542f5fSchristos if (ptr == NULL) 32542542f5fSchristos return 0; 32642542f5fSchristos 32742542f5fSchristos if (ptr[(y*stride + x - (x % w))/4] != expected) { 32842542f5fSchristos printf("pixel[%d, %d]:%d = %08x\n", x, y, bpp, ptr[(y * stride + x)/4]); 32942542f5fSchristos return 0; 33042542f5fSchristos } 33142542f5fSchristos munmap(ptr, size); 33242542f5fSchristos 33342542f5fSchristos return 1; 33442542f5fSchristos} 33542542f5fSchristos 33642542f5fSchristosstatic GC get_gc(Display *dpy, Drawable d, int depth) 33742542f5fSchristos{ 33842542f5fSchristos static GC gc[33]; 33942542f5fSchristos if (gc[depth] == NULL) { 34042542f5fSchristos XGCValues gcv; 34142542f5fSchristos 34242542f5fSchristos gcv.graphics_exposures = False; 34342542f5fSchristos gc[depth] = XCreateGC(dpy, d, GCGraphicsExposures, &gcv); 34442542f5fSchristos } 34542542f5fSchristos return gc[depth]; 34642542f5fSchristos} 34742542f5fSchristos 34842542f5fSchristosstatic int 34942542f5fSchristoscan_use_shm(Display *dpy) 35042542f5fSchristos{ 35142542f5fSchristos int major, minor, has_pixmap; 35242542f5fSchristos 35342542f5fSchristos if (!XShmQueryExtension(dpy)) 35442542f5fSchristos return 0; 35542542f5fSchristos 35642542f5fSchristos XShmQueryVersion(dpy, &major, &minor, &has_pixmap); 35742542f5fSchristos return has_pixmap; 35842542f5fSchristos} 35942542f5fSchristos 36042542f5fSchristosstatic int gpu_fill(int device, int handle, int width, int height, int pitch, int bpp, int tiling, uint32_t pixel) 36142542f5fSchristos{ 36242542f5fSchristos struct drm_i915_gem_execbuffer2 execbuf; 36342542f5fSchristos struct drm_i915_gem_relocation_entry gem_reloc[2]; 36442542f5fSchristos struct drm_i915_gem_exec_object2 gem_exec[2]; 36542542f5fSchristos uint32_t batch[10]; 36642542f5fSchristos int gen = i915_gen(device); 36742542f5fSchristos int len = 0; 36842542f5fSchristos int ret; 36942542f5fSchristos 37042542f5fSchristos if (gen == 0) 37142542f5fSchristos return -ENODEV; 37242542f5fSchristos 37342542f5fSchristos batch[0] = 2 << 29 | 0x50 << 22; 37442542f5fSchristos batch[0] |= (gen >= 0100 ? 5 : 4); 37542542f5fSchristos batch[1] = pitch; 37642542f5fSchristos if (gen >= 040 && tiling) { 37742542f5fSchristos batch[0] |= 1 << 11; 37842542f5fSchristos batch[1] >>= 2; 37942542f5fSchristos } 38042542f5fSchristos 38142542f5fSchristos batch[1] |= 0xf0 << 16; 38242542f5fSchristos switch (bpp) { 38342542f5fSchristos default: assert(0); 38442542f5fSchristos case 32: batch[0] |= 1 << 21 | 1 << 20; 38542542f5fSchristos batch[1] |= 1 << 25; /* RGB8888 */ 38642542f5fSchristos case 16: batch[1] |= 1 << 24; /* RGB565 */ 38742542f5fSchristos case 8: break; 38842542f5fSchristos } 38942542f5fSchristos 39042542f5fSchristos batch[2] = 0; 39142542f5fSchristos batch[3] = height << 16 | width; 39242542f5fSchristos batch[4] = 0; 39342542f5fSchristos len = 5; 39442542f5fSchristos if (gen >= 0100) 39542542f5fSchristos batch[len++] = 0; 39642542f5fSchristos batch[len++] = pixel; 39742542f5fSchristos batch[len++] = 0xA << 23; 39842542f5fSchristos if (len & 1) 39942542f5fSchristos len++; 40042542f5fSchristos 40142542f5fSchristos gem_reloc[0].offset = 4 * sizeof(uint32_t); 40242542f5fSchristos gem_reloc[0].delta = 0; 40342542f5fSchristos gem_reloc[0].target_handle = handle; 40442542f5fSchristos gem_reloc[0].read_domains = I915_GEM_DOMAIN_RENDER; 40542542f5fSchristos gem_reloc[0].write_domain = I915_GEM_DOMAIN_RENDER; 40642542f5fSchristos gem_reloc[0].presumed_offset = 0; 40742542f5fSchristos 40842542f5fSchristos memset(gem_exec, 0, sizeof(gem_exec)); 40942542f5fSchristos gem_exec[0].handle = handle; 41042542f5fSchristos gem_exec[1].handle = gem_create(device, 4096); 41142542f5fSchristos gem_exec[1].relocation_count = 1; 41242542f5fSchristos gem_exec[1].relocs_ptr = (uintptr_t)gem_reloc; 41342542f5fSchristos 41442542f5fSchristos memset(&execbuf, 0, sizeof(execbuf)); 41542542f5fSchristos execbuf.buffers_ptr = (uintptr_t)gem_exec; 41642542f5fSchristos execbuf.buffer_count = 2; 41742542f5fSchristos execbuf.batch_len = len * sizeof(uint32_t); 41842542f5fSchristos execbuf.flags = gen >= 060 ? I915_EXEC_BLT : 0; 41942542f5fSchristos 42042542f5fSchristos ret = gem_write(device, gem_exec[1].handle, 0, batch, execbuf.batch_len); 42142542f5fSchristos if (ret == 0) 42242542f5fSchristos ret = drmIoctl(device, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); 42342542f5fSchristos if (ret < 0) 42442542f5fSchristos ret = -errno; 42542542f5fSchristos 42642542f5fSchristos gem_close(device, gem_exec[1].handle); 42742542f5fSchristos return ret; 42842542f5fSchristos} 42942542f5fSchristos 43042542f5fSchristosstatic int test_shm(Display *dpy, int device, 43142542f5fSchristos int width, int height) 43242542f5fSchristos{ 43342542f5fSchristos const int x_loc[] = {0, width/2, width-1}; 43442542f5fSchristos const int y_loc[] = {0, height/2, height-1}; 43542542f5fSchristos uint32_t pixel = 0xffff00ff; 43642542f5fSchristos XShmSegmentInfo shm; 43742542f5fSchristos Pixmap pixmap; 43842542f5fSchristos uint32_t handle = 0; 43942542f5fSchristos uint32_t *ptr; 44042542f5fSchristos int stride, fd; 44142542f5fSchristos int x, y; 44242542f5fSchristos int line; 44342542f5fSchristos 44442542f5fSchristos if (!can_use_shm(dpy)) 44542542f5fSchristos return 0; 44642542f5fSchristos 44742542f5fSchristos printf("Creating %dx%d SHM pixmap\n", width, height); 44842542f5fSchristos _x_error_occurred = 0; 44942542f5fSchristos 45042542f5fSchristos shm.shmid = shmget(IPC_PRIVATE, height * 4*width, IPC_CREAT | 0666); 45142542f5fSchristos if (shm.shmid == -1) 45242542f5fSchristos return 0; 45342542f5fSchristos 45442542f5fSchristos shm.shmaddr = shmat(shm.shmid, 0, 0); 45542542f5fSchristos if (shm.shmaddr == (char *) -1) { 45642542f5fSchristos shmctl(shm.shmid, IPC_RMID, NULL); 45742542f5fSchristos return 0; 45842542f5fSchristos } 45942542f5fSchristos 46042542f5fSchristos shm.readOnly = False; 46142542f5fSchristos XShmAttach(dpy, &shm); 46242542f5fSchristos 46342542f5fSchristos pixmap = XShmCreatePixmap(dpy, DefaultRootWindow(dpy), 46442542f5fSchristos shm.shmaddr, &shm, width, height, 24); 46542542f5fSchristos XSync(dpy, False); 46642542f5fSchristos shmctl(shm.shmid, IPC_RMID, NULL); 46742542f5fSchristos 46842542f5fSchristos if (_x_error_occurred) { 46942542f5fSchristos XShmDetach(dpy, &shm); 47042542f5fSchristos shmdt(shm.shmaddr); 47142542f5fSchristos return 0; 47242542f5fSchristos } 47342542f5fSchristos 47442542f5fSchristos printf("Testing write of %dx%d SHM pixmap via DRI3 fd\n", width, height); 47542542f5fSchristos 47642542f5fSchristos fd = dri3_create_fd(dpy, pixmap, &stride); 47742542f5fSchristos if (fd < 0) { 47842542f5fSchristos line = __LINE__; 47942542f5fSchristos goto fail; 48042542f5fSchristos } 48142542f5fSchristos 48242542f5fSchristos handle = gem_import(device, fd); 48342542f5fSchristos close(fd); 48442542f5fSchristos if (handle == 0) { 48542542f5fSchristos line = __LINE__; 48642542f5fSchristos goto fail; 48742542f5fSchristos } 48842542f5fSchristos 48942542f5fSchristos if (gpu_fill(device, handle, width, height, stride, 32, I915_TILING_NONE, pixel)) { 49042542f5fSchristos line = __LINE__; 49142542f5fSchristos goto fail; 49242542f5fSchristos } 49342542f5fSchristos 49442542f5fSchristos gem_sync(device, handle, CPU); 49542542f5fSchristos ptr = (uint32_t *)shm.shmaddr; 49642542f5fSchristos for (x = 0; x < sizeof(x_loc)/sizeof(x_loc[0]); x++) 49742542f5fSchristos for (y = 0; y < sizeof(y_loc)/sizeof(y_loc[0]); y++) 49842542f5fSchristos if (ptr[y_loc[y]*width + x_loc[x]] != pixel) { 49942542f5fSchristos printf("pixel[%d, %d]:%d = %08x\n", x, y, 32, ptr[y_loc[y] * width + x_loc[x]]); 50042542f5fSchristos line = __LINE__; 50142542f5fSchristos goto fail; 50242542f5fSchristos } 50342542f5fSchristos 50442542f5fSchristos for (x = 0; x < sizeof(x_loc)/sizeof(x_loc[0]); x++) 50542542f5fSchristos for (y = 0; y < sizeof(y_loc)/sizeof(y_loc[0]); y++) 50642542f5fSchristos if (!check_pixmap(dpy, pixmap, 50742542f5fSchristos x_loc[x], y_loc[y], 50842542f5fSchristos pixel, 32)) { 50942542f5fSchristos line = __LINE__; 51042542f5fSchristos goto fail; 51142542f5fSchristos } 51242542f5fSchristos 51342542f5fSchristos if (_x_error_occurred) { 51442542f5fSchristos line = __LINE__; 51542542f5fSchristos goto fail; 51642542f5fSchristos } 51742542f5fSchristos 51842542f5fSchristosout: 51942542f5fSchristos gem_close(device, handle); 52042542f5fSchristos XFreePixmap(dpy, pixmap); 52142542f5fSchristos XShmDetach(dpy, &shm); 52242542f5fSchristos shmdt(shm.shmaddr); 52342542f5fSchristos return fd != -1; 52442542f5fSchristos 52542542f5fSchristosfail: 52642542f5fSchristos printf("%s failed at (%dx%d), line %d\n", 52742542f5fSchristos __func__, width, height, line); 52842542f5fSchristos fd = -1; 52942542f5fSchristos goto out; 53042542f5fSchristos} 53142542f5fSchristos 53242542f5fSchristosstatic int test_read_after_write(Display *dpy, int device, 53342542f5fSchristos int width, int height, int depth, 53442542f5fSchristos int domain) 53542542f5fSchristos{ 53642542f5fSchristos const uint32_t pixel = 0xffff00ff; 53742542f5fSchristos const int x_loc[] = {0, width/2, width-1}; 53842542f5fSchristos const int y_loc[] = {0, height/2, height-1}; 53942542f5fSchristos Window root = RootWindow(dpy, DefaultScreen(dpy)); 54042542f5fSchristos uint32_t src, dst; 54142542f5fSchristos int src_fd, dst_fd; 54242542f5fSchristos int src_stride, src_size; 54342542f5fSchristos int dst_stride, dst_size; 54442542f5fSchristos Pixmap src_pix, dst_pix; 54542542f5fSchristos struct dri3_fence fence; 54642542f5fSchristos int x, y, bpp; 54742542f5fSchristos 54842542f5fSchristos _x_error_occurred = 0; 54942542f5fSchristos 55042542f5fSchristos switch (depth) { 55142542f5fSchristos case 8: bpp = 8; break; 55242542f5fSchristos case 16: bpp = 16; break; 55342542f5fSchristos case 24: bpp = 32; break; 55442542f5fSchristos case 32: bpp = 32; break; 55542542f5fSchristos default: return 0; 55642542f5fSchristos } 55742542f5fSchristos 55842542f5fSchristos src_stride = width * bpp/8; 55942542f5fSchristos src_size = PAGE_ALIGN(src_stride * height); 56042542f5fSchristos printf("Creating %dx%d (source stride=%d, size=%d, domain=%d)\n", 56142542f5fSchristos width, height, src_stride, src_size, domain); 56242542f5fSchristos 56342542f5fSchristos src = gem_create(device, src_size); 56442542f5fSchristos if (!src) 56542542f5fSchristos goto fail; 56642542f5fSchristos 56742542f5fSchristos if (domain == CPU) 56842542f5fSchristos gem_set_caching(device, src, 1); 56942542f5fSchristos 57042542f5fSchristos gem_fill(device, src, pixel, src_size, domain); 57142542f5fSchristos 57242542f5fSchristos src_fd = gem_export(device, src); 57342542f5fSchristos if (src_fd < 0) 57442542f5fSchristos goto fail; 57542542f5fSchristos 57642542f5fSchristos src_pix = dri3_create_pixmap(dpy, root, 57742542f5fSchristos width, height, depth, 57842542f5fSchristos src_fd, bpp, src_stride, src_size); 57942542f5fSchristos 58042542f5fSchristos for (x = 0; x < sizeof(x_loc)/sizeof(x_loc[0]); x++) 58142542f5fSchristos for (y = 0; y < sizeof(y_loc)/sizeof(y_loc[0]); y++) 58242542f5fSchristos if (!check_pixmap(dpy, src_pix, 58342542f5fSchristos x_loc[x], y_loc[y], 58442542f5fSchristos pixel, bpp)) 58542542f5fSchristos goto fail; 58642542f5fSchristos close(src_fd); 58742542f5fSchristos 58842542f5fSchristos dst_pix = XCreatePixmap(dpy, root, width, height, depth); 58942542f5fSchristos if (dri3_create_fence(dpy, dst_pix, &fence)) 59042542f5fSchristos goto fail; 59142542f5fSchristos 59242542f5fSchristos dst_fd = dri3_create_fd(dpy, dst_pix, &dst_stride); 59342542f5fSchristos if (dst_fd < 0) 59442542f5fSchristos goto fail; 59542542f5fSchristos dst_size = lseek(dst_fd, 0, SEEK_END); 59642542f5fSchristos printf("Comparing %dx%d (destination stride=%d, size=%d)\n", 59742542f5fSchristos width, height, dst_stride, dst_size); 59842542f5fSchristos dst = gem_import(device, dst_fd); 59942542f5fSchristos if (dst == 0) 60042542f5fSchristos goto fail; 60142542f5fSchristos close(dst_fd); 60242542f5fSchristos 60342542f5fSchristos XCopyArea(dpy, src_pix, dst_pix, 60442542f5fSchristos get_gc(dpy, dst_pix, depth), 60542542f5fSchristos 0, 0, width, height, 0, 0); 60642542f5fSchristos dri3_fence_sync(dpy, &fence); 60742542f5fSchristos dri3_fence_free(dpy, &fence); 60842542f5fSchristos 60942542f5fSchristos for (x = 0; x < sizeof(x_loc)/sizeof(x_loc[0]); x++) 61042542f5fSchristos for (y = 0; y < sizeof(y_loc)/sizeof(y_loc[0]); y++) 61142542f5fSchristos if (!check_pixel(device, dst, dst_stride, dst_size, 61242542f5fSchristos x_loc[x], y_loc[y], 61342542f5fSchristos pixel, bpp, GTT)) 61442542f5fSchristos goto fail; 61542542f5fSchristos 61642542f5fSchristos XFreePixmap(dpy, dst_pix); 61742542f5fSchristos XFreePixmap(dpy, src_pix); 61842542f5fSchristos 61942542f5fSchristos gem_close(device, src); 62042542f5fSchristos gem_close(device, dst); 62142542f5fSchristos 62242542f5fSchristos if (_x_error_occurred) 62342542f5fSchristos goto fail; 62442542f5fSchristos 62542542f5fSchristos return 0; 62642542f5fSchristos 62742542f5fSchristosfail: 62842542f5fSchristos printf("%s failed at (%dx%d), depth=%d, domain=%d\n", 62942542f5fSchristos __func__, width, height, depth, domain); 63042542f5fSchristos return 1; 63142542f5fSchristos} 63242542f5fSchristos 63342542f5fSchristosstatic XRenderPictFormat *format_for_depth(Display *dpy, int depth) 63442542f5fSchristos{ 63542542f5fSchristos switch (depth) { 63642542f5fSchristos case 8: return XRenderFindStandardFormat(dpy, PictStandardA8); 63742542f5fSchristos case 24: return XRenderFindStandardFormat(dpy, PictStandardRGB24); 63842542f5fSchristos case 32: return XRenderFindStandardFormat(dpy, PictStandardARGB32); 63942542f5fSchristos default: assert(0); return NULL; 64042542f5fSchristos } 64142542f5fSchristos} 64242542f5fSchristos 64342542f5fSchristosstatic int test_read(Display *dpy, int device, 64442542f5fSchristos int width, int height, 64542542f5fSchristos int domain) 64642542f5fSchristos{ 64742542f5fSchristos const uint32_t pixel = 0xffff00ff; 64842542f5fSchristos const XRenderColor color = { 0xffff, 0x0000, 0xffff, 0xffff }; 64942542f5fSchristos const int x_loc[] = {0, width/2, width-1}; 65042542f5fSchristos const int y_loc[] = {0, height/2, height-1}; 65142542f5fSchristos Window root = RootWindow(dpy, DefaultScreen(dpy)); 65242542f5fSchristos uint32_t dst; 65342542f5fSchristos int dst_stride, dst_size, dst_fd; 65442542f5fSchristos Pixmap src_pix, dst_pix; 65542542f5fSchristos Picture src_pic; 65642542f5fSchristos struct dri3_fence fence; 65742542f5fSchristos int depth = 32, bpp = 32; 65842542f5fSchristos int x, y; 65942542f5fSchristos 66042542f5fSchristos _x_error_occurred = 0; 66142542f5fSchristos 66242542f5fSchristos dst_stride = width * bpp/8; 66342542f5fSchristos dst_size = PAGE_ALIGN(dst_stride * height); 66442542f5fSchristos printf("Creating %dx%d (destination stride=%d, size=%d, domain=%d)\n", 66542542f5fSchristos width, height, dst_stride, dst_size, domain); 66642542f5fSchristos 66742542f5fSchristos dst = gem_create(device, dst_size); 66842542f5fSchristos if (!dst) 66942542f5fSchristos goto fail; 67042542f5fSchristos 67142542f5fSchristos if (domain == CPU) 67242542f5fSchristos gem_set_caching(device, dst, 1); 67342542f5fSchristos 67442542f5fSchristos gem_fill(device, dst, ~pixel, dst_size, domain); 67542542f5fSchristos 67642542f5fSchristos dst_fd = gem_export(device, dst); 67742542f5fSchristos if (dst_fd < 0) 67842542f5fSchristos goto fail; 67942542f5fSchristos 68042542f5fSchristos dst_pix = dri3_create_pixmap(dpy, root, 68142542f5fSchristos width, height, depth, 68242542f5fSchristos dst_fd, bpp, dst_stride, dst_size); 68342542f5fSchristos XSync(dpy, True); 68442542f5fSchristos if (_x_error_occurred) 68542542f5fSchristos goto fail; 68642542f5fSchristos if (dri3_create_fence(dpy, dst_pix, &fence)) 68742542f5fSchristos goto fail; 68842542f5fSchristos 68942542f5fSchristos src_pix = XCreatePixmap(dpy, root, width, height, depth); 69042542f5fSchristos src_pic = XRenderCreatePicture(dpy, src_pix, format_for_depth(dpy, depth), 0, NULL); 69142542f5fSchristos XRenderFillRectangle(dpy, PictOpSrc, src_pic, &color, 0, 0, width, height); 69242542f5fSchristos XCopyArea(dpy, src_pix, dst_pix, 69342542f5fSchristos get_gc(dpy, dst_pix, depth), 69442542f5fSchristos 0, 0, width, height, 0, 0); 69542542f5fSchristos dri3_fence_sync(dpy, &fence); 69642542f5fSchristos dri3_fence_free(dpy, &fence); 69742542f5fSchristos 69842542f5fSchristos for (x = 0; x < sizeof(x_loc)/sizeof(x_loc[0]); x++) 69942542f5fSchristos for (y = 0; y < sizeof(y_loc)/sizeof(y_loc[0]); y++) 70042542f5fSchristos if (!check_pixel(device, dst, dst_stride, dst_size, 70142542f5fSchristos x_loc[x], y_loc[y], 70242542f5fSchristos pixel, bpp, domain)) 70342542f5fSchristos goto fail; 70442542f5fSchristos 70542542f5fSchristos XFreePixmap(dpy, dst_pix); 70642542f5fSchristos XRenderFreePicture(dpy, src_pic); 70742542f5fSchristos XFreePixmap(dpy, src_pix); 70842542f5fSchristos 70942542f5fSchristos gem_close(device, dst); 71042542f5fSchristos 71142542f5fSchristos if (_x_error_occurred) 71242542f5fSchristos goto fail; 71342542f5fSchristos 71442542f5fSchristos return 0; 71542542f5fSchristos 71642542f5fSchristosfail: 71742542f5fSchristos printf("%s failed at (%dx%d), depth=%d, domain=%d\n", 71842542f5fSchristos __func__, width, height, depth, domain); 71942542f5fSchristos return 1; 72042542f5fSchristos} 72142542f5fSchristos 72242542f5fSchristosstatic int test_dup_pixmap(Display *dpy, int device) 72342542f5fSchristos{ 72442542f5fSchristos const uint32_t pixel = 0xffff00ff; 72542542f5fSchristos const XRenderColor color = { 0xffff, 0x0000, 0xffff, 0xffff }; 72642542f5fSchristos const XRenderColor inverse = { 0, 0xffff, 0, 0 }; 72742542f5fSchristos int width = 400, height = 400; 72842542f5fSchristos const int x_loc[] = {0, width/2, width-1}; 72942542f5fSchristos const int y_loc[] = {0, height/2, height-1}; 73042542f5fSchristos Window root = RootWindow(dpy, DefaultScreen(dpy)); 73142542f5fSchristos uint32_t handle; 73242542f5fSchristos int stride, size, fd; 73342542f5fSchristos Pixmap src_pix, dst_pix; 73442542f5fSchristos Picture src_pic, dst_pic; 73542542f5fSchristos struct dri3_fence fence; 73642542f5fSchristos int depth = 32, bpp = 32; 73742542f5fSchristos int x, y; 73842542f5fSchristos 73942542f5fSchristos _x_error_occurred = 0; 74042542f5fSchristos 74142542f5fSchristos printf("%s: Creating %dx%d pixmap\n", __func__, width, height); 74242542f5fSchristos src_pix = XCreatePixmap(dpy, root, width, height, depth); 74342542f5fSchristos src_pic = XRenderCreatePicture(dpy, src_pix, format_for_depth(dpy, depth), 0, NULL); 74442542f5fSchristos fd = dri3_create_fd(dpy, src_pix, &stride); 74542542f5fSchristos if (fd < 0) 74642542f5fSchristos goto fail; 74742542f5fSchristos 74842542f5fSchristos size = lseek(fd, 0, SEEK_END); 74942542f5fSchristos handle = gem_import(device, fd); 75042542f5fSchristos 75142542f5fSchristos printf("%s: Creating duplicate from pixmap exported fd\n", __func__); 75242542f5fSchristos dst_pix = dri3_create_pixmap(dpy, root, 75342542f5fSchristos width, height, depth, 75442542f5fSchristos fd, bpp, stride, size); 75542542f5fSchristos dst_pic = XRenderCreatePicture(dpy, dst_pix, format_for_depth(dpy, depth), 0, NULL); 75642542f5fSchristos XSync(dpy, True); 75742542f5fSchristos if (_x_error_occurred) 75842542f5fSchristos goto fail; 75942542f5fSchristos 76042542f5fSchristos printf("%s: Filling src with %08x, reading dst\n", __func__, pixel); 76142542f5fSchristos XRenderFillRectangle(dpy, PictOpSrc, src_pic, &color, 0, 0, width, height); 76242542f5fSchristos for (x = 0; x < sizeof(x_loc)/sizeof(x_loc[0]); x++) 76342542f5fSchristos for (y = 0; y < sizeof(y_loc)/sizeof(y_loc[0]); y++) 76442542f5fSchristos if (!check_pixmap(dpy, dst_pix, 76542542f5fSchristos x_loc[x], y_loc[y], 76642542f5fSchristos pixel, 32)) 76742542f5fSchristos goto fail; 76842542f5fSchristos 76942542f5fSchristos printf("%s: Filling dst with %08x, reading src\n", __func__, ~pixel); 77042542f5fSchristos XRenderFillRectangle(dpy, PictOpSrc, dst_pic, &inverse, 0, 0, width, height); 77142542f5fSchristos for (x = 0; x < sizeof(x_loc)/sizeof(x_loc[0]); x++) 77242542f5fSchristos for (y = 0; y < sizeof(y_loc)/sizeof(y_loc[0]); y++) 77342542f5fSchristos if (!check_pixmap(dpy, dst_pix, 77442542f5fSchristos x_loc[x], y_loc[y], 77542542f5fSchristos ~pixel, 32)) 77642542f5fSchristos goto fail; 77742542f5fSchristos 77842542f5fSchristos if (dri3_create_fence(dpy, src_pix, &fence)) 77942542f5fSchristos goto fail; 78042542f5fSchristos 78142542f5fSchristos printf("%s: Filling src with %08x, reading fd\n", __func__, pixel); 78242542f5fSchristos XRenderFillRectangle(dpy, PictOpSrc, src_pic, &color, 0, 0, width, height); 78342542f5fSchristos dri3_fence_sync(dpy, &fence); 78442542f5fSchristos dri3_fence_free(dpy, &fence); 78542542f5fSchristos for (x = 0; x < sizeof(x_loc)/sizeof(x_loc[0]); x++) 78642542f5fSchristos for (y = 0; y < sizeof(y_loc)/sizeof(y_loc[0]); y++) 78742542f5fSchristos if (!check_pixel(device, handle, stride, size, 78842542f5fSchristos x_loc[x], y_loc[y], 78942542f5fSchristos pixel, bpp, GTT)) 79042542f5fSchristos goto fail; 79142542f5fSchristos 79242542f5fSchristos printf("%s: Filling fd with %08x, reading src\n", __func__, ~pixel); 79342542f5fSchristos if (gpu_fill(device, handle, width, height, stride, 32, gem_get_tiling(device, handle), ~pixel)) 79442542f5fSchristos goto fail; 79542542f5fSchristos for (x = 0; x < sizeof(x_loc)/sizeof(x_loc[0]); x++) 79642542f5fSchristos for (y = 0; y < sizeof(y_loc)/sizeof(y_loc[0]); y++) 79742542f5fSchristos if (!check_pixmap(dpy, src_pix, 79842542f5fSchristos x_loc[x], y_loc[y], 79942542f5fSchristos ~pixel, 32)) 80042542f5fSchristos goto fail; 80142542f5fSchristos 80242542f5fSchristos if (dri3_create_fence(dpy, dst_pix, &fence)) 80342542f5fSchristos goto fail; 80442542f5fSchristos 80542542f5fSchristos printf("%s: Filling dst with %08x, reading fd\n", __func__, pixel); 80642542f5fSchristos XRenderFillRectangle(dpy, PictOpSrc, dst_pic, &color, 0, 0, width, height); 80742542f5fSchristos dri3_fence_sync(dpy, &fence); 80842542f5fSchristos dri3_fence_free(dpy, &fence); 80942542f5fSchristos for (x = 0; x < sizeof(x_loc)/sizeof(x_loc[0]); x++) 81042542f5fSchristos for (y = 0; y < sizeof(y_loc)/sizeof(y_loc[0]); y++) 81142542f5fSchristos if (!check_pixel(device, handle, stride, size, 81242542f5fSchristos x_loc[x], y_loc[y], 81342542f5fSchristos pixel, bpp, GTT)) 81442542f5fSchristos goto fail; 81542542f5fSchristos 81642542f5fSchristos printf("%s: Filling fd with %08x, reading dst\n", __func__, ~pixel); 81742542f5fSchristos if (gpu_fill(device, handle, width, height, stride, 32, gem_get_tiling(device, handle), ~pixel)) 81842542f5fSchristos goto fail; 81942542f5fSchristos for (x = 0; x < sizeof(x_loc)/sizeof(x_loc[0]); x++) 82042542f5fSchristos for (y = 0; y < sizeof(y_loc)/sizeof(y_loc[0]); y++) 82142542f5fSchristos if (!check_pixmap(dpy, dst_pix, 82242542f5fSchristos x_loc[x], y_loc[y], 82342542f5fSchristos ~pixel, 32)) 82442542f5fSchristos goto fail; 82542542f5fSchristos 82642542f5fSchristos XRenderFreePicture(dpy, src_pic); 82742542f5fSchristos XFreePixmap(dpy, src_pix); 82842542f5fSchristos 82942542f5fSchristos if (dri3_create_fence(dpy, dst_pix, &fence)) 83042542f5fSchristos goto fail; 83142542f5fSchristos 83242542f5fSchristos printf("%s: Closed original src, filling dst with %08x, reading fd\n", __func__, pixel); 83342542f5fSchristos XRenderFillRectangle(dpy, PictOpSrc, dst_pic, &color, 0, 0, width, height); 83442542f5fSchristos dri3_fence_sync(dpy, &fence); 83542542f5fSchristos dri3_fence_free(dpy, &fence); 83642542f5fSchristos for (x = 0; x < sizeof(x_loc)/sizeof(x_loc[0]); x++) 83742542f5fSchristos for (y = 0; y < sizeof(y_loc)/sizeof(y_loc[0]); y++) 83842542f5fSchristos if (!check_pixel(device, handle, stride, size, 83942542f5fSchristos x_loc[x], y_loc[y], 84042542f5fSchristos pixel, bpp, GTT)) 84142542f5fSchristos goto fail; 84242542f5fSchristos 84342542f5fSchristos XRenderFreePicture(dpy, dst_pic); 84442542f5fSchristos XFreePixmap(dpy, dst_pix); 84542542f5fSchristos 84642542f5fSchristos gem_close(device, handle); 84742542f5fSchristos 84842542f5fSchristos if (_x_error_occurred) 84942542f5fSchristos goto fail; 85042542f5fSchristos 85142542f5fSchristos return 0; 85242542f5fSchristos 85342542f5fSchristosfail: 85442542f5fSchristos printf("%s failed at (%dx%d), depth=%d\n", 85542542f5fSchristos __func__, width, height, depth); 85642542f5fSchristos return 1; 85742542f5fSchristos} 85842542f5fSchristos 85942542f5fSchristosstatic int test_bad_size(Display *dpy, int device) 86042542f5fSchristos{ 86142542f5fSchristos Window root = RootWindow(dpy, DefaultScreen(dpy)); 86242542f5fSchristos uint32_t src; 86342542f5fSchristos int src_fd; 86442542f5fSchristos Pixmap src_pix; 86542542f5fSchristos int line = -1; 86642542f5fSchristos 86742542f5fSchristos _x_error_occurred = 0; 86842542f5fSchristos 86942542f5fSchristos src = gem_create(device, 4096); 87042542f5fSchristos if (!src) 87142542f5fSchristos goto fail; 87242542f5fSchristos 87342542f5fSchristos src_fd = gem_export(device, src); 87442542f5fSchristos if (src_fd < 0) 87542542f5fSchristos goto fail; 87642542f5fSchristos 87742542f5fSchristos src_pix = dri3_create_pixmap(dpy, root, 87842542f5fSchristos 16, 16, 32, 87942542f5fSchristos dup(src_fd), 32, 16*4, 4096); 88042542f5fSchristos line = __LINE__; 88142542f5fSchristos XSync(dpy, True); 88242542f5fSchristos if (_x_error_occurred) 88342542f5fSchristos goto fail; 88442542f5fSchristos XFreePixmap(dpy, src_pix); 88542542f5fSchristos _x_error_occurred = 0; 88642542f5fSchristos 88742542f5fSchristos src_pix = dri3_create_pixmap(dpy, root, 88842542f5fSchristos 32, 32, 32, 88942542f5fSchristos dup(src_fd), 32, 32*4, 4096); 89042542f5fSchristos line = __LINE__; 89142542f5fSchristos XSync(dpy, True); 89242542f5fSchristos if (_x_error_occurred) 89342542f5fSchristos goto fail; 89442542f5fSchristos XFreePixmap(dpy, src_pix); 89542542f5fSchristos _x_error_occurred = 0; 89642542f5fSchristos 89742542f5fSchristos src_pix = dri3_create_pixmap(dpy, root, 89842542f5fSchristos 64, 64, 32, 89942542f5fSchristos dup(src_fd), 32, 64*4, 4096); 90042542f5fSchristos line = __LINE__; 90142542f5fSchristos XSync(dpy, True); 90242542f5fSchristos if (!_x_error_occurred) 90342542f5fSchristos goto fail; 90442542f5fSchristos _x_error_occurred = 0; 90542542f5fSchristos 90642542f5fSchristos src_pix = dri3_create_pixmap(dpy, root, 90742542f5fSchristos 64, 64, 32, 90842542f5fSchristos dup(src_fd), 32, 64*4, 64*64*4); 90942542f5fSchristos line = __LINE__; 91042542f5fSchristos XSync(dpy, True); 91142542f5fSchristos if (!_x_error_occurred) 91242542f5fSchristos goto fail; 91342542f5fSchristos _x_error_occurred = 0; 91442542f5fSchristos 91542542f5fSchristos src_pix = dri3_create_pixmap(dpy, root, 91642542f5fSchristos INT16_MAX, INT16_MAX, 8, 91742542f5fSchristos dup(src_fd), 8, INT16_MAX, UINT32_MAX); 91842542f5fSchristos line = __LINE__; 91942542f5fSchristos XSync(dpy, True); 92042542f5fSchristos if (!_x_error_occurred) 92142542f5fSchristos goto fail; 92242542f5fSchristos _x_error_occurred = 0; 92342542f5fSchristos 92442542f5fSchristos close(src_fd); 92542542f5fSchristos gem_close(device, src); 92642542f5fSchristos 92742542f5fSchristos return 0; 92842542f5fSchristos 92942542f5fSchristosfail: 93042542f5fSchristos printf("%s failed at line %d\n", __func__, line); 93142542f5fSchristos return 1; 93242542f5fSchristos} 93342542f5fSchristos 93442542f5fSchristosstatic int test_bad_pitch(Display *dpy, int device) 93542542f5fSchristos{ 93642542f5fSchristos Window root = RootWindow(dpy, DefaultScreen(dpy)); 93742542f5fSchristos uint32_t src; 93842542f5fSchristos int src_fd; 93942542f5fSchristos Pixmap src_pix; 94042542f5fSchristos int line = -1; 94142542f5fSchristos 94242542f5fSchristos _x_error_occurred = 0; 94342542f5fSchristos 94442542f5fSchristos src = gem_create(device, 4096); 94542542f5fSchristos if (!src) 94642542f5fSchristos goto fail; 94742542f5fSchristos 94842542f5fSchristos src_fd = gem_export(device, src); 94942542f5fSchristos if (src_fd < 0) 95042542f5fSchristos goto fail; 95142542f5fSchristos 95242542f5fSchristos src_pix = dri3_create_pixmap(dpy, root, 95342542f5fSchristos 16, 16, 32, 95442542f5fSchristos dup(src_fd), 32, 16*4, 4096); 95542542f5fSchristos line = __LINE__; 95642542f5fSchristos XSync(dpy, True); 95742542f5fSchristos if (_x_error_occurred) 95842542f5fSchristos goto fail; 95942542f5fSchristos XFreePixmap(dpy, src_pix); 96042542f5fSchristos _x_error_occurred = 0; 96142542f5fSchristos 96242542f5fSchristos src_pix = dri3_create_pixmap(dpy, root, 96342542f5fSchristos 256, 2, 32, 96442542f5fSchristos dup(src_fd), 32, 256*4, 4096); 96542542f5fSchristos line = __LINE__; 96642542f5fSchristos XSync(dpy, True); 96742542f5fSchristos if (_x_error_occurred) 96842542f5fSchristos goto fail; 96942542f5fSchristos XFreePixmap(dpy, src_pix); 97042542f5fSchristos _x_error_occurred = 0; 97142542f5fSchristos 97242542f5fSchristos src_pix = dri3_create_pixmap(dpy, root, 97342542f5fSchristos 256, 2, 32, 97442542f5fSchristos dup(src_fd), 32, 256, 4096); 97542542f5fSchristos line = __LINE__; 97642542f5fSchristos XSync(dpy, True); 97742542f5fSchristos if (!_x_error_occurred) 97842542f5fSchristos goto fail; 97942542f5fSchristos _x_error_occurred = 0; 98042542f5fSchristos 98142542f5fSchristos src_pix = dri3_create_pixmap(dpy, root, 98242542f5fSchristos 256, 2, 32, 98342542f5fSchristos dup(src_fd), 32, 16384, 4096); 98442542f5fSchristos line = __LINE__; 98542542f5fSchristos XSync(dpy, True); 98642542f5fSchristos if (!_x_error_occurred) 98742542f5fSchristos goto fail; 98842542f5fSchristos _x_error_occurred = 0; 98942542f5fSchristos 99042542f5fSchristos src_pix = dri3_create_pixmap(dpy, root, 99142542f5fSchristos 256, 2, 32, 99242542f5fSchristos dup(src_fd), 32, 1023, 4096); 99342542f5fSchristos line = __LINE__; 99442542f5fSchristos XSync(dpy, True); 99542542f5fSchristos if (!_x_error_occurred) 99642542f5fSchristos goto fail; 99742542f5fSchristos _x_error_occurred = 0; 99842542f5fSchristos 99942542f5fSchristos src_pix = dri3_create_pixmap(dpy, root, 100042542f5fSchristos 256, 2, 32, 100142542f5fSchristos dup(src_fd), 32, 1025, 4096); 100242542f5fSchristos line = __LINE__; 100342542f5fSchristos XSync(dpy, True); 100442542f5fSchristos if (!_x_error_occurred) 100542542f5fSchristos goto fail; 100642542f5fSchristos _x_error_occurred = 0; 100742542f5fSchristos 100842542f5fSchristos close(src_fd); 100942542f5fSchristos gem_close(device, src); 101042542f5fSchristos 101142542f5fSchristos return 0; 101242542f5fSchristos 101342542f5fSchristosfail: 101442542f5fSchristos printf("%s failed at line %d\n", __func__, line); 101542542f5fSchristos return 1; 101642542f5fSchristos} 101742542f5fSchristos 1018fe8aea9eSmrgstatic int gem_set_tiling(int fd, uint32_t handle, int tiling, int stride) 1019fe8aea9eSmrg{ 1020fe8aea9eSmrg struct drm_i915_gem_set_tiling set_tiling; 1021fe8aea9eSmrg 1022fe8aea9eSmrg set_tiling.handle = handle; 1023fe8aea9eSmrg set_tiling.tiling_mode = tiling; 1024fe8aea9eSmrg set_tiling.stride = stride; 1025fe8aea9eSmrg 1026fe8aea9eSmrg return drmIoctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling) == 0; 1027fe8aea9eSmrg} 1028fe8aea9eSmrg 1029fe8aea9eSmrgstatic int test_tiling(Display *dpy, int device) 1030fe8aea9eSmrg{ 1031fe8aea9eSmrg Window root = RootWindow(dpy, DefaultScreen(dpy)); 1032fe8aea9eSmrg const int tiling[] = { I915_TILING_NONE, I915_TILING_X, I915_TILING_Y }; 1033fe8aea9eSmrg int line = -1; 1034fe8aea9eSmrg int t; 1035fe8aea9eSmrg 1036fe8aea9eSmrg _x_error_occurred = 0; 1037fe8aea9eSmrg 1038fe8aea9eSmrg for (t = 0; t < sizeof(tiling)/sizeof(tiling[0]); t++) { 1039fe8aea9eSmrg uint32_t src; 1040fe8aea9eSmrg int src_fd; 1041fe8aea9eSmrg Pixmap src_pix; 1042fe8aea9eSmrg 1043fe8aea9eSmrg src = gem_create(device, 4*4096); 1044fe8aea9eSmrg if (!src) { 1045fe8aea9eSmrg line = __LINE__; 1046fe8aea9eSmrg goto fail; 1047fe8aea9eSmrg } 1048fe8aea9eSmrg 1049fe8aea9eSmrg gem_set_tiling(device, src, tiling[t], 512); 1050fe8aea9eSmrg 1051fe8aea9eSmrg src_fd = gem_export(device, src); 1052fe8aea9eSmrg if (src_fd < 0) { 1053fe8aea9eSmrg line = __LINE__; 1054fe8aea9eSmrg goto fail; 1055fe8aea9eSmrg } 1056fe8aea9eSmrg 1057fe8aea9eSmrg src_pix = dri3_create_pixmap(dpy, root, 1058fe8aea9eSmrg 128, 32, 32, 1059fe8aea9eSmrg src_fd, 32, 512, 4*4096); 1060fe8aea9eSmrg XSync(dpy, True); 1061fe8aea9eSmrg if (_x_error_occurred) { 1062fe8aea9eSmrg line = __LINE__; 1063fe8aea9eSmrg goto fail; 1064fe8aea9eSmrg } 1065fe8aea9eSmrg XFreePixmap(dpy, src_pix); 1066fe8aea9eSmrg _x_error_occurred = 0; 1067fe8aea9eSmrg 1068fe8aea9eSmrg close(src_fd); 1069fe8aea9eSmrg gem_close(device, src); 1070fe8aea9eSmrg } 1071fe8aea9eSmrg 1072fe8aea9eSmrg return 0; 1073fe8aea9eSmrg 1074fe8aea9eSmrgfail: 1075fe8aea9eSmrg printf("%s failed with tiling %d, line %d\n", __func__, tiling[t], line); 1076fe8aea9eSmrg return 1; 1077fe8aea9eSmrg} 1078fe8aea9eSmrg 107942542f5fSchristosstatic int 108042542f5fSchristos_check_error_handler(Display *display, 108142542f5fSchristos XErrorEvent *event) 108242542f5fSchristos{ 108342542f5fSchristos printf("X11 error from display %s, serial=%ld, error=%d, req=%d.%d\n", 108442542f5fSchristos DisplayString(display), 108542542f5fSchristos event->serial, 108642542f5fSchristos event->error_code, 108742542f5fSchristos event->request_code, 108842542f5fSchristos event->minor_code); 108942542f5fSchristos _x_error_occurred++; 109042542f5fSchristos return False; /* ignored */ 109142542f5fSchristos} 109242542f5fSchristos 109342542f5fSchristosint main(void) 109442542f5fSchristos{ 109542542f5fSchristos Display *dpy; 109642542f5fSchristos int device; 109742542f5fSchristos int error = 0; 109842542f5fSchristos 109942542f5fSchristos dpy = XOpenDisplay(NULL); 110042542f5fSchristos if (dpy == NULL) 110142542f5fSchristos return 77; 110242542f5fSchristos 110342542f5fSchristos if (DefaultDepth(dpy, DefaultScreen(dpy)) != 24) 110442542f5fSchristos return 77; 110542542f5fSchristos 110642542f5fSchristos XSetErrorHandler(_check_error_handler); 110742542f5fSchristos 110842542f5fSchristos device = dri3_open(dpy); 110942542f5fSchristos if (device < 0) 111042542f5fSchristos return 127; 111142542f5fSchristos 111242542f5fSchristos if (!is_intel(device)) 111342542f5fSchristos return 77; 111442542f5fSchristos 111542542f5fSchristos printf("Opened Intel DRI3 device\n"); 111642542f5fSchristos 111742542f5fSchristos error += test_bad_size(dpy, device); 111842542f5fSchristos error += test_bad_pitch(dpy, device); 1119fe8aea9eSmrg error += test_tiling(dpy, device); 112042542f5fSchristos 112142542f5fSchristos error += test_shm(dpy, device, 400, 300); 112242542f5fSchristos error += test_shm(dpy, device, 300, 400); 112342542f5fSchristos 112442542f5fSchristos error += test_read(dpy, device, 400, 200, GTT); 112542542f5fSchristos error += test_read(dpy, device, 4000, 20, GTT); 112642542f5fSchristos error += test_read(dpy, device, 16000, 10, GTT); 112742542f5fSchristos error += test_read(dpy, device, 30000, 10, GTT); 112842542f5fSchristos 112942542f5fSchristos error += test_read(dpy, device, 200, 400, GTT); 113042542f5fSchristos error += test_read(dpy, device, 20, 4000, GTT); 113142542f5fSchristos error += test_read(dpy, device, 16, 16000, GTT); 113242542f5fSchristos error += test_read(dpy, device, 16, 30000, GTT); 113342542f5fSchristos 113442542f5fSchristos error += test_read(dpy, device, 400, 200, CPU); 113542542f5fSchristos error += test_read(dpy, device, 4000, 20, CPU); 113642542f5fSchristos error += test_read(dpy, device, 16000, 10, CPU); 113742542f5fSchristos error += test_read(dpy, device, 30000, 10, CPU); 113842542f5fSchristos 113942542f5fSchristos error += test_read(dpy, device, 200, 400, CPU); 114042542f5fSchristos error += test_read(dpy, device, 20, 4000, CPU); 114142542f5fSchristos error += test_read(dpy, device, 16, 16000, CPU); 114242542f5fSchristos error += test_read(dpy, device, 16, 30000, CPU); 114342542f5fSchristos 114442542f5fSchristos error += test_read_after_write(dpy, device, 400, 200, 24, GTT); 114542542f5fSchristos error += test_read_after_write(dpy, device, 4000, 20, 24, GTT); 114642542f5fSchristos error += test_read_after_write(dpy, device, 16000, 10, 24, GTT); 114742542f5fSchristos error += test_read_after_write(dpy, device, 30000, 10, 24, GTT); 114842542f5fSchristos error += test_read_after_write(dpy, device, 30000, 10, 8, GTT); 114942542f5fSchristos 115042542f5fSchristos error += test_read_after_write(dpy, device, 200, 400, 24, GTT); 115142542f5fSchristos error += test_read_after_write(dpy, device, 20, 4000, 24, GTT); 115242542f5fSchristos error += test_read_after_write(dpy, device, 16, 16000, 24, GTT); 115342542f5fSchristos error += test_read_after_write(dpy, device, 16, 30000, 24, GTT); 115442542f5fSchristos 115542542f5fSchristos error += test_read_after_write(dpy, device, 400, 200, 24, CPU); 115642542f5fSchristos error += test_read_after_write(dpy, device, 4000, 20, 24, CPU); 115742542f5fSchristos error += test_read_after_write(dpy, device, 16000, 10, 24, CPU); 115842542f5fSchristos error += test_read_after_write(dpy, device, 30000, 10, 24, CPU); 115942542f5fSchristos error += test_read_after_write(dpy, device, 30000, 10, 8, CPU); 116042542f5fSchristos 116142542f5fSchristos error += test_read_after_write(dpy, device, 200, 400, 24, CPU); 116242542f5fSchristos error += test_read_after_write(dpy, device, 20, 4000, 24, CPU); 116342542f5fSchristos error += test_read_after_write(dpy, device, 16, 16000, 24, CPU); 116442542f5fSchristos error += test_read_after_write(dpy, device, 16, 30000, 24, CPU); 116542542f5fSchristos 116642542f5fSchristos error += test_dup_pixmap(dpy, device); 116742542f5fSchristos 116842542f5fSchristos return !!error; 116942542f5fSchristos} 1170