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