diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile.am | 4 | ||||
-rw-r--r-- | tests/dristat.c | 2 | ||||
-rw-r--r-- | tests/modedemo/Makefile | 14 | ||||
-rw-r--r-- | tests/modedemo/demo.c | 634 | ||||
-rwxr-xr-x | tests/modedemo/test | 1 | ||||
-rw-r--r-- | tests/modefb/Makefile | 14 | ||||
-rw-r--r-- | tests/modefb/demo.c | 230 | ||||
-rwxr-xr-x | tests/modefb/test | 1 | ||||
-rw-r--r-- | tests/modehotplug/Makefile | 14 | ||||
-rw-r--r-- | tests/modehotplug/demo.c | 157 | ||||
-rwxr-xr-x | tests/modehotplug/test | 1 | ||||
-rw-r--r-- | tests/modeprint/Makefile | 14 | ||||
-rw-r--r-- | tests/modeprint/modetest.c | 371 | ||||
-rwxr-xr-x | tests/modeprint/test | 1 | ||||
-rw-r--r-- | tests/radeon_gem_basic.c | 114 | ||||
-rw-r--r-- | tests/radeon_gem_mmap.c | 132 |
16 files changed, 1702 insertions, 2 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index 718cc436..a5f9967b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -25,7 +25,9 @@ TESTS = auth \ updatedraw \ gem_basic \ gem_readwrite \ - gem_mmap + gem_mmap \ + radeon_gem_mmap \ + radeon_gem_basic EXTRA_PROGRAMS = $(TESTS) CLEANFILES = $(EXTRA_PROGRAMS) $(EXTRA_LTLIBRARIES) diff --git a/tests/dristat.c b/tests/dristat.c index 89853164..48c3b51b 100644 --- a/tests/dristat.c +++ b/tests/dristat.c @@ -263,7 +263,7 @@ int main(int argc, char **argv) for (i = 0; i < 16; i++) if (!minor || i == minor) { sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, i); - fd = drmOpenMinor(i, 1); + fd = drmOpenMinor(i, 1, DRM_NODE_RENDER); if (fd >= 0) { printf("%s\n", buf); if (mask & DRM_BUSID) getbusid(fd); diff --git a/tests/modedemo/Makefile b/tests/modedemo/Makefile new file mode 100644 index 00000000..467fb11a --- /dev/null +++ b/tests/modedemo/Makefile @@ -0,0 +1,14 @@ + +all: app + +#CFLAGS = -g -ansi -pedantic -DPOSIX_C_SOURCE=199309L \ +# -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE \ + +app: demo.c + @gcc $(CFLAGS) -o app -Wall -I../../libdrm -I../../shared-core -L../../libdrm/.libs -ldrm demo.c + +clean: + @rm -f app + +run: app + sudo ./test diff --git a/tests/modedemo/demo.c b/tests/modedemo/demo.c new file mode 100644 index 00000000..72d69405 --- /dev/null +++ b/tests/modedemo/demo.c @@ -0,0 +1,634 @@ +/* + * Some defines to define the behavior of the program + */ + +#define CLEAN_FBDEV +#undef DEMO_CLONE + +#define SIZE_X 2048 +#define SIZE_Y 2048 +/* Pitch needs to be power of two */ +#define PITCH 2048 + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <unistd.h> +#include <string.h> +#ifdef CLEAN_FBDEV +#include <errno.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <linux/fb.h> +#endif +#include <signal.h> + +#include "xf86drm.h" +#include "xf86drmMode.h" + +/* old functions to be replaced */ +drmModeFBPtr createFB(int fd, drmModeResPtr res); +void testCursor(int fd, uint32_t crtc); +void prettyColors(int fd, unsigned int handle); +void prettyCursor(int fd, unsigned int handle, unsigned int color); + +#ifdef CLEAN_FBDEV +struct fb_var_screeninfo var; +struct fb_fix_screeninfo fix; +#endif + +/* structs for the demo_driver */ + +struct demo_driver; + +struct demo_screen +{ + /* drm stuff */ + drmBO buffer; + drmModeFBPtr fb; + drmModeCrtcPtr crtc; + + size_t num_outputs; + uint32_t outputs_id[8]; + drmModeOutputPtr outputs[8]; + + struct drm_mode_modeinfo *mode; + + /* virtual buffer */ + uint32_t virt_x; + uint32_t virt_y; + uint32_t pitch; + + /* parent */ + struct demo_driver *driver; +}; + +#define DEMO_MAX_SCREENS 4 +#define MAX_FIND_OUTPUTS 8 + +struct demo_driver +{ + /* drm stuff */ + int fd; + drmModeResPtr res; + + /* screens */ + size_t numScreens; + struct demo_screen screens[DEMO_MAX_SCREENS]; +}; + +struct demo_driver* demoCreateDriver(void); +void demoUpdateRes(struct demo_driver *driver); +int demoCreateScreens(struct demo_driver *driver); +int demoCreateScreenCloned(struct demo_driver *driver); +void demoTakeDownScreen(struct demo_screen *screen); +int demoFindConnectedOutputs(struct demo_driver *driver, drmModeOutputPtr *out, size_t max_out); +drmModeCrtcPtr demoFindFreeCrtc(struct demo_driver *driver, drmModeOutputPtr output); +void demoPanScreen(struct demo_screen *screen, uint16_t x, uint16_t y); +/* yet to be implemented */ +void demoMouseActivate(struct demo_screen *screen); +void demoMouseMove(struct demo_screen *screen, uint16_t x, uint16_t y); + +static struct drm_mode_modeinfo mode = { + .name = "Test mode", + .clock = 25200, + .hdisplay = 640, + .hsync_start = 656, + .hsync_end = 752, + .htotal = 800, + .hskew = 0, + .vdisplay = 480, + .vsync_start = 490, + .vsync_end = 492, + .vtotal = 525, + .vscan = 0, + .vrefresh = 60000, /* vertical refresh * 1000 */ + .flags = 10, +}; + +int main(int argc, char **argv) +{ + struct demo_driver *driver; + int num; + int i; + +#ifdef CLEAN_FBDEV + int fbdev_fd; + + fbdev_fd = open("/dev/fb0", O_RDWR); + + memset(&var, 0, sizeof(struct fb_var_screeninfo)); + memset(&fix, 0, sizeof(struct fb_fix_screeninfo)); + + if (ioctl(fbdev_fd, FBIOGET_VSCREENINFO, &var)) + printf("var %s\n", strerror(errno)); + if (ioctl(fbdev_fd, FBIOGET_FSCREENINFO, &fix)) + printf("fix %s\n", strerror(errno)); +#endif + + printf("starting demo\n"); + + driver = demoCreateDriver(); + + if (!driver) { + printf("failed to create driver\n"); + return 1; + } + +#ifndef DEMO_CLONE + num = demoCreateScreens(driver); +#else + num = demoCreateScreenCloned(driver); +#endif + + if (num < 1) { + printf("no screens attached or an error occured\n"); + return 1; + } + printf("created %i screens\n", num); + + for (i = 0; i < num; i++) { + prettyColors(driver->fd, driver->screens[i].fb->handle); + } + sleep(1); + + for (i = 0; i < num; i++) { + printf("%i: 100 0\n", i); + demoPanScreen(&driver->screens[i], 100, 0); + sleep(1); + + printf("%i: 0 100\n", i); + demoPanScreen(&driver->screens[i], 0, 100); + sleep(1); + + printf("%i: 100 100\n", i); + demoPanScreen(&driver->screens[i], 100, 100); + sleep(1); + + printf("%i: 0 0\n", i); + demoPanScreen(&driver->screens[i], 0, 1); + sleep(1); + testCursor(driver->fd, driver->screens[i].crtc->crtc_id); + } + + sleep(2); + printf("taking down screens\n"); + for (i = 0; i < num; i++) { + demoTakeDownScreen(&driver->screens[i]); + } + +#ifdef CLEAN_FBDEV + if (ioctl(fbdev_fd, FBIOPUT_VSCREENINFO, &var)) + printf("var %s\n", strerror(errno)); + + close(fbdev_fd); +#endif + + printf("ok\n"); + return 0; +} + +int demoCreateScreens(struct demo_driver *driver) +{ + drmModeOutputPtr out[MAX_FIND_OUTPUTS]; + int num; + int num_screens = 0; + struct demo_screen *screen; + int ret = 0; + int i; + + num = demoFindConnectedOutputs(driver, out, MAX_FIND_OUTPUTS); + if (num < 0) + return 0; + + printf("found %i connected outputs\n", num); + + for (i = 0; i < num; i++) { + screen = &driver->screens[i]; + + screen->crtc = demoFindFreeCrtc(driver, out[i]); + if (!screen->crtc) { + printf("found no free crtc for output\n"); + drmModeFreeOutput(out[i]); + continue; + } + + screen->fb = createFB(driver->fd, driver->res); + if (!screen->fb) { + drmModeFreeOutput(out[i]); + drmModeFreeCrtc(screen->crtc); + screen->crtc = 0; + printf("could not create framebuffer\n"); + continue; + } + + screen->virt_x = SIZE_X; + screen->virt_y = SIZE_Y; + screen->pitch = PITCH; + + screen->outputs[0] = out[i]; + screen->outputs_id[0] = out[i]->output_id; + screen->num_outputs = 1; + + screen->mode = &mode; + screen->driver = driver; + + ret = drmModeSetCrtc( + driver->fd, + screen->crtc->crtc_id, + screen->fb->buffer_id, + 0, 0, + screen->outputs_id, screen->num_outputs, + screen->mode); + + if (ret) { + printf("failed to set mode\n"); + demoTakeDownScreen(screen); + } else { + num_screens++; + } + + demoUpdateRes(driver); + } + + return num_screens; +} + +int demoCreateScreenCloned(struct demo_driver *driver) +{ + drmModeOutputPtr out[MAX_FIND_OUTPUTS]; + int num; + struct demo_screen *screen; + int ret = 0; + int i; + + num = demoFindConnectedOutputs(driver, out, MAX_FIND_OUTPUTS); + if (num < 0) + return 0; + + printf("found %i connected outputs\n", num); + + screen = &driver->screens[0]; + + screen->fb = createFB(driver->fd, driver->res); + if (!screen->fb) { + printf("could not create framebuffer\n"); + return 0; + } + + screen->mode = &mode; + screen->driver = driver; + + screen->virt_x = SIZE_X; + screen->virt_y = SIZE_Y; + screen->pitch = PITCH; + + screen->num_outputs = 0; + for (i = 0; i < num; i++) { + screen->crtc = demoFindFreeCrtc(driver, out[i]); + if (!screen->crtc) { + printf("found no free crtc for output\n"); + drmModeFreeOutput(out[i]); + continue; + } + + screen->outputs[screen->num_outputs] = out[i]; + screen->outputs_id[screen->num_outputs] = out[i]->output_id; + screen->num_outputs++; + printf("%u, %u\n", out[i]->output_id, screen->num_outputs); + } + + ret = drmModeSetCrtc( + driver->fd, + screen->crtc->crtc_id, + screen->fb->buffer_id, + 0, 0, + screen->outputs_id, screen->num_outputs, + screen->mode); + + if (ret) { + printf("failed to set mode\n"); + demoTakeDownScreen(screen); + return 0; + } + + demoUpdateRes(driver); + + return 1; +} + +void demoTakeDownScreen(struct demo_screen *screen) +{ + int fd = screen->driver->fd; + int i; + drmBO bo; + +#if 0 + /* This can bust the fbdev arrangement as it basically unhooks + * the outputs and the fbdev backend doesn't know how to put things + * back on track. Realistically, it's up to the crtc owner to restore + * things..... + * + * So if you are mixing API's make sure the modesetting owner puts + * back the original CRTC arrangement so fbdev can continue... + * + * Ho-hum.. + */ + if (screen->crtc) + drmModeSetCrtc(fd, screen->crtc->crtc_id, 0, 0, 0, 0, 0, 0); +#endif + + if (screen->fb) + drmModeRmFB(fd, screen->fb->buffer_id); + + /* maybe we should keep a pointer to the bo on the screen */ + if (screen->fb && !drmBOReference(fd, screen->fb->handle, &bo)) { + drmBOUnreference(fd, &bo); + drmBOUnreference(fd, &bo); + } else { + printf("bo error\n"); + } + + for (i = 0; i < screen->num_outputs; i++) { + drmModeFreeOutput(screen->outputs[i]); + screen->outputs[i] = NULL; + } + + drmModeFreeCrtc(screen->crtc); + drmModeFreeFB(screen->fb); + + screen->crtc = NULL; + screen->fb = NULL; +} + +drmModeCrtcPtr demoFindFreeCrtc(struct demo_driver *driver, drmModeOutputPtr output) +{ + drmModeCrtcPtr crtc; + int i, j, used = 0; + drmModeResPtr res = driver->res; + + for (i = 0; i < res->count_crtcs; i++) { + used = 0; + for (j = 0; j < DEMO_MAX_SCREENS; j++) { + crtc = driver->screens[j].crtc; + + if (crtc && crtc->crtc_id == res->crtcs[i]) + used = 1; + } + + if (!used) { + crtc = drmModeGetCrtc(driver->fd, res->crtcs[i]); + break; + } else { + crtc = 0; + } + } + + return crtc; +} + +static int driverfd; + +static void +hotplugSIGNAL(int sig, siginfo_t *si, void *d) +{ + union drm_wait_hotplug hw; + int ret; + + printf("GOT HOTPLUG EVENT!\n"); + + /* ask for another hotplug event ! */ + memset(&hw, 0, sizeof(hw)); + hw.request.type = _DRM_HOTPLUG_SIGNAL; + hw.request.signal = SIGUSR1; + ret = ioctl(driverfd, DRM_IOCTL_WAIT_HOTPLUG, &hw); +} + +struct demo_driver* demoCreateDriver(void) +{ + struct demo_driver* driver = malloc(sizeof(struct demo_driver)); + union drm_wait_hotplug hw; + int ret = 0; + + memset(driver, 0, sizeof(struct demo_driver)); + + driver->fd = drmOpen("i915",NULL); + + if (driver->fd < 0) { + printf("Failed to open the card fb\n"); + goto err_driver; + } + +#if 0 + /* ioctl wait for hotplug */ + do { + memset(&hw, 0, sizeof(hw)); + ret = ioctl(driver->fd, DRM_IOCTL_WAIT_HOTPLUG, &hw); + printf("HOTPLUG %d %d %d\n",ret,errno,hw.reply.counter); + } while (ret && errno == EBUSY); +#else + /* signal for hotplug */ + { + struct sigaction sa; + struct sigaction osa; + + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_SIGINFO; + sa.sa_sigaction = hotplugSIGNAL; + sigaction(SIGUSR1, &sa, &osa); + + driverfd = driver->fd; + + memset(&hw, 0, sizeof(hw)); + hw.request.type = _DRM_HOTPLUG_SIGNAL; + hw.request.signal = SIGUSR1; + ret = ioctl(driver->fd, DRM_IOCTL_WAIT_HOTPLUG, &hw); + } +#endif + + demoUpdateRes(driver); + if (!driver->res) { + printf("could not retrive resources\n"); + goto err_res; + } + + return driver; + +err_res: + drmClose(driver->fd); +err_driver: + free(driver); + return NULL; +} + +void demoUpdateRes(struct demo_driver *driver) +{ + if (driver->res) + drmModeFreeResources(driver->res); + + driver->res = drmModeGetResources(driver->fd); + + if (!driver->res) + printf("failed to get resources from kernel\n"); +} + +int demoFindConnectedOutputs(struct demo_driver *driver, drmModeOutputPtr *out, size_t max_out) +{ + int count = 0; + int i,j; + int fd = driver->fd; + drmModeResPtr res = driver->res; + + drmModeOutputPtr output; + + for (i = 0; i < res->count_outputs && count < max_out; i++) { + output = drmModeGetOutput(fd, res->outputs[i]); + + if (!output) + continue; + + if (output->connection == DRM_MODE_DISCONNECTED) { + drmModeFreeOutput(output); + continue; + } + + for (j = 0; j < output->count_props; j++) { + drmModePropertyPtr prop; + + prop = drmModeGetProperty(fd, output->props[j]); + + printf("Property: %s\n",prop->name); + if (prop->count_enums) + printf("%s\n",prop->enums[output->prop_values[j]].name); + } + + out[count++] = output; + } + + return count; +} + +void demoPanScreen(struct demo_screen *screen, uint16_t x, uint16_t y) +{ + drmModeSetCrtc( + screen->driver->fd, + screen->crtc->crtc_id, + screen->fb->buffer_id, + x, y, + screen->outputs_id, screen->num_outputs, + screen->mode); +} + +drmModeFBPtr createFB(int fd, drmModeResPtr res) +{ + drmModeFBPtr frame; + unsigned int fb = 0; + int ret = 0; + drmBO bo; + + ret = drmBOCreate(fd, SIZE_X * SIZE_Y * 4, 0, 0, + DRM_BO_FLAG_READ | + DRM_BO_FLAG_WRITE | + DRM_BO_FLAG_MEM_TT | + DRM_BO_FLAG_MEM_VRAM | + DRM_BO_FLAG_NO_EVICT, + DRM_BO_HINT_DONT_FENCE, &bo); + + if (ret) { + printf("failed to create framebuffer (ret %d)\n",ret); + goto err; + } + + ret = drmModeAddFB(fd, SIZE_X, SIZE_Y, 32, 32, PITCH * 4, bo.handle, &fb); + + if (ret) + goto err_bo; + + frame = drmModeGetFB(fd, fb); + + if (!frame) + goto err_bo; + + return frame; + +err_bo: + drmBOUnreference(fd, &bo); +err: + return 0; +} + +void draw(unsigned int x, unsigned int y, unsigned int w, unsigned int h, unsigned int v, unsigned int *ptr) +{ + int i, j; + + for (i = x; i < x + w; i++) + for(j = y; j < y + h; j++) + ptr[(i * PITCH) + j] = v; + +} + +void prettyColors(int fd, unsigned int handle) +{ + drmBO bo; + unsigned int *ptr; + int i; + + drmBOReference(fd, handle, &bo); + drmBOMap(fd, &bo, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, (void**)&ptr); + + for (i = 0; i < (SIZE_X*SIZE_Y); i++) + ptr[i] = 0xFFFFFFFF; + + for (i = 0; i < 8; i++) + draw(i * 40, i * 40, 40, 40, 0, ptr); + + + draw(200, 100, 40, 40, 0xff00ff, ptr); + draw(100, 200, 40, 40, 0xff00ff, ptr); + + drmBOUnmap(fd, &bo); +} + +void testCursor(int fd, uint32_t crtc) +{ + drmBO bo; + int ret; + ret = drmBOCreate(fd, 64 * 64 * 4, 0, 0, + DRM_BO_FLAG_READ | + DRM_BO_FLAG_WRITE | + DRM_BO_FLAG_MEM_VRAM | + DRM_BO_FLAG_NO_EVICT, + DRM_BO_HINT_DONT_FENCE, &bo); + + prettyCursor(fd, bo.handle, 0xFFFF00FF); + printf("set cursor\n"); + drmModeSetCursor(fd, crtc, bo.handle, 64, 64); + printf("move cursor 0, 0\n"); + drmModeMoveCursor(fd, crtc, 0, 0); + sleep(1); + prettyCursor(fd, bo.handle, 0xFFFF0000); + printf("move cursor 40, 40\n"); + drmModeMoveCursor(fd, crtc, 40, 40); + sleep(1); + printf("move cursor 100, 100\n"); + drmModeMoveCursor(fd, crtc, 100, 100); + sleep(1); + drmModeSetCursor(fd, crtc, 0, 0, 0); +} + +void prettyCursor(int fd, unsigned int handle, unsigned int color) +{ + drmBO bo; + unsigned int *ptr; + int i; + + drmBOReference(fd, handle, &bo); + drmBOMap(fd, &bo, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, (void**)&ptr); + + for (i = 0; i < (64 * 64); i++) + ptr[i] = color; + + drmBOUnmap(fd, &bo); + drmBOUnreference(fd, &bo); +} diff --git a/tests/modedemo/test b/tests/modedemo/test new file mode 100755 index 00000000..f98e3708 --- /dev/null +++ b/tests/modedemo/test @@ -0,0 +1 @@ +LD_PRELOAD=../../libdrm/.libs/libdrm.so ./app diff --git a/tests/modefb/Makefile b/tests/modefb/Makefile new file mode 100644 index 00000000..467fb11a --- /dev/null +++ b/tests/modefb/Makefile @@ -0,0 +1,14 @@ + +all: app + +#CFLAGS = -g -ansi -pedantic -DPOSIX_C_SOURCE=199309L \ +# -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE \ + +app: demo.c + @gcc $(CFLAGS) -o app -Wall -I../../libdrm -I../../shared-core -L../../libdrm/.libs -ldrm demo.c + +clean: + @rm -f app + +run: app + sudo ./test diff --git a/tests/modefb/demo.c b/tests/modefb/demo.c new file mode 100644 index 00000000..ead53334 --- /dev/null +++ b/tests/modefb/demo.c @@ -0,0 +1,230 @@ +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> +#include <fcntl.h> +#include <string.h> +#include "linux/fb.h" +#include <sys/mman.h> +#include "sys/ioctl.h" +#include "xf86drm.h" +#include "xf86drmMode.h" + +void pretty(int fd); +void setMode(struct fb_var_screeninfo *var); +void pan(int fd, struct fb_var_screeninfo *var, int x, int y); +void cursor(int fd, int drmfd); +void prettyColors(int fd); +void prettyCursor(int fd, unsigned int handle, unsigned int color); + +struct fb_var_screeninfo var; +struct fb_fix_screeninfo fix; + +int main(int argc, char **argv) +{ + char name[100]; + int i,d; + int fd; + int drmfd = drmOpen("i915", NULL); + + if (drmfd < 0) { + printf("drmOpenControl failed\n"); + return 1; + } + + /* try four devices */ + for (d = 0; d < 4; d++) { + snprintf(name, 100, "/dev/fb%d", d); + fd = open(name, O_RDWR); + + if (fd == -1) { + printf("open %s : %s\n", name, strerror(errno)); + return 1; + } + + memset(&var, 0, sizeof(struct fb_var_screeninfo)); + memset(&fix, 0, sizeof(struct fb_fix_screeninfo)); + + if (ioctl(fd, FBIOGET_VSCREENINFO, &var)) + printf("var %s\n", strerror(errno)); + if (ioctl(fd, FBIOGET_FSCREENINFO, &fix)) + printf("fix %s\n", strerror(errno)); + + setMode(&var); + + if (ioctl(fd, FBIOPUT_VSCREENINFO, &var)) + printf("var %s\n", strerror(errno)); + + for (i = 0; i < 1; i++) { + prettyColors(fd); + } + sleep(1); + + printf("pan: 0, 0\n"); + pan(fd, &var, 0, 0); + sleep(2); + printf("pan: 100, 0\n"); + pan(fd, &var, 100, 0); + sleep(2); + printf("pan: 0, 100\n"); + pan(fd, &var, 0, 100); + sleep(2); + printf("pan: 100, 100\n"); + pan(fd, &var, 100, 100); + sleep(2); + printf("pan: 0, 0\n"); + pan(fd, &var, 0, 0); + sleep(2); + + printf("cursor (may show up on wrong CRTC - fixme)\n"); + cursor(fd, drmfd); + + close(fd); + } + return 0; +} + +void pan(int fd, struct fb_var_screeninfo *var, int x, int y) +{ + var->xoffset = x; + var->yoffset = y; + + if (ioctl(fd, FBIOPAN_DISPLAY, var)) + printf("pan error: %s\n", strerror(errno)); +} + +void draw(unsigned int x, unsigned int y, unsigned int w, unsigned int h, unsigned int v, unsigned int *ptr) +{ + int i, j; + + for (i = x; i < x + w; i++) + for(j = y; j < y + h; j++) + ptr[(i * var.xres_virtual) + j] = v; +} + +void prettyColors(int fd) +{ + unsigned int *ptr; + int i; + int size = var.xres * var.yres * var.bits_per_pixel; + + ptr = (unsigned int *)mmap(NULL, size, + PROT_READ|PROT_WRITE, MAP_SHARED, fd, + 0); + if (ptr < 0) { + printf("FAILED MMAP %d\n",errno); + exit(1); + } + + memset(ptr, 0xFF, size); + + for (i = 0; i < 8; i++) + draw(i * 40, i * 40, 40, 40, 0, ptr); + + + draw(200, 100, 40, 40, 0xff00ff, ptr); + draw(100, 200, 40, 40, 0xff00ff, ptr); + + munmap(ptr, size); +} + +/* + * Cursor support removed from the fb kernel interface + * using drm instead. + */ +void cursor(int fd, int drmfd) +{ + drmModeResPtr res = drmModeGetResources(drmfd); + uint32_t crtc = res->crtcs[1]; /* select crtc here */ + drmBO bo; + int ret; + ret = drmBOCreate(drmfd, 64 * 64 * 4, 0, 0, + DRM_BO_FLAG_READ | + DRM_BO_FLAG_WRITE | + DRM_BO_FLAG_MEM_VRAM | + DRM_BO_FLAG_NO_EVICT, + DRM_BO_HINT_DONT_FENCE, &bo); + + if (ret) { + printf("failed to create buffer: %s\n", strerror(ret)); + return; + } + + prettyCursor(drmfd, bo.handle, 0xFFFF00FF); + drmModeSetCursor(drmfd, crtc, bo.handle, 64, 64); + drmModeMoveCursor(drmfd, crtc, 0, 0); + sleep(1); + prettyCursor(drmfd, bo.handle, 0xFFFF0000); + drmModeMoveCursor(drmfd, crtc, 40, 40); + sleep(1); + drmModeMoveCursor(drmfd, crtc, 100, 100); + sleep(1); + drmModeSetCursor(drmfd, crtc, 0, 0, 0); + drmBOUnreference(drmfd, &bo); +} + +void prettyCursor(int drmfd, unsigned int handle, unsigned int color) +{ + drmBO bo; + unsigned int *ptr; + int i; + + drmBOReference(drmfd, handle, &bo); + drmBOMap(drmfd, &bo, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, (void**)&ptr); + + for (i = 0; i < (64 * 64); i++) + ptr[i] = color; + + drmBOUnmap(drmfd, &bo); + drmBOUnreference(drmfd, &bo); +} + +struct drm_mode +{ + int clock; + int hdisplay; + int hsync_start; + int hsync_end; + int htotal; + int hskew; + int vdisplay; + int vsync_start; + int vsync_end; + int vtotal; + int vscan; + int vrefresh; + int flags; +}; + +struct drm_mode mode = +{ + .clock = 25200, + .hdisplay = 640, + .hsync_start = 656, + .hsync_end = 752, + .htotal = 800, + .hskew = 0, + .vdisplay = 480, + .vsync_start = 490, + .vsync_end = 492, + .vtotal = 525, + .vscan = 0, + .vrefresh = 60000, /* vertical refresh * 1000 */ + .flags = 10, +}; + +void setMode(struct fb_var_screeninfo *var) { + var->activate = FB_ACTIVATE_NOW; + var->xres = mode.hdisplay; + var->right_margin = mode.hsync_start - mode.hdisplay; + var->hsync_len = mode.hsync_end - mode.hsync_start; + var->left_margin = mode.htotal - mode.hsync_end; + var->yres = mode.vdisplay; + var->lower_margin = mode.vsync_start - mode.vdisplay; + var->vsync_len = mode.vsync_end - mode.vsync_start; + var->upper_margin = mode.vtotal - mode.vsync_end; + var->pixclock = 10000000 / mode.htotal * 1000 / mode.vtotal * 100; + /* avoid overflow */ + var->pixclock = var->pixclock * 1000 / mode.vrefresh; + var->bits_per_pixel = 32; +} diff --git a/tests/modefb/test b/tests/modefb/test new file mode 100755 index 00000000..f98e3708 --- /dev/null +++ b/tests/modefb/test @@ -0,0 +1 @@ +LD_PRELOAD=../../libdrm/.libs/libdrm.so ./app diff --git a/tests/modehotplug/Makefile b/tests/modehotplug/Makefile new file mode 100644 index 00000000..467fb11a --- /dev/null +++ b/tests/modehotplug/Makefile @@ -0,0 +1,14 @@ + +all: app + +#CFLAGS = -g -ansi -pedantic -DPOSIX_C_SOURCE=199309L \ +# -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE \ + +app: demo.c + @gcc $(CFLAGS) -o app -Wall -I../../libdrm -I../../shared-core -L../../libdrm/.libs -ldrm demo.c + +clean: + @rm -f app + +run: app + sudo ./test diff --git a/tests/modehotplug/demo.c b/tests/modehotplug/demo.c new file mode 100644 index 00000000..4ef2e386 --- /dev/null +++ b/tests/modehotplug/demo.c @@ -0,0 +1,157 @@ + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <unistd.h> +#include <string.h> + +#include "xf86drm.h" +#include "xf86drmMode.h" + +/* structs for the demo_driver */ + +#define DEMO_MAX_OUTPUTS 8 + +struct demo_driver +{ + /* drm stuff */ + int fd; + drmModeResPtr res; + uint32_t counter; + + drmModeOutputPtr outputs[DEMO_MAX_OUTPUTS]; +}; + +struct demo_driver* demoCreateDriver(void); +void demoUpdateRes(struct demo_driver *driver); + +void demoPopulateOutputs(struct demo_driver *driver); +void demoHotplug(struct demo_driver *driver); + +const char* demoGetStatus(drmModeOutputPtr out); + +int main(int argc, char **argv) +{ + struct demo_driver *driver; + uint32_t temp; + int i; + + printf("starting demo\n"); + + driver = demoCreateDriver(); + + if (!driver) { + printf("failed to create driver\n"); + return 1; + } + + driver->counter = drmModeGetHotplug(driver->fd); + demoPopulateOutputs(driver); + while (driver->counter != (temp = drmModeGetHotplug(driver->fd))) { + demoPopulateOutputs(driver); + driver->counter = temp; + } + + for (i = 0; i < driver->res->count_outputs && i < DEMO_MAX_OUTPUTS; i++) { + printf("Output %u is %s\n", + driver->outputs[i]->output_id, + demoGetStatus(driver->outputs[i])); + } + + while(1) { + usleep(100000); + temp = drmModeGetHotplug(driver->fd); + if (temp == driver->counter) + continue; + + demoHotplug(driver); + driver->counter = temp; + } + + return 0; +} + +const char* demoGetStatus(drmModeOutputPtr output) +{ + switch (output->connection) { + case DRM_MODE_CONNECTED: + return "connected"; + case DRM_MODE_DISCONNECTED: + return "disconnected"; + default: + return "unknown"; + } +} + +void demoHotplug(struct demo_driver *driver) +{ + drmModeResPtr res = driver->res; + int i; + drmModeOutputPtr temp, current; + + for (i = 0; i < res->count_outputs && i < DEMO_MAX_OUTPUTS; i++) { + temp = drmModeGetOutput(driver->fd, res->outputs[i]); + current = driver->outputs[i]; + + if (temp->connection != current->connection) { + printf("Output %u became %s was %s\n", + temp->output_id, + demoGetStatus(temp), + demoGetStatus(current)); + } + + drmModeFreeOutput(current); + driver->outputs[i] = temp; + } +} + +void demoPopulateOutputs(struct demo_driver *driver) +{ + drmModeResPtr res = driver->res; + int i; + + for (i = 0; i < res->count_outputs && i < DEMO_MAX_OUTPUTS; i++) { + drmModeFreeOutput(driver->outputs[i]); + driver->outputs[i] = drmModeGetOutput(driver->fd, res->outputs[i]); + } +} + +struct demo_driver* demoCreateDriver(void) +{ + struct demo_driver* driver = malloc(sizeof(struct demo_driver)); + + memset(driver, 0, sizeof(struct demo_driver)); + + driver->fd = drmOpen("i915", NULL); + + if (driver->fd < 0) { + printf("Failed to open the card fb\n"); + goto err_driver; + } + + demoUpdateRes(driver); + if (!driver->res) { + printf("could not retrive resources\n"); + goto err_res; + } + + return driver; + +err_res: + drmClose(driver->fd); +err_driver: + free(driver); + return NULL; +} + +void demoUpdateRes(struct demo_driver *driver) +{ + if (driver->res) + drmModeFreeResources(driver->res); + + driver->res = drmModeGetResources(driver->fd); + + if (!driver->res) + printf("failed to get resources from kernel\n"); +} diff --git a/tests/modehotplug/test b/tests/modehotplug/test new file mode 100755 index 00000000..f98e3708 --- /dev/null +++ b/tests/modehotplug/test @@ -0,0 +1 @@ +LD_PRELOAD=../../libdrm/.libs/libdrm.so ./app diff --git a/tests/modeprint/Makefile b/tests/modeprint/Makefile new file mode 100644 index 00000000..7a9c3c24 --- /dev/null +++ b/tests/modeprint/Makefile @@ -0,0 +1,14 @@ + +all: app + +#CFLAGS = -g -ansi -pedantic -DPOSIX_C_SOURCE=199309L \ +# -D_POSIX_SOURCE -D_XOPEN_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE \ + +app: modetest.c + @gcc $(CFLAGS) -o app -Wall -I../../libdrm -I../../shared-core -L../../libdrm/.libs -ldrm modetest.c + +clean: + @rm -f app + +run: app + @sudo ./test diff --git a/tests/modeprint/modetest.c b/tests/modeprint/modetest.c new file mode 100644 index 00000000..cefa5262 --- /dev/null +++ b/tests/modeprint/modetest.c @@ -0,0 +1,371 @@ + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <unistd.h> +#include <string.h> + +#include "xf86drm.h" +#include "xf86drmMode.h" + +int connectors; +int full_props; +int edid; +int modes; +int full_modes; +int encoders; +int crtcs; +int fbs; +char *module_name; + +const char* getConnectionText(drmModeConnection conn) +{ + switch (conn) { + case DRM_MODE_CONNECTED: + return "connected"; + case DRM_MODE_DISCONNECTED: + return "disconnected"; + default: + return "unknown"; + } + +} + +int printMode(struct drm_mode_modeinfo *mode) +{ + if (full_modes) { + printf("Mode: %s\n", mode->name); + printf("\tclock : %i\n", mode->clock); + printf("\thdisplay : %i\n", mode->hdisplay); + printf("\thsync_start : %i\n", mode->hsync_start); + printf("\thsync_end : %i\n", mode->hsync_end); + printf("\thtotal : %i\n", mode->htotal); + printf("\thskew : %i\n", mode->hskew); + printf("\tvdisplay : %i\n", mode->vdisplay); + printf("\tvsync_start : %i\n", mode->vsync_start); + printf("\tvsync_end : %i\n", mode->vsync_end); + printf("\tvtotal : %i\n", mode->vtotal); + printf("\tvscan : %i\n", mode->vscan); + printf("\tvrefresh : %i\n", mode->vrefresh); + printf("\tflags : %i\n", mode->flags); + } else { + printf("Mode: \"%s\" %ix%i %.0f\n", mode->name, + mode->hdisplay, mode->vdisplay, mode->vrefresh / 1000.0); + } + return 0; +} + +int printProperty(int fd, drmModeResPtr res, drmModePropertyPtr props, uint64_t value) +{ + const unsigned char *name = NULL; + int j; + + printf("Property: %s\n", props->name); + printf("\tid : %i\n", props->prop_id); + printf("\tflags : %i\n", props->flags); + printf("\tcount_values : %d\n", props->count_values); + + + if (props->count_values) { + printf("\tvalues :"); + for (j = 0; j < props->count_values; j++) + printf(" %lld", props->values[j]); + printf("\n"); + } + + + printf("\tcount_enums : %d\n", props->count_enums); + + if (props->flags & DRM_MODE_PROP_BLOB) { + drmModePropertyBlobPtr blob; + + blob = drmModeGetPropertyBlob(fd, value); + if (blob) { + printf("blob is %d length, %08X\n", blob->length, *(uint32_t *)blob->data); + drmModeFreePropertyBlob(blob); + } else { + printf("error getting blob %lld\n", value); + } + + } else { + if (!strncmp(props->name, "DPMS", 4)) + ; + + for (j = 0; j < props->count_enums; j++) { + printf("\t\t%lld = %s\n", props->enums[j].value, props->enums[j].name); + if (props->enums[j].value == value) + name = props->enums[j].name; + } + + if (props->count_enums && name) { + printf("\tcon_value : %s\n", name); + } else { + printf("\tcon_value : %lld\n", value); + } + } + + return 0; +} + +int printConnector(int fd, drmModeResPtr res, drmModeConnectorPtr connector, uint32_t id) +{ + int i = 0; + struct drm_mode_modeinfo *mode = NULL; + drmModePropertyPtr props; + + printf("Connector: %d-%d\n", connector->connector_type, connector->connector_type_id); + printf("\tid : %i\n", id); + printf("\tencoder id : %i\n", connector->encoder_id); + printf("\tconn : %s\n", getConnectionText(connector->connection)); + printf("\tsize : %ix%i (mm)\n", connector->mmWidth, connector->mmHeight); + printf("\tcount_modes : %i\n", connector->count_modes); + printf("\tcount_props : %i\n", connector->count_props); + if (connector->count_props) { + printf("\tprops :"); + for (i = 0; i < connector->count_props; i++) + printf(" %i", connector->props[i]); + printf("\n"); + } + + printf("\tcount_encoders : %i\n", connector->count_encoders); + if (connector->count_encoders) { + printf("\tencoders :"); + for (i = 0; i < connector->count_encoders; i++) + printf(" %i", connector->encoders[i]); + printf("\n"); + } + + if (modes) { + for (i = 0; i < connector->count_modes; i++) { + mode = &connector->modes[i]; + printMode(mode); + } + } + + if (full_props) { + for (i = 0; i < connector->count_props; i++) { + props = drmModeGetProperty(fd, connector->props[i]); + if (props) { + printProperty(fd, res, props, connector->prop_values[i]); + drmModeFreeProperty(props); + } + } + } + + return 0; +} + +int printEncoder(int fd, drmModeResPtr res, drmModeEncoderPtr encoder, uint32_t id) +{ + printf("Encoder\n"); + printf("\tid :%i\n", id); + printf("\tcrtc_id :%d\n", encoder->crtc_id); + printf("\ttype :%d\n", encoder->encoder_type); + printf("\tpossible_crtcs :%d\n", encoder->possible_crtcs); + printf("\tpossible_clones :%d\n", encoder->possible_clones); + return 0; +} + +int printCrtc(int fd, drmModeResPtr res, drmModeCrtcPtr crtc, uint32_t id) +{ + printf("Crtc\n"); + printf("\tid : %i\n", id); + printf("\tx : %i\n", crtc->x); + printf("\ty : %i\n", crtc->y); + printf("\twidth : %i\n", crtc->width); + printf("\theight : %i\n", crtc->height); + printf("\tmode : %p\n", &crtc->mode); + printf("\tgamma size : %d\n", crtc->gamma_size); + + return 0; +} + +int printFrameBuffer(int fd, drmModeResPtr res, drmModeFBPtr fb) +{ + printf("Framebuffer\n"); + printf("\thandle : %i\n", fb->handle); + printf("\twidth : %i\n", fb->width); + printf("\theight : %i\n", fb->height); + printf("\tpitch : %i\n", fb->pitch);; + printf("\tbpp : %i\n", fb->bpp); + printf("\tdepth : %i\n", fb->depth); + printf("\tbuffer_id : %i\n", fb->buffer_id); + + return 0; +} + +int printRes(int fd, drmModeResPtr res) +{ + int i; + drmModeFBPtr fb; + drmModeCrtcPtr crtc; + drmModeEncoderPtr encoder; + drmModeConnectorPtr connector; + + printf("Resources\n\n"); + + printf("count_connectors : %i\n", res->count_connectors); + printf("count_encoders : %i\n", res->count_encoders); + printf("count_crtcs : %i\n", res->count_crtcs); + printf("count_fbs : %i\n", res->count_fbs); + + printf("\n"); + + if (connectors) { + for (i = 0; i < res->count_connectors; i++) { + connector = drmModeGetConnector(fd, res->connectors[i]); + + if (!connector) + printf("Could not get connector %i\n", res->connectors[i]); + else { + printConnector(fd, res, connector, res->connectors[i]); + drmModeFreeConnector(connector); + } + } + printf("\n"); + } + + + if (encoders) { + for (i = 0; i < res->count_encoders; i++) { + encoder = drmModeGetEncoder(fd, res->encoders[i]); + + if (!encoder) + printf("Could not get encoder %i\n", res->encoders[i]); + else { + printEncoder(fd, res, encoder, res->encoders[i]); + drmModeFreeEncoder(encoder); + } + } + printf("\n"); + } + + if (crtcs) { + for (i = 0; i < res->count_crtcs; i++) { + crtc = drmModeGetCrtc(fd, res->crtcs[i]); + + if (!crtc) + printf("Could not get crtc %i\n", res->crtcs[i]); + else { + printCrtc(fd, res, crtc, res->crtcs[i]); + drmModeFreeCrtc(crtc); + } + } + printf("\n"); + } + + if (fbs) { + for (i = 0; i < res->count_fbs; i++) { + fb = drmModeGetFB(fd, res->fbs[i]); + + if (!fb) + printf("Could not get fb %i\n", res->fbs[i]); + else { + printFrameBuffer(fd, res, fb); + drmModeFreeFB(fb); + } + } + } + + return 0; +} + +void args(int argc, char **argv) +{ + int i; + + fbs = 0; + edid = 0; + crtcs = 0; + modes = 0; + encoders = 0; + full_modes = 0; + full_props = 0; + connectors = 0; + + module_name = argv[1]; + + for (i = 2; i < argc; i++) { + if (strcmp(argv[i], "-fb") == 0) { + fbs = 1; + } else if (strcmp(argv[i], "-crtcs") == 0) { + crtcs = 1; + } else if (strcmp(argv[i], "-cons") == 0) { + connectors = 1; + modes = 1; + } else if (strcmp(argv[i], "-modes") == 0) { + connectors = 1; + modes = 1; + } else if (strcmp(argv[i], "-full") == 0) { + connectors = 1; + modes = 1; + full_modes = 1; + } else if (strcmp(argv[i], "-props") == 0) { + connectors = 1; + full_props = 1; + } else if (strcmp(argv[i], "-edids") == 0) { + connectors = 1; + edid = 1; + } else if (strcmp(argv[i], "-encoders") == 0) { + encoders = 1; + } else if (strcmp(argv[i], "-v") == 0) { + fbs = 1; + edid = 1; + crtcs = 1; + modes = 1; + encoders = 1; + full_modes = 1; + full_props = 1; + connectors = 1; + } + } + + if (argc == 2) { + fbs = 1; + edid = 1; + crtcs = 1; + modes = 1; + encoders = 1; + full_modes = 0; + full_props = 0; + connectors = 1; + } +} + +int main(int argc, char **argv) +{ + int fd; + drmModeResPtr res; + + if (argc == 1) { + printf("Please add modulename as first argument\n"); + return 1; + } + + args(argc, argv); + + printf("Starting test\n"); + + fd = drmOpen(module_name, NULL); + + if (fd < 0) { + printf("Failed to open the card fd (%d)\n",fd); + return 1; + } + + res = drmModeGetResources(fd); + if (res == 0) { + printf("Failed to get resources from card\n"); + drmClose(fd); + return 1; + } + + printRes(fd, res); + + drmModeFreeResources(res); + + printf("Ok\n"); + + return 0; +} diff --git a/tests/modeprint/test b/tests/modeprint/test new file mode 100755 index 00000000..bd1952cc --- /dev/null +++ b/tests/modeprint/test @@ -0,0 +1 @@ +LD_PRELOAD=../../libdrm/.libs/libdrm.so ./app $@ diff --git a/tests/radeon_gem_basic.c b/tests/radeon_gem_basic.c new file mode 100644 index 00000000..d8231879 --- /dev/null +++ b/tests/radeon_gem_basic.c @@ -0,0 +1,114 @@ +/* + * Copyright © 2008 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include "drm.h" +#include "radeon_drm.h" + +static void +test_bad_close(int fd) +{ + struct drm_gem_close close; + int ret; + + printf("Testing error return on bad close ioctl.\n"); + + close.handle = 0x10101010; + ret = ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close); + + assert(ret == -1 && errno == EINVAL); +} + +static void +test_create_close(int fd) +{ + struct drm_radeon_gem_create create; + struct drm_gem_close close; + int ret; + + printf("Testing creating and closing an object.\n"); + + memset(&create, 0, sizeof(create)); + create.size = 16 * 1024; + ret = ioctl(fd, DRM_IOCTL_RADEON_GEM_CREATE, &create); + assert(ret == 0); + + close.handle = create.handle; + ret = ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close); +} + +static void +test_create_fd_close(int fd) +{ + struct drm_radeon_gem_create create; + int ret; + + printf("Testing closing with an object allocated.\n"); + + memset(&create, 0, sizeof(create)); + create.size = 16 * 1024; + ret = ioctl(fd, DRM_IOCTL_RADEON_GEM_CREATE, &create); + assert(ret == 0); + + close(fd); +} + +int test_gem_info(int fd) +{ + struct drm_radeon_gem_info info; + int ret; + + ret = ioctl(fd, DRM_IOCTL_RADEON_GEM_INFO, &info); + assert(ret == 0); + + fprintf(stderr,"%lld %lld %lld %lld %lld\n", + info.gtt_start, info.gtt_size, + info.vram_start, info.vram_size, + info.vram_visible); + +} + +int main(int argc, char **argv) +{ + int fd; + + fd = drm_open_any(); + + test_gem_info(fd); + test_bad_close(fd); + test_create_close(fd); + test_create_fd_close(fd); + + return 0; +} diff --git a/tests/radeon_gem_mmap.c b/tests/radeon_gem_mmap.c new file mode 100644 index 00000000..aa7b0196 --- /dev/null +++ b/tests/radeon_gem_mmap.c @@ -0,0 +1,132 @@ +/* + * Copyright © 2008 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt <eric@anholt.net> + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include <fcntl.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/stat.h> +#include "drm.h" +#include "radeon_drm.h" + +#define OBJECT_SIZE 16384 + +int do_read(int fd, int handle, void *buf, int offset, int size) +{ + struct drm_radeon_gem_pread read; + + /* Ensure that we don't have any convenient data in buf in case + * we fail. + */ + memset(buf, 0xd0, size); + + memset(&read, 0, sizeof(read)); + read.handle = handle; + read.data_ptr = (uintptr_t)buf; + read.size = size; + read.offset = offset; + + return ioctl(fd, DRM_IOCTL_RADEON_GEM_PREAD, &read); +} + +int do_write(int fd, int handle, void *buf, int offset, int size) +{ + struct drm_radeon_gem_pwrite write; + + memset(&write, 0, sizeof(write)); + write.handle = handle; + write.data_ptr = (uintptr_t)buf; + write.size = size; + write.offset = offset; + + return ioctl(fd, DRM_IOCTL_RADEON_GEM_PWRITE, &write); +} + +int main(int argc, char **argv) +{ + int fd; + struct drm_radeon_gem_create create; + struct drm_radeon_gem_mmap mmap; + struct drm_gem_close unref; + uint8_t expected[OBJECT_SIZE]; + uint8_t buf[OBJECT_SIZE]; + uint8_t *addr; + int ret; + int handle; + + fd = drm_open_any(); + + memset(&mmap, 0, sizeof(mmap)); + mmap.handle = 0x10101010; + mmap.offset = 0; + mmap.size = 4096; + printf("Testing mmaping of bad object.\n"); + ret = ioctl(fd, DRM_IOCTL_RADEON_GEM_MMAP, &mmap); + assert(ret == -1 && errno == EINVAL); + + memset(&create, 0, sizeof(create)); + create.size = OBJECT_SIZE; + ret = ioctl(fd, DRM_IOCTL_RADEON_GEM_CREATE, &create); + assert(ret == 0); + handle = create.handle; + + printf("Testing mmaping of newly created object.\n"); + mmap.handle = handle; + mmap.offset = 0; + mmap.size = OBJECT_SIZE; + ret = ioctl(fd, DRM_IOCTL_RADEON_GEM_MMAP, &mmap); + assert(ret == 0); + addr = (uint8_t *)(uintptr_t)mmap.addr_ptr; + + printf("Testing contents of newly created object.\n"); + memset(expected, 0, sizeof(expected)); + assert(memcmp(addr, expected, sizeof(expected)) == 0); + + printf("Testing coherency of writes and mmap reads.\n"); + memset(buf, 0, sizeof(buf)); + memset(buf + 1024, 0x01, 1024); + memset(expected + 1024, 0x01, 1024); + ret = do_write(fd, handle, buf, 0, OBJECT_SIZE); + assert(ret == 0); + assert(memcmp(buf, addr, sizeof(buf)) == 0); + + printf("Testing that mapping stays after close\n"); + unref.handle = handle; + ret = ioctl(fd, DRM_IOCTL_GEM_CLOSE, &unref); + assert(ret == 0); + assert(memcmp(buf, addr, sizeof(buf)) == 0); + + printf("Testing unmapping\n"); + munmap(addr, OBJECT_SIZE); + + close(fd); + + return 0; +} |