"Fossies" - the Fresh Open Source Software Archive

Member "xorg-server-1.20.8/hw/xfree86/modes/xf86Rotate.c" (29 Mar 2020, 16552 Bytes) of package /linux/misc/xorg-server-1.20.8.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "xf86Rotate.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.20.7_vs_1.20.8.

    1 /*
    2  * Copyright © 2006 Keith Packard
    3  * Copyright © 2011 Aaron Plattner
    4  *
    5  * Permission to use, copy, modify, distribute, and sell this software and its
    6  * documentation for any purpose is hereby granted without fee, provided that
    7  * the above copyright notice appear in all copies and that both that copyright
    8  * notice and this permission notice appear in supporting documentation, and
    9  * that the name of the copyright holders not be used in advertising or
   10  * publicity pertaining to distribution of the software without specific,
   11  * written prior permission.  The copyright holders make no representations
   12  * about the suitability of this software for any purpose.  It is provided "as
   13  * is" without express or implied warranty.
   14  *
   15  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
   16  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
   17  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
   18  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
   19  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
   20  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
   21  * OF THIS SOFTWARE.
   22  */
   23 
   24 #ifdef HAVE_XORG_CONFIG_H
   25 #include <xorg-config.h>
   26 #endif
   27 
   28 #include <stddef.h>
   29 #include <string.h>
   30 #include <stdio.h>
   31 #include "mi.h"
   32 #include "xf86.h"
   33 #include "xf86DDC.h"
   34 #include "windowstr.h"
   35 #include "xf86Crtc.h"
   36 #include "xf86Modes.h"
   37 #include "xf86RandR12.h"
   38 #include "X11/extensions/render.h"
   39 #include "X11/extensions/dpmsconst.h"
   40 #include "X11/Xatom.h"
   41 
   42 static void
   43 xf86RotateCrtcRedisplay(xf86CrtcPtr crtc, RegionPtr region)
   44 {
   45     ScrnInfoPtr scrn = crtc->scrn;
   46     ScreenPtr screen = scrn->pScreen;
   47     WindowPtr root = screen->root;
   48     PixmapPtr dst_pixmap = crtc->rotatedPixmap;
   49     PictFormatPtr format = PictureWindowFormat(screen->root);
   50     int error;
   51     PicturePtr src, dst;
   52     int n = RegionNumRects(region);
   53     BoxPtr b = RegionRects(region);
   54     XID include_inferiors = IncludeInferiors;
   55 
   56     if (crtc->driverIsPerformingTransform & XF86DriverTransformOutput)
   57         return;
   58 
   59     src = CreatePicture(None,
   60                         &root->drawable,
   61                         format,
   62                         CPSubwindowMode,
   63                         &include_inferiors, serverClient, &error);
   64     if (!src)
   65         return;
   66 
   67     dst = CreatePicture(None,
   68                         &dst_pixmap->drawable,
   69                         format, 0L, NULL, serverClient, &error);
   70     if (!dst)
   71         return;
   72 
   73     error = SetPictureTransform(src, &crtc->crtc_to_framebuffer);
   74     if (error)
   75         return;
   76     if (crtc->transform_in_use && crtc->filter)
   77         SetPicturePictFilter(src, crtc->filter, crtc->params, crtc->nparams);
   78 
   79     if (crtc->shadowClear) {
   80         CompositePicture(PictOpSrc,
   81                          src, NULL, dst,
   82                          0, 0, 0, 0, 0, 0,
   83                          crtc->mode.HDisplay, crtc->mode.VDisplay);
   84         crtc->shadowClear = FALSE;
   85     }
   86     else {
   87         while (n--) {
   88             BoxRec dst_box;
   89 
   90             dst_box = *b;
   91             dst_box.x1 -= crtc->filter_width >> 1;
   92             dst_box.x2 += crtc->filter_width >> 1;
   93             dst_box.y1 -= crtc->filter_height >> 1;
   94             dst_box.y2 += crtc->filter_height >> 1;
   95             pixman_f_transform_bounds(&crtc->f_framebuffer_to_crtc, &dst_box);
   96             CompositePicture(PictOpSrc,
   97                              src, NULL, dst,
   98                              dst_box.x1, dst_box.y1, 0, 0, dst_box.x1,
   99                              dst_box.y1, dst_box.x2 - dst_box.x1,
  100                              dst_box.y2 - dst_box.y1);
  101             b++;
  102         }
  103     }
  104     FreePicture(src, None);
  105     FreePicture(dst, None);
  106 }
  107 
  108 static void
  109 xf86CrtcDamageShadow(xf86CrtcPtr crtc)
  110 {
  111     ScrnInfoPtr pScrn = crtc->scrn;
  112     BoxRec damage_box;
  113     RegionRec damage_region;
  114     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
  115 
  116     damage_box.x1 = 0;
  117     damage_box.x2 = crtc->mode.HDisplay;
  118     damage_box.y1 = 0;
  119     damage_box.y2 = crtc->mode.VDisplay;
  120     if (!pixman_transform_bounds(&crtc->crtc_to_framebuffer, &damage_box)) {
  121         damage_box.x1 = 0;
  122         damage_box.y1 = 0;
  123         damage_box.x2 = pScreen->width;
  124         damage_box.y2 = pScreen->height;
  125     }
  126     if (damage_box.x1 < 0)
  127         damage_box.x1 = 0;
  128     if (damage_box.y1 < 0)
  129         damage_box.y1 = 0;
  130     if (damage_box.x2 > pScreen->width)
  131         damage_box.x2 = pScreen->width;
  132     if (damage_box.y2 > pScreen->height)
  133         damage_box.y2 = pScreen->height;
  134     RegionInit(&damage_region, &damage_box, 1);
  135     DamageDamageRegion(&(*pScreen->GetScreenPixmap) (pScreen)->drawable,
  136                        &damage_region);
  137     RegionUninit(&damage_region);
  138     crtc->shadowClear = TRUE;
  139 }
  140 
  141 static void
  142 xf86RotatePrepare(ScreenPtr pScreen)
  143 {
  144     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
  145     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
  146     int c;
  147 
  148     for (c = 0; c < xf86_config->num_crtc; c++) {
  149         xf86CrtcPtr crtc = xf86_config->crtc[c];
  150 
  151         if (crtc->rotatedData && !crtc->rotatedPixmap) {
  152             crtc->rotatedPixmap = crtc->funcs->shadow_create(crtc,
  153                                                              crtc->rotatedData,
  154                                                              crtc->mode.
  155                                                              HDisplay,
  156                                                              crtc->mode.
  157                                                              VDisplay);
  158             if (!xf86_config->rotation_damage_registered) {
  159                 /* Hook damage to screen pixmap */
  160                 DamageRegister(&pScreen->root->drawable,
  161                                xf86_config->rotation_damage);
  162                 xf86_config->rotation_damage_registered = TRUE;
  163                 EnableLimitedSchedulingLatency();
  164             }
  165 
  166             xf86CrtcDamageShadow(crtc);
  167         }
  168     }
  169 }
  170 
  171 static Bool
  172 xf86RotateRedisplay(ScreenPtr pScreen)
  173 {
  174     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
  175     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
  176     DamagePtr damage = xf86_config->rotation_damage;
  177     RegionPtr region;
  178 
  179     if (!damage || !pScreen->root)
  180         return FALSE;
  181     xf86RotatePrepare(pScreen);
  182     region = DamageRegion(damage);
  183     if (RegionNotEmpty(region)) {
  184         int c;
  185         SourceValidateProcPtr SourceValidate;
  186 
  187         /*
  188          * SourceValidate is used by the software cursor code
  189          * to pull the cursor off of the screen when reading
  190          * bits from the frame buffer. Bypassing this function
  191          * leaves the software cursor in place
  192          */
  193         SourceValidate = pScreen->SourceValidate;
  194         pScreen->SourceValidate = miSourceValidate;
  195 
  196         for (c = 0; c < xf86_config->num_crtc; c++) {
  197             xf86CrtcPtr crtc = xf86_config->crtc[c];
  198 
  199             if (crtc->transform_in_use && crtc->enabled) {
  200                 RegionRec crtc_damage;
  201 
  202                 /* compute portion of damage that overlaps crtc */
  203                 RegionInit(&crtc_damage, &crtc->bounds, 1);
  204                 RegionIntersect(&crtc_damage, &crtc_damage, region);
  205 
  206                 /* update damaged region */
  207                 if (RegionNotEmpty(&crtc_damage))
  208                     xf86RotateCrtcRedisplay(crtc, &crtc_damage);
  209 
  210                 RegionUninit(&crtc_damage);
  211             }
  212         }
  213         pScreen->SourceValidate = SourceValidate;
  214         DamageEmpty(damage);
  215     }
  216     return TRUE;
  217 }
  218 
  219 static void
  220 xf86RotateBlockHandler(ScreenPtr pScreen, void *pTimeout)
  221 {
  222     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
  223     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
  224 
  225     /* Unwrap before redisplay in case the software
  226      * cursor layer wants to add its block handler to the
  227      * chain
  228      */
  229     pScreen->BlockHandler = xf86_config->BlockHandler;
  230 
  231     xf86RotateRedisplay(pScreen);
  232 
  233     (*pScreen->BlockHandler) (pScreen, pTimeout);
  234 
  235     /* Re-wrap if we still need this hook */
  236     if (xf86_config->rotation_damage != NULL) {
  237         xf86_config->BlockHandler = pScreen->BlockHandler;
  238         pScreen->BlockHandler = xf86RotateBlockHandler;
  239     } else
  240         xf86_config->BlockHandler = NULL;
  241 }
  242 
  243 void
  244 xf86RotateDestroy(xf86CrtcPtr crtc)
  245 {
  246     ScrnInfoPtr pScrn = crtc->scrn;
  247     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
  248     int c;
  249 
  250     /* Free memory from rotation */
  251     if (crtc->rotatedPixmap || crtc->rotatedData) {
  252         crtc->funcs->shadow_destroy(crtc, crtc->rotatedPixmap,
  253                                     crtc->rotatedData);
  254         crtc->rotatedPixmap = NULL;
  255         crtc->rotatedData = NULL;
  256     }
  257 
  258     for (c = 0; c < xf86_config->num_crtc; c++)
  259         if (xf86_config->crtc[c]->rotatedData)
  260             return;
  261 
  262     /*
  263      * Clean up damage structures when no crtcs are rotated
  264      */
  265     if (xf86_config->rotation_damage) {
  266         /* Free damage structure */
  267         if (xf86_config->rotation_damage_registered) {
  268             xf86_config->rotation_damage_registered = FALSE;
  269             DisableLimitedSchedulingLatency();
  270         }
  271         DamageDestroy(xf86_config->rotation_damage);
  272         xf86_config->rotation_damage = NULL;
  273     }
  274 }
  275 
  276 void
  277 xf86RotateFreeShadow(ScrnInfoPtr pScrn)
  278 {
  279     xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
  280     int c;
  281 
  282     for (c = 0; c < config->num_crtc; c++) {
  283         xf86CrtcPtr crtc = config->crtc[c];
  284 
  285         if (crtc->rotatedPixmap || crtc->rotatedData) {
  286             crtc->funcs->shadow_destroy(crtc, crtc->rotatedPixmap,
  287                                         crtc->rotatedData);
  288             crtc->rotatedPixmap = NULL;
  289             crtc->rotatedData = NULL;
  290         }
  291     }
  292 }
  293 
  294 void
  295 xf86RotateCloseScreen(ScreenPtr screen)
  296 {
  297     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
  298     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
  299     int c;
  300 
  301     /* This has already been destroyed when the root window was destroyed */
  302     xf86_config->rotation_damage = NULL;
  303     for (c = 0; c < xf86_config->num_crtc; c++)
  304         xf86RotateDestroy(xf86_config->crtc[c]);
  305 }
  306 
  307 static Bool
  308 xf86CrtcFitsScreen(xf86CrtcPtr crtc, struct pict_f_transform *crtc_to_fb)
  309 {
  310     ScrnInfoPtr pScrn = crtc->scrn;
  311     BoxRec b;
  312 
  313     /* When called before PreInit, the driver is
  314      * presumably doing load detect
  315      */
  316     if (pScrn->is_gpu) {
  317     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
  318     if (pScreen->current_master)
  319         pScrn = xf86ScreenToScrn(pScreen->current_master);
  320     }
  321 
  322     if (pScrn->virtualX == 0 || pScrn->virtualY == 0)
  323         return TRUE;
  324 
  325     b.x1 = 0;
  326     b.y1 = 0;
  327     b.x2 = crtc->mode.HDisplay;
  328     b.y2 = crtc->mode.VDisplay;
  329     if (crtc_to_fb)
  330         pixman_f_transform_bounds(crtc_to_fb, &b);
  331     else {
  332         b.x1 += crtc->x;
  333         b.y1 += crtc->y;
  334         b.x2 += crtc->x;
  335         b.y2 += crtc->y;
  336     }
  337 
  338     return (0 <= b.x1 && b.x2 <= pScrn->virtualX &&
  339             0 <= b.y1 && b.y2 <= pScrn->virtualY);
  340 }
  341 
  342 Bool
  343 xf86CrtcRotate(xf86CrtcPtr crtc)
  344 {
  345     ScrnInfoPtr pScrn = crtc->scrn;
  346     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
  347     ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
  348     PictTransform crtc_to_fb;
  349     struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc;
  350     xFixed *new_params = NULL;
  351     int new_nparams = 0;
  352     PictFilterPtr new_filter = NULL;
  353     int new_width = 0;
  354     int new_height = 0;
  355     RRTransformPtr transform = NULL;
  356     Bool damage = FALSE;
  357 
  358     if (pScreen->isGPU)
  359         return TRUE;
  360     if (crtc->transformPresent)
  361         transform = &crtc->transform;
  362 
  363     if (!RRTransformCompute(crtc->x, crtc->y,
  364                             crtc->mode.HDisplay, crtc->mode.VDisplay,
  365                             crtc->rotation,
  366                             transform,
  367                             &crtc_to_fb,
  368                             &f_crtc_to_fb,
  369                             &f_fb_to_crtc) &&
  370         xf86CrtcFitsScreen(crtc, &f_crtc_to_fb)) {
  371         /*
  372          * If the untranslated transformation is the identity,
  373          * disable the shadow buffer
  374          */
  375         xf86RotateDestroy(crtc);
  376         crtc->transform_in_use = FALSE;
  377         free(new_params);
  378         new_params = NULL;
  379         new_nparams = 0;
  380         new_filter = NULL;
  381         new_width = 0;
  382         new_height = 0;
  383     }
  384     else {
  385         if (crtc->driverIsPerformingTransform & XF86DriverTransformOutput) {
  386             xf86RotateDestroy(crtc);
  387         }
  388         else {
  389             /*
  390              * these are the size of the shadow pixmap, which
  391              * matches the mode, not the pre-rotated copy in the
  392              * frame buffer
  393              */
  394             int width = crtc->mode.HDisplay;
  395             int height = crtc->mode.VDisplay;
  396             void *shadowData = crtc->rotatedData;
  397             PixmapPtr shadow = crtc->rotatedPixmap;
  398             int old_width = shadow ? shadow->drawable.width : 0;
  399             int old_height = shadow ? shadow->drawable.height : 0;
  400 
  401             /* Allocate memory for rotation */
  402             if (old_width != width || old_height != height) {
  403                 if (shadow || shadowData) {
  404                     crtc->funcs->shadow_destroy(crtc, shadow, shadowData);
  405                     crtc->rotatedPixmap = NULL;
  406                     crtc->rotatedData = NULL;
  407                 }
  408                 shadowData = crtc->funcs->shadow_allocate(crtc, width, height);
  409                 if (!shadowData)
  410                     goto bail1;
  411                 crtc->rotatedData = shadowData;
  412                 /* shadow will be damaged in xf86RotatePrepare */
  413             }
  414             else {
  415                 /* mark shadowed area as damaged so it will be repainted */
  416                 damage = TRUE;
  417             }
  418 
  419             if (!xf86_config->rotation_damage) {
  420                 /* Create damage structure */
  421                 xf86_config->rotation_damage = DamageCreate(NULL, NULL,
  422                                                             DamageReportNone,
  423                                                             TRUE, pScreen,
  424                                                             pScreen);
  425                 if (!xf86_config->rotation_damage)
  426                     goto bail2;
  427 
  428                 /* Wrap block handler */
  429                 if (!xf86_config->BlockHandler) {
  430                     xf86_config->BlockHandler = pScreen->BlockHandler;
  431                     pScreen->BlockHandler = xf86RotateBlockHandler;
  432                 }
  433             }
  434 
  435             if (0) {
  436  bail2:
  437                 if (shadow || shadowData) {
  438                     crtc->funcs->shadow_destroy(crtc, shadow, shadowData);
  439                     crtc->rotatedPixmap = NULL;
  440                     crtc->rotatedData = NULL;
  441                 }
  442  bail1:
  443                 if (old_width && old_height)
  444                     crtc->rotatedPixmap =
  445                         crtc->funcs->shadow_create(crtc, NULL, old_width,
  446                                                    old_height);
  447                 return FALSE;
  448             }
  449         }
  450 #ifdef RANDR_12_INTERFACE
  451         if (transform) {
  452             if (transform->nparams) {
  453                 new_params = malloc(transform->nparams * sizeof(xFixed));
  454                 if (new_params) {
  455                     memcpy(new_params, transform->params,
  456                            transform->nparams * sizeof(xFixed));
  457                     new_nparams = transform->nparams;
  458                     new_filter = transform->filter;
  459                 }
  460             }
  461             else
  462                 new_filter = transform->filter;
  463             if (new_filter) {
  464                 new_width = new_filter->width;
  465                 new_height = new_filter->height;
  466             }
  467         }
  468 #endif
  469         crtc->transform_in_use = TRUE;
  470     }
  471     crtc->crtc_to_framebuffer = crtc_to_fb;
  472     crtc->f_crtc_to_framebuffer = f_crtc_to_fb;
  473     crtc->f_framebuffer_to_crtc = f_fb_to_crtc;
  474     free(crtc->params);
  475     crtc->params = new_params;
  476     crtc->nparams = new_nparams;
  477     crtc->filter = new_filter;
  478     crtc->filter_width = new_width;
  479     crtc->filter_height = new_height;
  480     crtc->bounds.x1 = 0;
  481     crtc->bounds.x2 = crtc->mode.HDisplay;
  482     crtc->bounds.y1 = 0;
  483     crtc->bounds.y2 = crtc->mode.VDisplay;
  484     pixman_f_transform_bounds(&f_crtc_to_fb, &crtc->bounds);
  485 
  486     if (damage)
  487         xf86CrtcDamageShadow(crtc);
  488     else if (crtc->rotatedData && !crtc->rotatedPixmap)
  489         /* Make sure the new rotate buffer has valid transformed contents */
  490         xf86RotateRedisplay(pScreen);
  491 
  492     /* All done */
  493     return TRUE;
  494 }