xserver

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

present.c (9085B)


      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 #include <gcstruct.h>
     25 
     26 uint32_t
     27 present_query_capabilities(RRCrtcPtr crtc)
     28 {
     29     present_screen_priv_ptr screen_priv;
     30 
     31     if (!crtc)
     32         return 0;
     33 
     34     screen_priv = present_screen_priv(crtc->pScreen);
     35 
     36     if (!screen_priv)
     37         return 0;
     38 
     39     return screen_priv->query_capabilities(screen_priv);
     40 }
     41 
     42 RRCrtcPtr
     43 present_get_crtc(WindowPtr window)
     44 {
     45     ScreenPtr                   screen = window->drawable.pScreen;
     46     present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
     47     RRCrtcPtr                   crtc = NULL;
     48 
     49     if (!screen_priv)
     50         return NULL;
     51 
     52     crtc = screen_priv->get_crtc(screen_priv, window);
     53     if (crtc && !present_screen_priv(crtc->pScreen)) {
     54         crtc = RRFirstEnabledCrtc(screen);
     55     }
     56     if (crtc && !present_screen_priv(crtc->pScreen)) {
     57         crtc = NULL;
     58     }
     59     return crtc;
     60 }
     61 
     62 /*
     63  * Copies the update region from a pixmap to the target drawable
     64  */
     65 void
     66 present_copy_region(DrawablePtr drawable,
     67                     PixmapPtr pixmap,
     68                     RegionPtr update,
     69                     int16_t x_off,
     70                     int16_t y_off)
     71 {
     72     ScreenPtr   screen = drawable->pScreen;
     73     GCPtr       gc;
     74 
     75     gc = GetScratchGC(drawable->depth, screen);
     76     if (update) {
     77         ChangeGCVal     changes[2];
     78 
     79         changes[0].val = x_off;
     80         changes[1].val = y_off;
     81         ChangeGC(serverClient, gc,
     82                  GCClipXOrigin|GCClipYOrigin,
     83                  changes);
     84         (*gc->funcs->ChangeClip)(gc, CT_REGION, update, 0);
     85     }
     86     ValidateGC(drawable, gc);
     87     (*gc->ops->CopyArea)(&pixmap->drawable,
     88                          drawable,
     89                          gc,
     90                          0, 0,
     91                          pixmap->drawable.width, pixmap->drawable.height,
     92                          x_off, y_off);
     93     if (update)
     94         (*gc->funcs->ChangeClip)(gc, CT_NONE, NULL, 0);
     95     FreeScratchGC(gc);
     96 }
     97 
     98 void
     99 present_pixmap_idle(PixmapPtr pixmap, WindowPtr window, CARD32 serial, struct present_fence *present_fence)
    100 {
    101     if (present_fence)
    102         present_fence_set_triggered(present_fence);
    103     if (window) {
    104         DebugPresent(("\ti %08" PRIx32 "\n", pixmap ? pixmap->drawable.id : 0));
    105         present_send_idle_notify(window, serial, pixmap, present_fence);
    106     }
    107 }
    108 
    109 struct pixmap_visit {
    110     PixmapPtr   old;
    111     PixmapPtr   new;
    112 };
    113 
    114 static int
    115 present_set_tree_pixmap_visit(WindowPtr window, void *data)
    116 {
    117     struct pixmap_visit *visit = data;
    118     ScreenPtr           screen = window->drawable.pScreen;
    119 
    120     if ((*screen->GetWindowPixmap)(window) != visit->old)
    121         return WT_DONTWALKCHILDREN;
    122     (*screen->SetWindowPixmap)(window, visit->new);
    123     return WT_WALKCHILDREN;
    124 }
    125 
    126 void
    127 present_set_tree_pixmap(WindowPtr window,
    128                         PixmapPtr expected,
    129                         PixmapPtr pixmap)
    130 {
    131     struct pixmap_visit visit;
    132     ScreenPtr           screen = window->drawable.pScreen;
    133 
    134     visit.old = (*screen->GetWindowPixmap)(window);
    135     if (expected && visit.old != expected)
    136         return;
    137 
    138     visit.new = pixmap;
    139     if (visit.old == visit.new)
    140         return;
    141     TraverseTree(window, present_set_tree_pixmap_visit, &visit);
    142 }
    143 
    144 Bool
    145 present_can_window_flip(WindowPtr window)
    146 {
    147     ScreenPtr                   screen = window->drawable.pScreen;
    148     present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
    149 
    150     return screen_priv->can_window_flip(window);
    151 }
    152 
    153 uint64_t
    154 present_get_target_msc(uint64_t target_msc_arg,
    155                        uint64_t crtc_msc,
    156                        uint64_t divisor,
    157                        uint64_t remainder,
    158                        uint32_t options)
    159 {
    160     const Bool  synced_flip = !(options & PresentOptionAsync);
    161     uint64_t    target_msc;
    162 
    163     /* If the specified target-msc lies in the future, then this
    164      * defines the target-msc according to Present protocol.
    165      */
    166     if (msc_is_after(target_msc_arg, crtc_msc))
    167         return target_msc_arg;
    168 
    169     /* If no divisor is specified, the modulo is undefined
    170      * and we do present instead asap.
    171      */
    172     if (divisor == 0) {
    173         target_msc = crtc_msc;
    174 
    175         /* When no async presentation is forced, by default we sync the
    176          * presentation with vblank. But in this case we can't target
    177          * the current crtc-msc, which already has begun, but must aim
    178          * for the upcoming one.
    179          */
    180         if (synced_flip)
    181             target_msc++;
    182 
    183         return target_msc;
    184     }
    185 
    186     /* Calculate target-msc by the specified modulo parameters. According
    187      * to Present protocol this is after the next field with:
    188      *
    189      *      field-msc % divisor == remainder.
    190      *
    191      * The following formula calculates a target_msc solving above equation
    192      * and with |target_msc - crtc_msc| < divisor.
    193      *
    194      * Example with crtc_msc = 10, divisor = 4 and remainder = 3, 2, 1, 0:
    195      *      11 = 10 - 2 + 3 = 10 - (10 % 4) + 3,
    196      *      10 = 10 - 2 + 2 = 10 - (10 % 4) + 2,
    197      *       9 = 10 - 2 + 1 = 10 - (10 % 4) + 1,
    198      *       8 = 10 - 2 + 0 = 10 - (10 % 4) + 0.
    199      */
    200     target_msc = crtc_msc - (crtc_msc % divisor) + remainder;
    201 
    202     /* Here we already found the correct field-msc. */
    203     if (msc_is_after(target_msc, crtc_msc))
    204         return target_msc;
    205     /*
    206      * Here either:
    207      * a) target_msc == crtc_msc, i.e. crtc_msc actually solved
    208      * above equation with crtc_msc % divisor == remainder.
    209      *
    210      * => This means we want to present at target_msc + divisor for a synced
    211      *    flip or directly now for an async flip.
    212      *
    213      * b) target_msc < crtc_msc with target_msc + divisor > crtc_msc.
    214      *
    215      * => This means in any case we want to present at target_msc + divisor.
    216      */
    217     if (synced_flip || msc_is_after(crtc_msc, target_msc))
    218         target_msc += divisor;
    219     return target_msc;
    220 }
    221 
    222 int
    223 present_pixmap(WindowPtr window,
    224                PixmapPtr pixmap,
    225                CARD32 serial,
    226                RegionPtr valid,
    227                RegionPtr update,
    228                int16_t x_off,
    229                int16_t y_off,
    230                RRCrtcPtr target_crtc,
    231                SyncFence *wait_fence,
    232                SyncFence *idle_fence,
    233                uint32_t options,
    234                uint64_t window_msc,
    235                uint64_t divisor,
    236                uint64_t remainder,
    237                present_notify_ptr notifies,
    238                int num_notifies)
    239 {
    240     ScreenPtr                   screen = window->drawable.pScreen;
    241     present_screen_priv_ptr     screen_priv = present_screen_priv(screen);
    242 
    243     return screen_priv->present_pixmap(window,
    244                                        pixmap,
    245                                        serial,
    246                                        valid,
    247                                        update,
    248                                        x_off,
    249                                        y_off,
    250                                        target_crtc,
    251                                        wait_fence,
    252                                        idle_fence,
    253                                        options,
    254                                        window_msc,
    255                                        divisor,
    256                                        remainder,
    257                                        notifies,
    258                                        num_notifies);
    259 }
    260 
    261 int
    262 present_notify_msc(WindowPtr window,
    263                    CARD32 serial,
    264                    uint64_t target_msc,
    265                    uint64_t divisor,
    266                    uint64_t remainder)
    267 {
    268     return present_pixmap(window,
    269                           NULL,
    270                           serial,
    271                           NULL, NULL,
    272                           0, 0,
    273                           NULL,
    274                           NULL, NULL,
    275                           divisor == 0 ? PresentOptionAsync : 0,
    276                           target_msc, divisor, remainder, NULL, 0);
    277 }