cursor.c revision 857b0bc6
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 25857b0bc6Smrg#include "config.h" 26857b0bc6Smrg 27857b0bc6Smrg#include <assert.h> 28857b0bc6Smrg#include <errno.h> 29857b0bc6Smrg#include <stdio.h> 30857b0bc6Smrg#include <stdlib.h> 31857b0bc6Smrg#include <stdint.h> 32857b0bc6Smrg#include <string.h> 33857b0bc6Smrg#include <signal.h> 34857b0bc6Smrg#include <sys/time.h> 35857b0bc6Smrg 36857b0bc6Smrg#include "xf86drm.h" 37857b0bc6Smrg#include "xf86drmMode.h" 38857b0bc6Smrg 39857b0bc6Smrg#include "buffers.h" 40857b0bc6Smrg#include "cursor.h" 41857b0bc6Smrg 42857b0bc6Smrg#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 43857b0bc6Smrg 44857b0bc6Smrgstruct cursor { 45857b0bc6Smrg int fd; 46857b0bc6Smrg uint32_t bo_handle; 47857b0bc6Smrg uint32_t crtc_id; 48857b0bc6Smrg uint32_t crtc_w, crtc_h; 49857b0bc6Smrg uint32_t w, h; 50857b0bc6Smrg 51857b0bc6Smrg /* current state */ 52857b0bc6Smrg uint32_t enabled, x, y; 53857b0bc6Smrg int32_t dx, dy; 54857b0bc6Smrg}; 55857b0bc6Smrg 56857b0bc6Smrg#define MAX_CURSORS 8 57857b0bc6Smrgstatic struct cursor cursors[MAX_CURSORS]; 58857b0bc6Smrgstatic int ncursors; 59857b0bc6Smrg 60857b0bc6Smrg/* 61857b0bc6Smrg * Timer driven program loops through these steps to move/enable/disable 62857b0bc6Smrg * the cursor 63857b0bc6Smrg */ 64857b0bc6Smrg 65857b0bc6Smrgstruct cursor_step { 66857b0bc6Smrg void (*run)(struct cursor *cursor, struct cursor_step *step); 67857b0bc6Smrg uint32_t msec; 68857b0bc6Smrg uint32_t repeat; 69857b0bc6Smrg int arg; 70857b0bc6Smrg}; 71857b0bc6Smrg 72857b0bc6Smrgstatic uint32_t indx, count; 73857b0bc6Smrg 74857b0bc6Smrgstatic void set_cursor(struct cursor *cursor, struct cursor_step *step) 75857b0bc6Smrg{ 76857b0bc6Smrg int enabled = (step->arg ^ count) & 0x1; 77857b0bc6Smrg uint32_t handle = 0; 78857b0bc6Smrg 79857b0bc6Smrg if (enabled) 80857b0bc6Smrg handle = cursor->bo_handle; 81857b0bc6Smrg 82857b0bc6Smrg cursor->enabled = enabled; 83857b0bc6Smrg 84857b0bc6Smrg drmModeSetCursor(cursor->fd, cursor->crtc_id, handle, cursor->w, cursor->h); 85857b0bc6Smrg} 86857b0bc6Smrg 87857b0bc6Smrgstatic void move_cursor(struct cursor *cursor, struct cursor_step *step) 88857b0bc6Smrg{ 89857b0bc6Smrg int x = cursor->x; 90857b0bc6Smrg int y = cursor->y; 91857b0bc6Smrg 92857b0bc6Smrg if (!cursor->enabled) 93857b0bc6Smrg drmModeSetCursor(cursor->fd, cursor->crtc_id, 94857b0bc6Smrg cursor->bo_handle, cursor->w, cursor->h); 95857b0bc6Smrg 96857b0bc6Smrg /* calculate new cursor position: */ 97857b0bc6Smrg x += cursor->dx * step->arg; 98857b0bc6Smrg y += cursor->dy * step->arg; 99857b0bc6Smrg 100857b0bc6Smrg if (x < 0) { 101857b0bc6Smrg x = 0; 102857b0bc6Smrg cursor->dx = 1; 103857b0bc6Smrg } else if (x > (int)cursor->crtc_w) { 104857b0bc6Smrg x = cursor->crtc_w - 1; 105857b0bc6Smrg cursor->dx = -1; 106857b0bc6Smrg } 107857b0bc6Smrg 108857b0bc6Smrg if (y < 0) { 109857b0bc6Smrg y = 0; 110857b0bc6Smrg cursor->dy = 1; 111857b0bc6Smrg } else if (y > (int)cursor->crtc_h) { 112857b0bc6Smrg y = cursor->crtc_h - 1; 113857b0bc6Smrg cursor->dy = -1; 114857b0bc6Smrg } 115857b0bc6Smrg 116857b0bc6Smrg cursor->x = x; 117857b0bc6Smrg cursor->y = y; 118857b0bc6Smrg 119857b0bc6Smrg drmModeMoveCursor(cursor->fd, cursor->crtc_id, x, y); 120857b0bc6Smrg} 121857b0bc6Smrg 122857b0bc6Smrgstatic struct cursor_step steps[] = { 123857b0bc6Smrg { set_cursor, 10, 0, 1 }, /* enable */ 124857b0bc6Smrg { move_cursor, 1, 100, 1 }, 125857b0bc6Smrg { move_cursor, 1, 10, 10 }, 126857b0bc6Smrg { set_cursor, 1, 100, 0 }, /* disable/enable loop */ 127857b0bc6Smrg { move_cursor, 1, 10, 10 }, 128857b0bc6Smrg { move_cursor, 9, 100, 1 }, 129857b0bc6Smrg { move_cursor, 11, 100, 5 }, 130857b0bc6Smrg { set_cursor, 17, 10, 0 }, /* disable/enable loop */ 131857b0bc6Smrg { move_cursor, 9, 100, 1 }, 132857b0bc6Smrg { set_cursor, 13, 10, 0 }, /* disable/enable loop */ 133857b0bc6Smrg { move_cursor, 9, 100, 1 }, 134857b0bc6Smrg { set_cursor, 13, 10, 0 }, /* disable/enable loop */ 135857b0bc6Smrg { set_cursor, 10, 0, 0 }, /* disable */ 136857b0bc6Smrg}; 137857b0bc6Smrg 138857b0bc6Smrg/* 139857b0bc6Smrg * Cursor API: 140857b0bc6Smrg */ 141857b0bc6Smrg 142857b0bc6Smrgstatic void run_step(int sig) 143857b0bc6Smrg{ 144857b0bc6Smrg struct cursor_step *step = &steps[indx % ARRAY_SIZE(steps)]; 145857b0bc6Smrg struct itimerval itimer = { 146857b0bc6Smrg .it_value.tv_usec = 1000 * step->msec, 147857b0bc6Smrg }; 148857b0bc6Smrg int i; 149857b0bc6Smrg 150857b0bc6Smrg for (i = 0; i < ncursors; i++) { 151857b0bc6Smrg struct cursor *cursor = &cursors[i]; 152857b0bc6Smrg step->run(cursor, step); 153857b0bc6Smrg } 154857b0bc6Smrg 155857b0bc6Smrg /* iterate to next count/step: */ 156857b0bc6Smrg if (count < step->repeat) { 157857b0bc6Smrg count++; 158857b0bc6Smrg } else { 159857b0bc6Smrg count = 0; 160857b0bc6Smrg indx++; 161857b0bc6Smrg } 162857b0bc6Smrg 163857b0bc6Smrg /* and lastly, setup timer for next step */ 164857b0bc6Smrg setitimer(ITIMER_REAL, &itimer, NULL); 165857b0bc6Smrg} 166857b0bc6Smrg 167857b0bc6Smrgint cursor_init(int fd, uint32_t bo_handle, uint32_t crtc_id, 168857b0bc6Smrg uint32_t crtc_w, uint32_t crtc_h, uint32_t w, uint32_t h) 169857b0bc6Smrg{ 170857b0bc6Smrg struct cursor *cursor = &cursors[ncursors]; 171857b0bc6Smrg 172857b0bc6Smrg assert(ncursors < MAX_CURSORS); 173857b0bc6Smrg 174857b0bc6Smrg cursor->fd = fd; 175857b0bc6Smrg cursor->bo_handle = bo_handle; 176857b0bc6Smrg cursor->crtc_id = crtc_id; 177857b0bc6Smrg cursor->crtc_w = crtc_w; 178857b0bc6Smrg cursor->crtc_h = crtc_h; 179857b0bc6Smrg cursor->w = w; 180857b0bc6Smrg cursor->h = h; 181857b0bc6Smrg 182857b0bc6Smrg cursor->enabled = 0; 183857b0bc6Smrg cursor->x = w/2; 184857b0bc6Smrg cursor->y = h/2; 185857b0bc6Smrg cursor->dx = 1; 186857b0bc6Smrg cursor->dy = 1; 187857b0bc6Smrg 188857b0bc6Smrg ncursors++; 189857b0bc6Smrg 190857b0bc6Smrg return 0; 191857b0bc6Smrg} 192857b0bc6Smrg 193857b0bc6Smrgint cursor_start(void) 194857b0bc6Smrg{ 195857b0bc6Smrg /* setup signal handler to update cursor: */ 196857b0bc6Smrg signal(SIGALRM, run_step); 197857b0bc6Smrg printf("starting cursor\n"); 198857b0bc6Smrg run_step(SIGALRM); 199857b0bc6Smrg return 0; 200857b0bc6Smrg} 201857b0bc6Smrg 202857b0bc6Smrgint cursor_stop(void) 203857b0bc6Smrg{ 204857b0bc6Smrg signal(SIGALRM, NULL); 205857b0bc6Smrg printf("cursor stopped\n"); 206857b0bc6Smrg return 0; 207857b0bc6Smrg} 208