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