cursor.c revision 29bb4c6911b21c026c3863799dcbeaa29981bf7e
10e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark/* 20e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * DRM based mode setting test program 30e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * Copyright (C) 2013 Red Hat 40e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * Author: Rob Clark <robdclark@gmail.com> 50e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * 60e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * Permission is hereby granted, free of charge, to any person obtaining a 70e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * copy of this software and associated documentation files (the "Software"), 80e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * to deal in the Software without restriction, including without limitation 90e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * the rights to use, copy, modify, merge, publish, distribute, sublicense, 100e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * and/or sell copies of the Software, and to permit persons to whom the 110e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * Software is furnished to do so, subject to the following conditions: 120e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * 130e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * The above copyright notice and this permission notice shall be included in 140e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * all copies or substantial portions of the Software. 150e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * 160e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 170e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 180e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 190e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 200e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 210e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 220e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * IN THE SOFTWARE. 230e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark */ 240e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 258e93afc9765f1de613c65a76e9a86e17db96e653Emil Velikov#ifdef HAVE_CONFIG_H 260e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark#include "config.h" 278e93afc9765f1de613c65a76e9a86e17db96e653Emil Velikov#endif 280e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 290e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark#include <assert.h> 300e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark#include <errno.h> 310e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark#include <stdio.h> 320e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark#include <stdlib.h> 330e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark#include <stdint.h> 340e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark#include <string.h> 350e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark#include <signal.h> 360e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark#include <sys/time.h> 3729bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre#include <pthread.h> 3829bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre#include <unistd.h> 390e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 400e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark#include "xf86drm.h" 410e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark#include "xf86drmMode.h" 420e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 430e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark#include "buffers.h" 440e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark#include "cursor.h" 450e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 460e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 470e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 480e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clarkstruct cursor { 490e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark int fd; 500e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark uint32_t bo_handle; 510e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark uint32_t crtc_id; 520e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark uint32_t crtc_w, crtc_h; 530e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark uint32_t w, h; 540e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 550e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark /* current state */ 560e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark uint32_t enabled, x, y; 570e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark int32_t dx, dy; 580e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark}; 590e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 600e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark#define MAX_CURSORS 8 610e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clarkstatic struct cursor cursors[MAX_CURSORS]; 620e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clarkstatic int ncursors; 630e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 6429bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierrestatic pthread_t cursor_thread; 6529bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierrestatic int cursor_running; 6629bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre 670e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark/* 680e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * Timer driven program loops through these steps to move/enable/disable 690e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark * the cursor 700e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark */ 710e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 720e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clarkstruct cursor_step { 730e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark void (*run)(struct cursor *cursor, struct cursor_step *step); 740e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark uint32_t msec; 750e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark uint32_t repeat; 760e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark int arg; 770e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark}; 780e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 790e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clarkstatic uint32_t indx, count; 800e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 810e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clarkstatic void set_cursor(struct cursor *cursor, struct cursor_step *step) 820e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark{ 830e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark int enabled = (step->arg ^ count) & 0x1; 840e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark uint32_t handle = 0; 850e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 860e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark if (enabled) 870e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark handle = cursor->bo_handle; 880e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 890e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark cursor->enabled = enabled; 900e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 910e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark drmModeSetCursor(cursor->fd, cursor->crtc_id, handle, cursor->w, cursor->h); 920e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark} 930e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 940e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clarkstatic void move_cursor(struct cursor *cursor, struct cursor_step *step) 950e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark{ 960e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark int x = cursor->x; 970e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark int y = cursor->y; 980e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 990e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark if (!cursor->enabled) 1000e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark drmModeSetCursor(cursor->fd, cursor->crtc_id, 1010e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark cursor->bo_handle, cursor->w, cursor->h); 1020e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 1030e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark /* calculate new cursor position: */ 1040e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark x += cursor->dx * step->arg; 1050e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark y += cursor->dy * step->arg; 1060e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 1070e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark if (x < 0) { 1080e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark x = 0; 1090e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark cursor->dx = 1; 1100e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark } else if (x > (int)cursor->crtc_w) { 1110e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark x = cursor->crtc_w - 1; 1120e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark cursor->dx = -1; 1130e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark } 1140e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 1150e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark if (y < 0) { 1160e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark y = 0; 1170e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark cursor->dy = 1; 1180e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark } else if (y > (int)cursor->crtc_h) { 1190e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark y = cursor->crtc_h - 1; 1200e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark cursor->dy = -1; 1210e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark } 1220e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 1230e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark cursor->x = x; 1240e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark cursor->y = y; 1250e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 1260e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark drmModeMoveCursor(cursor->fd, cursor->crtc_id, x, y); 1270e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark} 1280e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 1290e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clarkstatic struct cursor_step steps[] = { 1300e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark { set_cursor, 10, 0, 1 }, /* enable */ 1310e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark { move_cursor, 1, 100, 1 }, 1320e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark { move_cursor, 1, 10, 10 }, 1330e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark { set_cursor, 1, 100, 0 }, /* disable/enable loop */ 1340e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark { move_cursor, 1, 10, 10 }, 1350e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark { move_cursor, 9, 100, 1 }, 1360e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark { move_cursor, 11, 100, 5 }, 1370e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark { set_cursor, 17, 10, 0 }, /* disable/enable loop */ 1380e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark { move_cursor, 9, 100, 1 }, 1390e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark { set_cursor, 13, 10, 0 }, /* disable/enable loop */ 1400e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark { move_cursor, 9, 100, 1 }, 1410e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark { set_cursor, 13, 10, 0 }, /* disable/enable loop */ 1420e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark { set_cursor, 10, 0, 0 }, /* disable */ 1430e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark}; 1440e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 14529bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierrestatic void *cursor_thread_func(void *data) 1460e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark{ 14729bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre while (cursor_running) { 14829bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre struct cursor_step *step = &steps[indx % ARRAY_SIZE(steps)]; 14929bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre int i; 15029bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre 15129bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre for (i = 0; i < ncursors; i++) { 15229bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre struct cursor *cursor = &cursors[i]; 15329bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre step->run(cursor, step); 15429bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre } 15529bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre 15629bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre /* iterate to next count/step: */ 15729bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre if (count < step->repeat) { 15829bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre count++; 15929bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre } else { 16029bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre count = 0; 16129bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre indx++; 16229bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre } 16329bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre 16429bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre usleep(1000 * step->msec); 1650e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark } 1660e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 16729bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre return NULL; 1680e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark} 1690e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 1700e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clarkint cursor_init(int fd, uint32_t bo_handle, uint32_t crtc_id, 1710e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark uint32_t crtc_w, uint32_t crtc_h, uint32_t w, uint32_t h) 1720e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark{ 1730e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark struct cursor *cursor = &cursors[ncursors]; 1740e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 1750e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark assert(ncursors < MAX_CURSORS); 1760e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 1770e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark cursor->fd = fd; 1780e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark cursor->bo_handle = bo_handle; 1790e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark cursor->crtc_id = crtc_id; 1800e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark cursor->crtc_w = crtc_w; 1810e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark cursor->crtc_h = crtc_h; 1820e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark cursor->w = w; 1830e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark cursor->h = h; 1840e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 1850e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark cursor->enabled = 0; 1860e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark cursor->x = w/2; 1870e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark cursor->y = h/2; 1880e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark cursor->dx = 1; 1890e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark cursor->dy = 1; 1900e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 1910e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark ncursors++; 1920e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 1930e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark return 0; 1940e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark} 1950e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 1960e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clarkint cursor_start(void) 1970e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark{ 19829bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre cursor_running = 1; 19929bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre pthread_create(&cursor_thread, NULL, cursor_thread_func, NULL); 2000e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark printf("starting cursor\n"); 2010e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark return 0; 2020e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark} 2030e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark 2040e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clarkint cursor_stop(void) 2050e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark{ 20629bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre cursor_running = 0; 20729bb4c6911b21c026c3863799dcbeaa29981bf7eJasper St. Pierre pthread_join(cursor_thread, NULL); 2080e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark printf("cursor stopped\n"); 2090e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark return 0; 2100e512794bf6281edfa4543ae7cc408d52ec6e2f3Rob Clark} 211