1 /* 2 * DRM based mode setting test program 3 * Copyright (C) 2013 Red Hat 4 * Author: Rob Clark <robdclark (at) 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 #include <pthread.h> 38 #include <unistd.h> 39 40 #include "xf86drm.h" 41 #include "xf86drmMode.h" 42 43 #include "util/common.h" 44 45 #include "buffers.h" 46 #include "cursor.h" 47 48 struct cursor { 49 int fd; 50 uint32_t bo_handle; 51 uint32_t crtc_id; 52 uint32_t crtc_w, crtc_h; 53 uint32_t w, h; 54 55 /* current state */ 56 uint32_t enabled, x, y; 57 int32_t dx, dy; 58 }; 59 60 #define MAX_CURSORS 8 61 static struct cursor cursors[MAX_CURSORS]; 62 static int ncursors; 63 64 static pthread_t cursor_thread; 65 static int cursor_running; 66 67 /* 68 * Timer driven program loops through these steps to move/enable/disable 69 * the cursor 70 */ 71 72 struct cursor_step { 73 void (*run)(struct cursor *cursor, const struct cursor_step *step); 74 uint32_t msec; 75 uint32_t repeat; 76 int arg; 77 }; 78 79 static uint32_t indx, count; 80 81 static void set_cursor(struct cursor *cursor, const struct cursor_step *step) 82 { 83 int enabled = (step->arg ^ count) & 0x1; 84 uint32_t handle = 0; 85 86 if (enabled) 87 handle = cursor->bo_handle; 88 89 cursor->enabled = enabled; 90 91 drmModeSetCursor(cursor->fd, cursor->crtc_id, handle, cursor->w, cursor->h); 92 } 93 94 static void move_cursor(struct cursor *cursor, const struct cursor_step *step) 95 { 96 int x = cursor->x; 97 int y = cursor->y; 98 99 if (!cursor->enabled) 100 drmModeSetCursor(cursor->fd, cursor->crtc_id, 101 cursor->bo_handle, cursor->w, cursor->h); 102 103 /* calculate new cursor position: */ 104 x += cursor->dx * step->arg; 105 y += cursor->dy * step->arg; 106 107 if (x < 0) { 108 x = 0; 109 cursor->dx = 1; 110 } else if (x > (int)cursor->crtc_w) { 111 x = cursor->crtc_w - 1; 112 cursor->dx = -1; 113 } 114 115 if (y < 0) { 116 y = 0; 117 cursor->dy = 1; 118 } else if (y > (int)cursor->crtc_h) { 119 y = cursor->crtc_h - 1; 120 cursor->dy = -1; 121 } 122 123 cursor->x = x; 124 cursor->y = y; 125 126 drmModeMoveCursor(cursor->fd, cursor->crtc_id, x, y); 127 } 128 129 static const struct cursor_step steps[] = { 130 { set_cursor, 10, 0, 1 }, /* enable */ 131 { move_cursor, 1, 100, 1 }, 132 { move_cursor, 1, 10, 10 }, 133 { set_cursor, 1, 100, 0 }, /* disable/enable loop */ 134 { move_cursor, 1, 10, 10 }, 135 { move_cursor, 9, 100, 1 }, 136 { move_cursor, 11, 100, 5 }, 137 { set_cursor, 17, 10, 0 }, /* disable/enable loop */ 138 { move_cursor, 9, 100, 1 }, 139 { set_cursor, 13, 10, 0 }, /* disable/enable loop */ 140 { move_cursor, 9, 100, 1 }, 141 { set_cursor, 13, 10, 0 }, /* disable/enable loop */ 142 { set_cursor, 10, 0, 0 }, /* disable */ 143 }; 144 145 static void *cursor_thread_func(void *data) 146 { 147 while (cursor_running) { 148 const struct cursor_step *step = &steps[indx % ARRAY_SIZE(steps)]; 149 int i; 150 151 for (i = 0; i < ncursors; i++) { 152 struct cursor *cursor = &cursors[i]; 153 step->run(cursor, step); 154 } 155 156 /* iterate to next count/step: */ 157 if (count < step->repeat) { 158 count++; 159 } else { 160 count = 0; 161 indx++; 162 } 163 164 usleep(1000 * step->msec); 165 } 166 167 return NULL; 168 } 169 170 int cursor_init(int fd, uint32_t bo_handle, uint32_t crtc_id, 171 uint32_t crtc_w, uint32_t crtc_h, uint32_t w, uint32_t h) 172 { 173 struct cursor *cursor = &cursors[ncursors]; 174 175 assert(ncursors < MAX_CURSORS); 176 177 cursor->fd = fd; 178 cursor->bo_handle = bo_handle; 179 cursor->crtc_id = crtc_id; 180 cursor->crtc_w = crtc_w; 181 cursor->crtc_h = crtc_h; 182 cursor->w = w; 183 cursor->h = h; 184 185 cursor->enabled = 0; 186 cursor->x = w/2; 187 cursor->y = h/2; 188 cursor->dx = 1; 189 cursor->dy = 1; 190 191 ncursors++; 192 193 return 0; 194 } 195 196 int cursor_start(void) 197 { 198 cursor_running = 1; 199 pthread_create(&cursor_thread, NULL, cursor_thread_func, NULL); 200 printf("starting cursor\n"); 201 return 0; 202 } 203 204 int cursor_stop(void) 205 { 206 cursor_running = 0; 207 pthread_join(cursor_thread, NULL); 208 printf("cursor stopped\n"); 209 return 0; 210 } 211