xserver

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

exa_migration_mixed.c (9223B)


      1 /*
      2  * Copyright © 2009 Maarten Maathuis
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     21  * SOFTWARE.
     22  *
     23  */
     24 
     25 #ifdef HAVE_DIX_CONFIG_H
     26 #include <dix-config.h>
     27 #endif
     28 
     29 #include <string.h>
     30 
     31 #include "exa_priv.h"
     32 #include "exa.h"
     33 
     34 void
     35 exaCreateDriverPixmap_mixed(PixmapPtr pPixmap)
     36 {
     37     ScreenPtr pScreen = pPixmap->drawable.pScreen;
     38 
     39     ExaScreenPriv(pScreen);
     40     ExaPixmapPriv(pPixmap);
     41     int w = pPixmap->drawable.width, h = pPixmap->drawable.height;
     42     int depth = pPixmap->drawable.depth, bpp = pPixmap->drawable.bitsPerPixel;
     43     int usage_hint = pPixmap->usage_hint;
     44     int paddedWidth = pExaPixmap->sys_pitch;
     45 
     46     /* Already done. */
     47     if (pExaPixmap->driverPriv)
     48         return;
     49 
     50     if (exaPixmapIsPinned(pPixmap))
     51         return;
     52 
     53     /* Can't accel 1/4 bpp. */
     54     if (pExaPixmap->accel_blocked || bpp < 8)
     55         return;
     56 
     57     if (pExaScr->info->CreatePixmap2) {
     58         int new_pitch = 0;
     59 
     60         pExaPixmap->driverPriv =
     61             pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp,
     62                                          &new_pitch);
     63         paddedWidth = pExaPixmap->fb_pitch = new_pitch;
     64     }
     65     else {
     66         if (paddedWidth < pExaPixmap->fb_pitch)
     67             paddedWidth = pExaPixmap->fb_pitch;
     68         pExaPixmap->driverPriv =
     69             pExaScr->info->CreatePixmap(pScreen, paddedWidth * h, 0);
     70     }
     71 
     72     if (!pExaPixmap->driverPriv)
     73         return;
     74 
     75     (*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0, paddedWidth, NULL);
     76 }
     77 
     78 void
     79 exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
     80 {
     81     int i;
     82 
     83     /* If anything is pinned in system memory, we won't be able to
     84      * accelerate.
     85      */
     86     for (i = 0; i < npixmaps; i++) {
     87         if (exaPixmapIsPinned(pixmaps[i].pPix) &&
     88             !exaPixmapHasGpuCopy(pixmaps[i].pPix)) {
     89             can_accel = FALSE;
     90             break;
     91         }
     92     }
     93 
     94     /* We can do nothing. */
     95     if (!can_accel)
     96         return;
     97 
     98     for (i = 0; i < npixmaps; i++) {
     99         PixmapPtr pPixmap = pixmaps[i].pPix;
    100 
    101         ExaPixmapPriv(pPixmap);
    102 
    103         if (!pExaPixmap->driverPriv)
    104             exaCreateDriverPixmap_mixed(pPixmap);
    105 
    106         if (pExaPixmap->pDamage && exaPixmapHasGpuCopy(pPixmap)) {
    107             ExaScreenPriv(pPixmap->drawable.pScreen);
    108 
    109             /* This pitch is needed for proper acceleration. For some reason
    110              * there are pixmaps without pDamage and a bad fb_pitch value.
    111              * So setting devKind when only exaPixmapHasGpuCopy() is true
    112              * causes corruption. Pixmaps without pDamage are not migrated
    113              * and should have a valid devKind at all times, so that's why this
    114              * isn't causing problems. Pixmaps have their gpu pitch set the
    115              * first time in the MPH call from exaCreateDriverPixmap_mixed().
    116              */
    117             pPixmap->devKind = pExaPixmap->fb_pitch;
    118             exaCopyDirtyToFb(pixmaps + i);
    119 
    120             if (pExaScr->deferred_mixed_pixmap == pPixmap &&
    121                 !pixmaps[i].as_dst && !pixmaps[i].pReg)
    122                 pExaScr->deferred_mixed_pixmap = NULL;
    123         }
    124 
    125         pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
    126     }
    127 }
    128 
    129 void
    130 exaMoveInPixmap_mixed(PixmapPtr pPixmap)
    131 {
    132     ExaMigrationRec pixmaps[1];
    133 
    134     pixmaps[0].as_dst = FALSE;
    135     pixmaps[0].as_src = TRUE;
    136     pixmaps[0].pPix = pPixmap;
    137     pixmaps[0].pReg = NULL;
    138 
    139     exaDoMigration(pixmaps, 1, TRUE);
    140 }
    141 
    142 void
    143 exaDamageReport_mixed(DamagePtr pDamage, RegionPtr pRegion, void *closure)
    144 {
    145     PixmapPtr pPixmap = closure;
    146 
    147     ExaPixmapPriv(pPixmap);
    148 
    149     /* Move back results of software rendering on system memory copy of mixed driver
    150      * pixmap (see exaPrepareAccessReg_mixed).
    151      *
    152      * Defer moving the destination back into the driver pixmap, to try and save
    153      * overhead on multiple subsequent software fallbacks.
    154      */
    155     if (!pExaPixmap->use_gpu_copy && exaPixmapHasGpuCopy(pPixmap)) {
    156         ExaScreenPriv(pPixmap->drawable.pScreen);
    157 
    158         if (pExaScr->deferred_mixed_pixmap &&
    159             pExaScr->deferred_mixed_pixmap != pPixmap)
    160             exaMoveInPixmap_mixed(pExaScr->deferred_mixed_pixmap);
    161         pExaScr->deferred_mixed_pixmap = pPixmap;
    162     }
    163 }
    164 
    165 /* With mixed pixmaps, if we fail to get direct access to the driver pixmap, we
    166  * use the DownloadFromScreen hook to retrieve contents to a copy in system
    167  * memory, perform software rendering on that and move back the results with the
    168  * UploadToScreen hook (see exaDamageReport_mixed).
    169  */
    170 void
    171 exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg)
    172 {
    173     ExaPixmapPriv(pPixmap);
    174     Bool has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
    175     Bool success;
    176 
    177     success = ExaDoPrepareAccess(pPixmap, index);
    178 
    179     if (success && has_gpu_copy && pExaPixmap->pDamage) {
    180         /* You cannot do accelerated operations while a buffer is mapped. */
    181         exaFinishAccess(&pPixmap->drawable, index);
    182         /* Update the gpu view of both deferred destination pixmaps and of
    183          * source pixmaps that were migrated with a bounding region.
    184          */
    185         exaMoveInPixmap_mixed(pPixmap);
    186         success = ExaDoPrepareAccess(pPixmap, index);
    187 
    188         if (success) {
    189             /* We have a gpu pixmap that can be accessed, we don't need the cpu
    190              * copy anymore. Drivers that prefer DFS, should fail prepare
    191              * access.
    192              */
    193             DamageDestroy(pExaPixmap->pDamage);
    194             pExaPixmap->pDamage = NULL;
    195 
    196             free(pExaPixmap->sys_ptr);
    197             pExaPixmap->sys_ptr = NULL;
    198 
    199             return;
    200         }
    201     }
    202 
    203     if (!success) {
    204         ExaMigrationRec pixmaps[1];
    205 
    206         /* Do we need to allocate our system buffer? */
    207         if (!pExaPixmap->sys_ptr) {
    208             pExaPixmap->sys_ptr = xallocarray(pExaPixmap->sys_pitch,
    209                                               pPixmap->drawable.height);
    210             if (!pExaPixmap->sys_ptr)
    211                 FatalError("EXA: malloc failed for size %d bytes\n",
    212                            pExaPixmap->sys_pitch * pPixmap->drawable.height);
    213         }
    214 
    215         if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
    216             pixmaps[0].as_dst = TRUE;
    217             pixmaps[0].as_src = FALSE;
    218         }
    219         else {
    220             pixmaps[0].as_dst = FALSE;
    221             pixmaps[0].as_src = TRUE;
    222         }
    223         pixmaps[0].pPix = pPixmap;
    224         pixmaps[0].pReg = pReg;
    225 
    226         if (!pExaPixmap->pDamage &&
    227             (has_gpu_copy || !exaPixmapIsPinned(pPixmap))) {
    228             Bool as_dst = pixmaps[0].as_dst;
    229 
    230             /* Set up damage tracking */
    231             pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL,
    232                                                DamageReportNonEmpty, TRUE,
    233                                                pPixmap->drawable.pScreen,
    234                                                pPixmap);
    235 
    236             if (pExaPixmap->pDamage) {
    237                 DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage);
    238                 /* This ensures that pending damage reflects the current
    239                  * operation. This is used by exa to optimize migration.
    240                  */
    241                 DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE);
    242             }
    243 
    244             if (has_gpu_copy) {
    245                 exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width,
    246                                pPixmap->drawable.height);
    247 
    248                 /* We don't know which region of the destination will be damaged,
    249                  * have to assume all of it
    250                  */
    251                 if (as_dst) {
    252                     pixmaps[0].as_dst = FALSE;
    253                     pixmaps[0].as_src = TRUE;
    254                     pixmaps[0].pReg = NULL;
    255                 }
    256                 exaCopyDirtyToSys(pixmaps);
    257             }
    258 
    259             if (as_dst)
    260                 exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width,
    261                                pPixmap->drawable.height);
    262         }
    263         else if (has_gpu_copy)
    264             exaCopyDirtyToSys(pixmaps);
    265 
    266         pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
    267         pPixmap->devKind = pExaPixmap->sys_pitch;
    268         pExaPixmap->use_gpu_copy = FALSE;
    269     }
    270 }