#include #include #include #include #include #include #include "linux/fb.h" #include #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; }