11b5d61b8Smrg/*
21b5d61b8Smrg * Copyright © 2013 Keith Packard
31b5d61b8Smrg *
41b5d61b8Smrg * Permission to use, copy, modify, distribute, and sell this software and its
51b5d61b8Smrg * documentation for any purpose is hereby granted without fee, provided that
61b5d61b8Smrg * the above copyright notice appear in all copies and that both that copyright
71b5d61b8Smrg * notice and this permission notice appear in supporting documentation, and
81b5d61b8Smrg * that the name of the copyright holders not be used in advertising or
91b5d61b8Smrg * publicity pertaining to distribution of the software without specific,
101b5d61b8Smrg * written prior permission.  The copyright holders make no representations
111b5d61b8Smrg * about the suitability of this software for any purpose.  It is provided "as
121b5d61b8Smrg * is" without express or implied warranty.
131b5d61b8Smrg *
141b5d61b8Smrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
151b5d61b8Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
161b5d61b8Smrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
171b5d61b8Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
181b5d61b8Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
191b5d61b8Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
201b5d61b8Smrg * OF THIS SOFTWARE.
211b5d61b8Smrg */
221b5d61b8Smrg
231b5d61b8Smrg#include "present_priv.h"
241b5d61b8Smrg
251b5d61b8Smrg/*
261b5d61b8Smrg * Called when the wait fence is triggered; just gets the current msc/ust and
271b5d61b8Smrg * calls the proper execute again. That will re-check the fence and pend the
281b5d61b8Smrg * request again if it's still not actually ready
291b5d61b8Smrg */
301b5d61b8Smrgstatic void
311b5d61b8Smrgpresent_wait_fence_triggered(void *param)
321b5d61b8Smrg{
331b5d61b8Smrg    present_vblank_ptr      vblank = param;
341b5d61b8Smrg    ScreenPtr               screen = vblank->screen;
351b5d61b8Smrg    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
361b5d61b8Smrg
371b5d61b8Smrg    screen_priv->re_execute(vblank);
381b5d61b8Smrg}
391b5d61b8Smrg
401b5d61b8SmrgBool
411b5d61b8Smrgpresent_execute_wait(present_vblank_ptr vblank, uint64_t crtc_msc)
421b5d61b8Smrg{
431b5d61b8Smrg    WindowPtr                   window = vblank->window;
441b5d61b8Smrg    ScreenPtr                   screen = window->drawable.pScreen;
451b5d61b8Smrg    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
461b5d61b8Smrg
475a7dfde8Smrg    /* We may have to requeue for the next MSC if check_flip_window prevented
485a7dfde8Smrg     * using a flip.
495a7dfde8Smrg     */
505a7dfde8Smrg    if (vblank->exec_msc == crtc_msc + 1 &&
515a7dfde8Smrg        screen_priv->queue_vblank(screen, window, vblank->crtc, vblank->event_id,
525a7dfde8Smrg                                  vblank->exec_msc) == Success)
535a7dfde8Smrg        return TRUE;
541b5d61b8Smrg
551b5d61b8Smrg    if (vblank->wait_fence) {
561b5d61b8Smrg        if (!present_fence_check_triggered(vblank->wait_fence)) {
571b5d61b8Smrg            present_fence_set_callback(vblank->wait_fence, present_wait_fence_triggered, vblank);
581b5d61b8Smrg            return TRUE;
591b5d61b8Smrg        }
601b5d61b8Smrg    }
611b5d61b8Smrg    return FALSE;
621b5d61b8Smrg}
631b5d61b8Smrg
641b5d61b8Smrgvoid
651b5d61b8Smrgpresent_execute_copy(present_vblank_ptr vblank, uint64_t crtc_msc)
661b5d61b8Smrg{
671b5d61b8Smrg    WindowPtr                   window = vblank->window;
681b5d61b8Smrg    ScreenPtr                   screen = window->drawable.pScreen;
691b5d61b8Smrg    present_screen_priv_ptr screen_priv = present_screen_priv(screen);
701b5d61b8Smrg
715a7dfde8Smrg    /* If present_flip failed, we may have to requeue for the next MSC */
725a7dfde8Smrg    if (vblank->exec_msc == crtc_msc + 1 &&
731b5d61b8Smrg        Success == screen_priv->queue_vblank(screen,
741b5d61b8Smrg                                             window,
751b5d61b8Smrg                                             vblank->crtc,
761b5d61b8Smrg                                             vblank->event_id,
775a7dfde8Smrg                                             vblank->exec_msc)) {
781b5d61b8Smrg        vblank->queued = TRUE;
791b5d61b8Smrg        return;
801b5d61b8Smrg    }
811b5d61b8Smrg
821b5d61b8Smrg    present_copy_region(&window->drawable, vblank->pixmap, vblank->update, vblank->x_off, vblank->y_off);
831b5d61b8Smrg
841b5d61b8Smrg    /* present_copy_region sticks the region into a scratch GC,
851b5d61b8Smrg     * which is then freed, freeing the region
861b5d61b8Smrg     */
871b5d61b8Smrg    vblank->update = NULL;
881b5d61b8Smrg    screen_priv->flush(window);
891b5d61b8Smrg
901b5d61b8Smrg    present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
911b5d61b8Smrg}
921b5d61b8Smrg
931b5d61b8Smrgvoid
941b5d61b8Smrgpresent_execute_post(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
951b5d61b8Smrg{
961b5d61b8Smrg    uint8_t mode;
971b5d61b8Smrg
981b5d61b8Smrg    /* Compute correct CompleteMode
991b5d61b8Smrg     */
1001b5d61b8Smrg    if (vblank->kind == PresentCompleteKindPixmap) {
1011b5d61b8Smrg        if (vblank->pixmap && vblank->window) {
1021b5d61b8Smrg            if (vblank->has_suboptimal && vblank->reason == PRESENT_FLIP_REASON_BUFFER_FORMAT)
1031b5d61b8Smrg                mode = PresentCompleteModeSuboptimalCopy;
1041b5d61b8Smrg            else
1051b5d61b8Smrg                mode = PresentCompleteModeCopy;
1061b5d61b8Smrg        } else {
1071b5d61b8Smrg            mode = PresentCompleteModeSkip;
1081b5d61b8Smrg        }
1091b5d61b8Smrg    }
1101b5d61b8Smrg    else
1111b5d61b8Smrg        mode = PresentCompleteModeCopy;
1121b5d61b8Smrg
1131b5d61b8Smrg    present_vblank_notify(vblank, vblank->kind, mode, ust, crtc_msc);
1141b5d61b8Smrg    present_vblank_destroy(vblank);
1151b5d61b8Smrg}
116