cursor.c revision 857b0bc6
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#include "config.h" 26 27#include <assert.h> 28#include <errno.h> 29#include <stdio.h> 30#include <stdlib.h> 31#include <stdint.h> 32#include <string.h> 33#include <signal.h> 34#include <sys/time.h> 35 36#include "xf86drm.h" 37#include "xf86drmMode.h" 38 39#include "buffers.h" 40#include "cursor.h" 41 42#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 43 44struct cursor { 45 int fd; 46 uint32_t bo_handle; 47 uint32_t crtc_id; 48 uint32_t crtc_w, crtc_h; 49 uint32_t w, h; 50 51 /* current state */ 52 uint32_t enabled, x, y; 53 int32_t dx, dy; 54}; 55 56#define MAX_CURSORS 8 57static struct cursor cursors[MAX_CURSORS]; 58static int ncursors; 59 60/* 61 * Timer driven program loops through these steps to move/enable/disable 62 * the cursor 63 */ 64 65struct cursor_step { 66 void (*run)(struct cursor *cursor, struct cursor_step *step); 67 uint32_t msec; 68 uint32_t repeat; 69 int arg; 70}; 71 72static uint32_t indx, count; 73 74static void set_cursor(struct cursor *cursor, struct cursor_step *step) 75{ 76 int enabled = (step->arg ^ count) & 0x1; 77 uint32_t handle = 0; 78 79 if (enabled) 80 handle = cursor->bo_handle; 81 82 cursor->enabled = enabled; 83 84 drmModeSetCursor(cursor->fd, cursor->crtc_id, handle, cursor->w, cursor->h); 85} 86 87static void move_cursor(struct cursor *cursor, struct cursor_step *step) 88{ 89 int x = cursor->x; 90 int y = cursor->y; 91 92 if (!cursor->enabled) 93 drmModeSetCursor(cursor->fd, cursor->crtc_id, 94 cursor->bo_handle, cursor->w, cursor->h); 95 96 /* calculate new cursor position: */ 97 x += cursor->dx * step->arg; 98 y += cursor->dy * step->arg; 99 100 if (x < 0) { 101 x = 0; 102 cursor->dx = 1; 103 } else if (x > (int)cursor->crtc_w) { 104 x = cursor->crtc_w - 1; 105 cursor->dx = -1; 106 } 107 108 if (y < 0) { 109 y = 0; 110 cursor->dy = 1; 111 } else if (y > (int)cursor->crtc_h) { 112 y = cursor->crtc_h - 1; 113 cursor->dy = -1; 114 } 115 116 cursor->x = x; 117 cursor->y = y; 118 119 drmModeMoveCursor(cursor->fd, cursor->crtc_id, x, y); 120} 121 122static struct cursor_step steps[] = { 123 { set_cursor, 10, 0, 1 }, /* enable */ 124 { move_cursor, 1, 100, 1 }, 125 { move_cursor, 1, 10, 10 }, 126 { set_cursor, 1, 100, 0 }, /* disable/enable loop */ 127 { move_cursor, 1, 10, 10 }, 128 { move_cursor, 9, 100, 1 }, 129 { move_cursor, 11, 100, 5 }, 130 { set_cursor, 17, 10, 0 }, /* disable/enable loop */ 131 { move_cursor, 9, 100, 1 }, 132 { set_cursor, 13, 10, 0 }, /* disable/enable loop */ 133 { move_cursor, 9, 100, 1 }, 134 { set_cursor, 13, 10, 0 }, /* disable/enable loop */ 135 { set_cursor, 10, 0, 0 }, /* disable */ 136}; 137 138/* 139 * Cursor API: 140 */ 141 142static void run_step(int sig) 143{ 144 struct cursor_step *step = &steps[indx % ARRAY_SIZE(steps)]; 145 struct itimerval itimer = { 146 .it_value.tv_usec = 1000 * step->msec, 147 }; 148 int i; 149 150 for (i = 0; i < ncursors; i++) { 151 struct cursor *cursor = &cursors[i]; 152 step->run(cursor, step); 153 } 154 155 /* iterate to next count/step: */ 156 if (count < step->repeat) { 157 count++; 158 } else { 159 count = 0; 160 indx++; 161 } 162 163 /* and lastly, setup timer for next step */ 164 setitimer(ITIMER_REAL, &itimer, NULL); 165} 166 167int cursor_init(int fd, uint32_t bo_handle, uint32_t crtc_id, 168 uint32_t crtc_w, uint32_t crtc_h, uint32_t w, uint32_t h) 169{ 170 struct cursor *cursor = &cursors[ncursors]; 171 172 assert(ncursors < MAX_CURSORS); 173 174 cursor->fd = fd; 175 cursor->bo_handle = bo_handle; 176 cursor->crtc_id = crtc_id; 177 cursor->crtc_w = crtc_w; 178 cursor->crtc_h = crtc_h; 179 cursor->w = w; 180 cursor->h = h; 181 182 cursor->enabled = 0; 183 cursor->x = w/2; 184 cursor->y = h/2; 185 cursor->dx = 1; 186 cursor->dy = 1; 187 188 ncursors++; 189 190 return 0; 191} 192 193int cursor_start(void) 194{ 195 /* setup signal handler to update cursor: */ 196 signal(SIGALRM, run_step); 197 printf("starting cursor\n"); 198 run_step(SIGALRM); 199 return 0; 200} 201 202int cursor_stop(void) 203{ 204 signal(SIGALRM, NULL); 205 printf("cursor stopped\n"); 206 return 0; 207} 208