xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

present_vblank.c (8322B)


      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 
     23 #include "present_priv.h"
     24 
     25 void
     26 present_vblank_notify(present_vblank_ptr vblank, CARD8 kind, CARD8 mode, uint64_t ust, uint64_t crtc_msc)
     27 {
     28     int n;
     29 
     30     if (vblank->window)
     31         present_send_complete_notify(vblank->window, kind, mode, vblank->serial, ust, crtc_msc - vblank->msc_offset);
     32     for (n = 0; n < vblank->num_notifies; n++) {
     33         WindowPtr   window = vblank->notifies[n].window;
     34         CARD32      serial = vblank->notifies[n].serial;
     35 
     36         if (window)
     37             present_send_complete_notify(window, kind, mode, serial, ust, crtc_msc - vblank->msc_offset);
     38     }
     39 }
     40 
     41 /* The memory vblank points to must be 0-initialized before calling this function.
     42  *
     43  * If this function returns FALSE, present_vblank_destroy must be called to clean
     44  * up.
     45  */
     46 Bool
     47 present_vblank_init(present_vblank_ptr vblank,
     48                     WindowPtr window,
     49                     PixmapPtr pixmap,
     50                     CARD32 serial,
     51                     RegionPtr valid,
     52                     RegionPtr update,
     53                     int16_t x_off,
     54                     int16_t y_off,
     55                     RRCrtcPtr target_crtc,
     56                     SyncFence *wait_fence,
     57                     SyncFence *idle_fence,
     58                     uint32_t options,
     59                     const uint32_t capabilities,
     60                     present_notify_ptr notifies,
     61                     int num_notifies,
     62                     uint64_t target_msc,
     63                     uint64_t crtc_msc)
     64 {
     65     ScreenPtr                   screen = window->drawable.pScreen;
     66     present_window_priv_ptr     window_priv = present_get_window_priv(window, TRUE);
     67     present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
     68     PresentFlipReason           reason = PRESENT_FLIP_REASON_UNKNOWN;
     69 
     70     if (target_crtc) {
     71         screen_priv = present_screen_priv(target_crtc->pScreen);
     72     }
     73 
     74     xorg_list_append(&vblank->window_list, &window_priv->vblank);
     75     xorg_list_init(&vblank->event_queue);
     76 
     77     vblank->screen = screen;
     78     vblank->window = window;
     79     vblank->pixmap = pixmap;
     80 
     81     if (pixmap) {
     82         vblank->kind = PresentCompleteKindPixmap;
     83         pixmap->refcnt++;
     84     } else
     85         vblank->kind = PresentCompleteKindNotifyMSC;
     86 
     87     vblank->serial = serial;
     88 
     89     if (valid) {
     90         vblank->valid = RegionDuplicate(valid);
     91         if (!vblank->valid)
     92             goto no_mem;
     93     }
     94     if (update) {
     95         vblank->update = RegionDuplicate(update);
     96         if (!vblank->update)
     97             goto no_mem;
     98     }
     99 
    100     vblank->x_off = x_off;
    101     vblank->y_off = y_off;
    102     vblank->target_msc = target_msc;
    103     vblank->exec_msc = target_msc;
    104     vblank->crtc = target_crtc;
    105     vblank->msc_offset = window_priv->msc_offset;
    106     vblank->notifies = notifies;
    107     vblank->num_notifies = num_notifies;
    108     vblank->has_suboptimal = (options & PresentOptionSuboptimal);
    109 
    110     if (pixmap != NULL &&
    111         !(options & PresentOptionCopy) &&
    112         screen_priv->check_flip) {
    113         if (msc_is_after(target_msc, crtc_msc) &&
    114             screen_priv->check_flip (target_crtc, window, pixmap, TRUE, valid, x_off, y_off, &reason))
    115         {
    116             vblank->flip = TRUE;
    117             vblank->sync_flip = TRUE;
    118         } else if ((capabilities & PresentCapabilityAsync) &&
    119             screen_priv->check_flip (target_crtc, window, pixmap, FALSE, valid, x_off, y_off, &reason))
    120         {
    121             vblank->flip = TRUE;
    122         }
    123     }
    124     vblank->reason = reason;
    125 
    126     if (wait_fence) {
    127         vblank->wait_fence = present_fence_create(wait_fence);
    128         if (!vblank->wait_fence)
    129             goto no_mem;
    130     }
    131 
    132     if (idle_fence) {
    133         vblank->idle_fence = present_fence_create(idle_fence);
    134         if (!vblank->idle_fence)
    135             goto no_mem;
    136     }
    137 
    138     if (pixmap)
    139         DebugPresent(("q %" PRIu64 " %p %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 " (crtc %p) flip %d vsync %d serial %d\n",
    140                       vblank->event_id, vblank, target_msc,
    141                       vblank->pixmap->drawable.id, vblank->window->drawable.id,
    142                       target_crtc, vblank->flip, vblank->sync_flip, vblank->serial));
    143     return TRUE;
    144 
    145 no_mem:
    146     vblank->notifies = NULL;
    147     return FALSE;
    148 }
    149 
    150 present_vblank_ptr
    151 present_vblank_create(WindowPtr window,
    152                       PixmapPtr pixmap,
    153                       CARD32 serial,
    154                       RegionPtr valid,
    155                       RegionPtr update,
    156                       int16_t x_off,
    157                       int16_t y_off,
    158                       RRCrtcPtr target_crtc,
    159                       SyncFence *wait_fence,
    160                       SyncFence *idle_fence,
    161                       uint32_t options,
    162                       const uint32_t capabilities,
    163                       present_notify_ptr notifies,
    164                       int num_notifies,
    165                       uint64_t target_msc,
    166                       uint64_t crtc_msc)
    167 {
    168     present_vblank_ptr vblank = calloc(1, sizeof(present_vblank_rec));
    169 
    170     if (!vblank)
    171         return NULL;
    172 
    173     if (present_vblank_init(vblank, window, pixmap, serial, valid, update,
    174                             x_off, y_off, target_crtc, wait_fence, idle_fence,
    175                             options, capabilities, notifies, num_notifies,
    176                             target_msc, crtc_msc))
    177         return vblank;
    178 
    179     present_vblank_destroy(vblank);
    180     return NULL;
    181 }
    182 
    183 void
    184 present_vblank_scrap(present_vblank_ptr vblank)
    185 {
    186     DebugPresent(("\tx %" PRIu64 " %p %" PRIu64 " %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 " (crtc %p)\n",
    187                   vblank->event_id, vblank, vblank->exec_msc, vblank->target_msc,
    188                   vblank->pixmap->drawable.id, vblank->window->drawable.id,
    189                   vblank->crtc));
    190 
    191     present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
    192     present_fence_destroy(vblank->idle_fence);
    193     dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id);
    194 
    195     vblank->pixmap = NULL;
    196     vblank->idle_fence = NULL;
    197     vblank->flip = FALSE;
    198 }
    199 
    200 void
    201 present_vblank_destroy(present_vblank_ptr vblank)
    202 {
    203     /* Remove vblank from window and screen lists */
    204     xorg_list_del(&vblank->window_list);
    205     /* Also make sure vblank is removed from event queue (wnmd) */
    206     xorg_list_del(&vblank->event_queue);
    207 
    208     DebugPresent(("\td %" PRIu64 " %p %" PRIu64 " %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n",
    209                   vblank->event_id, vblank, vblank->exec_msc, vblank->target_msc,
    210                   vblank->pixmap ? vblank->pixmap->drawable.id : 0,
    211                   vblank->window ? vblank->window->drawable.id : 0));
    212 
    213     /* Drop pixmap reference */
    214     if (vblank->pixmap)
    215         dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id);
    216 
    217     /* Free regions */
    218     if (vblank->valid)
    219         RegionDestroy(vblank->valid);
    220     if (vblank->update)
    221         RegionDestroy(vblank->update);
    222 
    223     if (vblank->wait_fence)
    224         present_fence_destroy(vblank->wait_fence);
    225 
    226     if (vblank->idle_fence)
    227         present_fence_destroy(vblank->idle_fence);
    228 
    229     if (vblank->notifies)
    230         present_destroy_notifies(vblank->notifies, vblank->num_notifies);
    231 
    232     free(vblank);
    233 }