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 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 60static pthread_t cursor_thread; 61static int cursor_running; 62 63/* 64 * Timer driven program loops through these steps to move/enable/disable 65 * the cursor 66 */ 67 68struct 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 75static uint32_t indx, count; 76 77static 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 90static 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 125static 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 141static 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 166int 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 192int 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 200int cursor_stop(void) 201{ 202 cursor_running = 0; 203 pthread_join(cursor_thread, NULL); 204 printf("cursor stopped\n"); 205 return 0; 206} 207