cursor.c revision baaff307
1/* 2 * DRM based mode setting test program 3 * Copyright (C) 2013 Red Hat 4 * Author: Rob Clark <robdclark@gmail.com> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 * IN THE SOFTWARE. 23 */ 24 25#ifdef HAVE_CONFIG_H 26#include "config.h" 27#endif 28 29#include <assert.h> 30#include <errno.h> 31#include <stdio.h> 32#include <stdlib.h> 33#include <stdint.h> 34#include <string.h> 35#include <signal.h> 36#include <sys/time.h> 37 38#include "xf86drm.h" 39#include "xf86drmMode.h" 40 41#include "buffers.h" 42#include "cursor.h" 43 44#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 45 46struct cursor { 47 int fd; 48 uint32_t bo_handle; 49 uint32_t crtc_id; 50 uint32_t crtc_w, crtc_h; 51 uint32_t w, h; 52 53 /* current state */ 54 uint32_t enabled, x, y; 55 int32_t dx, dy; 56}; 57 58#define MAX_CURSORS 8 59static struct cursor cursors[MAX_CURSORS]; 60static int ncursors; 61 62/* 63 * Timer driven program loops through these steps to move/enable/disable 64 * the cursor 65 */ 66 67struct cursor_step { 68 void (*run)(struct cursor *cursor, struct cursor_step *step); 69 uint32_t msec; 70 uint32_t repeat; 71 int arg; 72}; 73 74static uint32_t indx, count; 75 76static void set_cursor(struct cursor *cursor, struct cursor_step *step) 77{ 78 int enabled = (step->arg ^ count) & 0x1; 79 uint32_t handle = 0; 80 81 if (enabled) 82 handle = cursor->bo_handle; 83 84 cursor->enabled = enabled; 85 86 drmModeSetCursor(cursor->fd, cursor->crtc_id, handle, cursor->w, cursor->h); 87} 88 89static void move_cursor(struct cursor *cursor, struct cursor_step *step) 90{ 91 int x = cursor->x; 92 int y = cursor->y; 93 94 if (!cursor->enabled) 95 drmModeSetCursor(cursor->fd, cursor->crtc_id, 96 cursor->bo_handle, cursor->w, cursor->h); 97 98 /* calculate new cursor position: */ 99 x += cursor->dx * step->arg; 100 y += cursor->dy * step->arg; 101 102 if (x < 0) { 103 x = 0; 104 cursor->dx = 1; 105 } else if (x > (int)cursor->crtc_w) { 106 x = cursor->crtc_w - 1; 107 cursor->dx = -1; 108 } 109 110 if (y < 0) { 111 y = 0; 112 cursor->dy = 1; 113 } else if (y > (int)cursor->crtc_h) { 114 y = cursor->crtc_h - 1; 115 cursor->dy = -1; 116 } 117 118 cursor->x = x; 119 cursor->y = y; 120 121 drmModeMoveCursor(cursor->fd, cursor->crtc_id, x, y); 122} 123 124static struct cursor_step steps[] = { 125 { set_cursor, 10, 0, 1 }, /* enable */ 126 { move_cursor, 1, 100, 1 }, 127 { move_cursor, 1, 10, 10 }, 128 { set_cursor, 1, 100, 0 }, /* disable/enable loop */ 129 { move_cursor, 1, 10, 10 }, 130 { move_cursor, 9, 100, 1 }, 131 { move_cursor, 11, 100, 5 }, 132 { set_cursor, 17, 10, 0 }, /* disable/enable loop */ 133 { move_cursor, 9, 100, 1 }, 134 { set_cursor, 13, 10, 0 }, /* disable/enable loop */ 135 { move_cursor, 9, 100, 1 }, 136 { set_cursor, 13, 10, 0 }, /* disable/enable loop */ 137 { set_cursor, 10, 0, 0 }, /* disable */ 138}; 139 140/* 141 * Cursor API: 142 */ 143 144static void run_step(int sig) 145{ 146 struct cursor_step *step = &steps[indx % ARRAY_SIZE(steps)]; 147 struct itimerval itimer = { 148 .it_value.tv_usec = 1000 * step->msec, 149 }; 150 int i; 151 152 for (i = 0; i < ncursors; i++) { 153 struct cursor *cursor = &cursors[i]; 154 step->run(cursor, step); 155 } 156 157 /* iterate to next count/step: */ 158 if (count < step->repeat) { 159 count++; 160 } else { 161 count = 0; 162 indx++; 163 } 164 165 /* and lastly, setup timer for next step */ 166 setitimer(ITIMER_REAL, &itimer, NULL); 167} 168 169int cursor_init(int fd, uint32_t bo_handle, uint32_t crtc_id, 170 uint32_t crtc_w, uint32_t crtc_h, uint32_t w, uint32_t h) 171{ 172 struct cursor *cursor = &cursors[ncursors]; 173 174 assert(ncursors < MAX_CURSORS); 175 176 cursor->fd = fd; 177 cursor->bo_handle = bo_handle; 178 cursor->crtc_id = crtc_id; 179 cursor->crtc_w = crtc_w; 180 cursor->crtc_h = crtc_h; 181 cursor->w = w; 182 cursor->h = h; 183 184 cursor->enabled = 0; 185 cursor->x = w/2; 186 cursor->y = h/2; 187 cursor->dx = 1; 188 cursor->dy = 1; 189 190 ncursors++; 191 192 return 0; 193} 194 195int cursor_start(void) 196{ 197 /* setup signal handler to update cursor: */ 198 signal(SIGALRM, run_step); 199 printf("starting cursor\n"); 200 run_step(SIGALRM); 201 return 0; 202} 203 204int cursor_stop(void) 205{ 206 signal(SIGALRM, NULL); 207 printf("cursor stopped\n"); 208 return 0; 209} 210