summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <daenzer@vmware.com>2009-09-26 01:59:39 +0200
committerMichel Dänzer <daenzer@vmware.com>2009-09-26 01:59:39 +0200
commit1818cbd70fc1f2e1487b4c678e67e28f1265c0ef (patch)
treec19cc48b73ed6885079f48a321aa775068fae57e
parente23bffc41b007f1bc2b8f5cd4ac54213062c95cc (diff)
EXA: Extend mixed pixmaps scheme to allow driver PrepareAccess hook to fail.
If the PrepareAccess hook fails, use the DownloadFromScreen hook to retrieve driver pixmap contents to a system RAM copy, perform software rendering on that and copy the results back using the UploadToScreen hook. Use the classic migration logic to minimize transfers (which as a bonus allows slightly cleaning up some of the existing mixed pixmap code). This enables things that weren't possible before with driver-allocated pixmap storage: If some (or all) GPU pixmap storage can't be mapped directly by the CPU, this can be handled between the PrepareAccess and DownloadFrom/UploadToScreen hooks, e.g.: * Radeon KMS on big endian machines can fail PrepareAccess if the pixmap requires byte-swapping and swap bytes in DownloadFrom/UploadToScreen. * Environments where GPU and CPU don't have a shared address space at all. Here the driver PrepareAccess hook will always fail and leave all transfers between GPU / CPU storage to the Download/From/UploadToScreen hooks. Drivers which can handle all pixmaps in the PrepareAccess hook should notice little if any difference.
-rw-r--r--exa/exa.c78
-rw-r--r--exa/exa_migration_classic.c30
-rw-r--r--exa/exa_migration_mixed.c179
-rw-r--r--exa/exa_mixed.c87
-rw-r--r--exa/exa_priv.h22
-rw-r--r--exa/exa_unaccel.c52
6 files changed, 232 insertions, 216 deletions
diff --git a/exa/exa.c b/exa/exa.c
index 483e3b4eb..e264d440c 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -286,11 +286,10 @@ exaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp)
286 * Returns TRUE if pixmap can be accessed offscreen. 286 * Returns TRUE if pixmap can be accessed offscreen.
287 */ 287 */
288Bool 288Bool
289ExaDoPrepareAccess(DrawablePtr pDrawable, int index) 289ExaDoPrepareAccess(PixmapPtr pPixmap, int index)
290{ 290{
291 ScreenPtr pScreen = pDrawable->pScreen; 291 ScreenPtr pScreen = pPixmap->drawable.pScreen;
292 ExaScreenPriv (pScreen); 292 ExaScreenPriv (pScreen);
293 PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
294 ExaPixmapPriv(pPixmap); 293 ExaPixmapPriv(pPixmap);
295 Bool offscreen; 294 Bool offscreen;
296 int i; 295 int i;
@@ -324,7 +323,7 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
324 323
325 offscreen = exaPixmapIsOffscreen(pPixmap); 324 offscreen = exaPixmapIsOffscreen(pPixmap);
326 325
327 if (offscreen) 326 if (offscreen && pExaPixmap->fb_ptr)
328 pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr; 327 pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
329 else 328 else
330 pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr; 329 pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
@@ -333,20 +332,10 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
333 pExaScr->access[index].pixmap = pPixmap; 332 pExaScr->access[index].pixmap = pPixmap;
334 pExaScr->access[index].count = 1; 333 pExaScr->access[index].count = 1;
335 334
336 if (!offscreen) { 335 if (!offscreen)
337 /* Do we need to allocate our system buffer? */
338 if ((pExaScr->info->flags & EXA_HANDLES_PIXMAPS) && (pExaScr->info->flags & EXA_MIXED_PIXMAPS)) {
339 if (!pExaPixmap->sys_ptr && !exaPixmapIsPinned(pPixmap)) {
340 pExaPixmap->sys_ptr = malloc(pExaPixmap->sys_pitch * pDrawable->height);
341 if (!pExaPixmap->sys_ptr)
342 FatalError("EXA: malloc failed for size %d bytes\n", pExaPixmap->sys_pitch * pDrawable->height);
343 pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
344 }
345 }
346 return FALSE; 336 return FALSE;
347 }
348 337
349 exaWaitSync (pDrawable->pScreen); 338 exaWaitSync (pScreen);
350 339
351 if (pExaScr->info->PrepareAccess == NULL) 340 if (pExaScr->info->PrepareAccess == NULL)
352 return TRUE; 341 return TRUE;
@@ -360,7 +349,8 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
360 } 349 }
361 350
362 if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) { 351 if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) {
363 if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) 352 if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED &&
353 !(pExaScr->info->flags & EXA_MIXED_PIXMAPS))
364 FatalError("Driver failed PrepareAccess on a pinned pixmap.\n"); 354 FatalError("Driver failed PrepareAccess on a pinned pixmap.\n");
365 exaMoveOutPixmap (pPixmap); 355 exaMoveOutPixmap (pPixmap);
366 356
@@ -370,31 +360,6 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
370 return TRUE; 360 return TRUE;
371} 361}
372 362
373void
374exaPrepareAccessReg(DrawablePtr pDrawable, int index, RegionPtr pReg)
375{
376 PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
377 ExaScreenPriv(pPixmap->drawable.pScreen);
378
379 if (pExaScr->do_migration) {
380 ExaMigrationRec pixmaps[1];
381
382 if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
383 pixmaps[0].as_dst = TRUE;
384 pixmaps[0].as_src = FALSE;
385 } else {
386 pixmaps[0].as_dst = FALSE;
387 pixmaps[0].as_src = TRUE;
388 }
389 pixmaps[0].pPix = pPixmap;
390 pixmaps[0].pReg = pReg;
391
392 exaDoMigration(pixmaps, 1, FALSE);
393 }
394
395 ExaDoPrepareAccess(pDrawable, index);
396}
397
398/** 363/**
399 * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler. 364 * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler.
400 * 365 *
@@ -404,7 +369,13 @@ exaPrepareAccessReg(DrawablePtr pDrawable, int index, RegionPtr pReg)
404void 369void
405exaPrepareAccess(DrawablePtr pDrawable, int index) 370exaPrepareAccess(DrawablePtr pDrawable, int index)
406{ 371{
407 exaPrepareAccessReg(pDrawable, index, NULL); 372 PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
373 ExaScreenPriv(pDrawable->pScreen);
374
375 if (pExaScr->prepare_access_reg)
376 pExaScr->prepare_access_reg(pPixmap, index, NULL);
377 else
378 (void)ExaDoPrepareAccess(pPixmap, index);
408} 379}
409 380
410/** 381/**
@@ -432,7 +403,6 @@ exaFinishAccess(DrawablePtr pDrawable, int index)
432 if (pExaScr->access[i].pixmap == pPixmap) { 403 if (pExaScr->access[i].pixmap == pPixmap) {
433 if (--pExaScr->access[i].count > 0) 404 if (--pExaScr->access[i].count > 0)
434 return; 405 return;
435 index = i;
436 break; 406 break;
437 } 407 }
438 } 408 }
@@ -442,25 +412,25 @@ exaFinishAccess(DrawablePtr pDrawable, int index)
442 EXA_FatalErrorDebug(("EXA bug: FinishAccess called without PrepareAccess for pixmap 0x%p.\n", 412 EXA_FatalErrorDebug(("EXA bug: FinishAccess called without PrepareAccess for pixmap 0x%p.\n",
443 pPixmap)); 413 pPixmap));
444 414
445 pExaScr->access[index].pixmap = NULL; 415 pExaScr->access[i].pixmap = NULL;
446 416
447 /* We always hide the devPrivate.ptr. */ 417 /* We always hide the devPrivate.ptr. */
448 pPixmap->devPrivate.ptr = NULL; 418 pPixmap->devPrivate.ptr = NULL;
449 419
450 if (pExaScr->info->FinishAccess == NULL) 420 if (pExaScr->finish_access)
451 return; 421 pExaScr->finish_access(pPixmap, index);
452 422
453 if (!exaPixmapIsOffscreen (pPixmap)) 423 if (!pExaScr->info->FinishAccess || !exaPixmapIsOffscreen(pPixmap))
454 return; 424 return;
455 425
456 if (index >= EXA_PREPARE_AUX_DEST && 426 if (i >= EXA_PREPARE_AUX_DEST &&
457 !(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) { 427 !(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) {
458 ErrorF("EXA bug: Trying to call driver FinishAccess hook with " 428 ErrorF("EXA bug: Trying to call driver FinishAccess hook with "
459 "unsupported index EXA_PREPARE_AUX*\n"); 429 "unsupported index EXA_PREPARE_AUX*\n");
460 return; 430 return;
461 } 431 }
462 432
463 (*pExaScr->info->FinishAccess) (pPixmap, index); 433 (*pExaScr->info->FinishAccess) (pPixmap, i);
464} 434}
465 435
466/** 436/**
@@ -537,7 +507,7 @@ exaCreatePixmapWithPrepare(ScreenPtr pScreen, int w, int h, int depth,
537 * For EXA_HANDLES_PIXMAPS the driver will handle whatever is needed. 507 * For EXA_HANDLES_PIXMAPS the driver will handle whatever is needed.
538 * We want to signal that the pixmaps will be used as destination. 508 * We want to signal that the pixmaps will be used as destination.
539 */ 509 */
540 ExaDoPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST); 510 ExaDoPrepareAccess(pPixmap, EXA_PREPARE_AUX_DEST);
541 511
542 return pPixmap; 512 return pPixmap;
543} 513}
@@ -1071,6 +1041,8 @@ exaDriverInit (ScreenPtr pScreen,
1071 pExaScr->pixmap_is_offscreen = exaPixmapIsOffscreen_mixed; 1041 pExaScr->pixmap_is_offscreen = exaPixmapIsOffscreen_mixed;
1072 pExaScr->do_move_in_pixmap = exaMoveInPixmap_mixed; 1042 pExaScr->do_move_in_pixmap = exaMoveInPixmap_mixed;
1073 pExaScr->do_move_out_pixmap = NULL; 1043 pExaScr->do_move_out_pixmap = NULL;
1044 pExaScr->prepare_access_reg = exaPrepareAccessReg_mixed;
1045 pExaScr->finish_access = exaFinishAccess_mixed;
1074 } else { 1046 } else {
1075 wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_driver); 1047 wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_driver);
1076 wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_driver); 1048 wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_driver);
@@ -1079,6 +1051,8 @@ exaDriverInit (ScreenPtr pScreen,
1079 pExaScr->pixmap_is_offscreen = exaPixmapIsOffscreen_driver; 1051 pExaScr->pixmap_is_offscreen = exaPixmapIsOffscreen_driver;
1080 pExaScr->do_move_in_pixmap = NULL; 1052 pExaScr->do_move_in_pixmap = NULL;
1081 pExaScr->do_move_out_pixmap = NULL; 1053 pExaScr->do_move_out_pixmap = NULL;
1054 pExaScr->prepare_access_reg = NULL;
1055 pExaScr->finish_access = NULL;
1082 } 1056 }
1083 } else { 1057 } else {
1084 wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_classic); 1058 wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_classic);
@@ -1088,6 +1062,8 @@ exaDriverInit (ScreenPtr pScreen,
1088 pExaScr->pixmap_is_offscreen = exaPixmapIsOffscreen_classic; 1062 pExaScr->pixmap_is_offscreen = exaPixmapIsOffscreen_classic;
1089 pExaScr->do_move_in_pixmap = exaMoveInPixmap_classic; 1063 pExaScr->do_move_in_pixmap = exaMoveInPixmap_classic;
1090 pExaScr->do_move_out_pixmap = exaMoveOutPixmap_classic; 1064 pExaScr->do_move_out_pixmap = exaMoveOutPixmap_classic;
1065 pExaScr->prepare_access_reg = exaPrepareAccessReg_classic;
1066 pExaScr->finish_access = NULL;
1091 } 1067 }
1092 if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) { 1068 if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) {
1093 LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %lu bytes\n", 1069 LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %lu bytes\n",
diff --git a/exa/exa_migration_classic.c b/exa/exa_migration_classic.c
index d8e1e86da..0032f02f9 100644
--- a/exa/exa_migration_classic.c
+++ b/exa/exa_migration_classic.c
@@ -120,7 +120,7 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
120 Bool need_sync = FALSE; 120 Bool need_sync = FALSE;
121 121
122 /* Damaged bits are valid in current copy but invalid in other one */ 122 /* Damaged bits are valid in current copy but invalid in other one */
123 if (exaPixmapIsOffscreen(pPixmap)) { 123 if (pExaPixmap->offscreen) {
124 REGION_UNION(pScreen, &pExaPixmap->validFB, &pExaPixmap->validFB, 124 REGION_UNION(pScreen, &pExaPixmap->validFB, &pExaPixmap->validFB,
125 damage); 125 damage);
126 REGION_SUBTRACT(pScreen, &pExaPixmap->validSys, &pExaPixmap->validSys, 126 REGION_SUBTRACT(pScreen, &pExaPixmap->validSys, &pExaPixmap->validSys,
@@ -225,7 +225,7 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
225 pExaPixmap->sys_pitch)) 225 pExaPixmap->sys_pitch))
226 { 226 {
227 if (!access_prepared) { 227 if (!access_prepared) {
228 ExaDoPrepareAccess(&pPixmap->drawable, fallback_index); 228 ExaDoPrepareAccess(pPixmap, fallback_index);
229 access_prepared = TRUE; 229 access_prepared = TRUE;
230 } 230 }
231 exaMemcpyBox (pPixmap, pBox, 231 exaMemcpyBox (pPixmap, pBox,
@@ -263,7 +263,7 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
263 * the framebuffer memory copy to the system memory copy. Both areas must be 263 * the framebuffer memory copy to the system memory copy. Both areas must be
264 * allocated. 264 * allocated.
265 */ 265 */
266static void 266void
267exaCopyDirtyToSys (ExaMigrationPtr migrate) 267exaCopyDirtyToSys (ExaMigrationPtr migrate)
268{ 268{
269 PixmapPtr pPixmap = migrate->pPix; 269 PixmapPtr pPixmap = migrate->pPix;
@@ -281,7 +281,7 @@ exaCopyDirtyToSys (ExaMigrationPtr migrate)
281 * the system memory copy to the framebuffer memory copy. Both areas must be 281 * the system memory copy to the framebuffer memory copy. Both areas must be
282 * allocated. 282 * allocated.
283 */ 283 */
284static void 284void
285exaCopyDirtyToFb (ExaMigrationPtr migrate) 285exaCopyDirtyToFb (ExaMigrationPtr migrate)
286{ 286{
287 PixmapPtr pPixmap = migrate->pPix; 287 PixmapPtr pPixmap = migrate->pPix;
@@ -545,7 +545,7 @@ exaAssertNotDirty (PixmapPtr pPixmap)
545 pExaPixmap->offscreen = TRUE; 545 pExaPixmap->offscreen = TRUE;
546 pPixmap->devKind = pExaPixmap->fb_pitch; 546 pPixmap->devKind = pExaPixmap->fb_pitch;
547 547
548 if (!ExaDoPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC)) 548 if (!ExaDoPrepareAccess(pPixmap, EXA_PREPARE_SRC))
549 goto skip; 549 goto skip;
550 550
551 while (nbox--) { 551 while (nbox--) {
@@ -718,3 +718,23 @@ exaDoMigration_classic (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
718 } 718 }
719 } 719 }
720} 720}
721
722void
723exaPrepareAccessReg_classic(PixmapPtr pPixmap, int index, RegionPtr pReg)
724{
725 ExaMigrationRec pixmaps[1];
726
727 if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
728 pixmaps[0].as_dst = TRUE;
729 pixmaps[0].as_src = FALSE;
730 } else {
731 pixmaps[0].as_dst = FALSE;
732 pixmaps[0].as_src = TRUE;
733 }
734 pixmaps[0].pPix = pPixmap;
735 pixmaps[0].pReg = pReg;
736
737 exaDoMigration(pixmaps, 1, FALSE);
738
739 (void)ExaDoPrepareAccess(pPixmap, index);
740}
diff --git a/exa/exa_migration_mixed.c b/exa/exa_migration_mixed.c
index d1ee9871b..f42c9c233 100644
--- a/exa/exa_migration_mixed.c
+++ b/exa/exa_migration_mixed.c
@@ -31,55 +31,16 @@
31#include "exa_priv.h" 31#include "exa_priv.h"
32#include "exa.h" 32#include "exa.h"
33 33
34static void
35exaUploadFallback(PixmapPtr pPixmap, CARD8 *src, int src_pitch)
36{
37 ExaPixmapPriv(pPixmap);
38 RegionPtr damage = DamageRegion (pExaPixmap->pDamage);
39 GCPtr pGC = GetScratchGC (pPixmap->drawable.depth,
40 pPixmap->drawable.pScreen);
41 int nbox, cpp = pPixmap->drawable.bitsPerPixel / 8;
42 DamagePtr backup = pExaPixmap->pDamage;
43 BoxPtr pbox;
44 CARD8 *src2;
45
46 /* We don't want damage optimisations. */
47 pExaPixmap->pDamage = NULL;
48 ValidateGC (&pPixmap->drawable, pGC);
49
50 pbox = REGION_RECTS(damage);
51 nbox = REGION_NUM_RECTS(damage);
52
53 while (nbox--) {
54 src2 = src + pbox->y1 * src_pitch + pbox->x1 * cpp;
55
56 ExaCheckPutImage(&pPixmap->drawable, pGC,
57 pPixmap->drawable.depth, pbox->x1, pbox->y1,
58 pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, 0,
59 ZPixmap, (char*) src2);
60
61 pbox++;
62 }
63
64 FreeScratchGC (pGC);
65 pExaPixmap->pDamage = backup;
66}
67
68void 34void
69exaCreateDriverPixmap_mixed(PixmapPtr pPixmap) 35exaCreateDriverPixmap_mixed(PixmapPtr pPixmap)
70{ 36{
71 ScreenPtr pScreen = pPixmap->drawable.pScreen; 37 ScreenPtr pScreen = pPixmap->drawable.pScreen;
72 ExaScreenPriv(pScreen); 38 ExaScreenPriv(pScreen);
73 ExaPixmapPriv(pPixmap); 39 ExaPixmapPriv(pPixmap);
74 RegionPtr damage = DamageRegion (pExaPixmap->pDamage);
75 void *sys_buffer = pExaPixmap->sys_ptr;
76 int w = pPixmap->drawable.width, h = pPixmap->drawable.height; 40 int w = pPixmap->drawable.width, h = pPixmap->drawable.height;
77 int depth = pPixmap->drawable.depth, bpp = pPixmap->drawable.bitsPerPixel; 41 int depth = pPixmap->drawable.depth, bpp = pPixmap->drawable.bitsPerPixel;
78 int usage_hint = pPixmap->usage_hint; 42 int usage_hint = pPixmap->usage_hint;
79 int sys_pitch = pExaPixmap->sys_pitch; 43 int paddedWidth = pExaPixmap->sys_pitch;
80 int paddedWidth = sys_pitch;
81 int nbox;
82 BoxPtr pbox;
83 44
84 /* Already done. */ 45 /* Already done. */
85 if (pExaPixmap->driverPriv) 46 if (pExaPixmap->driverPriv)
@@ -105,50 +66,8 @@ exaCreateDriverPixmap_mixed(PixmapPtr pPixmap)
105 if (!pExaPixmap->driverPriv) 66 if (!pExaPixmap->driverPriv)
106 return; 67 return;
107 68
108 pExaPixmap->offscreen = TRUE;
109 pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr = NULL;
110 pExaPixmap->sys_pitch = pPixmap->devKind = 0;
111
112 pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
113 (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0, 69 (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
114 paddedWidth, NULL); 70 paddedWidth, NULL);
115
116 /* scratch pixmaps */
117 if (!w || !h)
118 goto finish;
119
120 /* we do not malloc memory by default. */
121 if (!sys_buffer)
122 goto finish;
123
124 if (!pExaScr->info->UploadToScreen)
125 goto fallback;
126
127 pbox = REGION_RECTS(damage);
128 nbox = REGION_NUM_RECTS(damage);
129
130 while (nbox--) {
131 if (!pExaScr->info->UploadToScreen(pPixmap, pbox->x1, pbox->y1, pbox->x2 - pbox->x1,
132 pbox->y2 - pbox->y1, (char *) (sys_buffer) + pbox->y1 * sys_pitch + pbox->x1 * (bpp / 8), sys_pitch))
133 goto fallback;
134
135 pbox++;
136 }
137
138 goto finish;
139
140fallback:
141 exaUploadFallback(pPixmap, sys_buffer, sys_pitch);
142
143finish:
144 free(sys_buffer);
145
146 /* We no longer need this. */
147 if (pExaPixmap->pDamage) {
148 DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
149 DamageDestroy(pExaPixmap->pDamage);
150 pExaPixmap->pDamage = NULL;
151 }
152} 71}
153 72
154void 73void
@@ -175,8 +94,16 @@ exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
175 for (i = 0; i < npixmaps; i++) { 94 for (i = 0; i < npixmaps; i++) {
176 PixmapPtr pPixmap = pixmaps[i].pPix; 95 PixmapPtr pPixmap = pixmaps[i].pPix;
177 ExaPixmapPriv(pPixmap); 96 ExaPixmapPriv(pPixmap);
97
178 if (!pExaPixmap->driverPriv) 98 if (!pExaPixmap->driverPriv)
179 exaCreateDriverPixmap_mixed(pPixmap); 99 exaCreateDriverPixmap_mixed(pPixmap);
100
101 if (pExaPixmap->pDamage && exaPixmapIsOffscreen(pPixmap)) {
102 pPixmap->devKind = pExaPixmap->fb_pitch;
103 exaCopyDirtyToFb(pixmaps + i);
104 }
105
106 pExaPixmap->offscreen = exaPixmapIsOffscreen(pPixmap);
180 } 107 }
181} 108}
182 109
@@ -192,3 +119,91 @@ exaMoveInPixmap_mixed(PixmapPtr pPixmap)
192 119
193 exaDoMigration(pixmaps, 1, TRUE); 120 exaDoMigration(pixmaps, 1, TRUE);
194} 121}
122
123/* With mixed pixmaps, if we fail to get direct access to the driver pixmap, we
124 * use the DownloadFromScreen hook to retrieve contents to a copy in system
125 * memory, perform software rendering on that and move back the results with the
126 * UploadToScreen hook (see exaFinishAccess_mixed).
127 */
128void
129exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg)
130{
131 if (!ExaDoPrepareAccess(pPixmap, index)) {
132 ExaPixmapPriv(pPixmap);
133 Bool is_offscreen = exaPixmapIsOffscreen(pPixmap);
134 ExaMigrationRec pixmaps[1];
135
136 /* Do we need to allocate our system buffer? */
137 if (!pExaPixmap->sys_ptr) {
138 pExaPixmap->sys_ptr = malloc(pExaPixmap->sys_pitch *
139 pPixmap->drawable.height);
140 if (!pExaPixmap->sys_ptr)
141 FatalError("EXA: malloc failed for size %d bytes\n",
142 pExaPixmap->sys_pitch * pPixmap->drawable.height);
143 }
144
145 if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
146 pixmaps[0].as_dst = TRUE;
147 pixmaps[0].as_src = FALSE;
148 } else {
149 pixmaps[0].as_dst = FALSE;
150 pixmaps[0].as_src = TRUE;
151 }
152 pixmaps[0].pPix = pPixmap;
153 pixmaps[0].pReg = pReg;
154
155 if (!pExaPixmap->pDamage && (is_offscreen || !exaPixmapIsPinned(pPixmap))) {
156 Bool as_dst = pixmaps[0].as_dst;
157
158 /* Set up damage tracking */
159 pExaPixmap->pDamage = DamageCreate(NULL, NULL, DamageReportNone,
160 TRUE, pPixmap->drawable.pScreen,
161 pPixmap);
162
163 DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage);
164 /* This ensures that pending damage reflects the current operation. */
165 /* This is used by exa to optimize migration. */
166 DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE);
167
168 if (is_offscreen) {
169 exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width,
170 pPixmap->drawable.height);
171
172 /* We don't know which region of the destination will be damaged,
173 * have to assume all of it
174 */
175 if (as_dst) {
176 pixmaps[0].as_dst = FALSE;
177 pixmaps[0].as_src = TRUE;
178 pixmaps[0].pReg = NULL;
179 }
180 pPixmap->devKind = pExaPixmap->fb_pitch;
181 exaCopyDirtyToSys(pixmaps);
182 }
183
184 if (as_dst)
185 exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width,
186 pPixmap->drawable.height);
187 } else if (is_offscreen) {
188 pPixmap->devKind = pExaPixmap->fb_pitch;
189 exaCopyDirtyToSys(pixmaps);
190 }
191
192 pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
193 pPixmap->devKind = pExaPixmap->sys_pitch;
194 pExaPixmap->offscreen = FALSE;
195 }
196}
197
198/* Move back results of software rendering on system memory copy of mixed driver
199 * pixmap (see exaPrepareAccessReg_mixed).
200 */
201void exaFinishAccess_mixed(PixmapPtr pPixmap, int index)
202{
203 ExaPixmapPriv(pPixmap);
204
205 if (pExaPixmap->pDamage && exaPixmapIsOffscreen(pPixmap)) {
206 DamageRegionProcessPending(&pPixmap->drawable);
207 exaMoveInPixmap_mixed(pPixmap);
208 }
209}
diff --git a/exa/exa_mixed.c b/exa/exa_mixed.c
index 6aa73f2b6..167ffa9d5 100644
--- a/exa/exa_mixed.c
+++ b/exa/exa_mixed.c
@@ -32,8 +32,6 @@
32#include "exa.h" 32#include "exa.h"
33 33
34/* This file holds the driver allocated pixmaps + better initial placement code. 34/* This file holds the driver allocated pixmaps + better initial placement code.
35 * A pinned pixmap implies one that is either driver based already or otherwise altered.
36 * Proper care is taken to free the initially allocated buffer.
37 */ 35 */
38 36
39static _X_INLINE void* 37static _X_INLINE void*
@@ -46,9 +44,6 @@ ExaGetPixmapAddress(PixmapPtr p)
46 44
47/** 45/**
48 * exaCreatePixmap() creates a new pixmap. 46 * exaCreatePixmap() creates a new pixmap.
49 *
50 * Pixmaps are always marked as pinned, unless the pixmap can still be transfered to a
51 * driver pixmaps.
52 */ 47 */
53PixmapPtr 48PixmapPtr
54exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth, 49exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
@@ -85,7 +80,6 @@ exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
85 pExaPixmap->sys_pitch = paddedWidth; 80 pExaPixmap->sys_pitch = paddedWidth;
86 81
87 pExaPixmap->area = NULL; 82 pExaPixmap->area = NULL;
88 pExaPixmap->offscreen = FALSE;
89 pExaPixmap->fb_ptr = NULL; 83 pExaPixmap->fb_ptr = NULL;
90 pExaPixmap->pDamage = NULL; 84 pExaPixmap->pDamage = NULL;
91 85
@@ -93,36 +87,15 @@ exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
93 exaSetAccelBlock(pExaScr, pExaPixmap, 87 exaSetAccelBlock(pExaScr, pExaPixmap,
94 w, h, bpp); 88 w, h, bpp);
95 89
96 /* Avoid freeing sys_ptr. */
97 pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
98
99 (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0, 90 (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
100 paddedWidth, NULL); 91 paddedWidth, NULL);
101 92
102 /* We want to be able to transfer the pixmap to driver memory later on. */
103 pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;
104
105 /* A scratch pixmap will become a driver pixmap right away. */ 93 /* A scratch pixmap will become a driver pixmap right away. */
106 if (!w || !h) { 94 if (!w || !h) {
107 exaCreateDriverPixmap_mixed(pPixmap); 95 exaCreateDriverPixmap_mixed(pPixmap);
108 } else { 96 pExaPixmap->offscreen = exaPixmapIsOffscreen(pPixmap);
109 /* Set up damage tracking */ 97 } else
110 pExaPixmap->pDamage = DamageCreate (NULL, NULL, 98 pExaPixmap->offscreen = FALSE;
111 DamageReportNone, TRUE,
112 pScreen, pPixmap);
113
114 if (pExaPixmap->pDamage == NULL) {
115 swap(pExaScr, pScreen, DestroyPixmap);
116 pScreen->DestroyPixmap (pPixmap);
117 swap(pExaScr, pScreen, DestroyPixmap);
118 return NULL;
119 }
120
121 DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage);
122 /* This ensures that pending damage reflects the current operation. */
123 /* This is used by exa to optimize migration. */
124 DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE);
125 }
126 99
127 return pPixmap; 100 return pPixmap;
128} 101}
@@ -134,7 +107,7 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
134 ScreenPtr pScreen = pPixmap->drawable.pScreen; 107 ScreenPtr pScreen = pPixmap->drawable.pScreen;
135 ExaScreenPrivPtr pExaScr; 108 ExaScreenPrivPtr pExaScr;
136 ExaPixmapPrivPtr pExaPixmap; 109 ExaPixmapPrivPtr pExaPixmap;
137 Bool ret; 110 Bool ret, is_offscreen;
138 111
139 if (!pPixmap) 112 if (!pPixmap)
140 return FALSE; 113 return FALSE;
@@ -142,26 +115,23 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
142 pExaScr = ExaGetScreenPriv(pScreen); 115 pExaScr = ExaGetScreenPriv(pScreen);
143 pExaPixmap = ExaGetPixmapPriv(pPixmap); 116 pExaPixmap = ExaGetPixmapPriv(pPixmap);
144 117
145 if (pExaPixmap) { 118 if (pPixData) {
146 if (!exaPixmapIsPinned(pPixmap)) { 119 if (pExaPixmap->driverPriv) {
147 free(pExaPixmap->sys_ptr);
148 pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr = NULL;
149 pExaPixmap->sys_pitch = pPixmap->devKind = 0;
150
151 /* We no longer need this. */
152 if (pExaPixmap->pDamage) { 120 if (pExaPixmap->pDamage) {
153 DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage); 121 DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
154 DamageDestroy(pExaPixmap->pDamage); 122 DamageDestroy(pExaPixmap->pDamage);
155 pExaPixmap->pDamage = NULL; 123 pExaPixmap->pDamage = NULL;
156 } 124 }
157 }
158 125
159 if (pPixData) 126 pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
160 pExaPixmap->sys_ptr = pPixData; 127 pExaPixmap->driverPriv = NULL;
128 }
161 129
162 if (devKind > 0) 130 pExaPixmap->offscreen = FALSE;
163 pExaPixmap->sys_pitch = devKind; 131 pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
132 }
164 133
134 if (pExaPixmap->driverPriv) {
165 if (width > 0 && height > 0 && bitsPerPixel > 0) { 135 if (width > 0 && height > 0 && bitsPerPixel > 0) {
166 exaSetFbPitch(pExaScr, pExaPixmap, 136 exaSetFbPitch(pExaScr, pExaPixmap,
167 width, height, bitsPerPixel); 137 width, height, bitsPerPixel);
@@ -169,9 +139,15 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
169 exaSetAccelBlock(pExaScr, pExaPixmap, 139 exaSetAccelBlock(pExaScr, pExaPixmap,
170 width, height, bitsPerPixel); 140 width, height, bitsPerPixel);
171 } 141 }
142 }
172 143
173 /* Anything can happen, don't try to predict it all. */ 144 is_offscreen = exaPixmapIsOffscreen(pPixmap);
174 pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED; 145 if (is_offscreen) {
146 pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
147 pPixmap->devKind = pExaPixmap->fb_pitch;
148 } else {
149 pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
150 pPixmap->devKind = pExaPixmap->sys_pitch;
175 } 151 }
176 152
177 /* Only pass driver pixmaps to the driver. */ 153 /* Only pass driver pixmaps to the driver. */
@@ -182,10 +158,6 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
182 * If pPixmap->devPrivate.ptr is non-NULL, then we've got a non-offscreen pixmap. 158 * If pPixmap->devPrivate.ptr is non-NULL, then we've got a non-offscreen pixmap.
183 * We need to store the pointer, because PrepareAccess won't be called. 159 * We need to store the pointer, because PrepareAccess won't be called.
184 */ 160 */
185 if (!pPixData && pPixmap->devPrivate.ptr && pPixmap->devKind) {
186 pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
187 pExaPixmap->sys_pitch = pPixmap->devKind;
188 }
189 if (ret == TRUE) 161 if (ret == TRUE)
190 goto out; 162 goto out;
191 } 163 }
@@ -196,6 +168,13 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
196 swap(pExaScr, pScreen, ModifyPixmapHeader); 168 swap(pExaScr, pScreen, ModifyPixmapHeader);
197 169
198out: 170out:
171 if (is_offscreen) {
172 pExaPixmap->fb_ptr = pPixmap->devPrivate.ptr;
173 pExaPixmap->fb_pitch = pPixmap->devKind;
174 } else {
175 pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
176 pExaPixmap->sys_pitch = pPixmap->devKind;
177 }
199 /* Always NULL this, we don't want lingering pointers. */ 178 /* Always NULL this, we don't want lingering pointers. */
200 pPixmap->devPrivate.ptr = NULL; 179 pPixmap->devPrivate.ptr = NULL;
201 180
@@ -215,10 +194,14 @@ exaDestroyPixmap_mixed(PixmapPtr pPixmap)
215 194
216 if (pExaPixmap->driverPriv) 195 if (pExaPixmap->driverPriv)
217 pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv); 196 pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
218 else if (pExaPixmap->sys_ptr && !exaPixmapIsPinned(pPixmap))
219 free(pExaPixmap->sys_ptr);
220 pExaPixmap->driverPriv = NULL; 197 pExaPixmap->driverPriv = NULL;
221 pExaPixmap->sys_ptr = NULL; 198
199 if (pExaPixmap->pDamage) {
200 if (pExaPixmap->sys_ptr)
201 free(pExaPixmap->sys_ptr);
202 pExaPixmap->sys_ptr = NULL;
203 pExaPixmap->pDamage = NULL;
204 }
222 } 205 }
223 206
224 swap(pExaScr, pScreen, DestroyPixmap); 207 swap(pExaScr, pScreen, DestroyPixmap);
diff --git a/exa/exa_priv.h b/exa/exa_priv.h
index 869cf1772..1aec8e966 100644
--- a/exa/exa_priv.h
+++ b/exa/exa_priv.h
@@ -176,6 +176,8 @@ typedef struct {
176 Bool (*pixmap_is_offscreen) (PixmapPtr pPixmap); 176 Bool (*pixmap_is_offscreen) (PixmapPtr pPixmap);
177 void (*do_move_in_pixmap) (PixmapPtr pPixmap); 177 void (*do_move_in_pixmap) (PixmapPtr pPixmap);
178 void (*do_move_out_pixmap) (PixmapPtr pPixmap); 178 void (*do_move_out_pixmap) (PixmapPtr pPixmap);
179 void (*prepare_access_reg)(PixmapPtr pPixmap, int index, RegionPtr pReg);
180 void (*finish_access)(PixmapPtr pPixmap, int index);
179 181
180 Bool swappedOut; 182 Bool swappedOut;
181 enum ExaMigrationHeuristic migration; 183 enum ExaMigrationHeuristic migration;
@@ -511,10 +513,7 @@ ExaOffscreenFini (ScreenPtr pScreen);
511 513
512/* exa.c */ 514/* exa.c */
513Bool 515Bool
514ExaDoPrepareAccess(DrawablePtr pDrawable, int index); 516ExaDoPrepareAccess(PixmapPtr pPixmap, int index);
515
516void
517exaPrepareAccessReg(DrawablePtr pDrawable, int index, RegionPtr pReg);
518 517
519void 518void
520exaPrepareAccess(DrawablePtr pDrawable, int index); 519exaPrepareAccess(DrawablePtr pDrawable, int index);
@@ -609,6 +608,12 @@ exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
609void 608void
610exaMoveInPixmap_mixed(PixmapPtr pPixmap); 609exaMoveInPixmap_mixed(PixmapPtr pPixmap);
611 610
611void
612exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg);
613
614void
615exaFinishAccess_mixed(PixmapPtr pPixmap, int index);
616
612/* exa_render.c */ 617/* exa_render.c */
613Bool 618Bool
614exaOpReadsDestination (CARD8 op); 619exaOpReadsDestination (CARD8 op);
@@ -665,6 +670,12 @@ exaGlyphs (CARD8 op,
665 670
666/* exa_migration_classic.c */ 671/* exa_migration_classic.c */
667void 672void
673exaCopyDirtyToSys (ExaMigrationPtr migrate);
674
675void
676exaCopyDirtyToFb (ExaMigrationPtr migrate);
677
678void
668exaDoMigration_classic (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel); 679exaDoMigration_classic (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
669 680
670void 681void
@@ -676,4 +687,7 @@ exaMoveOutPixmap_classic (PixmapPtr pPixmap);
676void 687void
677exaMoveInPixmap_classic (PixmapPtr pPixmap); 688exaMoveInPixmap_classic (PixmapPtr pPixmap);
678 689
690void
691exaPrepareAccessReg_classic(PixmapPtr pPixmap, int index, RegionPtr pReg);
692
679#endif /* EXAPRIV_H */ 693#endif /* EXAPRIV_H */
diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c
index f4700adac..c8f017243 100644
--- a/exa/exa_unaccel.c
+++ b/exa/exa_unaccel.c
@@ -101,16 +101,19 @@ ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth,
101 int x, int y, int w, int h, int leftPad, int format, 101 int x, int y, int w, int h, int leftPad, int format,
102 char *bits) 102 char *bits)
103{ 103{
104 ExaPixmapPriv(exaGetDrawablePixmap(pDrawable)); 104 PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
105 ExaPixmapPriv(pPixmap);
106 ExaScreenPriv(pDrawable->pScreen);
105 107
106 EXA_GC_PROLOGUE(pGC); 108 EXA_GC_PROLOGUE(pGC);
107 EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable))); 109 EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
108 if (exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle, 110 if (!pExaScr->prepare_access_reg || !pExaPixmap->pDamage ||
111 exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle,
109 pGC->alu, pGC->clientClipType)) 112 pGC->alu, pGC->clientClipType))
110 exaPrepareAccess (pDrawable, EXA_PREPARE_DEST); 113 exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
111 else 114 else
112 exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST, pExaPixmap->pDamage ? 115 pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_DEST,
113 DamagePendingRegion(pExaPixmap->pDamage) : NULL); 116 DamagePendingRegion(pExaPixmap->pDamage));
114 pGC->ops->PutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits); 117 pGC->ops->PutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits);
115 exaFinishAccess (pDrawable, EXA_PREPARE_DEST); 118 exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
116 EXA_GC_EPILOGUE(pGC); 119 EXA_GC_EPILOGUE(pGC);
@@ -323,9 +326,6 @@ void
323ExaCheckGetImage(DrawablePtr pDrawable, int x, int y, int w, int h, 326ExaCheckGetImage(DrawablePtr pDrawable, int x, int y, int w, int h,
324 unsigned int format, unsigned long planeMask, char *d) 327 unsigned int format, unsigned long planeMask, char *d)
325{ 328{
326 BoxRec Box;
327 RegionRec Reg;
328 int xoff, yoff;
329 ScreenPtr pScreen = pDrawable->pScreen; 329 ScreenPtr pScreen = pDrawable->pScreen;
330 PixmapPtr pPix = exaGetDrawablePixmap (pDrawable); 330 PixmapPtr pPix = exaGetDrawablePixmap (pDrawable);
331 ExaScreenPriv(pScreen); 331 ExaScreenPriv(pScreen);
@@ -333,16 +333,24 @@ ExaCheckGetImage(DrawablePtr pDrawable, int x, int y, int w, int h,
333 EXA_FALLBACK(("from %p (%c)\n", pDrawable, 333 EXA_FALLBACK(("from %p (%c)\n", pDrawable,
334 exaDrawableLocation(pDrawable))); 334 exaDrawableLocation(pDrawable)));
335 335
336 exaGetDrawableDeltas(pDrawable, pPix, &xoff, &yoff); 336 if (pExaScr->prepare_access_reg) {
337 int xoff, yoff;
338 BoxRec Box;
339 RegionRec Reg;
340
341 exaGetDrawableDeltas(pDrawable, pPix, &xoff, &yoff);
342
343 Box.x1 = pDrawable->y + x + xoff;
344 Box.y1 = pDrawable->y + y + yoff;
345 Box.x2 = Box.x1 + w;
346 Box.y2 = Box.y1 + h;
337 347
338 Box.x1 = pDrawable->y + x + xoff; 348 REGION_INIT(pScreen, &Reg, &Box, 1);
339 Box.y1 = pDrawable->y + y + yoff;
340 Box.x2 = Box.x1 + w;
341 Box.y2 = Box.y1 + h;
342 349
343 REGION_INIT(pScreen, &Reg, &Box, 1); 350 pExaScr->prepare_access_reg(pPix, EXA_PREPARE_SRC, &Reg);
351 } else
352 exaPrepareAccess(pDrawable, EXA_PREPARE_SRC);
344 353
345 exaPrepareAccessReg (pDrawable, EXA_PREPARE_SRC, &Reg);
346 swap(pExaScr, pScreen, GetImage); 354 swap(pExaScr, pScreen, GetImage);
347 pScreen->GetImage (pDrawable, x, y, w, h, format, planeMask, d); 355 pScreen->GetImage (pDrawable, x, y, w, h, format, planeMask, d);
348 swap(pExaScr, pScreen, GetImage); 356 swap(pExaScr, pScreen, GetImage);
@@ -401,23 +409,23 @@ ExaCheckComposite (CARD8 op,
401 if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable) 409 if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
402 exaPrepareAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX_MASK); 410 exaPrepareAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX_MASK);
403 411
404 if (!exaOpReadsDestination(op)) { 412 if (!exaOpReadsDestination(op) && pExaScr->prepare_access_reg) {
413 PixmapPtr pDstPix;
414
405 if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst, 415 if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
406 xSrc, ySrc, xMask, yMask, xDst, yDst, 416 xSrc, ySrc, xMask, yMask, xDst, yDst,
407 width, height)) 417 width, height))
408 goto skip; 418 goto skip;
409 419
410 exaGetDrawableDeltas (pDst->pDrawable, 420 pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
411 exaGetDrawablePixmap(pDst->pDrawable), 421 exaGetDrawableDeltas (pDst->pDrawable, pDstPix, &xoff, &yoff);
412 &xoff, &yoff);
413
414 REGION_TRANSLATE(pScreen, &region, xoff, yoff); 422 REGION_TRANSLATE(pScreen, &region, xoff, yoff);
415 423
416 if (pDst->alphaMap && pDst->alphaMap->pDrawable) 424 if (pDst->alphaMap && pDst->alphaMap->pDrawable)
417 exaPrepareAccessReg(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX_DEST, 425 pExaScr->prepare_access_reg(exaGetDrawablePixmap(pDst->alphaMap->pDrawable),
418 &region); 426 EXA_PREPARE_AUX_DEST, &region);
419 427
420 exaPrepareAccessReg (pDst->pDrawable, EXA_PREPARE_DEST, &region); 428 pExaScr->prepare_access_reg(pDstPix, EXA_PREPARE_DEST, &region);
421 } else { 429 } else {
422 if (pDst->alphaMap && pDst->alphaMap->pDrawable) 430 if (pDst->alphaMap && pDst->alphaMap->pDrawable)
423 exaPrepareAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX_DEST); 431 exaPrepareAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX_DEST);