First import
[xorg_rtime.git] / xorg-server-1.4 / hw / kdrive / src / kaa.c
blobc9805ddb6a59cc032c8dd53d928f4e2e12af6335
1 /*
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_CONFIG_H
26 #include <kdrive-config.h>
27 #endif
28 #include "kdrive.h"
29 #include "kaa.h"
30 #include "dixfontstr.h"
32 #define DEBUG_MIGRATE 0
33 #define DEBUG_PIXMAP 0
34 #if DEBUG_MIGRATE
35 #define DBG_MIGRATE(a) ErrorF a
36 #else
37 #define DBG_MIGRATE(a)
38 #endif
39 #if DEBUG_PIXMAP
40 #define DBG_PIXMAP(a) ErrorF a
41 #else
42 #define DBG_PIXMAP(a)
43 #endif
45 int kaaGeneration;
46 int kaaScreenPrivateIndex;
47 int kaaPixmapPrivateIndex;
49 #define KAA_PIXMAP_SCORE_MOVE_IN 10
50 #define KAA_PIXMAP_SCORE_MAX 20
51 #define KAA_PIXMAP_SCORE_MOVE_OUT -10
52 #define KAA_PIXMAP_SCORE_MIN -20
53 #define KAA_PIXMAP_SCORE_PINNED 1000
54 #define KAA_PIXMAP_SCORE_INIT 1001
56 void
57 kaaDrawableDirty (DrawablePtr pDrawable)
59 PixmapPtr pPixmap;
60 KaaPixmapPrivPtr pKaaPixmap;
62 if (pDrawable->type == DRAWABLE_WINDOW)
63 pPixmap = (*pDrawable->pScreen->GetWindowPixmap)((WindowPtr) pDrawable);
64 else
65 pPixmap = (PixmapPtr)pDrawable;
67 pKaaPixmap = KaaGetPixmapPriv(pPixmap);
68 if (pKaaPixmap != NULL)
69 pKaaPixmap->dirty = TRUE;
72 static void
73 kaaPixmapSave (ScreenPtr pScreen, KdOffscreenArea *area)
75 PixmapPtr pPixmap = area->privData;
76 KaaPixmapPriv(pPixmap);
77 int dst_pitch, src_pitch, bytes;
78 unsigned char *dst, *src;
79 int i;
81 DBG_MIGRATE (("Save 0x%08x (0x%x) (%dx%d)\n",
82 pPixmap->drawable.id,
83 KaaGetPixmapPriv(pPixmap)->area ?
84 KaaGetPixmapPriv(pPixmap)->area->offset : -1,
85 pPixmap->drawable.width,
86 pPixmap->drawable.height));
88 src_pitch = pPixmap->devKind;
89 dst_pitch = pKaaPixmap->devKind;
91 src = pPixmap->devPrivate.ptr;
92 dst = pKaaPixmap->devPrivate.ptr;
94 pPixmap->devKind = dst_pitch;
95 pPixmap->devPrivate.ptr = dst;
96 pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
97 pKaaPixmap->area = NULL;
99 #if 0
100 if (!pKaaPixmap->dirty)
101 return;
102 #endif
104 kaaWaitSync (pPixmap->drawable.pScreen);
106 bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch;
108 i = pPixmap->drawable.height;
109 while (i--) {
110 memcpy (dst, src, bytes);
111 dst += dst_pitch;
112 src += src_pitch;
116 static int
117 kaaLog2(int val)
119 int bits;
121 if (!val)
122 return 0;
123 for (bits = 0; val != 0; bits++)
124 val >>= 1;
125 return bits - 1;
128 static Bool
129 kaaPixmapAllocArea (PixmapPtr pPixmap)
131 ScreenPtr pScreen = pPixmap->drawable.pScreen;
132 KaaScreenPriv (pScreen);
133 KaaPixmapPriv (pPixmap);
134 KdScreenPriv (pScreen);
135 int bpp = pPixmap->drawable.bitsPerPixel;
136 CARD16 h = pPixmap->drawable.height;
137 CARD16 w = pPixmap->drawable.width;
138 int pitch;
140 if (pKaaScr->info->flags & KAA_OFFSCREEN_ALIGN_POT && w != 1)
141 w = 1 << (kaaLog2(w - 1) + 1);
142 pitch = (w * bpp / 8 + pKaaScr->info->pitchAlign - 1) &
143 ~(pKaaScr->info->pitchAlign - 1);
145 pKaaPixmap->devKind = pPixmap->devKind;
146 pKaaPixmap->devPrivate = pPixmap->devPrivate;
147 pKaaPixmap->area = KdOffscreenAlloc (pScreen, pitch * h,
148 pKaaScr->info->offsetAlign,
149 FALSE,
150 kaaPixmapSave, (pointer) pPixmap);
151 if (!pKaaPixmap->area)
152 return FALSE;
154 DBG_PIXMAP(("++ 0x%08x (0x%x) (%dx%d)\n",
155 pPixmap->drawable.id,
156 KaaGetPixmapPriv(pPixmap)->area ?
157 KaaGetPixmapPriv(pPixmap)->area->offset : -1,
158 pPixmap->drawable.width,
159 pPixmap->drawable.height));
160 pPixmap->devKind = pitch;
161 pPixmap->devPrivate.ptr = (pointer) ((CARD8 *) pScreenPriv->screen->memory_base + pKaaPixmap->area->offset);
162 pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
163 return TRUE;
166 void
167 kaaMoveInPixmap (PixmapPtr pPixmap)
169 ScreenPtr pScreen = pPixmap->drawable.pScreen;
170 KaaScreenPriv (pScreen);
171 KaaPixmapPriv (pPixmap);
172 int dst_pitch, src_pitch, bytes;
173 unsigned char *dst, *src;
174 int i;
176 DBG_MIGRATE (("-> 0x%08x (0x%x) (%dx%d)\n",
177 pPixmap->drawable.id,
178 KaaGetPixmapPriv(pPixmap)->area ?
179 KaaGetPixmapPriv(pPixmap)->area->offset : -1,
180 pPixmap->drawable.width,
181 pPixmap->drawable.height));
183 src = pPixmap->devPrivate.ptr;
184 src_pitch = pPixmap->devKind;
186 if (!kaaPixmapAllocArea (pPixmap))
187 return;
189 pKaaPixmap->dirty = FALSE;
191 if (pKaaScr->info->UploadToScreen)
193 if (pKaaScr->info->UploadToScreen(pPixmap, (char *) src, src_pitch))
194 return;
197 dst = pPixmap->devPrivate.ptr;
198 dst_pitch = pPixmap->devKind;
200 bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch;
202 kaaWaitSync (pPixmap->drawable.pScreen);
204 i = pPixmap->drawable.height;
205 while (i--) {
206 memcpy (dst, src, bytes);
207 dst += dst_pitch;
208 src += src_pitch;
212 static void
213 kaaMoveOutPixmap (PixmapPtr pPixmap)
215 KaaPixmapPriv (pPixmap);
216 KdOffscreenArea *area = pKaaPixmap->area;
218 DBG_MIGRATE (("<- 0x%08x (0x%x) (%dx%d)\n",
219 pPixmap->drawable.id,
220 KaaGetPixmapPriv(pPixmap)->area ?
221 KaaGetPixmapPriv(pPixmap)->area->offset : -1,
222 pPixmap->drawable.width,
223 pPixmap->drawable.height));
224 if (area)
226 kaaPixmapSave (pPixmap->drawable.pScreen, area);
227 KdOffscreenFree (pPixmap->drawable.pScreen, area);
231 void
232 kaaPixmapUseScreen (PixmapPtr pPixmap)
234 KaaPixmapPriv (pPixmap);
236 if (pKaaPixmap->score == KAA_PIXMAP_SCORE_PINNED)
237 return;
239 if (pKaaPixmap->score == KAA_PIXMAP_SCORE_INIT) {
240 kaaMoveInPixmap(pPixmap);
241 pKaaPixmap->score = 0;
244 if (pKaaPixmap->score < KAA_PIXMAP_SCORE_MAX)
246 pKaaPixmap->score++;
247 if (!kaaPixmapIsOffscreen(pPixmap) &&
248 pKaaPixmap->score >= KAA_PIXMAP_SCORE_MOVE_IN)
249 kaaMoveInPixmap (pPixmap);
251 KdOffscreenMarkUsed (pPixmap);
254 void
255 kaaPixmapUseMemory (PixmapPtr pPixmap)
257 KaaPixmapPriv (pPixmap);
259 if (pKaaPixmap->score == KAA_PIXMAP_SCORE_PINNED)
260 return;
262 if (pKaaPixmap->score == KAA_PIXMAP_SCORE_INIT)
263 pKaaPixmap->score = 0;
265 if (pKaaPixmap->score > KAA_PIXMAP_SCORE_MIN)
267 pKaaPixmap->score--;
268 if (pKaaPixmap->area &&
269 pKaaPixmap->score <= KAA_PIXMAP_SCORE_MOVE_OUT)
270 kaaMoveOutPixmap (pPixmap);
274 static Bool
275 kaaDestroyPixmap (PixmapPtr pPixmap)
277 if (pPixmap->refcnt == 1)
279 KaaPixmapPriv (pPixmap);
280 if (pKaaPixmap->area)
282 DBG_PIXMAP(("-- 0x%08x (0x%x) (%dx%d)\n",
283 pPixmap->drawable.id,
284 KaaGetPixmapPriv(pPixmap)->area->offset,
285 pPixmap->drawable.width,
286 pPixmap->drawable.height));
287 /* Free the offscreen area */
288 KdOffscreenFree (pPixmap->drawable.pScreen, pKaaPixmap->area);
289 pPixmap->devPrivate = pKaaPixmap->devPrivate;
290 pPixmap->devKind = pKaaPixmap->devKind;
293 return fbDestroyPixmap (pPixmap);
296 static PixmapPtr
297 kaaCreatePixmap(ScreenPtr pScreen, int w, int h, int depth)
299 PixmapPtr pPixmap;
300 KaaPixmapPrivPtr pKaaPixmap;
301 int bpp;
303 bpp = BitsPerPixel (depth);
304 if (bpp == 32 && depth == 24)
306 int fb;
307 KdScreenPriv (pScreen);
309 for (fb = 0; fb < KD_MAX_FB && pScreenPriv->screen->fb[fb].depth; fb++)
310 if (pScreenPriv->screen->fb[fb].depth == 24)
312 bpp = pScreenPriv->screen->fb[fb].bitsPerPixel;
313 break;
317 pPixmap = fbCreatePixmapBpp (pScreen, w, h, depth, bpp);
318 if (!pPixmap)
319 return NULL;
320 pKaaPixmap = KaaGetPixmapPriv(pPixmap);
321 if (!w || !h)
322 pKaaPixmap->score = KAA_PIXMAP_SCORE_PINNED;
323 else
324 pKaaPixmap->score = KAA_PIXMAP_SCORE_INIT;
326 pKaaPixmap->area = NULL;
327 pKaaPixmap->dirty = FALSE;
329 return pPixmap;
332 Bool
333 kaaPixmapIsOffscreen(PixmapPtr p)
335 ScreenPtr pScreen = p->drawable.pScreen;
336 KdScreenPriv(pScreen);
338 return ((unsigned long) ((CARD8 *) p->devPrivate.ptr -
339 (CARD8 *) pScreenPriv->screen->memory_base) <
340 pScreenPriv->screen->memory_size);
343 PixmapPtr
344 kaaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp)
346 PixmapPtr pPixmap;
347 int x, y;
349 if (pDrawable->type == DRAWABLE_WINDOW) {
350 pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable);
351 #ifdef COMPOSITE
352 x = -pPixmap->screen_x;
353 y = -pPixmap->screen_y;
354 #else
355 x = 0;
356 y = 0;
357 #endif
359 else
361 pPixmap = (PixmapPtr) pDrawable;
362 x = 0;
363 y = 0;
365 *xp = x;
366 *yp = y;
367 if (kaaPixmapIsOffscreen (pPixmap))
368 return pPixmap;
369 else
370 return NULL;
373 Bool
374 kaaDrawableIsOffscreen (DrawablePtr pDrawable)
376 PixmapPtr pPixmap;
377 if (pDrawable->type == DRAWABLE_WINDOW)
378 pPixmap = (*pDrawable->pScreen->GetWindowPixmap) ((WindowPtr) pDrawable);
379 else
380 pPixmap = (PixmapPtr) pDrawable;
381 return kaaPixmapIsOffscreen (pPixmap);
384 #if 0
385 static void
386 kaaFillTiled(int dst_x,
387 int dst_y,
388 int width,
389 int height,
390 int src_x,
391 int src_y,
392 int src_width,
393 int src_height,
394 void (*Copy) (int srcX,
395 int srcY,
396 int dstX,
397 int dstY,
398 int width,
399 int height))
401 modulus (src_x, src_width, src_x);
402 modulus (src_y, src_height, src_y);
404 while (height)
406 int dst_x_tmp = dst_x;
407 int src_x_tmp = src_x;
408 int width_tmp = width;
409 int height_left = src_height - src_y;
410 int height_this = min (height, height_left);
412 while (width_tmp)
414 int width_left = src_width - src_x_tmp;
415 int width_this = min (width_tmp, width_left);
417 (*Copy) (src_x_tmp, src_y,
418 dst_x_tmp, dst_y,
419 width_this, height_this);
421 width_tmp -= width_this;
422 dst_x_tmp += width_this;
424 height -= height_this;
425 dst_y += height_this;
426 src_y = 0;
429 #endif
431 static void
432 kaaFillSpans(DrawablePtr pDrawable, GCPtr pGC, int n,
433 DDXPointPtr ppt, int *pwidth, int fSorted)
435 ScreenPtr pScreen = pDrawable->pScreen;
436 KdScreenPriv (pScreen);
437 KaaScreenPriv (pScreen);
438 RegionPtr pClip = fbGetCompositeClip(pGC);
439 PixmapPtr pPixmap;
440 BoxPtr pextent, pbox;
441 int nbox;
442 int extentX1, extentX2, extentY1, extentY2;
443 int fullX1, fullX2, fullY1;
444 int partX1, partX2;
445 int off_x, off_y;
447 if (!pScreenPriv->enabled ||
448 pGC->fillStyle != FillSolid ||
449 !(pPixmap = kaaGetOffscreenPixmap (pDrawable, &off_x, &off_y)) ||
450 !(*pKaaScr->info->PrepareSolid) (pPixmap,
451 pGC->alu,
452 pGC->planemask,
453 pGC->fgPixel))
455 KdCheckFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted);
456 return;
459 pextent = REGION_EXTENTS(pGC->pScreen, pClip);
460 extentX1 = pextent->x1;
461 extentY1 = pextent->y1;
462 extentX2 = pextent->x2;
463 extentY2 = pextent->y2;
464 while (n--)
466 fullX1 = ppt->x;
467 fullY1 = ppt->y;
468 fullX2 = fullX1 + (int) *pwidth;
469 ppt++;
470 pwidth++;
472 if (fullY1 < extentY1 || extentY2 <= fullY1)
473 continue;
475 if (fullX1 < extentX1)
476 fullX1 = extentX1;
478 if (fullX2 > extentX2)
479 fullX2 = extentX2;
481 if (fullX1 >= fullX2)
482 continue;
484 nbox = REGION_NUM_RECTS (pClip);
485 if (nbox == 1)
487 (*pKaaScr->info->Solid) (fullX1 + off_x, fullY1 + off_y,
488 fullX2 + off_x, fullY1 + 1 + off_y);
490 else
492 pbox = REGION_RECTS(pClip);
493 while(nbox--)
495 if (pbox->y1 <= fullY1 && fullY1 < pbox->y2)
497 partX1 = pbox->x1;
498 if (partX1 < fullX1)
499 partX1 = fullX1;
500 partX2 = pbox->x2;
501 if (partX2 > fullX2)
502 partX2 = fullX2;
503 if (partX2 > partX1)
504 (*pKaaScr->info->Solid) (partX1 + off_x, fullY1 + off_y,
505 partX2 + off_x, fullY1 + 1 + off_y);
507 pbox++;
511 (*pKaaScr->info->DoneSolid) ();
512 kaaDrawableDirty (pDrawable);
513 kaaMarkSync (pDrawable->pScreen);
516 void
517 kaaCopyNtoN (DrawablePtr pSrcDrawable,
518 DrawablePtr pDstDrawable,
519 GCPtr pGC,
520 BoxPtr pbox,
521 int nbox,
522 int dx,
523 int dy,
524 Bool reverse,
525 Bool upsidedown,
526 Pixel bitplane,
527 void *closure)
529 KdScreenPriv (pDstDrawable->pScreen);
530 KaaScreenPriv (pDstDrawable->pScreen);
531 PixmapPtr pSrcPixmap, pDstPixmap;
532 int src_off_x, src_off_y;
533 int dst_off_x, dst_off_y;
535 /* Migrate pixmaps to same place as destination */
536 if (pScreenPriv->enabled && pSrcDrawable->type == DRAWABLE_PIXMAP) {
537 if (kaaDrawableIsOffscreen (pDstDrawable))
538 kaaPixmapUseScreen ((PixmapPtr) pSrcDrawable);
539 else
540 kaaPixmapUseMemory ((PixmapPtr) pSrcDrawable);
543 if (pScreenPriv->enabled &&
544 (pSrcPixmap = kaaGetOffscreenPixmap (pSrcDrawable, &src_off_x, &src_off_y)) &&
545 (pDstPixmap = kaaGetOffscreenPixmap (pDstDrawable, &dst_off_x, &dst_off_y)) &&
546 (*pKaaScr->info->PrepareCopy) (pSrcPixmap,
547 pDstPixmap,
550 pGC ? pGC->alu : GXcopy,
551 pGC ? pGC->planemask : FB_ALLONES))
553 while (nbox--)
555 (*pKaaScr->info->Copy) (pbox->x1 + dx + src_off_x,
556 pbox->y1 + dy + src_off_y,
557 pbox->x1 + dst_off_x, pbox->y1 + dst_off_y,
558 pbox->x2 - pbox->x1,
559 pbox->y2 - pbox->y1);
560 pbox++;
562 (*pKaaScr->info->DoneCopy) ();
563 kaaMarkSync (pDstDrawable->pScreen);
565 else
567 kaaWaitSync (pDstDrawable->pScreen);
568 fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC,
569 pbox, nbox, dx, dy, reverse, upsidedown,
570 bitplane, closure);
572 kaaDrawableDirty (pDstDrawable);
575 static RegionPtr
576 kaaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
577 int srcx, int srcy, int width, int height, int dstx, int dsty)
579 return fbDoCopy (pSrcDrawable, pDstDrawable, pGC,
580 srcx, srcy, width, height,
581 dstx, dsty, kaaCopyNtoN, 0, 0);
584 static void
585 kaaPolyFillRect(DrawablePtr pDrawable,
586 GCPtr pGC,
587 int nrect,
588 xRectangle *prect)
590 KdScreenPriv (pDrawable->pScreen);
591 KaaScreenPriv (pDrawable->pScreen);
592 RegionPtr pClip = fbGetCompositeClip(pGC);
593 PixmapPtr pPixmap;
594 register BoxPtr pbox;
595 BoxPtr pextent;
596 int extentX1, extentX2, extentY1, extentY2;
597 int fullX1, fullX2, fullY1, fullY2;
598 int partX1, partX2, partY1, partY2;
599 int xoff, yoff;
600 int xorg, yorg;
601 int n;
603 if (!pScreenPriv->enabled ||
604 pGC->fillStyle != FillSolid ||
605 !(pPixmap = kaaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) ||
606 !(*pKaaScr->info->PrepareSolid) (pPixmap,
607 pGC->alu,
608 pGC->planemask,
609 pGC->fgPixel))
611 KdCheckPolyFillRect (pDrawable, pGC, nrect, prect);
612 return;
615 xorg = pDrawable->x;
616 yorg = pDrawable->y;
618 pextent = REGION_EXTENTS(pGC->pScreen, pClip);
619 extentX1 = pextent->x1;
620 extentY1 = pextent->y1;
621 extentX2 = pextent->x2;
622 extentY2 = pextent->y2;
623 while (nrect--)
625 fullX1 = prect->x + xorg;
626 fullY1 = prect->y + yorg;
627 fullX2 = fullX1 + (int) prect->width;
628 fullY2 = fullY1 + (int) prect->height;
629 prect++;
631 if (fullX1 < extentX1)
632 fullX1 = extentX1;
634 if (fullY1 < extentY1)
635 fullY1 = extentY1;
637 if (fullX2 > extentX2)
638 fullX2 = extentX2;
640 if (fullY2 > extentY2)
641 fullY2 = extentY2;
643 if ((fullX1 >= fullX2) || (fullY1 >= fullY2))
644 continue;
645 n = REGION_NUM_RECTS (pClip);
646 if (n == 1)
648 (*pKaaScr->info->Solid) (fullX1 + xoff, fullY1 + yoff,
649 fullX2 + xoff, fullY2 + yoff);
651 else
653 pbox = REGION_RECTS(pClip);
655 * clip the rectangle to each box in the clip region
656 * this is logically equivalent to calling Intersect()
658 while(n--)
660 partX1 = pbox->x1;
661 if (partX1 < fullX1)
662 partX1 = fullX1;
663 partY1 = pbox->y1;
664 if (partY1 < fullY1)
665 partY1 = fullY1;
666 partX2 = pbox->x2;
667 if (partX2 > fullX2)
668 partX2 = fullX2;
669 partY2 = pbox->y2;
670 if (partY2 > fullY2)
671 partY2 = fullY2;
673 pbox++;
675 if (partX1 < partX2 && partY1 < partY2)
676 (*pKaaScr->info->Solid) (partX1 + xoff, partY1 + yoff,
677 partX2 + xoff, partY2 + yoff);
681 (*pKaaScr->info->DoneSolid) ();
682 kaaDrawableDirty (pDrawable);
683 kaaMarkSync (pDrawable->pScreen);
686 static void
687 kaaSolidBoxClipped (DrawablePtr pDrawable,
688 RegionPtr pClip,
689 FbBits pm,
690 FbBits fg,
691 int x1,
692 int y1,
693 int x2,
694 int y2)
696 KdScreenPriv (pDrawable->pScreen);
697 KaaScreenPriv (pDrawable->pScreen);
698 PixmapPtr pPixmap;
699 BoxPtr pbox;
700 int nbox;
701 int xoff, yoff;
702 int partX1, partX2, partY1, partY2;
704 if (!pScreenPriv->enabled ||
705 !(pPixmap = kaaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) ||
706 !(*pKaaScr->info->PrepareSolid) (pPixmap, GXcopy, pm, fg))
708 kaaWaitSync (pDrawable->pScreen);
709 fg = fbReplicatePixel (fg, pDrawable->bitsPerPixel);
710 fbSolidBoxClipped (pDrawable, pClip, x1, y1, x2, y2,
711 fbAnd (GXcopy, fg, pm),
712 fbXor (GXcopy, fg, pm));
713 kaaDrawableDirty (pDrawable);
714 return;
716 for (nbox = REGION_NUM_RECTS(pClip), pbox = REGION_RECTS(pClip);
717 nbox--;
718 pbox++)
720 partX1 = pbox->x1;
721 if (partX1 < x1)
722 partX1 = x1;
724 partX2 = pbox->x2;
725 if (partX2 > x2)
726 partX2 = x2;
728 if (partX2 <= partX1)
729 continue;
731 partY1 = pbox->y1;
732 if (partY1 < y1)
733 partY1 = y1;
735 partY2 = pbox->y2;
736 if (partY2 > y2)
737 partY2 = y2;
739 if (partY2 <= partY1)
740 continue;
742 (*pKaaScr->info->Solid) (partX1 + xoff, partY1 + yoff,
743 partX2 + xoff, partY2 + yoff);
745 (*pKaaScr->info->DoneSolid) ();
746 kaaDrawableDirty (pDrawable);
747 kaaMarkSync (pDrawable->pScreen);
750 static void
751 kaaImageGlyphBlt (DrawablePtr pDrawable,
752 GCPtr pGC,
753 int x,
754 int y,
755 unsigned int nglyph,
756 CharInfoPtr *ppciInit,
757 pointer pglyphBase)
759 FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
760 CharInfoPtr *ppci;
761 CharInfoPtr pci;
762 unsigned char *pglyph; /* pointer bits in glyph */
763 int gWidth, gHeight; /* width and height of glyph */
764 FbStride gStride; /* stride of glyph */
765 Bool opaque;
766 int n;
767 int gx, gy;
768 void (*glyph) (FbBits *,
769 FbStride,
770 int,
771 FbStip *,
772 FbBits,
773 int,
774 int);
775 FbBits *dst;
776 FbStride dstStride;
777 int dstBpp;
778 int dstXoff, dstYoff;
779 FbBits depthMask;
781 depthMask = FbFullMask(pDrawable->depth);
782 if ((pGC->planemask & depthMask) != depthMask)
784 KdCheckImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppciInit, pglyphBase);
785 return;
787 glyph = 0;
788 fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
789 switch (dstBpp) {
790 case 8: glyph = fbGlyph8; break;
791 case 16: glyph = fbGlyph16; break;
792 case 24: glyph = fbGlyph24; break;
793 case 32: glyph = fbGlyph32; break;
796 x += pDrawable->x;
797 y += pDrawable->y;
799 if (TERMINALFONT (pGC->font) && !glyph)
801 opaque = TRUE;
803 else
805 int xBack, widthBack;
806 int yBack, heightBack;
808 ppci = ppciInit;
809 n = nglyph;
810 widthBack = 0;
811 while (n--)
812 widthBack += (*ppci++)->metrics.characterWidth;
814 xBack = x;
815 if (widthBack < 0)
817 xBack += widthBack;
818 widthBack = -widthBack;
820 yBack = y - FONTASCENT(pGC->font);
821 heightBack = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
822 kaaSolidBoxClipped (pDrawable,
823 fbGetCompositeClip(pGC),
824 pGC->planemask,
825 pGC->bgPixel,
826 xBack,
827 yBack,
828 xBack + widthBack,
829 yBack + heightBack);
830 opaque = FALSE;
833 kaaWaitSync (pDrawable->pScreen);
834 kaaDrawableDirty (pDrawable);
836 ppci = ppciInit;
837 while (nglyph--)
839 pci = *ppci++;
840 pglyph = FONTGLYPHBITS(pglyphBase, pci);
841 gWidth = GLYPHWIDTHPIXELS(pci);
842 gHeight = GLYPHHEIGHTPIXELS(pci);
843 if (gWidth && gHeight)
845 gx = x + pci->metrics.leftSideBearing;
846 gy = y - pci->metrics.ascent;
847 if (glyph && gWidth <= sizeof (FbStip) * 8 &&
848 fbGlyphIn (fbGetCompositeClip(pGC), gx, gy, gWidth, gHeight))
850 (*glyph) (dst + (gy + dstYoff) * dstStride,
851 dstStride,
852 dstBpp,
853 (FbStip *) pglyph,
854 pPriv->fg,
855 gx + dstXoff,
856 gHeight);
858 else
860 gStride = GLYPHWIDTHBYTESPADDED(pci) / sizeof (FbStip);
861 fbPutXYImage (pDrawable,
862 fbGetCompositeClip(pGC),
863 pPriv->fg,
864 pPriv->bg,
865 pPriv->pm,
866 GXcopy,
867 opaque,
871 gWidth, gHeight,
873 (FbStip *) pglyph,
874 gStride,
878 x += pci->metrics.characterWidth;
882 static const GCOps kaaOps = {
883 kaaFillSpans,
884 KdCheckSetSpans,
885 KdCheckPutImage,
886 kaaCopyArea,
887 KdCheckCopyPlane,
888 KdCheckPolyPoint,
889 KdCheckPolylines,
890 KdCheckPolySegment,
891 miPolyRectangle,
892 KdCheckPolyArc,
893 miFillPolygon,
894 kaaPolyFillRect,
895 miPolyFillArc,
896 miPolyText8,
897 miPolyText16,
898 miImageText8,
899 miImageText16,
900 kaaImageGlyphBlt,
901 KdCheckPolyGlyphBlt,
902 KdCheckPushPixels,
905 static void
906 kaaValidateGC (GCPtr pGC, Mask changes, DrawablePtr pDrawable)
908 fbValidateGC (pGC, changes, pDrawable);
910 if (kaaDrawableIsOffscreen (pDrawable))
911 pGC->ops = (GCOps *) &kaaOps;
912 else
913 pGC->ops = (GCOps *) &kdAsyncPixmapGCOps;
916 GCFuncs kaaGCFuncs = {
917 kaaValidateGC,
918 miChangeGC,
919 miCopyGC,
920 miDestroyGC,
921 miChangeClip,
922 miDestroyClip,
923 miCopyClip
926 static int
927 kaaCreateGC (GCPtr pGC)
929 if (!fbCreateGC (pGC))
930 return FALSE;
932 pGC->funcs = &kaaGCFuncs;
934 return TRUE;
938 static void
939 kaaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
941 RegionRec rgnDst;
942 int dx, dy;
943 PixmapPtr pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin);
945 dx = ptOldOrg.x - pWin->drawable.x;
946 dy = ptOldOrg.y - pWin->drawable.y;
947 REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
949 REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0);
951 REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
952 #ifdef COMPOSITE
953 if (pPixmap->screen_x || pPixmap->screen_y)
954 REGION_TRANSLATE (pWin->drawable.pScreen, &rgnDst,
955 -pPixmap->screen_x, -pPixmap->screen_y);
956 #endif
958 fbCopyRegion (&pPixmap->drawable, &pPixmap->drawable,
960 &rgnDst, dx, dy, kaaCopyNtoN, 0, 0);
962 REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
965 static void
966 kaaFillRegionSolid (DrawablePtr pDrawable,
967 RegionPtr pRegion,
968 Pixel pixel)
970 KdScreenPriv(pDrawable->pScreen);
971 KaaScreenPriv(pDrawable->pScreen);
972 PixmapPtr pPixmap;
973 int xoff, yoff;
975 if (pScreenPriv->enabled &&
976 (pPixmap = kaaGetOffscreenPixmap (pDrawable, &xoff, &yoff)) &&
977 (*pKaaScr->info->PrepareSolid) (pPixmap, GXcopy, FB_ALLONES, pixel))
979 int nbox = REGION_NUM_RECTS (pRegion);
980 BoxPtr pBox = REGION_RECTS (pRegion);
982 while (nbox--)
984 (*pKaaScr->info->Solid) (pBox->x1 + xoff, pBox->y1 + yoff,
985 pBox->x2 + xoff, pBox->y2 + yoff);
986 pBox++;
988 (*pKaaScr->info->DoneSolid) ();
989 kaaMarkSync (pDrawable->pScreen);
991 else
993 kaaWaitSync (pDrawable->pScreen);
994 fbFillRegionSolid (pDrawable, pRegion, 0,
995 fbReplicatePixel (pixel, pDrawable->bitsPerPixel));
997 kaaDrawableDirty (pDrawable);
1000 #if 0
1001 static void
1002 kaaFillRegionTiled (DrawablePtr pDrawable,
1003 RegionPtr pRegion,
1004 Pixmap pTile)
1006 else
1008 kaaWaitSync
1010 #endif
1012 static void
1013 kaaPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
1016 if (!REGION_NUM_RECTS(pRegion))
1017 return;
1018 switch (what) {
1019 case PW_BACKGROUND:
1020 switch (pWin->backgroundState) {
1021 case None:
1022 return;
1023 case ParentRelative:
1024 do {
1025 pWin = pWin->parent;
1026 } while (pWin->backgroundState == ParentRelative);
1027 (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion,
1028 what);
1029 return;
1030 case BackgroundPixel:
1031 kaaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->background.pixel);
1032 return;
1033 #if 0
1034 case BackgroundPixmap:
1035 kaaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->background.pixmap);
1036 return;
1037 #endif
1039 break;
1040 case PW_BORDER:
1041 if (pWin->borderIsPixel)
1043 kaaFillRegionSolid((DrawablePtr)pWin, pRegion, pWin->border.pixel);
1044 return;
1046 #if 0
1047 else
1049 kaaFillRegionTiled((DrawablePtr)pWin, pRegion, pWin->border.pixmap);
1050 return;
1052 #endif
1053 break;
1055 KdCheckPaintWindow (pWin, pRegion, what);
1058 Bool
1059 kaaDrawInit (ScreenPtr pScreen,
1060 KaaScreenInfoPtr pScreenInfo)
1062 KaaScreenPrivPtr pKaaScr;
1063 KdScreenPriv(pScreen);
1064 KdScreenInfo *screen = pScreenPriv->screen;
1065 #ifdef RENDER
1066 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
1067 #endif
1069 if (kaaGeneration != serverGeneration)
1071 kaaScreenPrivateIndex = AllocateScreenPrivateIndex();
1072 kaaPixmapPrivateIndex = AllocatePixmapPrivateIndex();
1073 kaaGeneration = serverGeneration;
1076 pKaaScr = xalloc (sizeof (KaaScreenPrivRec));
1078 if (!pKaaScr)
1079 return FALSE;
1081 pKaaScr->info = pScreenInfo;
1083 pScreen->devPrivates[kaaScreenPrivateIndex].ptr = (pointer) pKaaScr;
1086 * Hook up asynchronous drawing
1088 KdScreenInitAsync (pScreen);
1090 * Replace various fb screen functions
1092 pScreen->CreateGC = kaaCreateGC;
1093 pScreen->CopyWindow = kaaCopyWindow;
1094 pScreen->PaintWindowBackground = kaaPaintWindow;
1095 pScreen->PaintWindowBorder = kaaPaintWindow;
1096 #ifdef RENDER
1097 if (ps) {
1098 ps->Composite = kaaComposite;
1099 ps->RasterizeTrapezoid = kaaRasterizeTrapezoid;
1101 #endif
1104 * Hookup offscreen pixmaps
1106 if ((pKaaScr->info->flags & KAA_OFFSCREEN_PIXMAPS) &&
1107 screen->off_screen_base < screen->memory_size)
1109 if (!AllocatePixmapPrivate(pScreen, kaaPixmapPrivateIndex,
1110 sizeof (KaaPixmapPrivRec)))
1111 return FALSE;
1112 pScreen->CreatePixmap = kaaCreatePixmap;
1113 pScreen->DestroyPixmap = kaaDestroyPixmap;
1115 else
1117 if (!AllocatePixmapPrivate(pScreen, kaaPixmapPrivateIndex, 0))
1118 return FALSE;
1121 return TRUE;
1124 void
1125 kaaDrawFini (ScreenPtr pScreen)
1127 KaaScreenPriv(pScreen);
1129 xfree (pKaaScr);
1132 void
1133 kaaMarkSync (ScreenPtr pScreen)
1135 KdScreenPriv(pScreen);
1136 KaaScreenPriv(pScreen);
1138 pScreenPriv->card->needSync = TRUE;
1139 if (pKaaScr->info->markSync != NULL) {
1140 pScreenPriv->card->lastMarker = (*pKaaScr->info->markSync) (pScreen);
1144 void
1145 kaaWaitSync (ScreenPtr pScreen)
1147 KdScreenPriv(pScreen);
1148 KaaScreenPriv(pScreen);
1149 KdCardInfo *card = pScreenPriv->card;
1151 if (card->needSync) {
1152 (*pKaaScr->info->waitMarker) (pScreen, card->lastMarker);
1153 card->needSync = FALSE;