cursor.c revision baaff307
1857b0bc6Smrg/* 2857b0bc6Smrg * DRM based mode setting test program 3857b0bc6Smrg * Copyright (C) 2013 Red Hat 4857b0bc6Smrg * Author: Rob Clark <robdclark@gmail.com> 5857b0bc6Smrg * 6857b0bc6Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7857b0bc6Smrg * copy of this software and associated documentation files (the "Software"), 8857b0bc6Smrg * to deal in the Software without restriction, including without limitation 9857b0bc6Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10857b0bc6Smrg * and/or sell copies of the Software, and to permit persons to whom the 11857b0bc6Smrg * Software is furnished to do so, subject to the following conditions: 12857b0bc6Smrg * 13857b0bc6Smrg * The above copyright notice and this permission notice shall be included in 14857b0bc6Smrg * all copies or substantial portions of the Software. 15857b0bc6Smrg * 16857b0bc6Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17857b0bc6Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18857b0bc6Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19857b0bc6Smrg * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20857b0bc6Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21857b0bc6Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22857b0bc6Smrg * IN THE SOFTWARE. 23857b0bc6Smrg */ 24857b0bc6Smrg 25baaff307Smrg#ifdef HAVE_CONFIG_H 26857b0bc6Smrg#include "config.h" 27baaff307Smrg#endif 28857b0bc6Smrg 29857b0bc6Smrg#include <assert.h> 30857b0bc6Smrg#include <errno.h> 31857b0bc6Smrg#include <stdio.h> 32857b0bc6Smrg#include <stdlib.h> 33857b0bc6Smrg#include <stdint.h> 34857b0bc6Smrg#include <string.h> 35857b0bc6Smrg#include <signal.h> 36857b0bc6Smrg#include <sys/time.h> 37857b0bc6Smrg 38857b0bc6Smrg#include "xf86drm.h" 39857b0bc6Smrg#include "xf86drmMode.h" 40857b0bc6Smrg 41857b0bc6Smrg#include "buffers.h" 42857b0bc6Smrg#include "cursor.h" 43857b0bc6Smrg 44857b0bc6Smrg#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 45857b0bc6Smrg 46857b0bc6Smrgstruct cursor { 47857b0bc6Smrg int fd; 48857b0bc6Smrg uint32_t bo_handle; 49857b0bc6Smrg uint32_t crtc_id; 50857b0bc6Smrg uint32_t crtc_w, crtc_h; 51857b0bc6Smrg uint32_t w, h; 52857b0bc6Smrg 53857b0bc6Smrg /* current state */ 54857b0bc6Smrg uint32_t enabled, x, y; 55857b0bc6Smrg int32_t dx, dy; 56857b0bc6Smrg}; 57857b0bc6Smrg 58857b0bc6Smrg#define MAX_CURSORS 8 59857b0bc6Smrgstatic struct cursor cursors[MAX_CURSORS]; 60857b0bc6Smrgstatic int ncursors; 61857b0bc6Smrg 62857b0bc6Smrg/* 63857b0bc6Smrg * Timer driven program loops through these steps to move/enable/disable 64857b0bc6Smrg * the cursor 65857b0bc6Smrg */ 66857b0bc6Smrg 67857b0bc6Smrgstruct cursor_step { 68857b0bc6Smrg void (*run)(struct cursor *cursor, struct cursor_step *step); 69857b0bc6Smrg uint32_t msec; 70857b0bc6Smrg uint32_t repeat; 71857b0bc6Smrg int arg; 72857b0bc6Smrg}; 73857b0bc6Smrg 74857b0bc6Smrgstatic uint32_t indx, count; 75857b0bc6Smrg 76857b0bc6Smrgstatic void set_cursor(struct cursor *cursor, struct cursor_step *step) 77857b0bc6Smrg{ 78857b0bc6Smrg int enabled = (step->arg ^ count) & 0x1; 79857b0bc6Smrg uint32_t handle = 0; 80857b0bc6Smrg 81857b0bc6Smrg if (enabled) 82857b0bc6Smrg handle = cursor->bo_handle; 83857b0bc6Smrg 84857b0bc6Smrg cursor->enabled = enabled; 85857b0bc6Smrg 86857b0bc6Smrg drmModeSetCursor(cursor->fd, cursor->crtc_id, handle, cursor->w, cursor->h); 87857b0bc6Smrg} 88857b0bc6Smrg 89857b0bc6Smrgstatic void move_cursor(struct cursor *cursor, struct cursor_step *step) 90857b0bc6Smrg{ 91857b0bc6Smrg int x = cursor->x; 92857b0bc6Smrg int y = cursor->y; 93857b0bc6Smrg 94857b0bc6Smrg if (!cursor->enabled) 95857b0bc6Smrg drmModeSetCursor(cursor->fd, cursor->crtc_id, 96857b0bc6Smrg cursor->bo_handle, cursor->w, cursor->h); 97857b0bc6Smrg 98857b0bc6Smrg /* calculate new cursor position: */ 99857b0bc6Smrg x += cursor->dx * step->arg; 100857b0bc6Smrg y += cursor->dy * step->arg; 101857b0bc6Smrg 102857b0bc6Smrg if (x < 0) { 103857b0bc6Smrg x = 0; 104857b0bc6Smrg cursor->dx = 1; 105857b0bc6Smrg } else if (x > (int)cursor->crtc_w) { 106857b0bc6Smrg x = cursor->crtc_w - 1; 107857b0bc6Smrg cursor->dx = -1; 108857b0bc6Smrg } 109857b0bc6Smrg 110857b0bc6Smrg if (y < 0) { 111857b0bc6Smrg y = 0; 112857b0bc6Smrg cursor->dy = 1; 113857b0bc6Smrg } else if (y > (int)cursor->crtc_h) { 114857b0bc6Smrg y = cursor->crtc_h - 1; 115857b0bc6Smrg cursor->dy = -1; 116857b0bc6Smrg } 117857b0bc6Smrg 118857b0bc6Smrg cursor->x = x; 119857b0bc6Smrg cursor->y = y; 120857b0bc6Smrg 121857b0bc6Smrg drmModeMoveCursor(cursor->fd, cursor->crtc_id, x, y); 122857b0bc6Smrg} 123857b0bc6Smrg 124857b0bc6Smrgstatic struct cursor_step steps[] = { 125857b0bc6Smrg { set_cursor, 10, 0, 1 }, /* enable */ 126857b0bc6Smrg { move_cursor, 1, 100, 1 }, 127857b0bc6Smrg { move_cursor, 1, 10, 10 }, 128857b0bc6Smrg { set_cursor, 1, 100, 0 }, /* disable/enable loop */ 129857b0bc6Smrg { move_cursor, 1, 10, 10 }, 130857b0bc6Smrg { move_cursor, 9, 100, 1 }, 131857b0bc6Smrg { move_cursor, 11, 100, 5 }, 132857b0bc6Smrg { set_cursor, 17, 10, 0 }, /* disable/enable loop */ 133857b0bc6Smrg { move_cursor, 9, 100, 1 }, 134857b0bc6Smrg { set_cursor, 13, 10, 0 }, /* disable/enable loop */ 135857b0bc6Smrg { move_cursor, 9, 100, 1 }, 136857b0bc6Smrg { set_cursor, 13, 10, 0 }, /* disable/enable loop */ 137857b0bc6Smrg { set_cursor, 10, 0, 0 }, /* disable */ 138857b0bc6Smrg}; 139857b0bc6Smrg 140857b0bc6Smrg/* 141857b0bc6Smrg * Cursor API: 142857b0bc6Smrg */ 143857b0bc6Smrg 144857b0bc6Smrgstatic void run_step(int sig) 145857b0bc6Smrg{ 146857b0bc6Smrg struct cursor_step *step = &steps[indx % ARRAY_SIZE(steps)]; 147857b0bc6Smrg struct itimerval itimer = { 148857b0bc6Smrg .it_value.tv_usec = 1000 * step->msec, 149857b0bc6Smrg }; 150857b0bc6Smrg int i; 151857b0bc6Smrg 152857b0bc6Smrg for (i = 0; i < ncursors; i++) { 153857b0bc6Smrg struct cursor *cursor = &cursors[i]; 154857b0bc6Smrg step->run(cursor, step); 155857b0bc6Smrg } 156857b0bc6Smrg 157857b0bc6Smrg /* iterate to next count/step: */ 158857b0bc6Smrg if (count < step->repeat) { 159857b0bc6Smrg count++; 160857b0bc6Smrg } else { 161857b0bc6Smrg count = 0; 162857b0bc6Smrg indx++; 163857b0bc6Smrg } 164857b0bc6Smrg 165857b0bc6Smrg /* and lastly, setup timer for next step */ 166857b0bc6Smrg setitimer(ITIMER_REAL, &itimer, NULL); 167857b0bc6Smrg} 168857b0bc6Smrg 169857b0bc6Smrgint cursor_init(int fd, uint32_t bo_handle, uint32_t crtc_id, 170857b0bc6Smrg uint32_t crtc_w, uint32_t crtc_h, uint32_t w, uint32_t h) 171857b0bc6Smrg{ 172857b0bc6Smrg struct cursor *cursor = &cursors[ncursors]; 173857b0bc6Smrg 174857b0bc6Smrg assert(ncursors < MAX_CURSORS); 175857b0bc6Smrg 176857b0bc6Smrg cursor->fd = fd; 177857b0bc6Smrg cursor->bo_handle = bo_handle; 178857b0bc6Smrg cursor->crtc_id = crtc_id; 179857b0bc6Smrg cursor->crtc_w = crtc_w; 180857b0bc6Smrg cursor->crtc_h = crtc_h; 181857b0bc6Smrg cursor->w = w; 182857b0bc6Smrg cursor->h = h; 183857b0bc6Smrg 184857b0bc6Smrg cursor->enabled = 0; 185857b0bc6Smrg cursor->x = w/2; 186857b0bc6Smrg cursor->y = h/2; 187857b0bc6Smrg cursor->dx = 1; 188857b0bc6Smrg cursor->dy = 1; 189857b0bc6Smrg 190857b0bc6Smrg ncursors++; 191857b0bc6Smrg 192857b0bc6Smrg return 0; 193857b0bc6Smrg} 194857b0bc6Smrg 195857b0bc6Smrgint cursor_start(void) 196857b0bc6Smrg{ 197857b0bc6Smrg /* setup signal handler to update cursor: */ 198857b0bc6Smrg signal(SIGALRM, run_step); 199857b0bc6Smrg printf("starting cursor\n"); 200857b0bc6Smrg run_step(SIGALRM); 201857b0bc6Smrg return 0; 202857b0bc6Smrg} 203857b0bc6Smrg 204857b0bc6Smrgint cursor_stop(void) 205857b0bc6Smrg{ 206857b0bc6Smrg signal(SIGALRM, NULL); 207857b0bc6Smrg printf("cursor stopped\n"); 208857b0bc6Smrg return 0; 209857b0bc6Smrg} 210