cursor.c 4.8 KB

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