diff options
author | Michel Dänzer <daenzer@vmware.com> | 2009-09-26 01:59:39 +0200 |
---|---|---|
committer | Michel Dänzer <daenzer@vmware.com> | 2009-09-26 01:59:39 +0200 |
commit | 1818cbd70fc1f2e1487b4c678e67e28f1265c0ef (patch) | |
tree | c19cc48b73ed6885079f48a321aa775068fae57e | |
parent | e23bffc41b007f1bc2b8f5cd4ac54213062c95cc (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.c | 78 | ||||
-rw-r--r-- | exa/exa_migration_classic.c | 30 | ||||
-rw-r--r-- | exa/exa_migration_mixed.c | 179 | ||||
-rw-r--r-- | exa/exa_mixed.c | 87 | ||||
-rw-r--r-- | exa/exa_priv.h | 22 | ||||
-rw-r--r-- | exa/exa_unaccel.c | 52 |
6 files changed, 232 insertions, 216 deletions
@@ -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 | */ |
288 | Bool | 288 | Bool |
289 | ExaDoPrepareAccess(DrawablePtr pDrawable, int index) | 289 | ExaDoPrepareAccess(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 | ||
373 | void | ||
374 | exaPrepareAccessReg(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) | |||
404 | void | 369 | void |
405 | exaPrepareAccess(DrawablePtr pDrawable, int index) | 370 | exaPrepareAccess(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 | */ |
266 | static void | 266 | void |
267 | exaCopyDirtyToSys (ExaMigrationPtr migrate) | 267 | exaCopyDirtyToSys (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 | */ |
284 | static void | 284 | void |
285 | exaCopyDirtyToFb (ExaMigrationPtr migrate) | 285 | exaCopyDirtyToFb (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 | |||
722 | void | ||
723 | exaPrepareAccessReg_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 | ||
34 | static void | ||
35 | exaUploadFallback(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 | |||
68 | void | 34 | void |
69 | exaCreateDriverPixmap_mixed(PixmapPtr pPixmap) | 35 | exaCreateDriverPixmap_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 | |||
140 | fallback: | ||
141 | exaUploadFallback(pPixmap, sys_buffer, sys_pitch); | ||
142 | |||
143 | finish: | ||
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 | ||
154 | void | 73 | void |
@@ -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 | */ | ||
128 | void | ||
129 | exaPrepareAccessReg_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 | */ | ||
201 | void 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 | ||
39 | static _X_INLINE void* | 37 | static _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 | */ |
53 | PixmapPtr | 48 | PixmapPtr |
54 | exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth, | 49 | exaCreatePixmap_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 | ||
198 | out: | 170 | out: |
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 */ |
513 | Bool | 515 | Bool |
514 | ExaDoPrepareAccess(DrawablePtr pDrawable, int index); | 516 | ExaDoPrepareAccess(PixmapPtr pPixmap, int index); |
515 | |||
516 | void | ||
517 | exaPrepareAccessReg(DrawablePtr pDrawable, int index, RegionPtr pReg); | ||
518 | 517 | ||
519 | void | 518 | void |
520 | exaPrepareAccess(DrawablePtr pDrawable, int index); | 519 | exaPrepareAccess(DrawablePtr pDrawable, int index); |
@@ -609,6 +608,12 @@ exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel); | |||
609 | void | 608 | void |
610 | exaMoveInPixmap_mixed(PixmapPtr pPixmap); | 609 | exaMoveInPixmap_mixed(PixmapPtr pPixmap); |
611 | 610 | ||
611 | void | ||
612 | exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg); | ||
613 | |||
614 | void | ||
615 | exaFinishAccess_mixed(PixmapPtr pPixmap, int index); | ||
616 | |||
612 | /* exa_render.c */ | 617 | /* exa_render.c */ |
613 | Bool | 618 | Bool |
614 | exaOpReadsDestination (CARD8 op); | 619 | exaOpReadsDestination (CARD8 op); |
@@ -665,6 +670,12 @@ exaGlyphs (CARD8 op, | |||
665 | 670 | ||
666 | /* exa_migration_classic.c */ | 671 | /* exa_migration_classic.c */ |
667 | void | 672 | void |
673 | exaCopyDirtyToSys (ExaMigrationPtr migrate); | ||
674 | |||
675 | void | ||
676 | exaCopyDirtyToFb (ExaMigrationPtr migrate); | ||
677 | |||
678 | void | ||
668 | exaDoMigration_classic (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel); | 679 | exaDoMigration_classic (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel); |
669 | 680 | ||
670 | void | 681 | void |
@@ -676,4 +687,7 @@ exaMoveOutPixmap_classic (PixmapPtr pPixmap); | |||
676 | void | 687 | void |
677 | exaMoveInPixmap_classic (PixmapPtr pPixmap); | 688 | exaMoveInPixmap_classic (PixmapPtr pPixmap); |
678 | 689 | ||
690 | void | ||
691 | exaPrepareAccessReg_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 | |||
323 | ExaCheckGetImage(DrawablePtr pDrawable, int x, int y, int w, int h, | 326 | ExaCheckGetImage(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 (®ion, pSrc, pMask, pDst, | 415 | if (!miComputeCompositeRegion (®ion, 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, ®ion, xoff, yoff); | 422 | REGION_TRANSLATE(pScreen, ®ion, 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 | ®ion); | 426 | EXA_PREPARE_AUX_DEST, ®ion); |
419 | 427 | ||
420 | exaPrepareAccessReg (pDst->pDrawable, EXA_PREPARE_DEST, ®ion); | 428 | pExaScr->prepare_access_reg(pDstPix, EXA_PREPARE_DEST, ®ion); |
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); |