| @@ -1,1232 +1,1242 @@ | | | @@ -1,1232 +1,1242 @@ |
1 | /* | | 1 | /* |
2 | * Copyright © 2001 Keith Packard | | 2 | * Copyright © 2001 Keith Packard |
3 | * | | 3 | * |
4 | * Partly based on code that is Copyright © The XFree86 Project Inc. | | 4 | * Partly based on code that is Copyright © The XFree86 Project Inc. |
5 | * | | 5 | * |
6 | * Permission to use, copy, modify, distribute, and sell this software and its | | 6 | * Permission to use, copy, modify, distribute, and sell this software and its |
7 | * documentation for any purpose is hereby granted without fee, provided that | | 7 | * documentation for any purpose is hereby granted without fee, provided that |
8 | * the above copyright notice appear in all copies and that both that | | 8 | * the above copyright notice appear in all copies and that both that |
9 | * copyright notice and this permission notice appear in supporting | | 9 | * copyright notice and this permission notice appear in supporting |
10 | * documentation, and that the name of Keith Packard not be used in | | 10 | * documentation, and that the name of Keith Packard not be used in |
11 | * advertising or publicity pertaining to distribution of the software without | | 11 | * advertising or publicity pertaining to distribution of the software without |
12 | * specific, written prior permission. Keith Packard makes no | | 12 | * specific, written prior permission. Keith Packard makes no |
13 | * representations about the suitability of this software for any purpose. It | | 13 | * representations about the suitability of this software for any purpose. It |
14 | * is provided "as is" without express or implied warranty. | | 14 | * is provided "as is" without express or implied warranty. |
15 | * | | 15 | * |
16 | * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | | 16 | * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
17 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | | 17 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO |
18 | * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR | | 18 | * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
19 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | | 19 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, |
20 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | | 20 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
21 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | | 21 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
22 | * PERFORMANCE OF THIS SOFTWARE. | | 22 | * PERFORMANCE OF THIS SOFTWARE. |
23 | * | | 23 | * |
24 | * Authors: | | 24 | * Authors: |
25 | * Eric Anholt <eric@anholt.net> | | 25 | * Eric Anholt <eric@anholt.net> |
26 | * Michel Dänzer <michel@tungstengraphics.com> | | 26 | * Michel Dänzer <michel@tungstengraphics.com> |
27 | * | | 27 | * |
28 | */ | | 28 | */ |
29 | | | 29 | |
30 | #ifdef HAVE_DIX_CONFIG_H | | 30 | #ifdef HAVE_DIX_CONFIG_H |
31 | #include <dix-config.h> | | 31 | #include <dix-config.h> |
32 | #endif | | 32 | #endif |
33 | #include "exa_priv.h" | | 33 | #include "exa_priv.h" |
34 | #include <X11/fonts/fontstruct.h> | | 34 | #include <X11/fonts/fontstruct.h> |
35 | #include "dixfontstr.h" | | 35 | #include "dixfontstr.h" |
36 | #include "exa.h" | | 36 | #include "exa.h" |
37 | | | 37 | |
38 | static void | | 38 | static void |
39 | exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, | | 39 | exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n, |
40 | DDXPointPtr ppt, int *pwidth, int fSorted) | | 40 | DDXPointPtr ppt, int *pwidth, int fSorted) |
41 | { | | 41 | { |
42 | ScreenPtr pScreen = pDrawable->pScreen; | | 42 | ScreenPtr pScreen = pDrawable->pScreen; |
43 | ExaScreenPriv (pScreen); | | 43 | ExaScreenPriv (pScreen); |
44 | RegionPtr pClip = fbGetCompositeClip(pGC); | | 44 | RegionPtr pClip = fbGetCompositeClip(pGC); |
45 | PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); | | 45 | PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); |
46 | ExaPixmapPriv (pPixmap); | | 46 | ExaPixmapPriv (pPixmap); |
47 | BoxPtr pextent, pbox; | | 47 | BoxPtr pextent, pbox; |
48 | int nbox; | | 48 | int nbox; |
49 | int extentX1, extentX2, extentY1, extentY2; | | 49 | int extentX1, extentX2, extentY1, extentY2; |
50 | int fullX1, fullX2, fullY1; | | 50 | int fullX1, fullX2, fullY1; |
51 | int partX1, partX2; | | 51 | int partX1, partX2; |
52 | int off_x, off_y; | | 52 | int off_x, off_y; |
53 | ExaMigrationRec pixmaps[1]; | | 53 | ExaMigrationRec pixmaps[1]; |
54 | | | 54 | |
55 | pixmaps[0].as_dst = TRUE; | | 55 | pixmaps[0].as_dst = TRUE; |
56 | pixmaps[0].as_src = FALSE; | | 56 | pixmaps[0].as_src = FALSE; |
57 | pixmaps[0].pPix = pPixmap; | | 57 | pixmaps[0].pPix = pPixmap; |
58 | pixmaps[0].pReg = NULL; | | 58 | pixmaps[0].pReg = NULL; |
59 | | | 59 | |
60 | if (pExaScr->swappedOut || | | 60 | if (pExaScr->swappedOut || |
61 | pGC->fillStyle != FillSolid || | | 61 | pGC->fillStyle != FillSolid || |
62 | pExaPixmap->accel_blocked) | | 62 | pExaPixmap->accel_blocked) |
63 | { | | 63 | { |
64 | ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted); | | 64 | ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted); |
65 | return; | | 65 | return; |
66 | } else { | | 66 | } else { |
67 | exaDoMigration (pixmaps, 1, TRUE); | | 67 | exaDoMigration (pixmaps, 1, TRUE); |
68 | } | | 68 | } |
69 | | | 69 | |
70 | if (!(pPixmap = exaGetOffscreenPixmap (pDrawable, &off_x, &off_y)) || | | 70 | if (!(pPixmap = exaGetOffscreenPixmap (pDrawable, &off_x, &off_y)) || |
71 | !(*pExaScr->info->PrepareSolid) (pPixmap, | | 71 | !(*pExaScr->info->PrepareSolid) (pPixmap, |
72 | pGC->alu, | | 72 | pGC->alu, |
73 | pGC->planemask, | | 73 | pGC->planemask, |
74 | pGC->fgPixel)) | | 74 | pGC->fgPixel)) |
75 | { | | 75 | { |
76 | ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted); | | 76 | ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted); |
77 | return; | | 77 | return; |
78 | } | | 78 | } |
79 | | | 79 | |
80 | pextent = REGION_EXTENTS(pGC->pScreen, pClip); | | 80 | pextent = REGION_EXTENTS(pGC->pScreen, pClip); |
81 | extentX1 = pextent->x1; | | 81 | extentX1 = pextent->x1; |
82 | extentY1 = pextent->y1; | | 82 | extentY1 = pextent->y1; |
83 | extentX2 = pextent->x2; | | 83 | extentX2 = pextent->x2; |
84 | extentY2 = pextent->y2; | | 84 | extentY2 = pextent->y2; |
85 | while (n--) | | 85 | while (n--) |
86 | { | | 86 | { |
87 | fullX1 = ppt->x; | | 87 | fullX1 = ppt->x; |
88 | fullY1 = ppt->y; | | 88 | fullY1 = ppt->y; |
89 | fullX2 = fullX1 + (int) *pwidth; | | 89 | fullX2 = fullX1 + (int) *pwidth; |
90 | ppt++; | | 90 | ppt++; |
91 | pwidth++; | | 91 | pwidth++; |
92 | | | 92 | |
93 | if (fullY1 < extentY1 || extentY2 <= fullY1) | | 93 | if (fullY1 < extentY1 || extentY2 <= fullY1) |
94 | continue; | | 94 | continue; |
95 | | | 95 | |
96 | if (fullX1 < extentX1) | | 96 | if (fullX1 < extentX1) |
97 | fullX1 = extentX1; | | 97 | fullX1 = extentX1; |
98 | | | 98 | |
99 | if (fullX2 > extentX2) | | 99 | if (fullX2 > extentX2) |
100 | fullX2 = extentX2; | | 100 | fullX2 = extentX2; |
101 | | | 101 | |
102 | if (fullX1 >= fullX2) | | 102 | if (fullX1 >= fullX2) |
103 | continue; | | 103 | continue; |
104 | | | 104 | |
105 | nbox = REGION_NUM_RECTS (pClip); | | 105 | nbox = REGION_NUM_RECTS (pClip); |
106 | if (nbox == 1) | | 106 | if (nbox == 1) |
107 | { | | 107 | { |
108 | (*pExaScr->info->Solid) (pPixmap, | | 108 | (*pExaScr->info->Solid) (pPixmap, |
109 | fullX1 + off_x, fullY1 + off_y, | | 109 | fullX1 + off_x, fullY1 + off_y, |
110 | fullX2 + off_x, fullY1 + 1 + off_y); | | 110 | fullX2 + off_x, fullY1 + 1 + off_y); |
111 | } | | 111 | } |
112 | else | | 112 | else |
113 | { | | 113 | { |
114 | pbox = REGION_RECTS(pClip); | | 114 | pbox = REGION_RECTS(pClip); |
115 | while(nbox--) | | 115 | while(nbox--) |
116 | { | | 116 | { |
117 | if (pbox->y1 <= fullY1 && fullY1 < pbox->y2) | | 117 | if (pbox->y1 <= fullY1 && fullY1 < pbox->y2) |
118 | { | | 118 | { |
119 | partX1 = pbox->x1; | | 119 | partX1 = pbox->x1; |
120 | if (partX1 < fullX1) | | 120 | if (partX1 < fullX1) |
121 | partX1 = fullX1; | | 121 | partX1 = fullX1; |
122 | partX2 = pbox->x2; | | 122 | partX2 = pbox->x2; |
123 | if (partX2 > fullX2) | | 123 | if (partX2 > fullX2) |
124 | partX2 = fullX2; | | 124 | partX2 = fullX2; |
125 | if (partX2 > partX1) { | | 125 | if (partX2 > partX1) { |
126 | (*pExaScr->info->Solid) (pPixmap, | | 126 | (*pExaScr->info->Solid) (pPixmap, |
127 | partX1 + off_x, fullY1 + off_y, | | 127 | partX1 + off_x, fullY1 + off_y, |
128 | partX2 + off_x, fullY1 + 1 + off_y); | | 128 | partX2 + off_x, fullY1 + 1 + off_y); |
129 | } | | 129 | } |
130 | } | | 130 | } |
131 | pbox++; | | 131 | pbox++; |
132 | } | | 132 | } |
133 | } | | 133 | } |
134 | } | | 134 | } |
135 | (*pExaScr->info->DoneSolid) (pPixmap); | | 135 | (*pExaScr->info->DoneSolid) (pPixmap); |
136 | exaMarkSync(pScreen); | | 136 | exaMarkSync(pScreen); |
137 | } | | 137 | } |
138 | | | 138 | |
139 | static Bool | | 139 | static Bool |
140 | exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, | | 140 | exaDoPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, |
141 | int w, int h, int format, char *bits, int src_stride) | | 141 | int w, int h, int format, char *bits, int src_stride) |
142 | { | | 142 | { |
143 | ExaScreenPriv (pDrawable->pScreen); | | 143 | ExaScreenPriv (pDrawable->pScreen); |
144 | PixmapPtr pPix = exaGetDrawablePixmap (pDrawable); | | 144 | PixmapPtr pPix = exaGetDrawablePixmap (pDrawable); |
145 | ExaPixmapPriv(pPix); | | 145 | ExaPixmapPriv(pPix); |
146 | RegionPtr pClip; | | 146 | RegionPtr pClip; |
147 | BoxPtr pbox; | | 147 | BoxPtr pbox; |
148 | int nbox; | | 148 | int nbox; |
149 | int xoff, yoff; | | 149 | int xoff, yoff; |
150 | int bpp = pDrawable->bitsPerPixel; | | 150 | int bpp = pDrawable->bitsPerPixel; |
151 | Bool access_prepared = FALSE; | | 151 | Bool access_prepared = FALSE; |
152 | | | 152 | |
153 | if (pExaPixmap->accel_blocked) | | 153 | if (pExaPixmap->accel_blocked) |
154 | return FALSE; | | 154 | return FALSE; |
155 | | | 155 | |
156 | /* Don't bother with under 8bpp, XYPixmaps. */ | | 156 | /* Don't bother with under 8bpp, XYPixmaps. */ |
157 | if (format != ZPixmap || bpp < 8) | | 157 | if (format != ZPixmap || bpp < 8) |
158 | return FALSE; | | 158 | return FALSE; |
159 | | | 159 | |
160 | /* Only accelerate copies: no rop or planemask. */ | | 160 | /* Only accelerate copies: no rop or planemask. */ |
161 | if (!EXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy) | | 161 | if (!EXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy) |
162 | return FALSE; | | 162 | return FALSE; |
163 | | | 163 | |
164 | if (pExaScr->swappedOut) | | 164 | if (pExaScr->swappedOut) |
165 | return FALSE; | | 165 | return FALSE; |
166 | | | 166 | |
167 | if (pExaPixmap->pDamage) { | | 167 | if (pExaPixmap->pDamage) { |
168 | ExaMigrationRec pixmaps[1]; | | 168 | ExaMigrationRec pixmaps[1]; |
169 | | | 169 | |
170 | pixmaps[0].as_dst = TRUE; | | 170 | pixmaps[0].as_dst = TRUE; |
171 | pixmaps[0].as_src = FALSE; | | 171 | pixmaps[0].as_src = FALSE; |
172 | pixmaps[0].pPix = pPix; | | 172 | pixmaps[0].pPix = pPix; |
173 | pixmaps[0].pReg = DamagePendingRegion(pExaPixmap->pDamage); | | 173 | pixmaps[0].pReg = DamagePendingRegion(pExaPixmap->pDamage); |
174 | | | 174 | |
175 | exaDoMigration (pixmaps, 1, TRUE); | | 175 | exaDoMigration (pixmaps, 1, TRUE); |
176 | } | | 176 | } |
177 | | | 177 | |
178 | pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); | | 178 | pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); |
179 | | | 179 | |
180 | if (!pPix || !pExaScr->info->UploadToScreen) | | 180 | if (!pPix || !pExaScr->info->UploadToScreen) |
181 | return FALSE; | | 181 | return FALSE; |
182 | | | 182 | |
183 | x += pDrawable->x; | | 183 | x += pDrawable->x; |
184 | y += pDrawable->y; | | 184 | y += pDrawable->y; |
185 | | | 185 | |
186 | pClip = fbGetCompositeClip(pGC); | | 186 | pClip = fbGetCompositeClip(pGC); |
187 | for (nbox = REGION_NUM_RECTS(pClip), | | 187 | for (nbox = REGION_NUM_RECTS(pClip), |
188 | pbox = REGION_RECTS(pClip); | | 188 | pbox = REGION_RECTS(pClip); |
189 | nbox--; | | 189 | nbox--; |
190 | pbox++) | | 190 | pbox++) |
191 | { | | 191 | { |
192 | int x1 = x; | | 192 | int x1 = x; |
193 | int y1 = y; | | 193 | int y1 = y; |
194 | int x2 = x + w; | | 194 | int x2 = x + w; |
195 | int y2 = y + h; | | 195 | int y2 = y + h; |
196 | char *src; | | 196 | char *src; |
197 | Bool ok; | | 197 | Bool ok; |
198 | | | 198 | |
199 | if (x1 < pbox->x1) | | 199 | if (x1 < pbox->x1) |
200 | x1 = pbox->x1; | | 200 | x1 = pbox->x1; |
201 | if (y1 < pbox->y1) | | 201 | if (y1 < pbox->y1) |
202 | y1 = pbox->y1; | | 202 | y1 = pbox->y1; |
203 | if (x2 > pbox->x2) | | 203 | if (x2 > pbox->x2) |
204 | x2 = pbox->x2; | | 204 | x2 = pbox->x2; |
205 | if (y2 > pbox->y2) | | 205 | if (y2 > pbox->y2) |
206 | y2 = pbox->y2; | | 206 | y2 = pbox->y2; |
207 | if (x1 >= x2 || y1 >= y2) | | 207 | if (x1 >= x2 || y1 >= y2) |
208 | continue; | | 208 | continue; |
209 | | | 209 | |
210 | src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8); | | 210 | src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8); |
211 | ok = pExaScr->info->UploadToScreen(pPix, x1 + xoff, y1 + yoff, | | 211 | ok = pExaScr->info->UploadToScreen(pPix, x1 + xoff, y1 + yoff, |
212 | x2 - x1, y2 - y1, src, src_stride); | | 212 | x2 - x1, y2 - y1, src, src_stride); |
213 | /* If we fail to accelerate the upload, fall back to using unaccelerated | | 213 | /* If we fail to accelerate the upload, fall back to using unaccelerated |
214 | * fb calls. | | 214 | * fb calls. |
215 | */ | | 215 | */ |
216 | if (!ok) { | | 216 | if (!ok) { |
217 | FbStip *dst; | | 217 | FbStip *dst; |
218 | FbStride dst_stride; | | 218 | FbStride dst_stride; |
219 | int dstBpp; | | 219 | int dstBpp; |
220 | int dstXoff, dstYoff; | | 220 | int dstXoff, dstYoff; |
221 | | | 221 | |
222 | if (!access_prepared) { | | 222 | if (!access_prepared) { |
223 | ExaDoPrepareAccess(pDrawable, EXA_PREPARE_DEST); | | 223 | ExaDoPrepareAccess(pDrawable, EXA_PREPARE_DEST); |
224 | | | 224 | |
225 | access_prepared = TRUE; | | 225 | access_prepared = TRUE; |
226 | } | | 226 | } |
227 | | | 227 | |
228 | fbGetStipDrawable(pDrawable, dst, dst_stride, dstBpp, | | 228 | fbGetStipDrawable(pDrawable, dst, dst_stride, dstBpp, |
229 | dstXoff, dstYoff); | | 229 | dstXoff, dstYoff); |
230 | | | 230 | |
231 | fbBltStip((FbStip *)bits + (y1 - y) * (src_stride / sizeof(FbStip)), | | 231 | fbBltStip((FbStip *)bits + (y1 - y) * (src_stride / sizeof(FbStip)), |
232 | src_stride / sizeof(FbStip), | | 232 | src_stride / sizeof(FbStip), |
233 | (x1 - x) * dstBpp, | | 233 | (x1 - x) * dstBpp, |
234 | dst + (y1 + dstYoff) * dst_stride, | | 234 | dst + (y1 + dstYoff) * dst_stride, |
235 | dst_stride, | | 235 | dst_stride, |
236 | (x1 + dstXoff) * dstBpp, | | 236 | (x1 + dstXoff) * dstBpp, |
237 | (x2 - x1) * dstBpp, | | 237 | (x2 - x1) * dstBpp, |
238 | y2 - y1, | | 238 | y2 - y1, |
239 | GXcopy, FB_ALLONES, dstBpp); | | 239 | GXcopy, FB_ALLONES, dstBpp); |
240 | } | | 240 | } |
241 | } | | 241 | } |
242 | | | 242 | |
243 | if (access_prepared) | | 243 | if (access_prepared) |
244 | exaFinishAccess(pDrawable, EXA_PREPARE_DEST); | | 244 | exaFinishAccess(pDrawable, EXA_PREPARE_DEST); |
245 | else | | 245 | else |
246 | exaMarkSync(pDrawable->pScreen); | | 246 | exaMarkSync(pDrawable->pScreen); |
247 | | | 247 | |
248 | return TRUE; | | 248 | return TRUE; |
249 | } | | 249 | } |
250 | | | 250 | |
251 | static void | | 251 | static void |
252 | exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, | | 252 | exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, |
253 | int w, int h, int leftPad, int format, char *bits) | | 253 | int w, int h, int leftPad, int format, char *bits) |
254 | { | | 254 | { |
255 | if (!exaDoPutImage(pDrawable, pGC, depth, x, y, w, h, format, bits, | | 255 | if (!exaDoPutImage(pDrawable, pGC, depth, x, y, w, h, format, bits, |
256 | PixmapBytePad(w, pDrawable->depth))) | | 256 | PixmapBytePad(w, pDrawable->depth))) |
257 | ExaCheckPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, | | 257 | ExaCheckPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, |
258 | bits); | | 258 | bits); |
259 | } | | 259 | } |
260 | | | 260 | |
261 | static Bool inline | | 261 | static Bool inline |
262 | exaCopyNtoNTwoDir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, | | 262 | exaCopyNtoNTwoDir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, |
263 | GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy) | | 263 | GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy) |
264 | { | | 264 | { |
265 | ExaScreenPriv (pDstDrawable->pScreen); | | 265 | ExaScreenPriv (pDstDrawable->pScreen); |
266 | PixmapPtr pSrcPixmap, pDstPixmap; | | 266 | PixmapPtr pSrcPixmap, pDstPixmap; |
267 | int src_off_x, src_off_y, dst_off_x, dst_off_y; | | 267 | int src_off_x, src_off_y, dst_off_x, dst_off_y; |
268 | int dirsetup; | | 268 | int dirsetup; |
269 | | | 269 | |
270 | /* Need to get both pixmaps to call the driver routines */ | | 270 | /* Need to get both pixmaps to call the driver routines */ |
271 | pSrcPixmap = exaGetOffscreenPixmap (pSrcDrawable, &src_off_x, &src_off_y); | | 271 | pSrcPixmap = exaGetOffscreenPixmap (pSrcDrawable, &src_off_x, &src_off_y); |
272 | pDstPixmap = exaGetOffscreenPixmap (pDstDrawable, &dst_off_x, &dst_off_y); | | 272 | pDstPixmap = exaGetOffscreenPixmap (pDstDrawable, &dst_off_x, &dst_off_y); |
273 | if (!pSrcPixmap || !pDstPixmap) | | 273 | if (!pSrcPixmap || !pDstPixmap) |
274 | return FALSE; | | 274 | return FALSE; |
275 | | | 275 | |
276 | /* | | 276 | /* |
277 | * Now the case of a chip that only supports xdir = ydir = 1 or | | 277 | * Now the case of a chip that only supports xdir = ydir = 1 or |
278 | * xdir = ydir = -1, but we have xdir != ydir. | | 278 | * xdir = ydir = -1, but we have xdir != ydir. |
279 | */ | | 279 | */ |
280 | dirsetup = 0; /* No direction set up yet. */ | | 280 | dirsetup = 0; /* No direction set up yet. */ |
281 | for (; nbox; pbox++, nbox--) { | | 281 | for (; nbox; pbox++, nbox--) { |
282 | if (dx >= 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) { | | 282 | if (dx >= 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) { |
283 | /* Do a xdir = ydir = -1 blit instead. */ | | 283 | /* Do a xdir = ydir = -1 blit instead. */ |
284 | if (dirsetup != -1) { | | 284 | if (dirsetup != -1) { |
285 | if (dirsetup != 0) | | 285 | if (dirsetup != 0) |
286 | pExaScr->info->DoneCopy(pDstPixmap); | | 286 | pExaScr->info->DoneCopy(pDstPixmap); |
287 | dirsetup = -1; | | 287 | dirsetup = -1; |
288 | if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap, | | 288 | if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap, |
289 | pDstPixmap, | | 289 | pDstPixmap, |
290 | -1, -1, | | 290 | -1, -1, |
291 | pGC ? pGC->alu : GXcopy, | | 291 | pGC ? pGC->alu : GXcopy, |
292 | pGC ? pGC->planemask : | | 292 | pGC ? pGC->planemask : |
293 | FB_ALLONES)) | | 293 | FB_ALLONES)) |
294 | return FALSE; | | 294 | return FALSE; |
295 | } | | 295 | } |
296 | (*pExaScr->info->Copy)(pDstPixmap, | | 296 | (*pExaScr->info->Copy)(pDstPixmap, |
297 | src_off_x + pbox->x1 + dx, | | 297 | src_off_x + pbox->x1 + dx, |
298 | src_off_y + pbox->y1 + dy, | | 298 | src_off_y + pbox->y1 + dy, |
299 | dst_off_x + pbox->x1, | | 299 | dst_off_x + pbox->x1, |
300 | dst_off_y + pbox->y1, | | 300 | dst_off_y + pbox->y1, |
301 | pbox->x2 - pbox->x1, | | 301 | pbox->x2 - pbox->x1, |
302 | pbox->y2 - pbox->y1); | | 302 | pbox->y2 - pbox->y1); |
303 | } else if (dx < 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) { | | 303 | } else if (dx < 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) { |
304 | /* Do a xdir = ydir = 1 blit instead. */ | | 304 | /* Do a xdir = ydir = 1 blit instead. */ |
305 | if (dirsetup != 1) { | | 305 | if (dirsetup != 1) { |
306 | if (dirsetup != 0) | | 306 | if (dirsetup != 0) |
307 | pExaScr->info->DoneCopy(pDstPixmap); | | 307 | pExaScr->info->DoneCopy(pDstPixmap); |
308 | dirsetup = 1; | | 308 | dirsetup = 1; |
309 | if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap, | | 309 | if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap, |
310 | pDstPixmap, | | 310 | pDstPixmap, |
311 | 1, 1, | | 311 | 1, 1, |
312 | pGC ? pGC->alu : GXcopy, | | 312 | pGC ? pGC->alu : GXcopy, |
313 | pGC ? pGC->planemask : | | 313 | pGC ? pGC->planemask : |
314 | FB_ALLONES)) | | 314 | FB_ALLONES)) |
315 | return FALSE; | | 315 | return FALSE; |
316 | } | | 316 | } |
317 | (*pExaScr->info->Copy)(pDstPixmap, | | 317 | (*pExaScr->info->Copy)(pDstPixmap, |
318 | src_off_x + pbox->x1 + dx, | | 318 | src_off_x + pbox->x1 + dx, |
319 | src_off_y + pbox->y1 + dy, | | 319 | src_off_y + pbox->y1 + dy, |
320 | dst_off_x + pbox->x1, | | 320 | dst_off_x + pbox->x1, |
321 | dst_off_y + pbox->y1, | | 321 | dst_off_y + pbox->y1, |
322 | pbox->x2 - pbox->x1, | | 322 | pbox->x2 - pbox->x1, |
323 | pbox->y2 - pbox->y1); | | 323 | pbox->y2 - pbox->y1); |
324 | } else if (dx >= 0) { | | 324 | } else if (dx >= 0) { |
325 | /* | | 325 | /* |
326 | * xdir = 1, ydir = -1. | | 326 | * xdir = 1, ydir = -1. |
327 | * Perform line-by-line xdir = ydir = 1 blits, going up. | | 327 | * Perform line-by-line xdir = ydir = 1 blits, going up. |
328 | */ | | 328 | */ |
329 | int i; | | 329 | int i; |
330 | if (dirsetup != 1) { | | 330 | if (dirsetup != 1) { |
331 | if (dirsetup != 0) | | 331 | if (dirsetup != 0) |
332 | pExaScr->info->DoneCopy(pDstPixmap); | | 332 | pExaScr->info->DoneCopy(pDstPixmap); |
333 | dirsetup = 1; | | 333 | dirsetup = 1; |
334 | if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap, | | 334 | if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap, |
335 | pDstPixmap, | | 335 | pDstPixmap, |
336 | 1, 1, | | 336 | 1, 1, |
337 | pGC ? pGC->alu : GXcopy, | | 337 | pGC ? pGC->alu : GXcopy, |
338 | pGC ? pGC->planemask : | | 338 | pGC ? pGC->planemask : |
339 | FB_ALLONES)) | | 339 | FB_ALLONES)) |
340 | return FALSE; | | 340 | return FALSE; |
341 | } | | 341 | } |
342 | for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--) | | 342 | for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--) |
343 | (*pExaScr->info->Copy)(pDstPixmap, | | 343 | (*pExaScr->info->Copy)(pDstPixmap, |
344 | src_off_x + pbox->x1 + dx, | | 344 | src_off_x + pbox->x1 + dx, |
345 | src_off_y + pbox->y1 + dy + i, | | 345 | src_off_y + pbox->y1 + dy + i, |
346 | dst_off_x + pbox->x1, | | 346 | dst_off_x + pbox->x1, |
347 | dst_off_y + pbox->y1 + i, | | 347 | dst_off_y + pbox->y1 + i, |
348 | pbox->x2 - pbox->x1, 1); | | 348 | pbox->x2 - pbox->x1, 1); |
349 | } else { | | 349 | } else { |
350 | /* | | 350 | /* |
351 | * xdir = -1, ydir = 1. | | 351 | * xdir = -1, ydir = 1. |
352 | * Perform line-by-line xdir = ydir = -1 blits, going down. | | 352 | * Perform line-by-line xdir = ydir = -1 blits, going down. |
353 | */ | | 353 | */ |
354 | int i; | | 354 | int i; |
355 | if (dirsetup != -1) { | | 355 | if (dirsetup != -1) { |
356 | if (dirsetup != 0) | | 356 | if (dirsetup != 0) |
357 | pExaScr->info->DoneCopy(pDstPixmap); | | 357 | pExaScr->info->DoneCopy(pDstPixmap); |
358 | dirsetup = -1; | | 358 | dirsetup = -1; |
359 | if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap, | | 359 | if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap, |
360 | pDstPixmap, | | 360 | pDstPixmap, |
361 | -1, -1, | | 361 | -1, -1, |
362 | pGC ? pGC->alu : GXcopy, | | 362 | pGC ? pGC->alu : GXcopy, |
363 | pGC ? pGC->planemask : | | 363 | pGC ? pGC->planemask : |
364 | FB_ALLONES)) | | 364 | FB_ALLONES)) |
365 | return FALSE; | | 365 | return FALSE; |
366 | } | | 366 | } |
367 | for (i = 0; i < pbox->y2 - pbox->y1; i++) | | 367 | for (i = 0; i < pbox->y2 - pbox->y1; i++) |
368 | (*pExaScr->info->Copy)(pDstPixmap, | | 368 | (*pExaScr->info->Copy)(pDstPixmap, |
369 | src_off_x + pbox->x1 + dx, | | 369 | src_off_x + pbox->x1 + dx, |
370 | src_off_y + pbox->y1 + dy + i, | | 370 | src_off_y + pbox->y1 + dy + i, |
371 | dst_off_x + pbox->x1, | | 371 | dst_off_x + pbox->x1, |
372 | dst_off_y + pbox->y1 + i, | | 372 | dst_off_y + pbox->y1 + i, |
373 | pbox->x2 - pbox->x1, 1); | | 373 | pbox->x2 - pbox->x1, 1); |
374 | } | | 374 | } |
375 | } | | 375 | } |
376 | if (dirsetup != 0) | | 376 | if (dirsetup != 0) |
377 | pExaScr->info->DoneCopy(pDstPixmap); | | 377 | pExaScr->info->DoneCopy(pDstPixmap); |
378 | exaMarkSync(pDstDrawable->pScreen); | | 378 | exaMarkSync(pDstDrawable->pScreen); |
379 | return TRUE; | | 379 | return TRUE; |
380 | } | | 380 | } |
381 | | | 381 | |
382 | void | | 382 | void |
383 | exaCopyNtoN (DrawablePtr pSrcDrawable, | | 383 | exaCopyNtoN (DrawablePtr pSrcDrawable, |
384 | DrawablePtr pDstDrawable, | | 384 | DrawablePtr pDstDrawable, |
385 | GCPtr pGC, | | 385 | GCPtr pGC, |
386 | BoxPtr pbox, | | 386 | BoxPtr pbox, |
387 | int nbox, | | 387 | int nbox, |
388 | int dx, | | 388 | int dx, |
389 | int dy, | | 389 | int dy, |
390 | Bool reverse, | | 390 | Bool reverse, |
391 | Bool upsidedown, | | 391 | Bool upsidedown, |
392 | Pixel bitplane, | | 392 | Pixel bitplane, |
393 | void *closure) | | 393 | void *closure) |
394 | { | | 394 | { |
395 | ExaScreenPriv (pDstDrawable->pScreen); | | 395 | ExaScreenPriv (pDstDrawable->pScreen); |
396 | PixmapPtr pSrcPixmap, pDstPixmap; | | 396 | PixmapPtr pSrcPixmap, pDstPixmap; |
397 | ExaPixmapPrivPtr pSrcExaPixmap, pDstExaPixmap; | | 397 | ExaPixmapPrivPtr pSrcExaPixmap, pDstExaPixmap; |
398 | int src_off_x, src_off_y; | | 398 | int src_off_x, src_off_y; |
399 | int dst_off_x, dst_off_y; | | 399 | int dst_off_x, dst_off_y; |
400 | ExaMigrationRec pixmaps[2]; | | 400 | ExaMigrationRec pixmaps[2]; |
401 | RegionPtr srcregion = NULL, dstregion = NULL; | | 401 | RegionPtr srcregion = NULL, dstregion = NULL; |
402 | xRectangle *rects; | | 402 | xRectangle *rects; |
403 | | | 403 | |
404 | /* avoid doing copy operations if no boxes */ | | 404 | /* avoid doing copy operations if no boxes */ |
405 | if (nbox == 0) | | 405 | if (nbox == 0) |
406 | return; | | 406 | return; |
407 | | | 407 | |
408 | pSrcPixmap = exaGetDrawablePixmap (pSrcDrawable); | | 408 | pSrcPixmap = exaGetDrawablePixmap (pSrcDrawable); |
409 | pDstPixmap = exaGetDrawablePixmap (pDstDrawable); | | 409 | pDstPixmap = exaGetDrawablePixmap (pDstDrawable); |
410 | | | 410 | |
411 | exaGetDrawableDeltas (pSrcDrawable, pSrcPixmap, &src_off_x, &src_off_y); | | 411 | exaGetDrawableDeltas (pSrcDrawable, pSrcPixmap, &src_off_x, &src_off_y); |
412 | exaGetDrawableDeltas (pDstDrawable, pDstPixmap, &dst_off_x, &dst_off_y); | | 412 | exaGetDrawableDeltas (pDstDrawable, pDstPixmap, &dst_off_x, &dst_off_y); |
413 | | | 413 | |
414 | rects = xalloc(nbox * sizeof(xRectangle)); | | 414 | rects = xalloc(nbox * sizeof(xRectangle)); |
415 | | | 415 | |
416 | if (rects) { | | 416 | if (rects) { |
417 | int i; | | 417 | int i; |
| | | 418 | int ordering; |
418 | | | 419 | |
419 | for (i = 0; i < nbox; i++) { | | 420 | for (i = 0; i < nbox; i++) { |
420 | rects[i].x = pbox[i].x1 + dx + src_off_x; | | 421 | rects[i].x = pbox[i].x1 + dx + src_off_x; |
421 | rects[i].y = pbox[i].y1 + dy + src_off_y; | | 422 | rects[i].y = pbox[i].y1 + dy + src_off_y; |
422 | rects[i].width = pbox[i].x2 - pbox[i].x1; | | 423 | rects[i].width = pbox[i].x2 - pbox[i].x1; |
423 | rects[i].height = pbox[i].y2 - pbox[i].y1; | | 424 | rects[i].height = pbox[i].y2 - pbox[i].y1; |
424 | } | | 425 | } |
425 | | | 426 | |
426 | srcregion = RECTS_TO_REGION(pScreen, nbox, rects, CT_YXBANDED); | | 427 | /* This must match the miRegionCopy() logic for reversing rect order */ |
| | | 428 | if (nbox == 1 || (dx > 0 && dy > 0) || |
| | | 429 | (pDstDrawable != pSrcDrawable && |
| | | 430 | (pDstDrawable->type != DRAWABLE_WINDOW || |
| | | 431 | pSrcDrawable->type != DRAWABLE_WINDOW))) |
| | | 432 | ordering = CT_YXBANDED; |
| | | 433 | else |
| | | 434 | ordering = CT_UNSORTED; |
| | | 435 | |
| | | 436 | srcregion = RECTS_TO_REGION(pScreen, nbox, rects, ordering); |
427 | xfree(rects); | | 437 | xfree(rects); |
428 | | | 438 | |
429 | if (!pGC || !exaGCReadsDestination(pDstDrawable, pGC->planemask, | | 439 | if (!pGC || !exaGCReadsDestination(pDstDrawable, pGC->planemask, |
430 | pGC->fillStyle, pGC->alu, | | 440 | pGC->fillStyle, pGC->alu, |
431 | pGC->clientClipType)) { | | 441 | pGC->clientClipType)) { |
432 | dstregion = REGION_CREATE(pScreen, NullBox, 0); | | 442 | dstregion = REGION_CREATE(pScreen, NullBox, 0); |
433 | REGION_COPY(pScreen, dstregion, srcregion); | | 443 | REGION_COPY(pScreen, dstregion, srcregion); |
434 | REGION_TRANSLATE(pScreen, dstregion, dst_off_x - dx - src_off_x, | | 444 | REGION_TRANSLATE(pScreen, dstregion, dst_off_x - dx - src_off_x, |
435 | dst_off_y - dy - src_off_y); | | 445 | dst_off_y - dy - src_off_y); |
436 | } | | 446 | } |
437 | } | | 447 | } |
438 | | | 448 | |
439 | pixmaps[0].as_dst = TRUE; | | 449 | pixmaps[0].as_dst = TRUE; |
440 | pixmaps[0].as_src = FALSE; | | 450 | pixmaps[0].as_src = FALSE; |
441 | pixmaps[0].pPix = pDstPixmap; | | 451 | pixmaps[0].pPix = pDstPixmap; |
442 | pixmaps[0].pReg = dstregion; | | 452 | pixmaps[0].pReg = dstregion; |
443 | pixmaps[1].as_dst = FALSE; | | 453 | pixmaps[1].as_dst = FALSE; |
444 | pixmaps[1].as_src = TRUE; | | 454 | pixmaps[1].as_src = TRUE; |
445 | pixmaps[1].pPix = pSrcPixmap; | | 455 | pixmaps[1].pPix = pSrcPixmap; |
446 | pixmaps[1].pReg = srcregion; | | 456 | pixmaps[1].pReg = srcregion; |
447 | | | 457 | |
448 | pSrcExaPixmap = ExaGetPixmapPriv (pSrcPixmap); | | 458 | pSrcExaPixmap = ExaGetPixmapPriv (pSrcPixmap); |
449 | pDstExaPixmap = ExaGetPixmapPriv (pDstPixmap); | | 459 | pDstExaPixmap = ExaGetPixmapPriv (pDstPixmap); |
450 | | | 460 | |
451 | /* Check whether the accelerator can use this pixmap. | | 461 | /* Check whether the accelerator can use this pixmap. |
452 | * If the pitch of the pixmaps is out of range, there's nothing | | 462 | * If the pitch of the pixmaps is out of range, there's nothing |
453 | * we can do but fall back to software rendering. | | 463 | * we can do but fall back to software rendering. |
454 | */ | | 464 | */ |
455 | if (pSrcExaPixmap->accel_blocked & EXA_RANGE_PITCH || | | 465 | if (pSrcExaPixmap->accel_blocked & EXA_RANGE_PITCH || |
456 | pDstExaPixmap->accel_blocked & EXA_RANGE_PITCH) | | 466 | pDstExaPixmap->accel_blocked & EXA_RANGE_PITCH) |
457 | goto fallback; | | 467 | goto fallback; |
458 | | | 468 | |
459 | /* If the width or the height of either of the pixmaps | | 469 | /* If the width or the height of either of the pixmaps |
460 | * is out of range, check whether the boxes are actually out of the | | 470 | * is out of range, check whether the boxes are actually out of the |
461 | * addressable range as well. If they aren't, we can still do | | 471 | * addressable range as well. If they aren't, we can still do |
462 | * the copying in hardware. | | 472 | * the copying in hardware. |
463 | */ | | 473 | */ |
464 | if (pSrcExaPixmap->accel_blocked || pDstExaPixmap->accel_blocked) { | | 474 | if (pSrcExaPixmap->accel_blocked || pDstExaPixmap->accel_blocked) { |
465 | int i; | | 475 | int i; |
466 | | | 476 | |
467 | for (i = 0; i < nbox; i++) { | | 477 | for (i = 0; i < nbox; i++) { |
468 | /* src */ | | 478 | /* src */ |
469 | if ((pbox[i].x2 + dx + src_off_x) >= pExaScr->info->maxX || | | 479 | if ((pbox[i].x2 + dx + src_off_x) >= pExaScr->info->maxX || |
470 | (pbox[i].y2 + dy + src_off_y) >= pExaScr->info->maxY) | | 480 | (pbox[i].y2 + dy + src_off_y) >= pExaScr->info->maxY) |
471 | goto fallback; | | 481 | goto fallback; |
472 | | | 482 | |
473 | /* dst */ | | 483 | /* dst */ |
474 | if ((pbox[i].x2 + dst_off_x) >= pExaScr->info->maxX || | | 484 | if ((pbox[i].x2 + dst_off_x) >= pExaScr->info->maxX || |
475 | (pbox[i].y2 + dst_off_y) >= pExaScr->info->maxY) | | 485 | (pbox[i].y2 + dst_off_y) >= pExaScr->info->maxY) |
476 | goto fallback; | | 486 | goto fallback; |
477 | } | | 487 | } |
478 | } | | 488 | } |
479 | | | 489 | |
480 | exaDoMigration (pixmaps, 2, TRUE); | | 490 | exaDoMigration (pixmaps, 2, TRUE); |
481 | | | 491 | |
482 | /* Mixed directions must be handled specially if the card is lame */ | | 492 | /* Mixed directions must be handled specially if the card is lame */ |
483 | if ((pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) && | | 493 | if ((pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS) && |
484 | reverse != upsidedown) { | | 494 | reverse != upsidedown) { |
485 | if (exaCopyNtoNTwoDir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, | | 495 | if (exaCopyNtoNTwoDir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, |
486 | dx, dy)) | | 496 | dx, dy)) |
487 | goto out; | | 497 | goto out; |
488 | goto fallback; | | 498 | goto fallback; |
489 | } | | 499 | } |
490 | | | 500 | |
491 | if (!exaPixmapIsOffscreen(pSrcPixmap) || | | 501 | if (!exaPixmapIsOffscreen(pSrcPixmap) || |
492 | !exaPixmapIsOffscreen(pDstPixmap) || | | 502 | !exaPixmapIsOffscreen(pDstPixmap) || |
493 | !(*pExaScr->info->PrepareCopy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1, | | 503 | !(*pExaScr->info->PrepareCopy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1, |
494 | upsidedown ? -1 : 1, | | 504 | upsidedown ? -1 : 1, |
495 | pGC ? pGC->alu : GXcopy, | | 505 | pGC ? pGC->alu : GXcopy, |
496 | pGC ? pGC->planemask : FB_ALLONES)) { | | 506 | pGC ? pGC->planemask : FB_ALLONES)) { |
497 | goto fallback; | | 507 | goto fallback; |
498 | } | | 508 | } |
499 | | | 509 | |
500 | while (nbox--) | | 510 | while (nbox--) |
501 | { | | 511 | { |
502 | (*pExaScr->info->Copy) (pDstPixmap, | | 512 | (*pExaScr->info->Copy) (pDstPixmap, |
503 | pbox->x1 + dx + src_off_x, | | 513 | pbox->x1 + dx + src_off_x, |
504 | pbox->y1 + dy + src_off_y, | | 514 | pbox->y1 + dy + src_off_y, |
505 | pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, | | 515 | pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, |
506 | pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); | | 516 | pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); |
507 | pbox++; | | 517 | pbox++; |
508 | } | | 518 | } |
509 | | | 519 | |
510 | (*pExaScr->info->DoneCopy) (pDstPixmap); | | 520 | (*pExaScr->info->DoneCopy) (pDstPixmap); |
511 | exaMarkSync (pDstDrawable->pScreen); | | 521 | exaMarkSync (pDstDrawable->pScreen); |
512 | | | 522 | |
513 | goto out; | | 523 | goto out; |
514 | | | 524 | |
515 | fallback: | | 525 | fallback: |
516 | EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable, | | 526 | EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable, |
517 | exaDrawableLocation(pSrcDrawable), | | 527 | exaDrawableLocation(pSrcDrawable), |
518 | exaDrawableLocation(pDstDrawable))); | | 528 | exaDrawableLocation(pDstDrawable))); |
519 | exaPrepareAccessReg (pDstDrawable, EXA_PREPARE_DEST, dstregion); | | 529 | exaPrepareAccessReg (pDstDrawable, EXA_PREPARE_DEST, dstregion); |
520 | exaPrepareAccessReg (pSrcDrawable, EXA_PREPARE_SRC, srcregion); | | 530 | exaPrepareAccessReg (pSrcDrawable, EXA_PREPARE_SRC, srcregion); |
521 | fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, | | 531 | fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, |
522 | upsidedown, bitplane, closure); | | 532 | upsidedown, bitplane, closure); |
523 | exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC); | | 533 | exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC); |
524 | exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST); | | 534 | exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST); |
525 | | | 535 | |
526 | out: | | 536 | out: |
527 | if (dstregion) { | | 537 | if (dstregion) { |
528 | REGION_UNINIT(pScreen, dstregion); | | 538 | REGION_UNINIT(pScreen, dstregion); |
529 | REGION_DESTROY(pScreen, dstregion); | | 539 | REGION_DESTROY(pScreen, dstregion); |
530 | } | | 540 | } |
531 | if (srcregion) { | | 541 | if (srcregion) { |
532 | REGION_UNINIT(pScreen, srcregion); | | 542 | REGION_UNINIT(pScreen, srcregion); |
533 | REGION_DESTROY(pScreen, srcregion); | | 543 | REGION_DESTROY(pScreen, srcregion); |
534 | } | | 544 | } |
535 | } | | 545 | } |
536 | | | 546 | |
537 | RegionPtr | | 547 | RegionPtr |
538 | exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, | | 548 | exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, |
539 | int srcx, int srcy, int width, int height, int dstx, int dsty) | | 549 | int srcx, int srcy, int width, int height, int dstx, int dsty) |
540 | { | | 550 | { |
541 | ExaScreenPriv (pDstDrawable->pScreen); | | 551 | ExaScreenPriv (pDstDrawable->pScreen); |
542 | | | 552 | |
543 | if (pExaScr->swappedOut) { | | 553 | if (pExaScr->swappedOut) { |
544 | return ExaCheckCopyArea(pSrcDrawable, pDstDrawable, pGC, | | 554 | return ExaCheckCopyArea(pSrcDrawable, pDstDrawable, pGC, |
545 | srcx, srcy, width, height, dstx, dsty); | | 555 | srcx, srcy, width, height, dstx, dsty); |
546 | } | | 556 | } |
547 | | | 557 | |
548 | return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, | | 558 | return fbDoCopy (pSrcDrawable, pDstDrawable, pGC, |
549 | srcx, srcy, width, height, | | 559 | srcx, srcy, width, height, |
550 | dstx, dsty, exaCopyNtoN, 0, NULL); | | 560 | dstx, dsty, exaCopyNtoN, 0, NULL); |
551 | } | | 561 | } |
552 | | | 562 | |
553 | static void | | 563 | static void |
554 | exaPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, | | 564 | exaPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, |
555 | DDXPointPtr ppt) | | 565 | DDXPointPtr ppt) |
556 | { | | 566 | { |
557 | int i; | | 567 | int i; |
558 | xRectangle *prect; | | 568 | xRectangle *prect; |
559 | | | 569 | |
560 | /* If we can't reuse the current GC as is, don't bother accelerating the | | 570 | /* If we can't reuse the current GC as is, don't bother accelerating the |
561 | * points. | | 571 | * points. |
562 | */ | | 572 | */ |
563 | if (pGC->fillStyle != FillSolid) { | | 573 | if (pGC->fillStyle != FillSolid) { |
564 | ExaCheckPolyPoint(pDrawable, pGC, mode, npt, ppt); | | 574 | ExaCheckPolyPoint(pDrawable, pGC, mode, npt, ppt); |
565 | return; | | 575 | return; |
566 | } | | 576 | } |
567 | | | 577 | |
568 | prect = xalloc(sizeof(xRectangle) * npt); | | 578 | prect = xalloc(sizeof(xRectangle) * npt); |
569 | for (i = 0; i < npt; i++) { | | 579 | for (i = 0; i < npt; i++) { |
570 | prect[i].x = ppt[i].x; | | 580 | prect[i].x = ppt[i].x; |
571 | prect[i].y = ppt[i].y; | | 581 | prect[i].y = ppt[i].y; |
572 | if (i > 0 && mode == CoordModePrevious) { | | 582 | if (i > 0 && mode == CoordModePrevious) { |
573 | prect[i].x += prect[i - 1].x; | | 583 | prect[i].x += prect[i - 1].x; |
574 | prect[i].y += prect[i - 1].y; | | 584 | prect[i].y += prect[i - 1].y; |
575 | } | | 585 | } |
576 | prect[i].width = 1; | | 586 | prect[i].width = 1; |
577 | prect[i].height = 1; | | 587 | prect[i].height = 1; |
578 | } | | 588 | } |
579 | pGC->ops->PolyFillRect(pDrawable, pGC, npt, prect); | | 589 | pGC->ops->PolyFillRect(pDrawable, pGC, npt, prect); |
580 | xfree(prect); | | 590 | xfree(prect); |
581 | } | | 591 | } |
582 | | | 592 | |
583 | /** | | 593 | /** |
584 | * exaPolylines() checks if it can accelerate the lines as a group of | | 594 | * exaPolylines() checks if it can accelerate the lines as a group of |
585 | * horizontal or vertical lines (rectangles), and uses existing rectangle fill | | 595 | * horizontal or vertical lines (rectangles), and uses existing rectangle fill |
586 | * acceleration if so. | | 596 | * acceleration if so. |
587 | */ | | 597 | */ |
588 | static void | | 598 | static void |
589 | exaPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, | | 599 | exaPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, |
590 | DDXPointPtr ppt) | | 600 | DDXPointPtr ppt) |
591 | { | | 601 | { |
592 | xRectangle *prect; | | 602 | xRectangle *prect; |
593 | int x1, x2, y1, y2; | | 603 | int x1, x2, y1, y2; |
594 | int i; | | 604 | int i; |
595 | | | 605 | |
596 | /* Don't try to do wide lines or non-solid fill style. */ | | 606 | /* Don't try to do wide lines or non-solid fill style. */ |
597 | if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid || | | 607 | if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid || |
598 | pGC->fillStyle != FillSolid) { | | 608 | pGC->fillStyle != FillSolid) { |
599 | ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt); | | 609 | ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt); |
600 | return; | | 610 | return; |
601 | } | | 611 | } |
602 | | | 612 | |
603 | prect = xalloc(sizeof(xRectangle) * (npt - 1)); | | 613 | prect = xalloc(sizeof(xRectangle) * (npt - 1)); |
604 | x1 = ppt[0].x; | | 614 | x1 = ppt[0].x; |
605 | y1 = ppt[0].y; | | 615 | y1 = ppt[0].y; |
606 | /* If we have any non-horizontal/vertical, fall back. */ | | 616 | /* If we have any non-horizontal/vertical, fall back. */ |
607 | for (i = 0; i < npt - 1; i++) { | | 617 | for (i = 0; i < npt - 1; i++) { |
608 | if (mode == CoordModePrevious) { | | 618 | if (mode == CoordModePrevious) { |
609 | x2 = x1 + ppt[i + 1].x; | | 619 | x2 = x1 + ppt[i + 1].x; |
610 | y2 = y1 + ppt[i + 1].y; | | 620 | y2 = y1 + ppt[i + 1].y; |
611 | } else { | | 621 | } else { |
612 | x2 = ppt[i + 1].x; | | 622 | x2 = ppt[i + 1].x; |
613 | y2 = ppt[i + 1].y; | | 623 | y2 = ppt[i + 1].y; |
614 | } | | 624 | } |
615 | | | 625 | |
616 | if (x1 != x2 && y1 != y2) { | | 626 | if (x1 != x2 && y1 != y2) { |
617 | xfree(prect); | | 627 | xfree(prect); |
618 | ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt); | | 628 | ExaCheckPolylines(pDrawable, pGC, mode, npt, ppt); |
619 | return; | | 629 | return; |
620 | } | | 630 | } |
621 | | | 631 | |
622 | if (x1 < x2) { | | 632 | if (x1 < x2) { |
623 | prect[i].x = x1; | | 633 | prect[i].x = x1; |
624 | prect[i].width = x2 - x1 + 1; | | 634 | prect[i].width = x2 - x1 + 1; |
625 | } else { | | 635 | } else { |
626 | prect[i].x = x2; | | 636 | prect[i].x = x2; |
627 | prect[i].width = x1 - x2 + 1; | | 637 | prect[i].width = x1 - x2 + 1; |
628 | } | | 638 | } |
629 | if (y1 < y2) { | | 639 | if (y1 < y2) { |
630 | prect[i].y = y1; | | 640 | prect[i].y = y1; |
631 | prect[i].height = y2 - y1 + 1; | | 641 | prect[i].height = y2 - y1 + 1; |
632 | } else { | | 642 | } else { |
633 | prect[i].y = y2; | | 643 | prect[i].y = y2; |
634 | prect[i].height = y1 - y2 + 1; | | 644 | prect[i].height = y1 - y2 + 1; |
635 | } | | 645 | } |
636 | | | 646 | |
637 | x1 = x2; | | 647 | x1 = x2; |
638 | y1 = y2; | | 648 | y1 = y2; |
639 | } | | 649 | } |
640 | pGC->ops->PolyFillRect(pDrawable, pGC, npt - 1, prect); | | 650 | pGC->ops->PolyFillRect(pDrawable, pGC, npt - 1, prect); |
641 | xfree(prect); | | 651 | xfree(prect); |
642 | } | | 652 | } |
643 | | | 653 | |
644 | /** | | 654 | /** |
645 | * exaPolySegment() checks if it can accelerate the lines as a group of | | 655 | * exaPolySegment() checks if it can accelerate the lines as a group of |
646 | * horizontal or vertical lines (rectangles), and uses existing rectangle fill | | 656 | * horizontal or vertical lines (rectangles), and uses existing rectangle fill |
647 | * acceleration if so. | | 657 | * acceleration if so. |
648 | */ | | 658 | */ |
649 | static void | | 659 | static void |
650 | exaPolySegment (DrawablePtr pDrawable, GCPtr pGC, int nseg, | | 660 | exaPolySegment (DrawablePtr pDrawable, GCPtr pGC, int nseg, |
651 | xSegment *pSeg) | | 661 | xSegment *pSeg) |
652 | { | | 662 | { |
653 | xRectangle *prect; | | 663 | xRectangle *prect; |
654 | int i; | | 664 | int i; |
655 | | | 665 | |
656 | /* Don't try to do wide lines or non-solid fill style. */ | | 666 | /* Don't try to do wide lines or non-solid fill style. */ |
657 | if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid || | | 667 | if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid || |
658 | pGC->fillStyle != FillSolid) | | 668 | pGC->fillStyle != FillSolid) |
659 | { | | 669 | { |
660 | ExaCheckPolySegment(pDrawable, pGC, nseg, pSeg); | | 670 | ExaCheckPolySegment(pDrawable, pGC, nseg, pSeg); |
661 | return; | | 671 | return; |
662 | } | | 672 | } |
663 | | | 673 | |
664 | /* If we have any non-horizontal/vertical, fall back. */ | | 674 | /* If we have any non-horizontal/vertical, fall back. */ |
665 | for (i = 0; i < nseg; i++) { | | 675 | for (i = 0; i < nseg; i++) { |
666 | if (pSeg[i].x1 != pSeg[i].x2 && pSeg[i].y1 != pSeg[i].y2) { | | 676 | if (pSeg[i].x1 != pSeg[i].x2 && pSeg[i].y1 != pSeg[i].y2) { |
667 | ExaCheckPolySegment(pDrawable, pGC, nseg, pSeg); | | 677 | ExaCheckPolySegment(pDrawable, pGC, nseg, pSeg); |
668 | return; | | 678 | return; |
669 | } | | 679 | } |
670 | } | | 680 | } |
671 | | | 681 | |
672 | prect = xalloc(sizeof(xRectangle) * nseg); | | 682 | prect = xalloc(sizeof(xRectangle) * nseg); |
673 | for (i = 0; i < nseg; i++) { | | 683 | for (i = 0; i < nseg; i++) { |
674 | if (pSeg[i].x1 < pSeg[i].x2) { | | 684 | if (pSeg[i].x1 < pSeg[i].x2) { |
675 | prect[i].x = pSeg[i].x1; | | 685 | prect[i].x = pSeg[i].x1; |
676 | prect[i].width = pSeg[i].x2 - pSeg[i].x1 + 1; | | 686 | prect[i].width = pSeg[i].x2 - pSeg[i].x1 + 1; |
677 | } else { | | 687 | } else { |
678 | prect[i].x = pSeg[i].x2; | | 688 | prect[i].x = pSeg[i].x2; |
679 | prect[i].width = pSeg[i].x1 - pSeg[i].x2 + 1; | | 689 | prect[i].width = pSeg[i].x1 - pSeg[i].x2 + 1; |
680 | } | | 690 | } |
681 | if (pSeg[i].y1 < pSeg[i].y2) { | | 691 | if (pSeg[i].y1 < pSeg[i].y2) { |
682 | prect[i].y = pSeg[i].y1; | | 692 | prect[i].y = pSeg[i].y1; |
683 | prect[i].height = pSeg[i].y2 - pSeg[i].y1 + 1; | | 693 | prect[i].height = pSeg[i].y2 - pSeg[i].y1 + 1; |
684 | } else { | | 694 | } else { |
685 | prect[i].y = pSeg[i].y2; | | 695 | prect[i].y = pSeg[i].y2; |
686 | prect[i].height = pSeg[i].y1 - pSeg[i].y2 + 1; | | 696 | prect[i].height = pSeg[i].y1 - pSeg[i].y2 + 1; |
687 | } | | 697 | } |
688 | | | 698 | |
689 | /* don't paint last pixel */ | | 699 | /* don't paint last pixel */ |
690 | if (pGC->capStyle == CapNotLast) { | | 700 | if (pGC->capStyle == CapNotLast) { |
691 | if (prect[i].width == 1) | | 701 | if (prect[i].width == 1) |
692 | prect[i].height--; | | 702 | prect[i].height--; |
693 | else | | 703 | else |
694 | prect[i].width--; | | 704 | prect[i].width--; |
695 | } | | 705 | } |
696 | } | | 706 | } |
697 | pGC->ops->PolyFillRect(pDrawable, pGC, nseg, prect); | | 707 | pGC->ops->PolyFillRect(pDrawable, pGC, nseg, prect); |
698 | xfree(prect); | | 708 | xfree(prect); |
699 | } | | 709 | } |
700 | | | 710 | |
701 | static Bool exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, | | 711 | static Bool exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, |
702 | Pixel pixel, CARD32 planemask, CARD32 alu, | | 712 | Pixel pixel, CARD32 planemask, CARD32 alu, |
703 | unsigned int clientClipType); | | 713 | unsigned int clientClipType); |
704 | | | 714 | |
705 | static void | | 715 | static void |
706 | exaPolyFillRect(DrawablePtr pDrawable, | | 716 | exaPolyFillRect(DrawablePtr pDrawable, |
707 | GCPtr pGC, | | 717 | GCPtr pGC, |
708 | int nrect, | | 718 | int nrect, |
709 | xRectangle *prect) | | 719 | xRectangle *prect) |
710 | { | | 720 | { |
711 | ExaScreenPriv (pDrawable->pScreen); | | 721 | ExaScreenPriv (pDrawable->pScreen); |
712 | RegionPtr pClip = fbGetCompositeClip(pGC); | | 722 | RegionPtr pClip = fbGetCompositeClip(pGC); |
713 | PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); | | 723 | PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable); |
714 | ExaPixmapPriv (pPixmap); | | 724 | ExaPixmapPriv (pPixmap); |
715 | register BoxPtr pbox; | | 725 | register BoxPtr pbox; |
716 | BoxPtr pextent; | | 726 | BoxPtr pextent; |
717 | int extentX1, extentX2, extentY1, extentY2; | | 727 | int extentX1, extentX2, extentY1, extentY2; |
718 | int fullX1, fullX2, fullY1, fullY2; | | 728 | int fullX1, fullX2, fullY1, fullY2; |
719 | int partX1, partX2, partY1, partY2; | | 729 | int partX1, partX2, partY1, partY2; |
720 | int xoff, yoff; | | 730 | int xoff, yoff; |
721 | int xorg, yorg; | | 731 | int xorg, yorg; |
722 | int n; | | 732 | int n; |
723 | ExaMigrationRec pixmaps[2]; | | 733 | ExaMigrationRec pixmaps[2]; |
724 | RegionPtr pReg = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED); | | 734 | RegionPtr pReg = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED); |
725 | | | 735 | |
726 | /* Compute intersection of rects and clip region */ | | 736 | /* Compute intersection of rects and clip region */ |
727 | REGION_TRANSLATE(pScreen, pReg, pDrawable->x, pDrawable->y); | | 737 | REGION_TRANSLATE(pScreen, pReg, pDrawable->x, pDrawable->y); |
728 | REGION_INTERSECT(pScreen, pReg, pClip, pReg); | | 738 | REGION_INTERSECT(pScreen, pReg, pClip, pReg); |
729 | | | 739 | |
730 | if (!REGION_NUM_RECTS(pReg)) { | | 740 | if (!REGION_NUM_RECTS(pReg)) { |
731 | goto out; | | 741 | goto out; |
732 | } | | 742 | } |
733 | | | 743 | |
734 | pixmaps[0].as_dst = TRUE; | | 744 | pixmaps[0].as_dst = TRUE; |
735 | pixmaps[0].as_src = FALSE; | | 745 | pixmaps[0].as_src = FALSE; |
736 | pixmaps[0].pPix = pPixmap; | | 746 | pixmaps[0].pPix = pPixmap; |
737 | pixmaps[0].pReg = NULL; | | 747 | pixmaps[0].pReg = NULL; |
738 | | | 748 | |
739 | exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); | | 749 | exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); |
740 | | | 750 | |
741 | if (pExaScr->swappedOut || pExaPixmap->accel_blocked) | | 751 | if (pExaScr->swappedOut || pExaPixmap->accel_blocked) |
742 | { | | 752 | { |
743 | goto fallback; | | 753 | goto fallback; |
744 | } | | 754 | } |
745 | | | 755 | |
746 | /* For ROPs where overlaps don't matter, convert rectangles to region and | | 756 | /* For ROPs where overlaps don't matter, convert rectangles to region and |
747 | * call exaFillRegion{Solid,Tiled}. | | 757 | * call exaFillRegion{Solid,Tiled}. |
748 | */ | | 758 | */ |
749 | if ((pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) && | | 759 | if ((pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) && |
750 | (nrect == 1 || pGC->alu == GXcopy || pGC->alu == GXclear || | | 760 | (nrect == 1 || pGC->alu == GXcopy || pGC->alu == GXclear || |
751 | pGC->alu == GXnoop || pGC->alu == GXcopyInverted || | | 761 | pGC->alu == GXnoop || pGC->alu == GXcopyInverted || |
752 | pGC->alu == GXset)) { | | 762 | pGC->alu == GXset)) { |
753 | if (((pGC->fillStyle == FillSolid || pGC->tileIsPixel) && | | 763 | if (((pGC->fillStyle == FillSolid || pGC->tileIsPixel) && |
754 | exaFillRegionSolid(pDrawable, pReg, pGC->fillStyle == FillSolid ? | | 764 | exaFillRegionSolid(pDrawable, pReg, pGC->fillStyle == FillSolid ? |
755 | pGC->fgPixel : pGC->tile.pixel, pGC->planemask, | | 765 | pGC->fgPixel : pGC->tile.pixel, pGC->planemask, |
756 | pGC->alu, pGC->clientClipType)) || | | 766 | pGC->alu, pGC->clientClipType)) || |
757 | (pGC->fillStyle == FillTiled && !pGC->tileIsPixel && | | 767 | (pGC->fillStyle == FillTiled && !pGC->tileIsPixel && |
758 | exaFillRegionTiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg, | | 768 | exaFillRegionTiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg, |
759 | pGC->planemask, pGC->alu, | | 769 | pGC->planemask, pGC->alu, |
760 | pGC->clientClipType))) { | | 770 | pGC->clientClipType))) { |
761 | goto out; | | 771 | goto out; |
762 | } | | 772 | } |
763 | } | | 773 | } |
764 | | | 774 | |
765 | if (pGC->fillStyle != FillSolid && | | 775 | if (pGC->fillStyle != FillSolid && |
766 | !(pGC->tileIsPixel && pGC->fillStyle == FillTiled)) | | 776 | !(pGC->tileIsPixel && pGC->fillStyle == FillTiled)) |
767 | { | | 777 | { |
768 | goto fallback; | | 778 | goto fallback; |
769 | } | | 779 | } |
770 | | | 780 | |
771 | exaDoMigration (pixmaps, 1, TRUE); | | 781 | exaDoMigration (pixmaps, 1, TRUE); |
772 | | | 782 | |
773 | if (!exaPixmapIsOffscreen (pPixmap) || | | 783 | if (!exaPixmapIsOffscreen (pPixmap) || |
774 | !(*pExaScr->info->PrepareSolid) (pPixmap, | | 784 | !(*pExaScr->info->PrepareSolid) (pPixmap, |
775 | pGC->alu, | | 785 | pGC->alu, |
776 | pGC->planemask, | | 786 | pGC->planemask, |
777 | pGC->fgPixel)) | | 787 | pGC->fgPixel)) |
778 | { | | 788 | { |
779 | fallback: | | 789 | fallback: |
780 | ExaCheckPolyFillRect (pDrawable, pGC, nrect, prect); | | 790 | ExaCheckPolyFillRect (pDrawable, pGC, nrect, prect); |
781 | goto out; | | 791 | goto out; |
782 | } | | 792 | } |
783 | | | 793 | |
784 | xorg = pDrawable->x; | | 794 | xorg = pDrawable->x; |
785 | yorg = pDrawable->y; | | 795 | yorg = pDrawable->y; |
786 | | | 796 | |
787 | pextent = REGION_EXTENTS(pGC->pScreen, pClip); | | 797 | pextent = REGION_EXTENTS(pGC->pScreen, pClip); |
788 | extentX1 = pextent->x1; | | 798 | extentX1 = pextent->x1; |
789 | extentY1 = pextent->y1; | | 799 | extentY1 = pextent->y1; |
790 | extentX2 = pextent->x2; | | 800 | extentX2 = pextent->x2; |
791 | extentY2 = pextent->y2; | | 801 | extentY2 = pextent->y2; |
792 | while (nrect--) | | 802 | while (nrect--) |
793 | { | | 803 | { |
794 | fullX1 = prect->x + xorg; | | 804 | fullX1 = prect->x + xorg; |
795 | fullY1 = prect->y + yorg; | | 805 | fullY1 = prect->y + yorg; |
796 | fullX2 = fullX1 + (int) prect->width; | | 806 | fullX2 = fullX1 + (int) prect->width; |
797 | fullY2 = fullY1 + (int) prect->height; | | 807 | fullY2 = fullY1 + (int) prect->height; |
798 | prect++; | | 808 | prect++; |
799 | | | 809 | |
800 | if (fullX1 < extentX1) | | 810 | if (fullX1 < extentX1) |
801 | fullX1 = extentX1; | | 811 | fullX1 = extentX1; |
802 | | | 812 | |
803 | if (fullY1 < extentY1) | | 813 | if (fullY1 < extentY1) |
804 | fullY1 = extentY1; | | 814 | fullY1 = extentY1; |
805 | | | 815 | |
806 | if (fullX2 > extentX2) | | 816 | if (fullX2 > extentX2) |
807 | fullX2 = extentX2; | | 817 | fullX2 = extentX2; |
808 | | | 818 | |
809 | if (fullY2 > extentY2) | | 819 | if (fullY2 > extentY2) |
810 | fullY2 = extentY2; | | 820 | fullY2 = extentY2; |
811 | | | 821 | |
812 | if ((fullX1 >= fullX2) || (fullY1 >= fullY2)) | | 822 | if ((fullX1 >= fullX2) || (fullY1 >= fullY2)) |
813 | continue; | | 823 | continue; |
814 | n = REGION_NUM_RECTS (pClip); | | 824 | n = REGION_NUM_RECTS (pClip); |
815 | if (n == 1) | | 825 | if (n == 1) |
816 | { | | 826 | { |
817 | (*pExaScr->info->Solid) (pPixmap, | | 827 | (*pExaScr->info->Solid) (pPixmap, |
818 | fullX1 + xoff, fullY1 + yoff, | | 828 | fullX1 + xoff, fullY1 + yoff, |
819 | fullX2 + xoff, fullY2 + yoff); | | 829 | fullX2 + xoff, fullY2 + yoff); |
820 | } | | 830 | } |
821 | else | | 831 | else |
822 | { | | 832 | { |
823 | pbox = REGION_RECTS(pClip); | | 833 | pbox = REGION_RECTS(pClip); |
824 | /* | | 834 | /* |
825 | * clip the rectangle to each box in the clip region | | 835 | * clip the rectangle to each box in the clip region |
826 | * this is logically equivalent to calling Intersect(), | | 836 | * this is logically equivalent to calling Intersect(), |
827 | * but rectangles may overlap each other here. | | 837 | * but rectangles may overlap each other here. |
828 | */ | | 838 | */ |
829 | while(n--) | | 839 | while(n--) |
830 | { | | 840 | { |
831 | partX1 = pbox->x1; | | 841 | partX1 = pbox->x1; |
832 | if (partX1 < fullX1) | | 842 | if (partX1 < fullX1) |
833 | partX1 = fullX1; | | 843 | partX1 = fullX1; |
834 | partY1 = pbox->y1; | | 844 | partY1 = pbox->y1; |
835 | if (partY1 < fullY1) | | 845 | if (partY1 < fullY1) |
836 | partY1 = fullY1; | | 846 | partY1 = fullY1; |
837 | partX2 = pbox->x2; | | 847 | partX2 = pbox->x2; |
838 | if (partX2 > fullX2) | | 848 | if (partX2 > fullX2) |
839 | partX2 = fullX2; | | 849 | partX2 = fullX2; |
840 | partY2 = pbox->y2; | | 850 | partY2 = pbox->y2; |
841 | if (partY2 > fullY2) | | 851 | if (partY2 > fullY2) |
842 | partY2 = fullY2; | | 852 | partY2 = fullY2; |
843 | | | 853 | |
844 | pbox++; | | 854 | pbox++; |
845 | | | 855 | |
846 | if (partX1 < partX2 && partY1 < partY2) { | | 856 | if (partX1 < partX2 && partY1 < partY2) { |
847 | (*pExaScr->info->Solid) (pPixmap, | | 857 | (*pExaScr->info->Solid) (pPixmap, |
848 | partX1 + xoff, partY1 + yoff, | | 858 | partX1 + xoff, partY1 + yoff, |
849 | partX2 + xoff, partY2 + yoff); | | 859 | partX2 + xoff, partY2 + yoff); |
850 | } | | 860 | } |
851 | } | | 861 | } |
852 | } | | 862 | } |
853 | } | | 863 | } |
854 | (*pExaScr->info->DoneSolid) (pPixmap); | | 864 | (*pExaScr->info->DoneSolid) (pPixmap); |
855 | exaMarkSync(pDrawable->pScreen); | | 865 | exaMarkSync(pDrawable->pScreen); |
856 | | | 866 | |
857 | out: | | 867 | out: |
858 | REGION_UNINIT(pScreen, pReg); | | 868 | REGION_UNINIT(pScreen, pReg); |
859 | REGION_DESTROY(pScreen, pReg); | | 869 | REGION_DESTROY(pScreen, pReg); |
860 | } | | 870 | } |
861 | | | 871 | |
862 | const GCOps exaOps = { | | 872 | const GCOps exaOps = { |
863 | exaFillSpans, | | 873 | exaFillSpans, |
864 | ExaCheckSetSpans, | | 874 | ExaCheckSetSpans, |
865 | exaPutImage, | | 875 | exaPutImage, |
866 | exaCopyArea, | | 876 | exaCopyArea, |
867 | ExaCheckCopyPlane, | | 877 | ExaCheckCopyPlane, |
868 | exaPolyPoint, | | 878 | exaPolyPoint, |
869 | exaPolylines, | | 879 | exaPolylines, |
870 | exaPolySegment, | | 880 | exaPolySegment, |
871 | miPolyRectangle, | | 881 | miPolyRectangle, |
872 | ExaCheckPolyArc, | | 882 | ExaCheckPolyArc, |
873 | miFillPolygon, | | 883 | miFillPolygon, |
874 | exaPolyFillRect, | | 884 | exaPolyFillRect, |
875 | miPolyFillArc, | | 885 | miPolyFillArc, |
876 | miPolyText8, | | 886 | miPolyText8, |
877 | miPolyText16, | | 887 | miPolyText16, |
878 | miImageText8, | | 888 | miImageText8, |
879 | miImageText16, | | 889 | miImageText16, |
880 | ExaCheckImageGlyphBlt, | | 890 | ExaCheckImageGlyphBlt, |
881 | ExaCheckPolyGlyphBlt, | | 891 | ExaCheckPolyGlyphBlt, |
882 | ExaCheckPushPixels, | | 892 | ExaCheckPushPixels, |
883 | }; | | 893 | }; |
884 | | | 894 | |
885 | void | | 895 | void |
886 | exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) | | 896 | exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) |
887 | { | | 897 | { |
888 | RegionRec rgnDst; | | 898 | RegionRec rgnDst; |
889 | int dx, dy; | | 899 | int dx, dy; |
890 | PixmapPtr pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin); | | 900 | PixmapPtr pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin); |
891 | | | 901 | |
892 | dx = ptOldOrg.x - pWin->drawable.x; | | 902 | dx = ptOldOrg.x - pWin->drawable.x; |
893 | dy = ptOldOrg.y - pWin->drawable.y; | | 903 | dy = ptOldOrg.y - pWin->drawable.y; |
894 | REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); | | 904 | REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); |
895 | | | 905 | |
896 | REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0); | | 906 | REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0); |
897 | | | 907 | |
898 | REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc); | | 908 | REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc); |
899 | #ifdef COMPOSITE | | 909 | #ifdef COMPOSITE |
900 | if (pPixmap->screen_x || pPixmap->screen_y) | | 910 | if (pPixmap->screen_x || pPixmap->screen_y) |
901 | REGION_TRANSLATE (pWin->drawable.pScreen, &rgnDst, | | 911 | REGION_TRANSLATE (pWin->drawable.pScreen, &rgnDst, |
902 | -pPixmap->screen_x, -pPixmap->screen_y); | | 912 | -pPixmap->screen_x, -pPixmap->screen_y); |
903 | #endif | | 913 | #endif |
904 | | | 914 | |
905 | fbCopyRegion (&pPixmap->drawable, &pPixmap->drawable, | | 915 | fbCopyRegion (&pPixmap->drawable, &pPixmap->drawable, |
906 | NULL, | | 916 | NULL, |
907 | &rgnDst, dx, dy, exaCopyNtoN, 0, NULL); | | 917 | &rgnDst, dx, dy, exaCopyNtoN, 0, NULL); |
908 | | | 918 | |
909 | REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); | | 919 | REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); |
910 | } | | 920 | } |
911 | | | 921 | |
912 | static Bool | | 922 | static Bool |
913 | exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, Pixel pixel, | | 923 | exaFillRegionSolid (DrawablePtr pDrawable, RegionPtr pRegion, Pixel pixel, |
914 | CARD32 planemask, CARD32 alu, unsigned int clientClipType) | | 924 | CARD32 planemask, CARD32 alu, unsigned int clientClipType) |
915 | { | | 925 | { |
916 | ExaScreenPriv(pDrawable->pScreen); | | 926 | ExaScreenPriv(pDrawable->pScreen); |
917 | PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); | | 927 | PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable); |
918 | ExaPixmapPriv (pPixmap); | | 928 | ExaPixmapPriv (pPixmap); |
919 | int xoff, yoff; | | 929 | int xoff, yoff; |
920 | ExaMigrationRec pixmaps[1]; | | 930 | ExaMigrationRec pixmaps[1]; |
921 | Bool ret = FALSE; | | 931 | Bool ret = FALSE; |
922 | | | 932 | |
923 | pixmaps[0].as_dst = TRUE; | | 933 | pixmaps[0].as_dst = TRUE; |
924 | pixmaps[0].as_src = FALSE; | | 934 | pixmaps[0].as_src = FALSE; |
925 | pixmaps[0].pPix = pPixmap; | | 935 | pixmaps[0].pPix = pPixmap; |
926 | pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillSolid, | | 936 | pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillSolid, |
927 | alu, clientClipType) | | 937 | alu, clientClipType) |
928 | ? NULL : pRegion; | | 938 | ? NULL : pRegion; |
929 | | | 939 | |
930 | exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); | | 940 | exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff); |
931 | REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); | | 941 | REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); |
932 | | | 942 | |
933 | if (pExaPixmap->accel_blocked) | | 943 | if (pExaPixmap->accel_blocked) |
934 | { | | 944 | { |
935 | goto out; | | 945 | goto out; |
936 | } else { | | 946 | } else { |
937 | exaDoMigration (pixmaps, 1, TRUE); | | 947 | exaDoMigration (pixmaps, 1, TRUE); |
938 | } | | 948 | } |
939 | | | 949 | |
940 | if (exaPixmapIsOffscreen (pPixmap) && | | 950 | if (exaPixmapIsOffscreen (pPixmap) && |
941 | (*pExaScr->info->PrepareSolid) (pPixmap, alu, planemask, pixel)) | | 951 | (*pExaScr->info->PrepareSolid) (pPixmap, alu, planemask, pixel)) |
942 | { | | 952 | { |
943 | int nbox; | | 953 | int nbox; |
944 | BoxPtr pBox; | | 954 | BoxPtr pBox; |
945 | | | 955 | |
946 | nbox = REGION_NUM_RECTS (pRegion); | | 956 | nbox = REGION_NUM_RECTS (pRegion); |
947 | pBox = REGION_RECTS (pRegion); | | 957 | pBox = REGION_RECTS (pRegion); |
948 | | | 958 | |
949 | while (nbox--) | | 959 | while (nbox--) |
950 | { | | 960 | { |
951 | (*pExaScr->info->Solid) (pPixmap, pBox->x1, pBox->y1, pBox->x2, | | 961 | (*pExaScr->info->Solid) (pPixmap, pBox->x1, pBox->y1, pBox->x2, |
952 | pBox->y2); | | 962 | pBox->y2); |
953 | pBox++; | | 963 | pBox++; |
954 | } | | 964 | } |
955 | (*pExaScr->info->DoneSolid) (pPixmap); | | 965 | (*pExaScr->info->DoneSolid) (pPixmap); |
956 | exaMarkSync(pDrawable->pScreen); | | 966 | exaMarkSync(pDrawable->pScreen); |
957 | | | 967 | |
958 | if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS) && | | 968 | if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS) && |
959 | pDrawable->width == 1 && pDrawable->height == 1 && | | 969 | pDrawable->width == 1 && pDrawable->height == 1 && |
960 | pDrawable->bitsPerPixel != 24) { | | 970 | pDrawable->bitsPerPixel != 24) { |
961 | ExaPixmapPriv(pPixmap); | | 971 | ExaPixmapPriv(pPixmap); |
962 | | | 972 | |
963 | switch (pDrawable->bitsPerPixel) { | | 973 | switch (pDrawable->bitsPerPixel) { |
964 | case 32: | | 974 | case 32: |
965 | *(CARD32*)pExaPixmap->sys_ptr = pixel; | | 975 | *(CARD32*)pExaPixmap->sys_ptr = pixel; |
966 | break; | | 976 | break; |
967 | case 16: | | 977 | case 16: |
968 | *(CARD16*)pExaPixmap->sys_ptr = pixel; | | 978 | *(CARD16*)pExaPixmap->sys_ptr = pixel; |
969 | break; | | 979 | break; |
970 | case 8: | | 980 | case 8: |
971 | *(CARD8*)pExaPixmap->sys_ptr = pixel; | | 981 | *(CARD8*)pExaPixmap->sys_ptr = pixel; |
972 | } | | 982 | } |
973 | | | 983 | |
974 | REGION_UNION(pScreen, &pExaPixmap->validSys, &pExaPixmap->validSys, | | 984 | REGION_UNION(pScreen, &pExaPixmap->validSys, &pExaPixmap->validSys, |
975 | pRegion); | | 985 | pRegion); |
976 | } | | 986 | } |
977 | | | 987 | |
978 | ret = TRUE; | | 988 | ret = TRUE; |
979 | } | | 989 | } |
980 | | | 990 | |
981 | out: | | 991 | out: |
982 | REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); | | 992 | REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); |
983 | | | 993 | |
984 | return ret; | | 994 | return ret; |
985 | } | | 995 | } |
986 | | | 996 | |
987 | /* Try to do an accelerated tile of the pTile into pRegion of pDrawable. | | 997 | /* Try to do an accelerated tile of the pTile into pRegion of pDrawable. |
988 | * Based on fbFillRegionTiled(), fbTile(). | | 998 | * Based on fbFillRegionTiled(), fbTile(). |
989 | */ | | 999 | */ |
990 | Bool | | 1000 | Bool |
991 | exaFillRegionTiled (DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile, | | 1001 | exaFillRegionTiled (DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile, |
992 | DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu, | | 1002 | DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu, |
993 | unsigned int clientClipType) | | 1003 | unsigned int clientClipType) |
994 | { | | 1004 | { |
995 | ExaScreenPriv(pDrawable->pScreen); | | 1005 | ExaScreenPriv(pDrawable->pScreen); |
996 | PixmapPtr pPixmap; | | 1006 | PixmapPtr pPixmap; |
997 | ExaPixmapPrivPtr pExaPixmap; | | 1007 | ExaPixmapPrivPtr pExaPixmap; |
998 | ExaPixmapPrivPtr pTileExaPixmap = ExaGetPixmapPriv(pTile); | | 1008 | ExaPixmapPrivPtr pTileExaPixmap = ExaGetPixmapPriv(pTile); |
999 | int xoff, yoff; | | 1009 | int xoff, yoff; |
1000 | int tileWidth, tileHeight; | | 1010 | int tileWidth, tileHeight; |
1001 | ExaMigrationRec pixmaps[2]; | | 1011 | ExaMigrationRec pixmaps[2]; |
1002 | int nbox = REGION_NUM_RECTS (pRegion); | | 1012 | int nbox = REGION_NUM_RECTS (pRegion); |
1003 | BoxPtr pBox = REGION_RECTS (pRegion); | | 1013 | BoxPtr pBox = REGION_RECTS (pRegion); |
1004 | Bool ret = FALSE; | | 1014 | Bool ret = FALSE; |
1005 | int i; | | 1015 | int i; |
1006 | | | 1016 | |
1007 | tileWidth = pTile->drawable.width; | | 1017 | tileWidth = pTile->drawable.width; |
1008 | tileHeight = pTile->drawable.height; | | 1018 | tileHeight = pTile->drawable.height; |
1009 | | | 1019 | |
1010 | /* If we're filling with a solid color, grab it out and go to | | 1020 | /* If we're filling with a solid color, grab it out and go to |
1011 | * FillRegionSolid, saving numerous copies. | | 1021 | * FillRegionSolid, saving numerous copies. |
1012 | */ | | 1022 | */ |
1013 | if (tileWidth == 1 && tileHeight == 1) | | 1023 | if (tileWidth == 1 && tileHeight == 1) |
1014 | return exaFillRegionSolid(pDrawable, pRegion, | | 1024 | return exaFillRegionSolid(pDrawable, pRegion, |
1015 | exaGetPixmapFirstPixel (pTile), planemask, | | 1025 | exaGetPixmapFirstPixel (pTile), planemask, |
1016 | alu, clientClipType); | | 1026 | alu, clientClipType); |
1017 | | | 1027 | |
1018 | pixmaps[0].as_dst = TRUE; | | 1028 | pixmaps[0].as_dst = TRUE; |
1019 | pixmaps[0].as_src = FALSE; | | 1029 | pixmaps[0].as_src = FALSE; |
1020 | pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable); | | 1030 | pixmaps[0].pPix = pPixmap = exaGetDrawablePixmap (pDrawable); |
1021 | pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillTiled, | | 1031 | pixmaps[0].pReg = exaGCReadsDestination(pDrawable, planemask, FillTiled, |
1022 | alu, clientClipType) | | 1032 | alu, clientClipType) |
1023 | ? NULL : pRegion; | | 1033 | ? NULL : pRegion; |
1024 | pixmaps[1].as_dst = FALSE; | | 1034 | pixmaps[1].as_dst = FALSE; |
1025 | pixmaps[1].as_src = TRUE; | | 1035 | pixmaps[1].as_src = TRUE; |
1026 | pixmaps[1].pPix = pTile; | | 1036 | pixmaps[1].pPix = pTile; |
1027 | pixmaps[1].pReg = NULL; | | 1037 | pixmaps[1].pReg = NULL; |
1028 | | | 1038 | |
1029 | pExaPixmap = ExaGetPixmapPriv (pPixmap); | | 1039 | pExaPixmap = ExaGetPixmapPriv (pPixmap); |
1030 | | | 1040 | |
1031 | if (pExaPixmap->accel_blocked || pTileExaPixmap->accel_blocked) | | 1041 | if (pExaPixmap->accel_blocked || pTileExaPixmap->accel_blocked) |
1032 | { | | 1042 | { |
1033 | return FALSE; | | 1043 | return FALSE; |
1034 | } else { | | 1044 | } else { |
1035 | exaDoMigration (pixmaps, 2, TRUE); | | 1045 | exaDoMigration (pixmaps, 2, TRUE); |
1036 | } | | 1046 | } |
1037 | | | 1047 | |
1038 | pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); | | 1048 | pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); |
1039 | | | 1049 | |
1040 | if (!pPixmap || !exaPixmapIsOffscreen(pTile)) | | 1050 | if (!pPixmap || !exaPixmapIsOffscreen(pTile)) |
1041 | return FALSE; | | 1051 | return FALSE; |
1042 | | | 1052 | |
1043 | if ((*pExaScr->info->PrepareCopy) (pTile, pPixmap, 1, 1, alu, planemask)) | | 1053 | if ((*pExaScr->info->PrepareCopy) (pTile, pPixmap, 1, 1, alu, planemask)) |
1044 | { | | 1054 | { |
1045 | if (xoff || yoff) | | 1055 | if (xoff || yoff) |
1046 | REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); | | 1056 | REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); |
1047 | | | 1057 | |
1048 | for (i = 0; i < nbox; i++) | | 1058 | for (i = 0; i < nbox; i++) |
1049 | { | | 1059 | { |
1050 | int height = pBox[i].y2 - pBox[i].y1; | | 1060 | int height = pBox[i].y2 - pBox[i].y1; |
1051 | int dstY = pBox[i].y1; | | 1061 | int dstY = pBox[i].y1; |
1052 | int tileY; | | 1062 | int tileY; |
1053 | | | 1063 | |
1054 | if (alu == GXcopy) | | 1064 | if (alu == GXcopy) |
1055 | height = min(height, tileHeight); | | 1065 | height = min(height, tileHeight); |
1056 | | | 1066 | |
1057 | modulus(dstY - yoff - pDrawable->y - pPatOrg->y, tileHeight, tileY); | | 1067 | modulus(dstY - yoff - pDrawable->y - pPatOrg->y, tileHeight, tileY); |
1058 | | | 1068 | |
1059 | while (height > 0) { | | 1069 | while (height > 0) { |
1060 | int width = pBox[i].x2 - pBox[i].x1; | | 1070 | int width = pBox[i].x2 - pBox[i].x1; |
1061 | int dstX = pBox[i].x1; | | 1071 | int dstX = pBox[i].x1; |
1062 | int tileX; | | 1072 | int tileX; |
1063 | int h = tileHeight - tileY; | | 1073 | int h = tileHeight - tileY; |
1064 | | | 1074 | |
1065 | if (alu == GXcopy) | | 1075 | if (alu == GXcopy) |
1066 | width = min(width, tileWidth); | | 1076 | width = min(width, tileWidth); |
1067 | | | 1077 | |
1068 | if (h > height) | | 1078 | if (h > height) |
1069 | h = height; | | 1079 | h = height; |
1070 | height -= h; | | 1080 | height -= h; |
1071 | | | 1081 | |
1072 | modulus(dstX - xoff - pDrawable->x - pPatOrg->x, tileWidth, | | 1082 | modulus(dstX - xoff - pDrawable->x - pPatOrg->x, tileWidth, |
1073 | tileX); | | 1083 | tileX); |
1074 | | | 1084 | |
1075 | while (width > 0) { | | 1085 | while (width > 0) { |
1076 | int w = tileWidth - tileX; | | 1086 | int w = tileWidth - tileX; |
1077 | if (w > width) | | 1087 | if (w > width) |
1078 | w = width; | | 1088 | w = width; |
1079 | width -= w; | | 1089 | width -= w; |
1080 | | | 1090 | |
1081 | (*pExaScr->info->Copy) (pPixmap, tileX, tileY, dstX, dstY, | | 1091 | (*pExaScr->info->Copy) (pPixmap, tileX, tileY, dstX, dstY, |
1082 | w, h); | | 1092 | w, h); |
1083 | dstX += w; | | 1093 | dstX += w; |
1084 | tileX = 0; | | 1094 | tileX = 0; |
1085 | } | | 1095 | } |
1086 | dstY += h; | | 1096 | dstY += h; |
1087 | tileY = 0; | | 1097 | tileY = 0; |
1088 | } | | 1098 | } |
1089 | } | | 1099 | } |
1090 | (*pExaScr->info->DoneCopy) (pPixmap); | | 1100 | (*pExaScr->info->DoneCopy) (pPixmap); |
1091 | | | 1101 | |
1092 | /* With GXcopy, we only need to do the basic algorithm up to the tile | | 1102 | /* With GXcopy, we only need to do the basic algorithm up to the tile |
1093 | * size; then, we can just keep doubling the destination in each | | 1103 | * size; then, we can just keep doubling the destination in each |
1094 | * direction until it fills the box. This way, the number of copy | | 1104 | * direction until it fills the box. This way, the number of copy |
1095 | * operations is O(log(rx)) + O(log(ry)) instead of O(rx * ry), where | | 1105 | * operations is O(log(rx)) + O(log(ry)) instead of O(rx * ry), where |
1096 | * rx/ry is the ratio between box and tile width/height. This can make | | 1106 | * rx/ry is the ratio between box and tile width/height. This can make |
1097 | * a big difference if each driver copy incurs a significant constant | | 1107 | * a big difference if each driver copy incurs a significant constant |
1098 | * overhead. | | 1108 | * overhead. |
1099 | */ | | 1109 | */ |
1100 | if (alu != GXcopy) | | 1110 | if (alu != GXcopy) |
1101 | ret = TRUE; | | 1111 | ret = TRUE; |
1102 | else { | | 1112 | else { |
1103 | Bool more_copy = FALSE; | | 1113 | Bool more_copy = FALSE; |
1104 | | | 1114 | |
1105 | for (i = 0; i < nbox; i++) { | | 1115 | for (i = 0; i < nbox; i++) { |
1106 | int dstX = pBox[i].x1 + tileWidth; | | 1116 | int dstX = pBox[i].x1 + tileWidth; |
1107 | int dstY = pBox[i].y1 + tileHeight; | | 1117 | int dstY = pBox[i].y1 + tileHeight; |
1108 | | | 1118 | |
1109 | if ((dstX < pBox[i].x2) || (dstY < pBox[i].y2)) { | | 1119 | if ((dstX < pBox[i].x2) || (dstY < pBox[i].y2)) { |
1110 | more_copy = TRUE; | | 1120 | more_copy = TRUE; |
1111 | break; | | 1121 | break; |
1112 | } | | 1122 | } |
1113 | } | | 1123 | } |
1114 | | | 1124 | |
1115 | if (more_copy == FALSE) | | 1125 | if (more_copy == FALSE) |
1116 | ret = TRUE; | | 1126 | ret = TRUE; |
1117 | | | 1127 | |
1118 | if (more_copy && (*pExaScr->info->PrepareCopy) (pPixmap, pPixmap, | | 1128 | if (more_copy && (*pExaScr->info->PrepareCopy) (pPixmap, pPixmap, |
1119 | 1, 1, alu, planemask)) { | | 1129 | 1, 1, alu, planemask)) { |
1120 | for (i = 0; i < nbox; i++) | | 1130 | for (i = 0; i < nbox; i++) |
1121 | { | | 1131 | { |
1122 | int dstX = pBox[i].x1 + tileWidth; | | 1132 | int dstX = pBox[i].x1 + tileWidth; |
1123 | int dstY = pBox[i].y1 + tileHeight; | | 1133 | int dstY = pBox[i].y1 + tileHeight; |
1124 | int width = min(pBox[i].x2 - dstX, tileWidth); | | 1134 | int width = min(pBox[i].x2 - dstX, tileWidth); |
1125 | int height = min(pBox[i].y2 - pBox[i].y1, tileHeight); | | 1135 | int height = min(pBox[i].y2 - pBox[i].y1, tileHeight); |
1126 | | | 1136 | |
1127 | while (dstX < pBox[i].x2) { | | 1137 | while (dstX < pBox[i].x2) { |
1128 | (*pExaScr->info->Copy) (pPixmap, pBox[i].x1, pBox[i].y1, | | 1138 | (*pExaScr->info->Copy) (pPixmap, pBox[i].x1, pBox[i].y1, |
1129 | dstX, pBox[i].y1, width, height); | | 1139 | dstX, pBox[i].y1, width, height); |
1130 | dstX += width; | | 1140 | dstX += width; |
1131 | width = min(pBox[i].x2 - dstX, width * 2); | | 1141 | width = min(pBox[i].x2 - dstX, width * 2); |
1132 | } | | 1142 | } |
1133 | | | 1143 | |
1134 | width = pBox[i].x2 - pBox[i].x1; | | 1144 | width = pBox[i].x2 - pBox[i].x1; |
1135 | height = min(pBox[i].y2 - dstY, tileHeight); | | 1145 | height = min(pBox[i].y2 - dstY, tileHeight); |
1136 | | | 1146 | |
1137 | while (dstY < pBox[i].y2) { | | 1147 | while (dstY < pBox[i].y2) { |
1138 | (*pExaScr->info->Copy) (pPixmap, pBox[i].x1, pBox[i].y1, | | 1148 | (*pExaScr->info->Copy) (pPixmap, pBox[i].x1, pBox[i].y1, |
1139 | pBox[i].x1, dstY, width, height); | | 1149 | pBox[i].x1, dstY, width, height); |
1140 | dstY += height; | | 1150 | dstY += height; |
1141 | height = min(pBox[i].y2 - dstY, height * 2); | | 1151 | height = min(pBox[i].y2 - dstY, height * 2); |
1142 | } | | 1152 | } |
1143 | } | | 1153 | } |
1144 | | | 1154 | |
1145 | (*pExaScr->info->DoneCopy) (pPixmap); | | 1155 | (*pExaScr->info->DoneCopy) (pPixmap); |
1146 | | | 1156 | |
1147 | ret = TRUE; | | 1157 | ret = TRUE; |
1148 | } | | 1158 | } |
1149 | } | | 1159 | } |
1150 | | | 1160 | |
1151 | exaMarkSync(pDrawable->pScreen); | | 1161 | exaMarkSync(pDrawable->pScreen); |
1152 | | | 1162 | |
1153 | if (xoff || yoff) | | 1163 | if (xoff || yoff) |
1154 | REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); | | 1164 | REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); |
1155 | } | | 1165 | } |
1156 | | | 1166 | |
1157 | return ret; | | 1167 | return ret; |
1158 | } | | 1168 | } |
1159 | | | 1169 | |
1160 | | | 1170 | |
1161 | /** | | 1171 | /** |
1162 | * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory. | | 1172 | * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory. |
1163 | * | | 1173 | * |
1164 | * This is probably the only case we actually care about. The rest fall through | | 1174 | * This is probably the only case we actually care about. The rest fall through |
1165 | * to migration and fbGetImage, which hopefully will result in migration pushing | | 1175 | * to migration and fbGetImage, which hopefully will result in migration pushing |
1166 | * the pixmap out of framebuffer. | | 1176 | * the pixmap out of framebuffer. |
1167 | */ | | 1177 | */ |
1168 | void | | 1178 | void |
1169 | exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h, | | 1179 | exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h, |
1170 | unsigned int format, unsigned long planeMask, char *d) | | 1180 | unsigned int format, unsigned long planeMask, char *d) |
1171 | { | | 1181 | { |
1172 | ExaScreenPriv (pDrawable->pScreen); | | 1182 | ExaScreenPriv (pDrawable->pScreen); |
1173 | ExaMigrationRec pixmaps[1]; | | 1183 | ExaMigrationRec pixmaps[1]; |
1174 | BoxRec Box; | | 1184 | BoxRec Box; |
1175 | RegionRec Reg; | | 1185 | RegionRec Reg; |
1176 | PixmapPtr pPix; | | 1186 | PixmapPtr pPix; |
1177 | int xoff, yoff; | | 1187 | int xoff, yoff; |
1178 | Bool ok; | | 1188 | Bool ok; |
1179 | | | 1189 | |
1180 | pixmaps[0].as_dst = FALSE; | | 1190 | pixmaps[0].as_dst = FALSE; |
1181 | pixmaps[0].as_src = TRUE; | | 1191 | pixmaps[0].as_src = TRUE; |
1182 | pixmaps[0].pPix = pPix = exaGetDrawablePixmap (pDrawable); | | 1192 | pixmaps[0].pPix = pPix = exaGetDrawablePixmap (pDrawable); |
1183 | pixmaps[0].pReg = &Reg; | | 1193 | pixmaps[0].pReg = &Reg; |
1184 | | | 1194 | |
1185 | exaGetDrawableDeltas (pDrawable, pPix, &xoff, &yoff); | | 1195 | exaGetDrawableDeltas (pDrawable, pPix, &xoff, &yoff); |
1186 | | | 1196 | |
1187 | Box.x1 = pDrawable->y + x + xoff; | | 1197 | Box.x1 = pDrawable->y + x + xoff; |
1188 | Box.y1 = pDrawable->y + y + yoff; | | 1198 | Box.y1 = pDrawable->y + y + yoff; |
1189 | Box.x2 = Box.x1 + w; | | 1199 | Box.x2 = Box.x1 + w; |
1190 | Box.y2 = Box.y1 + h; | | 1200 | Box.y2 = Box.y1 + h; |
1191 | | | 1201 | |
1192 | REGION_INIT(pScreen, &Reg, &Box, 1); | | 1202 | REGION_INIT(pScreen, &Reg, &Box, 1); |
1193 | | | 1203 | |
1194 | if (pExaScr->swappedOut) | | 1204 | if (pExaScr->swappedOut) |
1195 | goto fallback; | | 1205 | goto fallback; |
1196 | | | 1206 | |
1197 | exaDoMigration(pixmaps, 1, FALSE); | | 1207 | exaDoMigration(pixmaps, 1, FALSE); |
1198 | | | 1208 | |
1199 | pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); | | 1209 | pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff); |
1200 | | | 1210 | |
1201 | if (pPix == NULL || pExaScr->info->DownloadFromScreen == NULL) | | 1211 | if (pPix == NULL || pExaScr->info->DownloadFromScreen == NULL) |
1202 | goto fallback; | | 1212 | goto fallback; |
1203 | | | 1213 | |
1204 | /* Only cover the ZPixmap, solid copy case. */ | | 1214 | /* Only cover the ZPixmap, solid copy case. */ |
1205 | if (format != ZPixmap || !EXA_PM_IS_SOLID(pDrawable, planeMask)) | | 1215 | if (format != ZPixmap || !EXA_PM_IS_SOLID(pDrawable, planeMask)) |
1206 | goto fallback; | | 1216 | goto fallback; |
1207 | | | 1217 | |
1208 | /* Only try to handle the 8bpp and up cases, since we don't want to think | | 1218 | /* Only try to handle the 8bpp and up cases, since we don't want to think |
1209 | * about <8bpp. | | 1219 | * about <8bpp. |
1210 | */ | | 1220 | */ |
1211 | if (pDrawable->bitsPerPixel < 8) | | 1221 | if (pDrawable->bitsPerPixel < 8) |
1212 | goto fallback; | | 1222 | goto fallback; |
1213 | | | 1223 | |
1214 | ok = pExaScr->info->DownloadFromScreen(pPix, pDrawable->x + x + xoff, | | 1224 | ok = pExaScr->info->DownloadFromScreen(pPix, pDrawable->x + x + xoff, |
1215 | pDrawable->y + y + yoff, w, h, d, | | 1225 | pDrawable->y + y + yoff, w, h, d, |
1216 | PixmapBytePad(w, pDrawable->depth)); | | 1226 | PixmapBytePad(w, pDrawable->depth)); |
1217 | if (ok) { | | 1227 | if (ok) { |
1218 | exaWaitSync(pDrawable->pScreen); | | 1228 | exaWaitSync(pDrawable->pScreen); |
1219 | goto out; | | 1229 | goto out; |
1220 | } | | 1230 | } |
1221 | | | 1231 | |
1222 | fallback: | | 1232 | fallback: |
1223 | EXA_FALLBACK(("from %p (%c)\n", pDrawable, | | 1233 | EXA_FALLBACK(("from %p (%c)\n", pDrawable, |
1224 | exaDrawableLocation(pDrawable))); | | 1234 | exaDrawableLocation(pDrawable))); |
1225 | | | 1235 | |
1226 | exaPrepareAccessReg (pDrawable, EXA_PREPARE_SRC, &Reg); | | 1236 | exaPrepareAccessReg (pDrawable, EXA_PREPARE_SRC, &Reg); |
1227 | fbGetImage (pDrawable, x, y, w, h, format, planeMask, d); | | 1237 | fbGetImage (pDrawable, x, y, w, h, format, planeMask, d); |
1228 | exaFinishAccess (pDrawable, EXA_PREPARE_SRC); | | 1238 | exaFinishAccess (pDrawable, EXA_PREPARE_SRC); |
1229 | | | 1239 | |
1230 | out: | | 1240 | out: |
1231 | REGION_UNINIT(pScreen, &Reg); | | 1241 | REGION_UNINIT(pScreen, &Reg); |
1232 | } | | 1242 | } |