present_fake.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. * Copyright © 2013 Keith Packard
  3. *
  4. * Permission to use, copy, modify, distribute, and sell this software and its
  5. * documentation for any purpose is hereby granted without fee, provided that
  6. * the above copyright notice appear in all copies and that both that copyright
  7. * notice and this permission notice appear in supporting documentation, and
  8. * that the name of the copyright holders not be used in advertising or
  9. * publicity pertaining to distribution of the software without specific,
  10. * written prior permission. The copyright holders make no representations
  11. * about the suitability of this software for any purpose. It is provided "as
  12. * is" without express or implied warranty.
  13. *
  14. * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15. * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  16. * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18. * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  19. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  20. * OF THIS SOFTWARE.
  21. */
  22. #ifdef HAVE_XORG_CONFIG_H
  23. #include <xorg-config.h>
  24. #endif
  25. #include "present_priv.h"
  26. #include "list.h"
  27. static struct xorg_list fake_vblank_queue;
  28. typedef struct present_fake_vblank {
  29. struct xorg_list list;
  30. uint64_t event_id;
  31. OsTimerPtr timer;
  32. ScreenPtr screen;
  33. } present_fake_vblank_rec, *present_fake_vblank_ptr;
  34. int
  35. present_fake_get_ust_msc(ScreenPtr screen, uint64_t *ust, uint64_t *msc)
  36. {
  37. present_screen_priv_ptr screen_priv = present_screen_priv(screen);
  38. *ust = GetTimeInMicros();
  39. *msc = (*ust + screen_priv->fake_interval / 2) / screen_priv->fake_interval;
  40. return Success;
  41. }
  42. static void
  43. present_fake_notify(ScreenPtr screen, uint64_t event_id)
  44. {
  45. uint64_t ust, msc;
  46. present_fake_get_ust_msc(screen, &ust, &msc);
  47. present_event_notify(event_id, ust, msc);
  48. }
  49. static CARD32
  50. present_fake_do_timer(OsTimerPtr timer,
  51. CARD32 time,
  52. void *arg)
  53. {
  54. present_fake_vblank_ptr fake_vblank = arg;
  55. present_fake_notify(fake_vblank->screen, fake_vblank->event_id);
  56. xorg_list_del(&fake_vblank->list);
  57. free(fake_vblank);
  58. return 0;
  59. }
  60. void
  61. present_fake_abort_vblank(ScreenPtr screen, uint64_t event_id, uint64_t msc)
  62. {
  63. present_fake_vblank_ptr fake_vblank, tmp;
  64. xorg_list_for_each_entry_safe(fake_vblank, tmp, &fake_vblank_queue, list) {
  65. if (fake_vblank->event_id == event_id) {
  66. TimerCancel(fake_vblank->timer);
  67. xorg_list_del(&fake_vblank->list);
  68. free (fake_vblank);
  69. break;
  70. }
  71. }
  72. }
  73. int
  74. present_fake_queue_vblank(ScreenPtr screen,
  75. uint64_t event_id,
  76. uint64_t msc)
  77. {
  78. present_screen_priv_ptr screen_priv = present_screen_priv(screen);
  79. uint64_t ust = msc * screen_priv->fake_interval;
  80. uint64_t now = GetTimeInMicros();
  81. INT32 delay = ((int64_t) (ust - now)) / 1000;
  82. present_fake_vblank_ptr fake_vblank;
  83. if (delay <= 0) {
  84. present_fake_notify(screen, event_id);
  85. return Success;
  86. }
  87. fake_vblank = calloc (1, sizeof (present_fake_vblank_rec));
  88. if (!fake_vblank)
  89. return BadAlloc;
  90. fake_vblank->screen = screen;
  91. fake_vblank->event_id = event_id;
  92. fake_vblank->timer = TimerSet(NULL, 0, delay, present_fake_do_timer, fake_vblank);
  93. if (!fake_vblank->timer) {
  94. free(fake_vblank);
  95. return BadAlloc;
  96. }
  97. xorg_list_add(&fake_vblank->list, &fake_vblank_queue);
  98. return Success;
  99. }
  100. void
  101. present_fake_screen_init(ScreenPtr screen)
  102. {
  103. present_screen_priv_ptr screen_priv = present_screen_priv(screen);
  104. /* For screens with hardware vblank support, the fake code
  105. * will be used for off-screen windows and while screens are blanked,
  106. * in which case we want a slow interval here
  107. *
  108. * Otherwise, pretend that the screen runs at 60Hz
  109. */
  110. if (screen_priv->info && screen_priv->info->get_crtc)
  111. screen_priv->fake_interval = 1000000;
  112. else
  113. screen_priv->fake_interval = 16667;
  114. }
  115. void
  116. present_fake_queue_init(void)
  117. {
  118. xorg_list_init(&fake_vblank_queue);
  119. }