2
* $XFree86: xc/programs/Xserver/hw/xfree86/xaa/xaaPict.c,v 1.18 2003/04/23 18:35:34 eich Exp $
4
* Copyright Ā© 2000 Keith Packard, member of 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_XORG_CONFIG_H
26
#include <xorg-config.h>
31
#include "xf86_ansic.h"
32
#include "xf86_OSproc.h"
35
#include "scrnintstr.h"
36
#include "pixmapstr.h"
37
#include "windowstr.h"
40
#include "picturestr.h"
48
#include "xf86fbman.h"
60
int rbits, bbits, gbits, abits;
61
int rshift, bshift, gshift, ashift;
65
if(!PICT_FORMAT_COLOR(format))
68
rbits = PICT_FORMAT_R(format);
69
gbits = PICT_FORMAT_G(format);
70
bbits = PICT_FORMAT_B(format);
71
abits = PICT_FORMAT_A(format);
73
if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
76
rshift = gshift + gbits;
77
ashift = rshift + rbits;
78
} else { /* PICT_TYPE_ABGR */
81
bshift = gshift + gbits;
82
ashift = bshift + bbits;
85
*pixel |= ( blue >> (16 - bbits)) << bshift;
86
*pixel |= ( red >> (16 - rbits)) << rshift;
87
*pixel |= (green >> (16 - gbits)) << gshift;
88
*pixel |= (alpha >> (16 - abits)) << ashift;
103
int rbits, bbits, gbits, abits;
104
int rshift, bshift, gshift, ashift;
106
if(!PICT_FORMAT_COLOR(format))
109
rbits = PICT_FORMAT_R(format);
110
gbits = PICT_FORMAT_G(format);
111
bbits = PICT_FORMAT_B(format);
112
abits = PICT_FORMAT_A(format);
114
if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
117
rshift = gshift + gbits;
118
ashift = rshift + rbits;
119
} else { /* PICT_TYPE_ABGR */
122
bshift = gshift + gbits;
123
ashift = bshift + bbits;
126
*red = ((pixel >> rshift ) & ((1 << rbits) - 1)) << (16 - rbits);
128
*red |= *red >> rbits;
132
*green = ((pixel >> gshift ) & ((1 << gbits) - 1)) << (16 - gbits);
134
*green |= *green >> gbits;
138
*blue = ((pixel >> bshift ) & ((1 << bbits) - 1)) << (16 - bbits);
140
*blue |= *blue >> bbits;
145
*alpha = ((pixel >> ashift ) & ((1 << abits) - 1)) << (16 - abits);
147
*alpha |= *alpha >> abits;
150
} else *alpha = 0xffff;
155
/* 8:8:8 + PICT_a8 -> 8:8:8:8 texture */
158
XAA_888_plus_PICT_a8_to_8888 (
160
CARD8 *alphaPtr, /* in bytes */
163
int dstPitch, /* in dwords */
172
for(x = 0; x < width; x++)
173
dstPtr[x] = color | (alphaPtr[x] << 24);
175
alphaPtr += alphaPitch;
179
#define DRAWABLE_IS_ON_CARD(pDraw) \
180
(pDraw->type == DRAWABLE_WINDOW || \
181
(pDraw->type == DRAWABLE_PIXMAP && IS_OFFSCREEN_PIXMAP(pDraw)))
198
ScreenPtr pScreen = pDst->pDrawable->pScreen;
199
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
201
CARD32 *formats, *dstformats;
206
if(!REGION_NUM_RECTS(pDst->pCompositeClip))
209
if(!infoRec->pScrn->vtSema || !DRAWABLE_IS_ON_CARD(pDst->pDrawable))
212
if(DRAWABLE_IS_ON_CARD(pSrc->pDrawable))
215
if (pSrc->transform || (pMask && pMask->transform))
218
if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap))
221
xDst += pDst->pDrawable->x;
222
yDst += pDst->pDrawable->y;
223
xSrc += pSrc->pDrawable->x;
224
ySrc += pSrc->pDrawable->y;
227
if(pMask->componentAlpha)
230
/* for now we only do it if there is a 1x1 (solid) source */
232
if((pSrc->pDrawable->width == 1) && (pSrc->pDrawable->height == 1)) {
233
CARD16 red, green, blue, alpha;
235
*((CARD32*)(((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr));
237
if(!XAAGetRGBAFromPixel(pixel,&red,&green,&blue,&alpha,pSrc->format))
240
xMask += pMask->pDrawable->x;
241
yMask += pMask->pDrawable->y;
243
/* pull out color expandable operations here */
244
if((pMask->format == PICT_a1) && (alpha == 0xffff) &&
245
(op == PictOpOver) && infoRec->WriteBitmap && !pMask->repeat &&
246
!(infoRec->WriteBitmapFlags & NO_TRANSPARENCY) &&
247
(!(infoRec->WriteBitmapFlags & RGB_EQUAL) ||
248
((red == green) && (green == blue))))
250
PixmapPtr pPix = (PixmapPtr)(pMask->pDrawable);
253
if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst,
254
xSrc, ySrc, xMask, yMask, xDst, yDst,
258
nbox = REGION_NUM_RECTS(®ion);
259
pbox = REGION_RECTS(®ion);
264
XAAGetPixelFromRGBA(&pixel, red, green, blue, 0, pDst->format);
270
skipleft = pbox->x1 + xMask;
272
(*infoRec->WriteBitmap)(infoRec->pScrn,
274
pbox->x2 - pbox->x1, pbox->y2 - pbox->y1,
275
(unsigned char*)(pPix->devPrivate.ptr) +
276
(pPix->devKind * (pbox->y1 + yMask)) +
277
((skipleft >> 3) & ~3), pPix->devKind,
278
skipleft & 31, pixel, -1, GXcopy, ~0);
282
/* WriteBitmap sets the Sync flag */
283
REGION_UNINIT(pScreen, ®ion);
287
formats = infoRec->CPUToScreenAlphaTextureFormats;
288
dstformats = infoRec->CPUToScreenAlphaTextureDstFormats;
289
if(!formats || !dstformats)
292
w = pMask->pDrawable->width;
293
h = pMask->pDrawable->height;
296
if((infoRec->CPUToScreenAlphaTextureFlags & XAA_RENDER_NO_TILE) ||
297
((infoRec->CPUToScreenAlphaTextureFlags &
298
XAA_RENDER_POWER_OF_2_TILE_ONLY) &&
299
((h & (h - 1)) || (w & (w - 1)))))
303
flags |= XAA_RENDER_REPEAT;
306
if((alpha != 0xffff) &&
307
(infoRec->CPUToScreenAlphaTextureFlags & XAA_RENDER_NO_SRC_ALPHA))
310
while(*formats != pMask->format) {
311
if(!(*formats)) return FALSE;
314
while(*dstformats != pDst->format) {
320
if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst,
321
xSrc, ySrc, xMask, yMask, xDst, yDst,
325
nbox = REGION_NUM_RECTS(®ion);
326
pbox = REGION_RECTS(®ion);
329
REGION_UNINIT(pScreen, ®ion);
333
if(!(infoRec->SetupForCPUToScreenAlphaTexture2)(infoRec->pScrn,
334
op, red, green, blue, alpha, pMask->format,
336
((PixmapPtr)(pMask->pDrawable))->devPrivate.ptr,
337
((PixmapPtr)(pMask->pDrawable))->devKind,
340
REGION_UNINIT(pScreen, ®ion);
348
(*infoRec->SubsequentCPUToScreenAlphaTexture)(infoRec->pScrn,
350
pbox->x1 + xMask, pbox->y1 + yMask,
351
pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
355
SET_SYNC_FLAG(infoRec);
356
REGION_UNINIT(pScreen, ®ion);
360
formats = infoRec->CPUToScreenTextureFormats;
361
dstformats = infoRec->CPUToScreenTextureDstFormats;
362
if(!formats || !dstformats)
365
w = pSrc->pDrawable->width;
366
h = pSrc->pDrawable->height;
369
if((infoRec->CPUToScreenTextureFlags & XAA_RENDER_NO_TILE) ||
370
((infoRec->CPUToScreenTextureFlags &
371
XAA_RENDER_POWER_OF_2_TILE_ONLY) &&
372
((h & (h - 1)) || (w & (w - 1)))))
376
flags |= XAA_RENDER_REPEAT;
379
while(*formats != pSrc->format) {
380
if(!(*formats)) return FALSE;
383
while(*dstformats != pDst->format) {
389
if (!miComputeCompositeRegion (®ion, pSrc, pMask, pDst,
390
xSrc, ySrc, xMask, yMask, xDst, yDst,
394
nbox = REGION_NUM_RECTS(®ion);
395
pbox = REGION_RECTS(®ion);
398
REGION_UNINIT(pScreen, ®ion);
402
if(!(infoRec->SetupForCPUToScreenTexture2)(infoRec->pScrn,
403
op, pSrc->format, pDst->format,
404
((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr,
405
((PixmapPtr)(pSrc->pDrawable))->devKind,
408
REGION_UNINIT(pScreen, ®ion);
417
(*infoRec->SubsequentCPUToScreenTexture)(infoRec->pScrn,
419
pbox->x1 + xSrc, pbox->y1 + ySrc,
420
pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
424
SET_SYNC_FLAG(infoRec);
425
REGION_UNINIT(pScreen, ®ion);
434
XAACompositeSrcCopy (PicturePtr pSrc,
443
ScreenPtr pScreen = pDst->pDrawable->pScreen;
444
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
451
xDst += pDst->pDrawable->x;
452
yDst += pDst->pDrawable->y;
453
xSrc += pSrc->pDrawable->x;
454
ySrc += pSrc->pDrawable->y;
456
if (!miComputeCompositeRegion (®ion, pSrc, NULL, pDst,
457
xSrc, ySrc, 0, 0, xDst, yDst,
461
nbox = REGION_NUM_RECTS(®ion);
462
pbox = REGION_RECTS(®ion);
465
REGION_UNINIT(pScreen, ®ion);
468
pptSrc = ALLOCATE_LOCAL(sizeof(DDXPointRec) * nbox);
470
REGION_UNINIT(pScreen, ®ion);
475
for (i = 0; i < nbox; i++) {
476
pptSrc[i].x = pbox[i].x1 + xoff;
477
pptSrc[i].y = pbox[i].y1 + yoff;
480
infoRec->ScratchGC.planemask = ~0L;
481
infoRec->ScratchGC.alu = GXcopy;
483
XAADoBitBlt(pSrc->pDrawable, pDst->pDrawable, &infoRec->ScratchGC, ®ion,
486
DEALLOCATE_LOCAL(pptSrc);
487
REGION_UNINIT(pScreen, ®ion);
492
XAAComposite (CARD8 op,
505
ScreenPtr pScreen = pDst->pDrawable->pScreen;
506
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
507
XAA_RENDER_PROLOGUE(pScreen, Composite);
509
if((op == PictOpSrc) && !pMask && infoRec->pScrn->vtSema &&
510
infoRec->ScreenToScreenBitBlt &&
512
DRAWABLE_IS_ON_CARD(pSrc->pDrawable) &&
513
DRAWABLE_IS_ON_CARD(pDst->pDrawable) &&
514
!pSrc->transform && !pSrc->repeat && (pSrc->format == pDst->format))
516
XAACompositeSrcCopy(pSrc, pDst, xSrc, ySrc, xDst, yDst, width, height);
517
} else if(!pSrc->pDrawable || (pMask && !pMask->pDrawable) ||
518
!infoRec->Composite ||
519
!(*infoRec->Composite)(op, pSrc, pMask, pDst,
520
xSrc, ySrc, xMask, yMask, xDst, yDst,
523
if(infoRec->pScrn->vtSema &&
525
(pSrc->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pSrc->pDrawable))) ||
526
pDst->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pDst->pDrawable))) {
527
SYNC_CHECK(pDst->pDrawable);
529
(*GetPictureScreen(pScreen)->Composite) (op,
543
if(pDst->pDrawable->type == DRAWABLE_PIXMAP)
544
(XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pDst->pDrawable)))->flags |= DIRTY;
546
XAA_RENDER_EPILOGUE(pScreen, Composite, XAAComposite);
550
XAADoGlyphs (CARD8 op,
553
PictFormatPtr maskFormat,
560
ScreenPtr pScreen = pDst->pDrawable->pScreen;
561
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
563
if(!REGION_NUM_RECTS(pDst->pCompositeClip))
566
if(!infoRec->pScrn->vtSema ||
567
((pDst->pDrawable->type != DRAWABLE_WINDOW) &&
568
!IS_OFFSCREEN_PIXMAP(pDst->pDrawable)))
571
if((pSrc->pDrawable->type != DRAWABLE_PIXMAP) ||
572
IS_OFFSCREEN_PIXMAP(pSrc->pDrawable))
575
if(maskFormat && (maskFormat->depth == 1) &&
576
(pSrc->pDrawable->width == 1) && (pSrc->pDrawable->height == 1) &&
577
(op == PictOpOver) && infoRec->WriteBitmap &&
578
!(infoRec->WriteBitmapFlags & NO_TRANSPARENCY))
580
CARD16 red, green, blue, alpha;
582
*((CARD32*)(((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr));
583
CARD32 *bits, *pntr, *pnt;
584
int x, y, i, n, left, top, right, bottom, width, height, pitch;
585
int L, T, R, B, X, Y, h, w, dwords, row, column, nbox;
586
int leftEdge, rightEdge, topLine, botLine;
590
if(!XAAGetRGBAFromPixel(pixel,&red,&green,&blue,&alpha,pSrc->format))
593
if(alpha != 0xffff) return FALSE;
595
XAAGetPixelFromRGBA(&pixel, red, green, blue, 0, pDst->format);
597
if((infoRec->WriteBitmapFlags & RGB_EQUAL) && !((red == green) && (green == blue)))
600
x = pDst->pDrawable->x;
601
y = pDst->pDrawable->y;
606
left = right = X = x;
607
top = bottom = Y = y;
608
for(i = 0; i < list->len; i++) {
611
L = X - glyph->info.x;
612
if(L < left) left = L;
613
R = L + glyph->info.width;
614
if(R > right) right = R;
616
T = Y - glyph->info.y;
618
B = T + glyph->info.height;
619
if(B > bottom) bottom = B;
621
X += glyph->info.xOff;
622
Y += glyph->info.yOff;
625
width = right - left;
626
height = bottom - top;
628
if(width && height) {
629
pitch = (((width + 31) & ~31) >> 5) + 1;
630
pntr = (CARD32*)xalloc(sizeof(CARD32) * pitch * height);
633
bzero(pntr, sizeof(CARD32) * pitch * height);
639
h = glyph->info.height;
640
w = glyph->info.width;
642
row = y - top - glyph->info.y;
643
column = x - left - glyph->info.x;
644
pnt = pntr + (row * pitch) + (column >> 5);
646
dwords = ((w + 31) >> 5) - 1;
647
bits = (CARD32*)(glyph + 1);
650
for(i = 0; i <= dwords; i++) {
652
pnt[i] |= SHIFT_L(*bits, column);
653
pnt[i + 1] |= SHIFT_R(*bits, 32 - column);
657
if(i != dwords) bits++;
665
pnt[0] |= SHIFT_L(*bits, column);
666
pnt[0 + 1] |= SHIFT_R(*bits, 32 - column);
678
x += glyph->info.xOff;
679
y += glyph->info.yOff;
682
nbox = REGION_NUM_RECTS(pDst->pCompositeClip);
683
pbox = REGION_RECTS(pDst->pCompositeClip);
685
while(nbox && (top >= pbox->y2)) {
689
while(nbox && (bottom > pbox->y1)) {
690
leftEdge = max(left, pbox->x1);
691
rightEdge = min(right, pbox->x2);
693
if(rightEdge > leftEdge) {
694
column = leftEdge - left;
695
topLine = max(top, pbox->y1);
696
botLine = min(bottom, pbox->y2);
697
h = botLine - topLine;
700
(*infoRec->WriteBitmap)(infoRec->pScrn,
701
leftEdge, topLine, rightEdge - leftEdge, h,
702
(unsigned char*)(pntr +
703
((topLine - top) * pitch) + (column >> 5)),
704
pitch << 2, column & 31, pixel, -1, GXcopy, ~0);
720
* If it looks like we have a chance of being able to draw these
721
* glyphs with an accelerated Composite, do that now to avoid
722
* unneeded and costly syncs.
725
if(!infoRec->CPUToScreenAlphaTextureFormats)
728
if(!infoRec->CPUToScreenTextureFormats)
732
miGlyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
742
PictFormatPtr maskFormat,
749
ScreenPtr pScreen = pDst->pDrawable->pScreen;
750
XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
751
XAA_RENDER_PROLOGUE(pScreen, Glyphs);
753
if(!pSrc->pDrawable || !infoRec->Glyphs ||
754
!(*infoRec->Glyphs)(op, pSrc, pDst, maskFormat,
755
xSrc, ySrc, nlist, list, glyphs))
757
if(infoRec->pScrn->vtSema &&
759
(pSrc->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pSrc->pDrawable))) ||
760
pDst->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pDst->pDrawable))) {
761
SYNC_CHECK(pDst->pDrawable);
763
(*GetPictureScreen(pScreen)->Glyphs) (op, pSrc, pDst, maskFormat,
764
xSrc, ySrc, nlist, list, glyphs);
767
if(pDst->pDrawable->type == DRAWABLE_PIXMAP)
768
(XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pDst->pDrawable)))->flags |= DIRTY;
770
XAA_RENDER_EPILOGUE(pScreen, Glyphs, XAAGlyphs);