2
* Copyright � 2001 Keith Packard
4
* Partly based on code that is Copyright � The XFree86 Project Inc.
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
8
* the above copyright notice appear in all copies and that both that
9
* copyright notice and this permission notice appear in supporting
10
* documentation, and that the name of Keith Packard not be used in
11
* advertising or publicity pertaining to distribution of the software without
12
* specific, written prior permission. Keith Packard makes no
13
* representations about the suitability of this software for any purpose. It
14
* is provided "as is" without express or implied warranty.
16
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
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
21
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22
* PERFORMANCE OF THIS SOFTWARE.
25
#ifdef HAVE_DIX_CONFIG_H
26
#include <dix-config.h>
29
#include <X11/fonts/fontstruct.h>
30
#include "dixfontstr.h"
35
exaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
36
DDXPointPtr ppt, int *pwidth, int fSorted)
38
ScreenPtr pScreen = pDrawable->pScreen;
39
ExaScreenPriv (pScreen);
40
RegionPtr pClip = fbGetCompositeClip(pGC);
44
int extentX1, extentX2, extentY1, extentY2;
45
int fullX1, fullX2, fullY1;
48
ExaMigrationRec pixmaps[1];
50
pixmaps[0].as_dst = TRUE;
51
pixmaps[0].as_src = FALSE;
52
pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
54
if (pExaScr->swappedOut ||
55
pGC->fillStyle != FillSolid ||
56
pDrawable->width > pExaScr->info->maxX ||
57
pDrawable->height > pExaScr->info->maxY)
59
exaDoMigration (pixmaps, 1, FALSE);
60
ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
63
exaDoMigration (pixmaps, 1, TRUE);
66
if (!(pPixmap = exaGetOffscreenPixmap (pDrawable, &off_x, &off_y)) ||
67
!(*pExaScr->info->PrepareSolid) (pPixmap,
72
ExaCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
76
pextent = REGION_EXTENTS(pGC->pScreen, pClip);
77
extentX1 = pextent->x1;
78
extentY1 = pextent->y1;
79
extentX2 = pextent->x2;
80
extentY2 = pextent->y2;
85
fullX2 = fullX1 + (int) *pwidth;
89
if (fullY1 < extentY1 || extentY2 <= fullY1)
92
if (fullX1 < extentX1)
95
if (fullX2 > extentX2)
101
nbox = REGION_NUM_RECTS (pClip);
104
(*pExaScr->info->Solid) (pPixmap,
105
fullX1 + off_x, fullY1 + off_y,
106
fullX2 + off_x, fullY1 + 1 + off_y);
110
pbox = REGION_RECTS(pClip);
113
if (pbox->y1 <= fullY1 && fullY1 < pbox->y2)
122
(*pExaScr->info->Solid) (pPixmap,
123
partX1 + off_x, fullY1 + off_y,
124
partX2 + off_x, fullY1 + 1 + off_y);
130
(*pExaScr->info->DoneSolid) (pPixmap);
131
exaDrawableDirty (pDrawable);
132
exaMarkSync(pScreen);
136
exaPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
137
int w, int h, int leftPad, int format, char *bits)
139
ExaScreenPriv (pDrawable->pScreen);
141
ExaMigrationRec pixmaps[1];
146
int src_stride, bpp = pDrawable->bitsPerPixel;
148
if (pExaScr->swappedOut || pExaScr->info->UploadToScreen == NULL)
149
goto migrate_and_fallback;
151
/* Don't bother with under 8bpp, XYPixmaps. */
152
if (format != ZPixmap || bpp < 8)
153
goto migrate_and_fallback;
155
/* Only accelerate copies: no rop or planemask. */
156
if (!EXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy)
157
goto migrate_and_fallback;
159
pixmaps[0].as_dst = TRUE;
160
pixmaps[0].as_src = FALSE;
161
pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
162
exaDoMigration (pixmaps, 1, TRUE);
163
pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
171
pClip = fbGetCompositeClip(pGC);
172
src_stride = PixmapBytePad(w, pDrawable->depth);
173
for (nbox = REGION_NUM_RECTS(pClip),
174
pbox = REGION_RECTS(pClip);
193
if (x1 >= x2 || y1 >= y2)
196
src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8);
197
ok = pExaScr->info->UploadToScreen(pPix, x1 + xoff, y1 + yoff,
198
x2 - x1, y2 - y1, src, src_stride);
199
/* If we fail to accelerate the upload, fall back to using unaccelerated
206
int dstXoff, dstYoff;
208
exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
210
fbGetStipDrawable(pDrawable, dst, dst_stride, dstBpp,
213
fbBltStip((FbStip *)bits + (y1 - y) * (src_stride / sizeof(FbStip)),
214
src_stride / sizeof(FbStip),
216
dst + (y1 + yoff) * dst_stride,
221
GXcopy, FB_ALLONES, bpp);
223
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
229
migrate_and_fallback:
230
pixmaps[0].as_dst = TRUE;
231
pixmaps[0].as_src = FALSE;
232
pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
233
exaDoMigration (pixmaps, 1, FALSE);
236
ExaCheckPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits);
240
exaCopyNtoNTwoDir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
241
GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy)
243
ExaScreenPriv (pDstDrawable->pScreen);
244
PixmapPtr pSrcPixmap, pDstPixmap;
245
int src_off_x, src_off_y, dst_off_x, dst_off_y;
248
/* Need to get both pixmaps to call the driver routines */
249
pSrcPixmap = exaGetOffscreenPixmap (pSrcDrawable, &src_off_x, &src_off_y);
250
pDstPixmap = exaGetOffscreenPixmap (pDstDrawable, &dst_off_x, &dst_off_y);
251
if (!pSrcPixmap || !pDstPixmap)
255
* Now the case of a chip that only supports xdir = ydir = 1 or
256
* xdir = ydir = -1, but we have xdir != ydir.
258
dirsetup = 0; /* No direction set up yet. */
259
for (; nbox; pbox++, nbox--) {
260
if (dx >= 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) {
261
/* Do a xdir = ydir = -1 blit instead. */
262
if (dirsetup != -1) {
264
pExaScr->info->DoneCopy(pDstPixmap);
266
if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap,
269
pGC ? pGC->alu : GXcopy,
270
pGC ? pGC->planemask :
274
(*pExaScr->info->Copy)(pDstPixmap,
275
src_off_x + pbox->x1 + dx,
276
src_off_y + pbox->y1 + dy,
277
dst_off_x + pbox->x1,
278
dst_off_y + pbox->y1,
280
pbox->y2 - pbox->y1);
281
} else if (dx < 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) {
282
/* Do a xdir = ydir = 1 blit instead. */
285
pExaScr->info->DoneCopy(pDstPixmap);
287
if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap,
290
pGC ? pGC->alu : GXcopy,
291
pGC ? pGC->planemask :
295
(*pExaScr->info->Copy)(pDstPixmap,
296
src_off_x + pbox->x1 + dx,
297
src_off_y + pbox->y1 + dy,
298
dst_off_x + pbox->x1,
299
dst_off_y + pbox->y1,
301
pbox->y2 - pbox->y1);
302
} else if (dx >= 0) {
304
* xdir = 1, ydir = -1.
305
* Perform line-by-line xdir = ydir = 1 blits, going up.
310
pExaScr->info->DoneCopy(pDstPixmap);
312
if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap,
315
pGC ? pGC->alu : GXcopy,
316
pGC ? pGC->planemask :
320
for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--)
321
(*pExaScr->info->Copy)(pDstPixmap,
322
src_off_x + pbox->x1 + dx,
323
src_off_y + pbox->y1 + dy + i,
324
dst_off_x + pbox->x1,
325
dst_off_y + pbox->y1 + i,
326
pbox->x2 - pbox->x1, 1);
329
* xdir = -1, ydir = 1.
330
* Perform line-by-line xdir = ydir = -1 blits, going down.
333
if (dirsetup != -1) {
335
pExaScr->info->DoneCopy(pDstPixmap);
337
if (!(*pExaScr->info->PrepareCopy)(pSrcPixmap,
340
pGC ? pGC->alu : GXcopy,
341
pGC ? pGC->planemask :
345
for (i = 0; i < pbox->y2 - pbox->y1; i++)
346
(*pExaScr->info->Copy)(pDstPixmap,
347
src_off_x + pbox->x1 + dx,
348
src_off_y + pbox->y1 + dy + i,
349
dst_off_x + pbox->x1,
350
dst_off_y + pbox->y1 + i,
351
pbox->x2 - pbox->x1, 1);
355
pExaScr->info->DoneCopy(pDstPixmap);
356
exaMarkSync(pDstDrawable->pScreen);
357
exaDrawableDirty(pDstDrawable);
362
exaCopyNtoN (DrawablePtr pSrcDrawable,
363
DrawablePtr pDstDrawable,
374
ExaScreenPriv (pDstDrawable->pScreen);
375
PixmapPtr pSrcPixmap, pDstPixmap;
376
int src_off_x, src_off_y;
377
int dst_off_x, dst_off_y;
378
ExaMigrationRec pixmaps[2];
380
pixmaps[0].as_dst = TRUE;
381
pixmaps[0].as_src = FALSE;
382
pixmaps[0].pPix = exaGetDrawablePixmap (pDstDrawable);
383
pixmaps[1].as_dst = FALSE;
384
pixmaps[1].as_src = TRUE;
385
pixmaps[1].pPix = exaGetDrawablePixmap (pSrcDrawable);
387
/* Respect maxX/maxY in a trivial way: don't set up drawing when we might
388
* violate the limits. The proper solution would be a temporary pixmap
389
* adjusted so that the drawing happened within limits.
391
if (pSrcDrawable->width > pExaScr->info->maxX ||
392
pSrcDrawable->height > pExaScr->info->maxY ||
393
pDstDrawable->width > pExaScr->info->maxX ||
394
pDstDrawable->height > pExaScr->info->maxY)
396
exaDoMigration (pixmaps, 2, FALSE);
399
exaDoMigration (pixmaps, 2, TRUE);
402
/* Mixed directions must be handled specially if the card is lame */
403
if (pExaScr->info->flags & EXA_TWO_BITBLT_DIRECTIONS && (dx*dy) < 0) {
404
if (!exaCopyNtoNTwoDir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox,
410
if ((pSrcPixmap = exaGetOffscreenPixmap (pSrcDrawable, &src_off_x, &src_off_y)) &&
411
(pDstPixmap = exaGetOffscreenPixmap (pDstDrawable, &dst_off_x, &dst_off_y)) &&
412
(*pExaScr->info->PrepareCopy) (pSrcPixmap, pDstPixmap,
414
pGC ? pGC->alu : GXcopy,
415
pGC ? pGC->planemask : FB_ALLONES))
419
(*pExaScr->info->Copy) (pDstPixmap,
420
pbox->x1 + dx + src_off_x,
421
pbox->y1 + dy + src_off_y,
422
pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
424
pbox->y2 - pbox->y1);
427
(*pExaScr->info->DoneCopy) (pDstPixmap);
428
exaMarkSync(pDstDrawable->pScreen);
429
exaDrawableDirty (pDstDrawable);
434
EXA_FALLBACK(("from 0x%lx to 0x%lx\n", (long)pSrcDrawable,
435
(long)pDstDrawable));
436
exaPrepareAccess (pDstDrawable, EXA_PREPARE_DEST);
437
exaPrepareAccess (pSrcDrawable, EXA_PREPARE_SRC);
438
fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC,
439
pbox, nbox, dx, dy, reverse, upsidedown,
441
exaFinishAccess (pSrcDrawable, EXA_PREPARE_SRC);
442
exaFinishAccess (pDstDrawable, EXA_PREPARE_DEST);
446
exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
447
int srcx, int srcy, int width, int height, int dstx, int dsty)
449
ExaScreenPriv (pDstDrawable->pScreen);
451
if (pExaScr->swappedOut) {
452
return ExaCheckCopyArea(pSrcDrawable, pDstDrawable, pGC,
453
srcx, srcy, width, height, dstx, dsty);
456
return fbDoCopy (pSrcDrawable, pDstDrawable, pGC,
457
srcx, srcy, width, height,
458
dstx, dsty, exaCopyNtoN, 0, NULL);
462
exaPolyFillRect(DrawablePtr pDrawable,
467
ExaScreenPriv (pDrawable->pScreen);
468
RegionPtr pClip = fbGetCompositeClip(pGC);
470
register BoxPtr pbox;
472
int extentX1, extentX2, extentY1, extentY2;
473
int fullX1, fullX2, fullY1, fullY2;
474
int partX1, partX2, partY1, partY2;
478
ExaMigrationRec pixmaps[1];
480
pixmaps[0].as_dst = TRUE;
481
pixmaps[0].as_src = FALSE;
482
pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
484
if (pExaScr->swappedOut ||
485
pGC->fillStyle != FillSolid ||
486
pDrawable->width > pExaScr->info->maxX ||
487
pDrawable->height > pExaScr->info->maxY)
489
exaDoMigration (pixmaps, 1, FALSE);
490
ExaCheckPolyFillRect (pDrawable, pGC, nrect, prect);
493
exaDoMigration (pixmaps, 1, TRUE);
496
if (!(pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) ||
497
!(*pExaScr->info->PrepareSolid) (pPixmap,
502
ExaCheckPolyFillRect (pDrawable, pGC, nrect, prect);
509
pextent = REGION_EXTENTS(pGC->pScreen, pClip);
510
extentX1 = pextent->x1;
511
extentY1 = pextent->y1;
512
extentX2 = pextent->x2;
513
extentY2 = pextent->y2;
516
fullX1 = prect->x + xorg;
517
fullY1 = prect->y + yorg;
518
fullX2 = fullX1 + (int) prect->width;
519
fullY2 = fullY1 + (int) prect->height;
522
if (fullX1 < extentX1)
525
if (fullY1 < extentY1)
528
if (fullX2 > extentX2)
531
if (fullY2 > extentY2)
534
if ((fullX1 >= fullX2) || (fullY1 >= fullY2))
536
n = REGION_NUM_RECTS (pClip);
539
(*pExaScr->info->Solid) (pPixmap,
540
fullX1 + xoff, fullY1 + yoff,
541
fullX2 + xoff, fullY2 + yoff);
545
pbox = REGION_RECTS(pClip);
547
* clip the rectangle to each box in the clip region
548
* this is logically equivalent to calling Intersect()
567
if (partX1 < partX2 && partY1 < partY2)
568
(*pExaScr->info->Solid) (pPixmap,
569
partX1 + xoff, partY1 + yoff,
570
partX2 + xoff, partY2 + yoff);
574
(*pExaScr->info->DoneSolid) (pPixmap);
575
exaDrawableDirty (pDrawable);
576
exaMarkSync(pDrawable->pScreen);
580
exaSolidBoxClipped (DrawablePtr pDrawable,
589
ExaScreenPriv (pDrawable->pScreen);
594
int partX1, partX2, partY1, partY2;
595
ExaMigrationRec pixmaps[1];
597
pixmaps[0].as_dst = TRUE;
598
pixmaps[0].as_src = FALSE;
599
pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
601
if (pExaScr->swappedOut ||
602
pDrawable->width > pExaScr->info->maxX ||
603
pDrawable->height > pExaScr->info->maxY)
605
EXA_FALLBACK(("to 0x%lx\n", (long)pDrawable));
606
exaDoMigration (pixmaps, 1, FALSE);
609
exaDoMigration (pixmaps, 1, TRUE);
612
if (!(pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) ||
613
!(*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, pm, fg))
616
EXA_FALLBACK(("to 0x%lx\n", (long)pDrawable));
617
exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
618
fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel);
619
fbSolidBoxClipped (pDrawable, pClip, x1, y1, x2, y2,
620
fbAnd (GXcopy, fg, pm),
621
fbXor (GXcopy, fg, pm));
622
exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
625
for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip);
637
if (partX2 <= partX1)
648
if (partY2 <= partY1)
651
(*pExaScr->info->Solid) (pPixmap,
652
partX1 + xoff, partY1 + yoff,
653
partX2 + xoff, partY2 + yoff);
655
(*pExaScr->info->DoneSolid) (pPixmap);
656
exaDrawableDirty (pDrawable);
657
exaMarkSync(pDrawable->pScreen);
661
exaImageGlyphBlt (DrawablePtr pDrawable,
666
CharInfoPtr *ppciInit,
669
FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
672
unsigned char *pglyph; /* pointer bits in glyph */
673
int gWidth, gHeight; /* width and height of glyph */
674
FbStride gStride; /* stride of glyph */
678
void (*glyph) (FbBits *,
688
int dstXoff, dstYoff;
691
depthMask = FbFullMask(pDrawable->depth);
692
if ((pGC->planemask & depthMask) != depthMask)
694
ExaCheckImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppciInit, pglyphBase);
698
switch (pDrawable->bitsPerPixel) {
699
case 8: glyph = fbGlyph8; break;
700
case 16: glyph = fbGlyph16; break;
701
case 24: glyph = fbGlyph24; break;
702
case 32: glyph = fbGlyph32; break;
708
if (TERMINALFONT (pGC->font) && !glyph)
714
int xBack, widthBack;
715
int yBack, heightBack;
721
widthBack += (*ppci++)->metrics.characterWidth;
727
widthBack = -widthBack;
729
yBack = y - FONTASCENT(pGC->font);
730
heightBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
731
exaSolidBoxClipped (pDrawable,
732
fbGetCompositeClip(pGC),
742
EXA_FALLBACK(("to 0x%lx\n", (long)pDrawable));
743
exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
744
exaPrepareAccessGC (pGC);
746
fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
752
pglyph = FONTGLYPHBITS(pglyphBase, pci);
753
gWidth = GLYPHWIDTHPIXELS(pci);
754
gHeight = GLYPHHEIGHTPIXELS(pci);
755
if (gWidth && gHeight)
757
gx = x + pci->metrics.leftSideBearing;
758
gy = y - pci->metrics.ascent;
759
if (glyph && gWidth <= sizeof (FbStip) * 8 &&
760
fbGlyphIn (fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight))
762
(*glyph) (dst + (gy + dstYoff) * dstStride,
772
gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip);
773
fbPutXYImage (pDrawable,
774
fbGetCompositeClip(pGC),
790
x += pci->metrics.characterWidth;
792
exaFinishAccessGC (pGC);
793
exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
796
const GCOps exaOps = {
815
ExaCheckPolyGlyphBlt,
817
#ifdef NEED_LINEHELPER
823
exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
827
PixmapPtr pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin);
829
dx = ptOldOrg.x - pWin->drawable.x;
830
dy = ptOldOrg.y - pWin->drawable.y;
831
REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
833
REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0);
835
REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
837
if (pPixmap->screen_x || pPixmap->screen_y)
838
REGION_TRANSLATE (pWin->drawable.pScreen, &rgnDst,
839
-pPixmap->screen_x, -pPixmap->screen_y);
842
fbCopyRegion (&pPixmap->drawable, &pPixmap->drawable,
844
&rgnDst, dx, dy, exaCopyNtoN, 0, NULL);
846
REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
850
exaFillRegionSolid (DrawablePtr pDrawable,
854
ExaScreenPriv(pDrawable->pScreen);
857
ExaMigrationRec pixmaps[1];
859
pixmaps[0].as_dst = TRUE;
860
pixmaps[0].as_src = FALSE;
861
pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
863
if (pDrawable->width > pExaScr->info->maxX ||
864
pDrawable->height > pExaScr->info->maxY)
866
exaDoMigration (pixmaps, 1, FALSE);
869
exaDoMigration (pixmaps, 1, TRUE);
872
if ((pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) &&
873
(*pExaScr->info->PrepareSolid) (pPixmap, GXcopy, FB_ALLONES, pixel))
875
int nbox = REGION_NUM_RECTS (pRegion);
876
BoxPtr pBox = REGION_RECTS (pRegion);
880
(*pExaScr->info->Solid) (pPixmap,
881
pBox->x1 + xoff, pBox->y1 + yoff,
882
pBox->x2 + xoff, pBox->y2 + yoff);
885
(*pExaScr->info->DoneSolid) (pPixmap);
886
exaMarkSync(pDrawable->pScreen);
887
exaDrawableDirty (pDrawable);
892
EXA_FALLBACK(("to 0x%lx\n", (long)pDrawable));
893
exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
894
fbFillRegionSolid (pDrawable, pRegion, 0,
895
fbReplicatePixel (pixel, pDrawable->bitsPerPixel));
896
exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
900
/* Try to do an accelerated tile of the pTile into pRegion of pDrawable.
901
* Based on fbFillRegionTiled(), fbTile().
904
exaFillRegionTiled (DrawablePtr pDrawable,
908
ExaScreenPriv(pDrawable->pScreen);
911
int tileWidth, tileHeight;
912
ExaMigrationRec pixmaps[2];
914
tileWidth = pTile->drawable.width;
915
tileHeight = pTile->drawable.height;
917
/* If we're filling with a solid color, grab it out and go to
918
* FillRegionSolid, saving numerous copies.
920
if (tileWidth == 1 && tileHeight == 1) {
921
exaFillRegionSolid(pDrawable, pRegion, exaGetPixmapFirstPixel (pTile));
925
pixmaps[0].as_dst = TRUE;
926
pixmaps[0].as_src = FALSE;
927
pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
928
pixmaps[1].as_dst = FALSE;
929
pixmaps[1].as_src = TRUE;
930
pixmaps[1].pPix = pTile;
932
if (pDrawable->width > pExaScr->info->maxX ||
933
pDrawable->height > pExaScr->info->maxY ||
934
tileWidth > pExaScr->info->maxX ||
935
tileHeight > pExaScr->info->maxY)
937
exaDoMigration (pixmaps, 2, FALSE);
940
exaDoMigration (pixmaps, 2, TRUE);
943
pPixmap = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
947
if (!exaPixmapIsOffscreen(pTile))
950
if ((*pExaScr->info->PrepareCopy) (pTile, pPixmap, 0, 0, GXcopy,
953
int nbox = REGION_NUM_RECTS (pRegion);
954
BoxPtr pBox = REGION_RECTS (pRegion);
958
int height = pBox->y2 - pBox->y1;
962
tileY = (dstY - pDrawable->y) % tileHeight;
964
int width = pBox->x2 - pBox->x1;
967
int h = tileHeight - tileY;
973
tileX = (dstX - pDrawable->x) % tileWidth;
975
int w = tileWidth - tileX;
980
(*pExaScr->info->Copy) (pPixmap,
982
dstX + xoff, dstY + yoff,
992
(*pExaScr->info->DoneCopy) (pPixmap);
993
exaMarkSync(pDrawable->pScreen);
994
exaDrawableDirty (pDrawable);
999
EXA_FALLBACK(("from 0x%lx to 0x%lx\n", (long)pTile, (long)pDrawable));
1000
exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
1001
exaPrepareAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC);
1002
fbFillRegionTiled (pDrawable, pRegion, pTile);
1003
exaFinishAccess ((DrawablePtr)pTile, EXA_PREPARE_SRC);
1004
exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
1008
exaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
1010
ExaScreenPriv (pWin->drawable.pScreen);
1011
if (!REGION_NUM_RECTS(pRegion))
1013
if (!pExaScr->swappedOut) {
1016
switch (pWin->backgroundState) {
1019
case ParentRelative:
1021
pWin = pWin->parent;
1022
} while (pWin->backgroundState == ParentRelative);
1023
(*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion,
1026
case BackgroundPixel:
1027
exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->background.pixel);
1029
case BackgroundPixmap:
1030
exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->background.pixmap);
1035
if (pWin->borderIsPixel) {
1036
exaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->border.pixel);
1039
exaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->border.pixmap);
1045
ExaCheckPaintWindow (pWin, pRegion, what);
1049
* Accelerates GetImage for solid ZPixmap downloads from framebuffer memory.
1051
* This is probably the only case we actually care about. The rest fall through
1052
* to migration and ExaCheckGetImage, which hopefully will result in migration
1053
* pushing the pixmap out of framebuffer.
1056
exaGetImage (DrawablePtr pDrawable, int x, int y, int w, int h,
1057
unsigned int format, unsigned long planeMask, char *d)
1059
ExaScreenPriv (pDrawable->pScreen);
1060
ExaMigrationRec pixmaps[1];
1065
if (pExaScr->swappedOut || pExaScr->info->DownloadFromScreen == NULL)
1068
/* Only cover the ZPixmap, solid copy case. */
1069
if (format != ZPixmap || !EXA_PM_IS_SOLID(pDrawable, planeMask))
1072
/* Only try to handle the 8bpp and up cases, since we don't want to think
1075
if (pDrawable->bitsPerPixel < 8)
1078
/* Migrate, but assume that we could accelerate the download. It is up to
1079
* the migration scheme to ensure that this case doesn't result in bad
1080
* moving of pixmaps.
1082
pixmaps[0].as_dst = FALSE;
1083
pixmaps[0].as_src = TRUE;
1084
pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
1085
exaDoMigration (pixmaps, 1, TRUE);
1086
pPix = exaGetOffscreenPixmap (pDrawable, &xoff, &yoff);
1090
xoff += pDrawable->x;
1091
yoff += pDrawable->y;
1093
ok = pExaScr->info->DownloadFromScreen(pPix, x + xoff, y + yoff, w, h, d,
1094
PixmapBytePad(w, pDrawable->depth));
1096
exaWaitSync(pDrawable->pScreen);
1101
pixmaps[0].as_dst = FALSE;
1102
pixmaps[0].as_src = TRUE;
1103
pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
1104
exaDoMigration (pixmaps, 1, FALSE);
1106
ExaCheckGetImage (pDrawable, x, y, w, h, format, planeMask, d);
1110
* GetSpans isn't accelerated yet, but performs migration so that we'll
1111
* hopefully avoid the read-from-framebuffer cost.
1114
exaGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, int *pwidth,
1115
int nspans, char *pdstStart)
1117
ExaMigrationRec pixmaps[1];
1119
pixmaps[0].as_dst = FALSE;
1120
pixmaps[0].as_src = TRUE;
1121
pixmaps[0].pPix = exaGetDrawablePixmap (pDrawable);
1122
exaDoMigration (pixmaps, 1, FALSE);
1124
ExaCheckGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);