2 * Copyright © 2013 Keith Packard
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.
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
23 #ifdef HAVE_XORG_CONFIG_H
24 #include <xorg-config.h>
27 #include "present_priv.h"
30 #include <misyncstr.h>
31 #ifdef MONOTONIC_CLOCK
35 static uint64_t present_event_id
;
36 static struct xorg_list present_exec_queue
;
37 static struct xorg_list present_flip_queue
;
40 #define DebugPresent(x) ErrorF x
42 #define DebugPresent(x)
46 * Copies the update region from a pixmap to the target drawable
49 present_copy_region(DrawablePtr drawable
,
55 ScreenPtr screen
= drawable
->pScreen
;
58 gc
= GetScratchGC(drawable
->depth
, screen
);
60 ChangeGCVal changes
[2];
62 changes
[0].val
= x_off
;
63 changes
[1].val
= y_off
;
64 ChangeGC(serverClient
, gc
,
65 GCClipXOrigin
|GCClipYOrigin
,
67 (*gc
->funcs
->ChangeClip
)(gc
, CT_REGION
, update
, 0);
69 ValidateGC(drawable
, gc
);
70 (*gc
->ops
->CopyArea
)(&pixmap
->drawable
,
74 pixmap
->drawable
.width
, pixmap
->drawable
.height
,
77 (*gc
->funcs
->ChangeClip
)(gc
, CT_NONE
, NULL
, 0);
82 present_check_flip(RRCrtcPtr crtc
,
90 ScreenPtr screen
= window
->drawable
.pScreen
;
91 WindowPtr root
= screen
->root
;
92 present_screen_priv_ptr screen_priv
= present_screen_priv(screen
);
97 if (!screen_priv
->info
)
103 /* Check to see if the driver supports flips at all */
104 if (!screen_priv
->info
->flip
)
107 /* Can't pend a flip while unflipping */
108 if (screen_priv
->unflip_event_id
) {
112 /* Can't have two pending flips at the same time */
113 if (screen_priv
->flip_pending
) {
117 /* Make sure the window hasn't been redirected with Composite */
118 if (screen
->GetWindowPixmap(window
) != screen
->GetScreenPixmap(screen
) &&
119 screen
->GetWindowPixmap(window
) != screen_priv
->flip_pixmap
)
122 /* Check for full-screen window */
123 if (!RegionEqual(&window
->clipList
, &root
->winSize
)) {
127 /* Source pixmap must align with window exactly */
128 if (x_off
|| y_off
) {
132 /* Make sure the area marked as valid fills the screen */
133 if (valid
&& !RegionEqual(valid
, &root
->winSize
)) {
137 /* Does the window match the pixmap exactly? */
138 if (window
->drawable
.x
!= 0 || window
->drawable
.y
!= 0 ||
140 window
->drawable
.x
!= pixmap
->screen_x
|| window
->drawable
.y
!= pixmap
->screen_y
||
142 window
->drawable
.width
!= pixmap
->drawable
.width
||
143 window
->drawable
.height
!= pixmap
->drawable
.height
) {
147 /* Ask the driver for permission */
148 if (screen_priv
->info
->check_flip
) {
149 if (!(*screen_priv
->info
->check_flip
) (crtc
, window
, pixmap
, sync_flip
)) {
158 present_flip(RRCrtcPtr crtc
,
164 ScreenPtr screen
= crtc
->pScreen
;
165 present_screen_priv_ptr screen_priv
= present_screen_priv(screen
);
167 return (*screen_priv
->info
->flip
) (crtc
, event_id
, target_msc
, pixmap
, sync_flip
);
171 present_vblank_notify(present_vblank_ptr vblank
, CARD8 kind
, CARD8 mode
, uint64_t ust
, uint64_t crtc_msc
)
176 present_send_complete_notify(vblank
->window
, kind
, mode
, vblank
->serial
, ust
, crtc_msc
- vblank
->msc_offset
);
177 for (n
= 0; n
< vblank
->num_notifies
; n
++) {
178 WindowPtr window
= vblank
->notifies
[n
].window
;
179 CARD32 serial
= vblank
->notifies
[n
].serial
;
182 present_send_complete_notify(window
, kind
, mode
, serial
, ust
, crtc_msc
- vblank
->msc_offset
);
187 present_pixmap_idle(PixmapPtr pixmap
, WindowPtr window
, CARD32 serial
, struct present_fence
*present_fence
)
190 present_fence_set_triggered(present_fence
);
192 present_send_idle_notify(window
, serial
, pixmap
, present_fence
);
196 present_get_crtc(WindowPtr window
)
198 ScreenPtr screen
= window
->drawable
.pScreen
;
199 present_screen_priv_ptr screen_priv
= present_screen_priv(screen
);
204 if (!screen_priv
->info
)
207 return (*screen_priv
->info
->get_crtc
)(window
);
211 present_query_capabilities(RRCrtcPtr crtc
)
213 present_screen_priv_ptr screen_priv
;
218 screen_priv
= present_screen_priv(crtc
->pScreen
);
223 if (!screen_priv
->info
)
226 return screen_priv
->info
->capabilities
;
230 present_get_ust_msc(WindowPtr window
, RRCrtcPtr crtc
, uint64_t *ust
, uint64_t *msc
)
232 ScreenPtr screen
= window
->drawable
.pScreen
;
233 present_screen_priv_ptr screen_priv
= present_screen_priv(screen
);
236 return present_fake_get_ust_msc(screen
, ust
, msc
);
238 return (*screen_priv
->info
->get_ust_msc
)(crtc
, ust
, msc
);
242 present_flush(WindowPtr window
)
244 ScreenPtr screen
= window
->drawable
.pScreen
;
245 present_screen_priv_ptr screen_priv
= present_screen_priv(screen
);
250 if (!screen_priv
->info
)
253 (*screen_priv
->info
->flush
) (window
);
257 present_queue_vblank(ScreenPtr screen
,
265 ret
= present_fake_queue_vblank(screen
, event_id
, msc
);
268 present_screen_priv_ptr screen_priv
= present_screen_priv(screen
);
269 ret
= (*screen_priv
->info
->queue_vblank
) (crtc
, event_id
, msc
);
275 present_window_to_crtc_msc(WindowPtr window
, RRCrtcPtr crtc
, uint64_t window_msc
, uint64_t new_msc
)
277 present_window_priv_ptr window_priv
= present_get_window_priv(window
, TRUE
);
279 if (crtc
!= window_priv
->crtc
) {
280 uint64_t old_ust
, old_msc
;
282 /* The old CRTC may have been turned off, in which case
283 * we'll just use whatever previous MSC we'd seen from this CRTC
286 if (present_get_ust_msc(window
, window_priv
->crtc
, &old_ust
, &old_msc
) != Success
)
287 old_msc
= window_priv
->msc
;
289 window_priv
->msc_offset
+= new_msc
- old_msc
;
290 window_priv
->crtc
= crtc
;
293 return window_msc
+ window_priv
->msc_offset
;
297 present_flip_idle(ScreenPtr screen
)
299 present_screen_priv_ptr screen_priv
= present_screen_priv(screen
);
301 if (screen_priv
->flip_pixmap
) {
302 present_pixmap_idle(screen_priv
->flip_pixmap
, screen_priv
->flip_window
,
303 screen_priv
->flip_serial
, screen_priv
->flip_idle_fence
);
304 if (screen_priv
->flip_idle_fence
)
305 present_fence_destroy(screen_priv
->flip_idle_fence
);
306 dixDestroyPixmap(screen_priv
->flip_pixmap
, screen_priv
->flip_pixmap
->drawable
.id
);
307 screen_priv
->flip_crtc
= NULL
;
308 screen_priv
->flip_window
= NULL
;
309 screen_priv
->flip_serial
= 0;
310 screen_priv
->flip_pixmap
= NULL
;
311 screen_priv
->flip_idle_fence
= NULL
;
315 struct pixmap_visit
{
321 present_set_tree_pixmap_visit(WindowPtr window
, pointer data
)
323 struct pixmap_visit
*visit
= data
;
324 ScreenPtr screen
= window
->drawable
.pScreen
;
326 if ((*screen
->GetWindowPixmap
)(window
) != visit
->old
)
327 return WT_DONTWALKCHILDREN
;
328 (*screen
->SetWindowPixmap
)(window
, visit
->new);
329 return WT_WALKCHILDREN
;
333 present_set_tree_pixmap(WindowPtr window
, PixmapPtr pixmap
)
335 struct pixmap_visit visit
;
336 ScreenPtr screen
= window
->drawable
.pScreen
;
338 visit
.old
= (*screen
->GetWindowPixmap
)(window
);
340 if (visit
.old
== visit
.new)
342 TraverseTree(window
, present_set_tree_pixmap_visit
, &visit
);
346 present_unflip(ScreenPtr screen
)
348 present_screen_priv_ptr screen_priv
= present_screen_priv(screen
);
350 assert (!screen_priv
->unflip_event_id
);
351 assert (!screen_priv
->flip_pending
);
353 if (screen_priv
->flip_window
)
354 present_set_tree_pixmap(screen_priv
->flip_window
,
355 (*screen
->GetScreenPixmap
)(screen
));
357 present_set_tree_pixmap(screen
->root
, (*screen
->GetScreenPixmap
)(screen
));
359 /* Update the screen pixmap with the current flip pixmap contents
361 if (screen_priv
->flip_pixmap
&& screen_priv
->flip_window
) {
362 present_copy_region(&screen_priv
->flip_window
->drawable
,
363 screen_priv
->flip_pixmap
,
366 screen_priv
->unflip_event_id
= ++present_event_id
;
367 DebugPresent(("u %lld\n", screen_priv
->unflip_event_id
));
368 (*screen_priv
->info
->unflip
) (screen
, screen_priv
->unflip_event_id
);
372 present_execute(present_vblank_ptr vblank
, uint64_t ust
, uint64_t crtc_msc
);
375 present_flip_notify(present_vblank_ptr vblank
, uint64_t ust
, uint64_t crtc_msc
)
377 ScreenPtr screen
= vblank
->screen
;
378 present_screen_priv_ptr screen_priv
= present_screen_priv(screen
);
380 DebugPresent(("\tn %p %8lld: %08lx -> %08lx\n", vblank
, vblank
->target_msc
,
381 vblank
->pixmap
? vblank
->pixmap
->drawable
.id
: 0,
382 vblank
->window
->drawable
.id
));
384 assert (vblank
== screen_priv
->flip_pending
);
386 present_flip_idle(screen
);
388 xorg_list_del(&vblank
->event_queue
);
390 /* Transfer reference for pixmap and fence from vblank to screen_priv */
391 screen_priv
->flip_crtc
= vblank
->crtc
;
392 screen_priv
->flip_window
= vblank
->window
;
393 screen_priv
->flip_serial
= vblank
->serial
;
394 screen_priv
->flip_pixmap
= vblank
->pixmap
;
395 screen_priv
->flip_idle_fence
= vblank
->idle_fence
;
397 vblank
->pixmap
= NULL
;
398 vblank
->idle_fence
= NULL
;
400 screen_priv
->flip_pending
= NULL
;
402 if (vblank
->abort_flip
)
403 present_unflip(screen
);
405 present_vblank_notify(vblank
, PresentCompleteKindPixmap
, PresentCompleteModeFlip
, ust
, crtc_msc
);
406 present_vblank_destroy(vblank
);
410 present_event_notify(uint64_t event_id
, uint64_t ust
, uint64_t msc
)
412 present_vblank_ptr vblank
, tmp
;
417 DebugPresent(("\te %lld ust %lld msc %lld\n", event_id
, ust
, msc
));
418 xorg_list_for_each_entry_safe(vblank
, tmp
, &present_exec_queue
, event_queue
) {
419 if (vblank
->event_id
== event_id
) {
420 present_execute(vblank
, ust
, msc
);
424 xorg_list_for_each_entry_safe(vblank
, tmp
, &present_flip_queue
, event_queue
) {
425 if (vblank
->event_id
== event_id
) {
426 present_flip_notify(vblank
, ust
, msc
);
431 for (s
= 0; s
< screenInfo
.numScreens
; s
++) {
432 ScreenPtr screen
= screenInfo
.screens
[s
];
433 present_screen_priv_ptr screen_priv
= present_screen_priv(screen
);
435 if (event_id
== screen_priv
->unflip_event_id
) {
436 DebugPresent(("\tun %lld\n", event_id
));
437 screen_priv
->unflip_event_id
= 0;
438 present_flip_idle(screen
);
445 * 'window' is being reconfigured. Check to see if it is involved
446 * in flipping and clean up as necessary
449 present_check_flip_window (WindowPtr window
)
451 ScreenPtr screen
= window
->drawable
.pScreen
;
452 present_screen_priv_ptr screen_priv
= present_screen_priv(screen
);
453 present_window_priv_ptr window_priv
= present_window_priv(window
);
454 present_vblank_ptr flip_pending
= screen_priv
->flip_pending
;
455 present_vblank_ptr vblank
;
457 /* If this window hasn't ever been used with Present, it can't be
463 if (screen_priv
->unflip_event_id
)
470 if (flip_pending
->window
== window
) {
471 if (!present_check_flip(flip_pending
->crtc
, window
, flip_pending
->pixmap
,
472 flip_pending
->sync_flip
, NULL
, 0, 0))
473 flip_pending
->abort_flip
= TRUE
;
479 if (window
== screen_priv
->flip_window
) {
480 if (!present_check_flip(screen_priv
->flip_crtc
, window
, screen_priv
->flip_pixmap
, FALSE
, NULL
, 0, 0))
481 present_unflip(screen
);
485 /* Now check any queued vblanks */
486 xorg_list_for_each_entry(vblank
, &window_priv
->vblank
, window_list
) {
487 if (vblank
->queued
&& vblank
->flip
&& !present_check_flip(vblank
->crtc
, window
, vblank
->pixmap
, FALSE
, NULL
, 0, 0))
488 vblank
->flip
= FALSE
;
493 * Called when the wait fence is triggered; just gets the current msc/ust and
494 * calls present_execute again. That will re-check the fence and pend the
495 * request again if it's still not actually ready
498 present_wait_fence_triggered(void *param
)
500 present_vblank_ptr vblank
= param
;
501 WindowPtr window
= vblank
->window
;
502 uint64_t ust
= 0, crtc_msc
= 0;
505 present_window_priv_ptr window_priv
= present_get_window_priv(window
, TRUE
);
507 (void) present_get_ust_msc(window
, window_priv
->crtc
, &ust
, &crtc_msc
);
509 present_execute(vblank
, ust
, crtc_msc
);
513 * Once the required MSC has been reached, execute the pending request.
515 * For requests to actually present something, either blt contents to
516 * the screen or queue a frame buffer swap.
518 * For requests to just get the current MSC/UST combo, skip that part and
519 * go straight to event delivery
523 present_execute(present_vblank_ptr vblank
, uint64_t ust
, uint64_t crtc_msc
)
525 WindowPtr window
= vblank
->window
;
526 ScreenPtr screen
= window
->drawable
.pScreen
;
527 present_screen_priv_ptr screen_priv
= present_screen_priv(screen
);
530 if (vblank
->wait_fence
) {
531 if (!present_fence_check_triggered(vblank
->wait_fence
)) {
532 present_fence_set_callback(vblank
->wait_fence
, present_wait_fence_triggered
, vblank
);
537 xorg_list_del(&vblank
->event_queue
);
538 vblank
->queued
= FALSE
;
540 if (vblank
->pixmap
&& vblank
->window
) {
542 if (vblank
->flip
&& screen_priv
->flip_pending
== NULL
&& !screen_priv
->unflip_event_id
) {
544 DebugPresent(("\tf %p %8lld: %08lx -> %08lx\n", vblank
, crtc_msc
, vblank
->pixmap
->drawable
.id
, vblank
->window
->drawable
.id
));
545 /* Prepare to flip by placing it in the flip queue and
546 * and sticking it into the flip_pending field
548 screen_priv
->flip_pending
= vblank
;
550 xorg_list_add(&vblank
->event_queue
, &present_flip_queue
);
553 if (present_flip(vblank
->crtc
, vblank
->event_id
, vblank
->target_msc
, vblank
->pixmap
, vblank
->sync_flip
)) {
556 /* Fix window pixmaps:
557 * 1) Restore previous flip window pixmap
558 * 2) Set current flip window pixmap to the new pixmap
560 if (screen_priv
->flip_window
&& screen_priv
->flip_window
!= window
)
561 present_set_tree_pixmap(screen_priv
->flip_window
,
562 (*screen
->GetScreenPixmap
)(screen
));
563 present_set_tree_pixmap(vblank
->window
, vblank
->pixmap
);
564 present_set_tree_pixmap(screen
->root
, vblank
->pixmap
);
566 /* Report update region as damaged
568 if (vblank
->update
) {
569 damage
= vblank
->update
;
570 RegionIntersect(damage
, damage
, &window
->clipList
);
572 damage
= &window
->clipList
;
574 DamageDamageRegion(&vblank
->window
->drawable
, damage
);
578 xorg_list_del(&vblank
->event_queue
);
579 /* Oops, flip failed. Clear the flip_pending field
581 screen_priv
->flip_pending
= NULL
;
582 vblank
->flip
= FALSE
;
584 DebugPresent(("\tc %p %8lld: %08lx -> %08lx\n", vblank
, crtc_msc
, vblank
->pixmap
->drawable
.id
, vblank
->window
->drawable
.id
));
585 if (screen_priv
->flip_pending
) {
587 /* Check pending flip
589 if (window
== screen_priv
->flip_pending
->window
)
590 screen_priv
->flip_pending
->abort_flip
= TRUE
;
591 } else if (!screen_priv
->unflip_event_id
) {
593 /* Check current flip
595 if (window
== screen_priv
->flip_window
)
596 present_unflip(screen
);
598 present_copy_region(&window
->drawable
, vblank
->pixmap
, vblank
->update
, vblank
->x_off
, vblank
->y_off
);
600 /* present_copy_region sticks the region into a scratch GC,
601 * which is then freed, freeing the region
603 vblank
->update
= NULL
;
604 present_flush(window
);
606 present_pixmap_idle(vblank
->pixmap
, vblank
->window
, vblank
->serial
, vblank
->idle_fence
);
609 /* Compute correct CompleteMode
611 if (vblank
->kind
== PresentCompleteKindPixmap
) {
612 if (vblank
->pixmap
&& vblank
->window
)
613 mode
= PresentCompleteModeCopy
;
615 mode
= PresentCompleteModeSkip
;
618 mode
= PresentCompleteModeCopy
;
621 present_vblank_notify(vblank
, vblank
->kind
, mode
, ust
, crtc_msc
);
622 present_vblank_destroy(vblank
);
626 present_pixmap(WindowPtr window
,
633 RRCrtcPtr target_crtc
,
634 SyncFence
*wait_fence
,
635 SyncFence
*idle_fence
,
640 present_notify_ptr notifies
,
647 present_vblank_ptr vblank
;
648 ScreenPtr screen
= window
->drawable
.pScreen
;
649 present_window_priv_ptr window_priv
= present_get_window_priv(window
, TRUE
);
650 present_screen_priv_ptr screen_priv
= present_screen_priv(screen
);
655 if (!screen_priv
|| !screen_priv
->info
)
657 else if (!target_crtc
) {
658 /* Update the CRTC if we have a pixmap or we don't have a CRTC
661 target_crtc
= window_priv
->crtc
;
664 target_crtc
= present_get_crtc(window
);
667 present_get_ust_msc(window
, target_crtc
, &ust
, &crtc_msc
);
669 target_msc
= present_window_to_crtc_msc(window
, target_crtc
, window_msc
, crtc_msc
);
671 /* Stash the current MSC away in case we need it later
673 window_priv
->msc
= crtc_msc
;
675 /* Adjust target_msc to match modulus
677 if (crtc_msc
>= target_msc
) {
679 target_msc
= crtc_msc
- (crtc_msc
% divisor
) + remainder
;
680 if (options
& PresentOptionAsync
) {
681 if (target_msc
< crtc_msc
)
682 target_msc
+= divisor
;
684 if (target_msc
<= crtc_msc
)
685 target_msc
+= divisor
;
688 target_msc
= crtc_msc
;
689 if (!(options
& PresentOptionAsync
))
695 * Look for a matching presentation already on the list and
696 * don't bother doing the previous one if this one will overwrite it
701 xorg_list_for_each_entry(vblank
, &window_priv
->vblank
, window_list
) {
709 if (vblank
->crtc
!= target_crtc
|| vblank
->target_msc
!= target_msc
)
712 DebugPresent(("\tx %lld %p %8lld: %08lx -> %08lx (crtc %p)\n",
713 vblank
->event_id
, vblank
, target_msc
,
714 vblank
->pixmap
->drawable
.id
, vblank
->window
->drawable
.id
,
717 present_pixmap_idle(vblank
->pixmap
, vblank
->window
, vblank
->serial
, vblank
->idle_fence
);
718 present_fence_destroy(vblank
->idle_fence
);
719 dixDestroyPixmap(vblank
->pixmap
, vblank
->pixmap
->drawable
.id
);
721 vblank
->pixmap
= NULL
;
722 vblank
->idle_fence
= NULL
;
726 vblank
= calloc (1, sizeof (present_vblank_rec
));
730 xorg_list_append(&vblank
->window_list
, &window_priv
->vblank
);
731 xorg_list_init(&vblank
->event_queue
);
733 vblank
->screen
= screen
;
734 vblank
->window
= window
;
735 vblank
->pixmap
= pixmap
;
736 vblank
->event_id
= ++present_event_id
;
738 vblank
->kind
= PresentCompleteKindPixmap
;
741 vblank
->kind
= PresentCompleteKindNotifyMSC
;
743 vblank
->serial
= serial
;
746 vblank
->valid
= RegionDuplicate(valid
);
751 vblank
->update
= RegionDuplicate(update
);
756 vblank
->x_off
= x_off
;
757 vblank
->y_off
= y_off
;
758 vblank
->target_msc
= target_msc
;
759 vblank
->crtc
= target_crtc
;
760 vblank
->msc_offset
= window_priv
->msc_offset
;
761 vblank
->notifies
= notifies
;
762 vblank
->num_notifies
= num_notifies
;
764 if (!screen_priv
->info
|| !(screen_priv
->info
->capabilities
& PresentCapabilityAsync
))
765 vblank
->sync_flip
= TRUE
;
767 if (pixmap
&& present_check_flip (target_crtc
, window
, pixmap
, vblank
->sync_flip
, valid
, x_off
, y_off
)) {
769 if (vblank
->sync_flip
)
774 vblank
->wait_fence
= present_fence_create(wait_fence
);
775 if (!vblank
->wait_fence
)
780 vblank
->idle_fence
= present_fence_create(idle_fence
);
781 if (!vblank
->idle_fence
)
786 DebugPresent(("q %lld %p %8lld: %08lx -> %08lx (crtc %p)\n",
787 vblank
->event_id
, vblank
, target_msc
,
788 vblank
->pixmap
->drawable
.id
, vblank
->window
->drawable
.id
,
791 xorg_list_add(&vblank
->event_queue
, &present_exec_queue
);
792 vblank
->queued
= TRUE
;
793 if (target_msc
>= crtc_msc
) {
794 ret
= present_queue_vblank(screen
, target_crtc
, vblank
->event_id
, target_msc
);
795 if (ret
!= Success
) {
796 xorg_list_del(&vblank
->event_queue
);
797 vblank
->queued
= FALSE
;
801 present_execute(vblank
, ust
, crtc_msc
);
808 vblank
->notifies
= NULL
;
809 present_vblank_destroy(vblank
);
814 present_abort_vblank(ScreenPtr screen
, RRCrtcPtr crtc
, uint64_t event_id
, uint64_t msc
)
816 present_vblank_ptr vblank
, tmp
;
819 present_fake_abort_vblank(screen
, event_id
, msc
);
822 present_screen_priv_ptr screen_priv
= present_screen_priv(screen
);
824 (*screen_priv
->info
->abort_vblank
) (crtc
, event_id
, msc
);
827 xorg_list_for_each_entry_safe(vblank
, tmp
, &present_exec_queue
, event_queue
) {
828 if (vblank
->event_id
== event_id
) {
829 xorg_list_del(&vblank
->event_queue
);
830 vblank
->queued
= FALSE
;
834 xorg_list_for_each_entry_safe(vblank
, tmp
, &present_flip_queue
, event_queue
) {
835 if (vblank
->event_id
== event_id
) {
836 xorg_list_del(&vblank
->event_queue
);
843 present_notify_msc(WindowPtr window
,
849 return present_pixmap(window
,
857 target_msc
, divisor
, remainder
, NULL
, 0);
861 present_flip_destroy(ScreenPtr screen
)
863 present_screen_priv_ptr screen_priv
= present_screen_priv(screen
);
865 /* XXX this needs to be synchronous for server reset */
867 /* Do the actual cleanup once the flip has been performed by the hardware */
868 if (screen_priv
->flip_pending
)
869 screen_priv
->flip_pending
->abort_flip
= TRUE
;
873 present_vblank_destroy(present_vblank_ptr vblank
)
875 /* Remove vblank from window and screen lists */
876 xorg_list_del(&vblank
->window_list
);
878 DebugPresent(("\td %p %8lld: %08lx -> %08lx\n", vblank
, vblank
->target_msc
,
879 vblank
->pixmap
? vblank
->pixmap
->drawable
.id
: 0,
880 vblank
->window
->drawable
.id
));
882 /* Drop pixmap reference */
884 dixDestroyPixmap(vblank
->pixmap
, vblank
->pixmap
->drawable
.id
);
888 RegionDestroy(vblank
->valid
);
890 RegionDestroy(vblank
->update
);
892 if (vblank
->wait_fence
)
893 present_fence_destroy(vblank
->wait_fence
);
895 if (vblank
->idle_fence
)
896 present_fence_destroy(vblank
->idle_fence
);
898 if (vblank
->notifies
)
899 present_destroy_notifies(vblank
->notifies
, vblank
->num_notifies
);
907 xorg_list_init(&present_exec_queue
);
908 xorg_list_init(&present_flip_queue
);
909 present_fake_queue_init();