1428d7b3dSmrg 2428d7b3dSmrg/* 3428d7b3dSmrg * Copyright ® 2001 Keith Packard 4428d7b3dSmrg * 5428d7b3dSmrg * Partly based on code that is Copyright ® The XFree86 Project Inc. 6428d7b3dSmrg * 7428d7b3dSmrg * Permission to use, copy, modify, distribute, and sell this software and its 8428d7b3dSmrg * documentation for any purpose is hereby granted without fee, provided that 9428d7b3dSmrg * the above copyright notice appear in all copies and that both that 10428d7b3dSmrg * copyright notice and this permission notice appear in supporting 11428d7b3dSmrg * documentation, and that the name of Keith Packard not be used in 12428d7b3dSmrg * advertising or publicity pertaining to distribution of the software without 13428d7b3dSmrg * specific, written prior permission. Keith Packard makes no 14428d7b3dSmrg * representations about the suitability of this software for any purpose. It 15428d7b3dSmrg * is provided "as is" without express or implied warranty. 16428d7b3dSmrg * 17428d7b3dSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 18428d7b3dSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 19428d7b3dSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 20428d7b3dSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21428d7b3dSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 22428d7b3dSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 23428d7b3dSmrg * PERFORMANCE OF THIS SOFTWARE. 24428d7b3dSmrg * 25428d7b3dSmrg * Authors: 26428d7b3dSmrg * Eric Anholt <eric@anholt.net> 27428d7b3dSmrg * Michel Dänzer <michel@tungstengraphics.com> 28428d7b3dSmrg * 29428d7b3dSmrg */ 30428d7b3dSmrg 31428d7b3dSmrg#ifdef HAVE_DIX_CONFIG_H 32428d7b3dSmrg#include <dix-config.h> 33428d7b3dSmrg#endif 34428d7b3dSmrg#include "uxa-priv.h" 35428d7b3dSmrg#include <X11/fonts/fontstruct.h> 36428d7b3dSmrg#include "dixfontstr.h" 37428d7b3dSmrg#include "uxa.h" 38428d7b3dSmrg 39428d7b3dSmrgstatic void 40428d7b3dSmrguxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n, 41428d7b3dSmrg DDXPointPtr ppt, int *pwidth, int fSorted) 42428d7b3dSmrg{ 43428d7b3dSmrg ScreenPtr screen = pDrawable->pScreen; 44428d7b3dSmrg uxa_screen_t *uxa_screen = uxa_get_screen(screen); 45428d7b3dSmrg RegionPtr pClip = fbGetCompositeClip(pGC); 46428d7b3dSmrg PixmapPtr dst_pixmap; 47428d7b3dSmrg BoxPtr pbox; 48428d7b3dSmrg int nbox; 49428d7b3dSmrg int x1, x2, y; 50428d7b3dSmrg int off_x, off_y; 51428d7b3dSmrg 52428d7b3dSmrg if (uxa_screen->force_fallback) 53428d7b3dSmrg goto fallback; 54428d7b3dSmrg 55428d7b3dSmrg if (pGC->fillStyle != FillSolid) 56428d7b3dSmrg goto fallback; 57428d7b3dSmrg 58428d7b3dSmrg dst_pixmap = uxa_get_offscreen_pixmap(pDrawable, &off_x, &off_y); 59428d7b3dSmrg if (!dst_pixmap) 60428d7b3dSmrg goto fallback; 61428d7b3dSmrg 62428d7b3dSmrg if (uxa_screen->info->check_solid && 63428d7b3dSmrg !uxa_screen->info->check_solid(pDrawable, pGC->alu, pGC->planemask)) 64428d7b3dSmrg goto fallback; 65428d7b3dSmrg 66428d7b3dSmrg if (!(*uxa_screen->info->prepare_solid) (dst_pixmap, 67428d7b3dSmrg pGC->alu, 68428d7b3dSmrg pGC->planemask, 69428d7b3dSmrg pGC->fgPixel)) 70428d7b3dSmrg goto fallback; 71428d7b3dSmrg 72428d7b3dSmrg while (n--) { 73428d7b3dSmrg x1 = ppt->x; 74428d7b3dSmrg y = ppt->y; 75428d7b3dSmrg x2 = x1 + (int)*pwidth; 76428d7b3dSmrg ppt++; 77428d7b3dSmrg pwidth++; 78428d7b3dSmrg 79428d7b3dSmrg nbox = REGION_NUM_RECTS(pClip); 80428d7b3dSmrg pbox = REGION_RECTS(pClip); 81428d7b3dSmrg while (nbox--) { 82428d7b3dSmrg int X1 = x1, X2 = x2; 83428d7b3dSmrg if (X1 < pbox->x1) 84428d7b3dSmrg X1 = pbox->x1; 85428d7b3dSmrg 86428d7b3dSmrg if (X2 > pbox->x2) 87428d7b3dSmrg X2 = pbox->x2; 88428d7b3dSmrg 89428d7b3dSmrg if (X2 > X1 && pbox->y1 <= y && pbox->y2 > y) 90428d7b3dSmrg (*uxa_screen->info->solid) (dst_pixmap, 91428d7b3dSmrg X1 + off_x, y + off_y, 92428d7b3dSmrg X2 + off_x, y + 1 + off_y); 93428d7b3dSmrg pbox++; 94428d7b3dSmrg } 95428d7b3dSmrg } 96428d7b3dSmrg (*uxa_screen->info->done_solid) (dst_pixmap); 97428d7b3dSmrg 98428d7b3dSmrg return; 99428d7b3dSmrg 100428d7b3dSmrgfallback: 101428d7b3dSmrg uxa_check_fill_spans(pDrawable, pGC, n, ppt, pwidth, fSorted); 102428d7b3dSmrg} 103428d7b3dSmrg 104428d7b3dSmrgstatic Bool 105428d7b3dSmrguxa_do_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, 106428d7b3dSmrg int w, int h, int format, char *bits, int src_stride) 107428d7b3dSmrg{ 108428d7b3dSmrg uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen); 109428d7b3dSmrg PixmapPtr pPix; 110428d7b3dSmrg RegionPtr pClip; 111428d7b3dSmrg BoxPtr pbox; 112428d7b3dSmrg int nbox; 113428d7b3dSmrg int xoff, yoff; 114428d7b3dSmrg int bpp = pDrawable->bitsPerPixel; 115428d7b3dSmrg 116428d7b3dSmrg /* Don't bother with under 8bpp, XYPixmaps. */ 117428d7b3dSmrg if (format != ZPixmap || bpp < 8) 118428d7b3dSmrg return FALSE; 119428d7b3dSmrg 120428d7b3dSmrg if (uxa_screen->force_fallback) 121428d7b3dSmrg return FALSE; 122428d7b3dSmrg 123428d7b3dSmrg if (!uxa_screen->info->put_image) 124428d7b3dSmrg return FALSE; 125428d7b3dSmrg 126428d7b3dSmrg /* Only accelerate copies: no rop or planemask. */ 127428d7b3dSmrg if (!UXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy) 128428d7b3dSmrg return FALSE; 129428d7b3dSmrg 130428d7b3dSmrg pPix = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff); 131428d7b3dSmrg if (!pPix) 132428d7b3dSmrg return FALSE; 133428d7b3dSmrg 134428d7b3dSmrg x += pDrawable->x; 135428d7b3dSmrg y += pDrawable->y; 136428d7b3dSmrg 137428d7b3dSmrg pClip = fbGetCompositeClip(pGC); 138428d7b3dSmrg for (nbox = REGION_NUM_RECTS(pClip), 139428d7b3dSmrg pbox = REGION_RECTS(pClip); nbox--; pbox++) { 140428d7b3dSmrg int x1 = x; 141428d7b3dSmrg int y1 = y; 142428d7b3dSmrg int x2 = x + w; 143428d7b3dSmrg int y2 = y + h; 144428d7b3dSmrg char *src; 145428d7b3dSmrg Bool ok; 146428d7b3dSmrg 147428d7b3dSmrg if (x1 < pbox->x1) 148428d7b3dSmrg x1 = pbox->x1; 149428d7b3dSmrg if (y1 < pbox->y1) 150428d7b3dSmrg y1 = pbox->y1; 151428d7b3dSmrg if (x2 > pbox->x2) 152428d7b3dSmrg x2 = pbox->x2; 153428d7b3dSmrg if (y2 > pbox->y2) 154428d7b3dSmrg y2 = pbox->y2; 155428d7b3dSmrg if (x1 >= x2 || y1 >= y2) 156428d7b3dSmrg continue; 157428d7b3dSmrg 158428d7b3dSmrg src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8); 159428d7b3dSmrg ok = uxa_screen->info->put_image(pPix, x1 + xoff, y1 + yoff, 160428d7b3dSmrg x2 - x1, y2 - y1, src, 161428d7b3dSmrg src_stride); 162428d7b3dSmrg /* If we fail to accelerate the upload, fall back to using 163428d7b3dSmrg * unaccelerated fb calls. 164428d7b3dSmrg */ 165428d7b3dSmrg if (!ok) { 166428d7b3dSmrg FbStip *dst; 167428d7b3dSmrg FbStride dst_stride; 168428d7b3dSmrg int dstBpp; 169428d7b3dSmrg int dstXoff, dstYoff; 170428d7b3dSmrg 171428d7b3dSmrg if (!uxa_prepare_access(pDrawable, UXA_ACCESS_RW)) 172428d7b3dSmrg return FALSE; 173428d7b3dSmrg 174428d7b3dSmrg fbGetStipDrawable(pDrawable, dst, dst_stride, dstBpp, 175428d7b3dSmrg dstXoff, dstYoff); 176428d7b3dSmrg 177428d7b3dSmrg fbBltStip((FbStip *) bits + 178428d7b3dSmrg (y1 - y) * (src_stride / sizeof(FbStip)), 179428d7b3dSmrg src_stride / sizeof(FbStip), 180428d7b3dSmrg (x1 - x) * dstBpp, 181428d7b3dSmrg dst + (y1 + dstYoff) * dst_stride, dst_stride, 182428d7b3dSmrg (x1 + dstXoff) * dstBpp, (x2 - x1) * dstBpp, 183428d7b3dSmrg y2 - y1, GXcopy, FB_ALLONES, dstBpp); 184428d7b3dSmrg 185428d7b3dSmrg uxa_finish_access(pDrawable, UXA_ACCESS_RW); 186428d7b3dSmrg } 187428d7b3dSmrg } 188428d7b3dSmrg 189428d7b3dSmrg 190428d7b3dSmrg return TRUE; 191428d7b3dSmrg} 192428d7b3dSmrg 193428d7b3dSmrgstatic void 194428d7b3dSmrguxa_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, 195428d7b3dSmrg int w, int h, int leftPad, int format, char *bits) 196428d7b3dSmrg{ 197428d7b3dSmrg if (!uxa_do_put_image(pDrawable, pGC, depth, x, y, w, h, format, bits, 198428d7b3dSmrg PixmapBytePad(w, pDrawable->depth))) { 199428d7b3dSmrg uxa_check_put_image(pDrawable, pGC, depth, x, y, w, h, leftPad, 200428d7b3dSmrg format, bits); 201428d7b3dSmrg } 202428d7b3dSmrg} 203428d7b3dSmrg 204428d7b3dSmrgstatic inline Bool 205428d7b3dSmrguxa_copy_n_to_n_two_dir(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, 206428d7b3dSmrg GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy) 207428d7b3dSmrg{ 208428d7b3dSmrg uxa_screen_t *uxa_screen = uxa_get_screen(pDstDrawable->pScreen); 209428d7b3dSmrg PixmapPtr pSrcPixmap, pDstPixmap; 210428d7b3dSmrg int src_off_x, src_off_y, dst_off_x, dst_off_y; 211428d7b3dSmrg int dirsetup; 212428d7b3dSmrg 213428d7b3dSmrg /* Need to get both pixmaps to call the driver routines */ 214428d7b3dSmrg pSrcPixmap = 215428d7b3dSmrg uxa_get_offscreen_pixmap(pSrcDrawable, &src_off_x, &src_off_y); 216428d7b3dSmrg pDstPixmap = 217428d7b3dSmrg uxa_get_offscreen_pixmap(pDstDrawable, &dst_off_x, &dst_off_y); 218428d7b3dSmrg if (!pSrcPixmap || !pDstPixmap) 219428d7b3dSmrg return FALSE; 220428d7b3dSmrg 221428d7b3dSmrg /* 222428d7b3dSmrg * Now the case of a chip that only supports xdir = ydir = 1 or 223428d7b3dSmrg * xdir = ydir = -1, but we have xdir != ydir. 224428d7b3dSmrg */ 225428d7b3dSmrg dirsetup = 0; /* No direction set up yet. */ 226428d7b3dSmrg for (; nbox; pbox++, nbox--) { 227428d7b3dSmrg if (dx >= 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) { 228428d7b3dSmrg /* Do a xdir = ydir = -1 blit instead. */ 229428d7b3dSmrg if (dirsetup != -1) { 230428d7b3dSmrg if (dirsetup != 0) 231428d7b3dSmrg uxa_screen->info->done_copy(pDstPixmap); 232428d7b3dSmrg dirsetup = -1; 233428d7b3dSmrg if (!(*uxa_screen->info->prepare_copy) 234428d7b3dSmrg (pSrcPixmap, pDstPixmap, -1, -1, 235428d7b3dSmrg pGC ? pGC->alu : GXcopy, 236428d7b3dSmrg pGC ? pGC->planemask : FB_ALLONES)) 237428d7b3dSmrg return FALSE; 238428d7b3dSmrg } 239428d7b3dSmrg (*uxa_screen->info->copy) (pDstPixmap, 240428d7b3dSmrg src_off_x + pbox->x1 + dx, 241428d7b3dSmrg src_off_y + pbox->y1 + dy, 242428d7b3dSmrg dst_off_x + pbox->x1, 243428d7b3dSmrg dst_off_y + pbox->y1, 244428d7b3dSmrg pbox->x2 - pbox->x1, 245428d7b3dSmrg pbox->y2 - pbox->y1); 246428d7b3dSmrg } else if (dx < 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) { 247428d7b3dSmrg /* Do a xdir = ydir = 1 blit instead. */ 248428d7b3dSmrg if (dirsetup != 1) { 249428d7b3dSmrg if (dirsetup != 0) 250428d7b3dSmrg uxa_screen->info->done_copy(pDstPixmap); 251428d7b3dSmrg dirsetup = 1; 252428d7b3dSmrg if (!(*uxa_screen->info->prepare_copy) 253428d7b3dSmrg (pSrcPixmap, pDstPixmap, 1, 1, 254428d7b3dSmrg pGC ? pGC->alu : GXcopy, 255428d7b3dSmrg pGC ? pGC->planemask : FB_ALLONES)) 256428d7b3dSmrg return FALSE; 257428d7b3dSmrg } 258428d7b3dSmrg (*uxa_screen->info->copy) (pDstPixmap, 259428d7b3dSmrg src_off_x + pbox->x1 + dx, 260428d7b3dSmrg src_off_y + pbox->y1 + dy, 261428d7b3dSmrg dst_off_x + pbox->x1, 262428d7b3dSmrg dst_off_y + pbox->y1, 263428d7b3dSmrg pbox->x2 - pbox->x1, 264428d7b3dSmrg pbox->y2 - pbox->y1); 265428d7b3dSmrg } else if (dx >= 0) { 266428d7b3dSmrg /* 267428d7b3dSmrg * xdir = 1, ydir = -1. 268428d7b3dSmrg * Perform line-by-line xdir = ydir = 1 blits, going up. 269428d7b3dSmrg */ 270428d7b3dSmrg int i; 271428d7b3dSmrg if (dirsetup != 1) { 272428d7b3dSmrg if (dirsetup != 0) 273428d7b3dSmrg uxa_screen->info->done_copy(pDstPixmap); 274428d7b3dSmrg dirsetup = 1; 275428d7b3dSmrg if (!(*uxa_screen->info->prepare_copy) 276428d7b3dSmrg (pSrcPixmap, pDstPixmap, 1, 1, 277428d7b3dSmrg pGC ? pGC->alu : GXcopy, 278428d7b3dSmrg pGC ? pGC->planemask : FB_ALLONES)) 279428d7b3dSmrg return FALSE; 280428d7b3dSmrg } 281428d7b3dSmrg for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--) 282428d7b3dSmrg (*uxa_screen->info->copy) (pDstPixmap, 283428d7b3dSmrg src_off_x + 284428d7b3dSmrg pbox->x1 + dx, 285428d7b3dSmrg src_off_y + 286428d7b3dSmrg pbox->y1 + dy + i, 287428d7b3dSmrg dst_off_x + pbox->x1, 288428d7b3dSmrg dst_off_y + 289428d7b3dSmrg pbox->y1 + i, 290428d7b3dSmrg pbox->x2 - pbox->x1, 291428d7b3dSmrg 1); 292428d7b3dSmrg } else { 293428d7b3dSmrg /* 294428d7b3dSmrg * xdir = -1, ydir = 1. 295428d7b3dSmrg * Perform line-by-line xdir = ydir = -1 blits, 296428d7b3dSmrg * going down. 297428d7b3dSmrg */ 298428d7b3dSmrg int i; 299428d7b3dSmrg if (dirsetup != -1) { 300428d7b3dSmrg if (dirsetup != 0) 301428d7b3dSmrg uxa_screen->info->done_copy(pDstPixmap); 302428d7b3dSmrg dirsetup = -1; 303428d7b3dSmrg if (!(*uxa_screen->info->prepare_copy) 304428d7b3dSmrg (pSrcPixmap, pDstPixmap, -1, -1, 305428d7b3dSmrg pGC ? pGC->alu : GXcopy, 306428d7b3dSmrg pGC ? pGC->planemask : FB_ALLONES)) 307428d7b3dSmrg return FALSE; 308428d7b3dSmrg } 309428d7b3dSmrg for (i = 0; i < pbox->y2 - pbox->y1; i++) 310428d7b3dSmrg (*uxa_screen->info->copy) (pDstPixmap, 311428d7b3dSmrg src_off_x + 312428d7b3dSmrg pbox->x1 + dx, 313428d7b3dSmrg src_off_y + 314428d7b3dSmrg pbox->y1 + dy + i, 315428d7b3dSmrg dst_off_x + pbox->x1, 316428d7b3dSmrg dst_off_y + 317428d7b3dSmrg pbox->y1 + i, 318428d7b3dSmrg pbox->x2 - pbox->x1, 319428d7b3dSmrg 1); 320428d7b3dSmrg } 321428d7b3dSmrg } 322428d7b3dSmrg if (dirsetup != 0) 323428d7b3dSmrg uxa_screen->info->done_copy(pDstPixmap); 324428d7b3dSmrg return TRUE; 325428d7b3dSmrg} 326428d7b3dSmrg 327428d7b3dSmrgvoid 328428d7b3dSmrguxa_copy_n_to_n(DrawablePtr pSrcDrawable, 329428d7b3dSmrg DrawablePtr pDstDrawable, 330428d7b3dSmrg GCPtr pGC, 331428d7b3dSmrg BoxPtr pbox, 332428d7b3dSmrg int nbox, 333428d7b3dSmrg int dx, 334428d7b3dSmrg int dy, 335428d7b3dSmrg Bool reverse, Bool upsidedown, Pixel bitplane, void *closure) 336428d7b3dSmrg{ 337428d7b3dSmrg ScreenPtr screen = pDstDrawable->pScreen; 338428d7b3dSmrg uxa_screen_t *uxa_screen = uxa_get_screen(screen); 339428d7b3dSmrg int src_off_x, src_off_y; 340428d7b3dSmrg int dst_off_x, dst_off_y; 341428d7b3dSmrg PixmapPtr pSrcPixmap, pDstPixmap; 342428d7b3dSmrg 343428d7b3dSmrg if (uxa_screen->force_fallback) 344428d7b3dSmrg goto fallback; 345428d7b3dSmrg 346428d7b3dSmrg pSrcPixmap = uxa_get_drawable_pixmap(pSrcDrawable); 347428d7b3dSmrg pDstPixmap = uxa_get_drawable_pixmap(pDstDrawable); 348428d7b3dSmrg if (!pSrcPixmap || !pDstPixmap) 349428d7b3dSmrg goto fallback; 350428d7b3dSmrg 351428d7b3dSmrg if (uxa_screen->info->check_copy && 352428d7b3dSmrg !uxa_screen->info->check_copy(pSrcPixmap, pDstPixmap, 353428d7b3dSmrg pGC ? pGC->alu : GXcopy, 354428d7b3dSmrg pGC ? pGC->planemask : FB_ALLONES)) 355428d7b3dSmrg goto fallback; 356428d7b3dSmrg 357428d7b3dSmrg uxa_get_drawable_deltas(pSrcDrawable, pSrcPixmap, &src_off_x, 358428d7b3dSmrg &src_off_y); 359428d7b3dSmrg uxa_get_drawable_deltas(pDstDrawable, pDstPixmap, &dst_off_x, 360428d7b3dSmrg &dst_off_y); 361428d7b3dSmrg 362428d7b3dSmrg /* Mixed directions must be handled specially if the card is lame */ 363428d7b3dSmrg if ((uxa_screen->info->flags & UXA_TWO_BITBLT_DIRECTIONS) && 364428d7b3dSmrg reverse != upsidedown) { 365428d7b3dSmrg if (uxa_copy_n_to_n_two_dir 366428d7b3dSmrg (pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy)) 367428d7b3dSmrg return; 368428d7b3dSmrg goto fallback; 369428d7b3dSmrg } 370428d7b3dSmrg 371428d7b3dSmrg if (!uxa_pixmap_is_offscreen(pDstPixmap)) { 372428d7b3dSmrg int stride, bpp; 373428d7b3dSmrg char *dst; 374428d7b3dSmrg 375428d7b3dSmrg if (!uxa_pixmap_is_offscreen(pSrcPixmap)) 376428d7b3dSmrg goto fallback; 377428d7b3dSmrg 378428d7b3dSmrg if (!uxa_screen->info->get_image) 379428d7b3dSmrg goto fallback; 380428d7b3dSmrg 381428d7b3dSmrg /* Don't bother with under 8bpp, XYPixmaps. */ 382428d7b3dSmrg bpp = pSrcPixmap->drawable.bitsPerPixel; 383428d7b3dSmrg if (bpp != pDstDrawable->bitsPerPixel || bpp < 8) 384428d7b3dSmrg goto fallback; 385428d7b3dSmrg 386428d7b3dSmrg /* Only accelerate copies: no rop or planemask. */ 387428d7b3dSmrg if (pGC && (!UXA_PM_IS_SOLID(pSrcDrawable, pGC->planemask) || pGC->alu != GXcopy)) 388428d7b3dSmrg goto fallback; 389428d7b3dSmrg 390428d7b3dSmrg dst = pDstPixmap->devPrivate.ptr; 391428d7b3dSmrg stride = pDstPixmap->devKind; 392428d7b3dSmrg bpp /= 8; 393428d7b3dSmrg while (nbox--) { 394428d7b3dSmrg if (!uxa_screen->info->get_image(pSrcPixmap, 395428d7b3dSmrg pbox->x1 + dx + src_off_x, 396428d7b3dSmrg pbox->y1 + dy + src_off_y, 397428d7b3dSmrg pbox->x2 - pbox->x1, 398428d7b3dSmrg pbox->y2 - pbox->y1, 399428d7b3dSmrg (char *) dst + 400428d7b3dSmrg (pbox->y1 + dst_off_y) * stride + 401428d7b3dSmrg (pbox->x1 + dst_off_x) * bpp, 402428d7b3dSmrg stride)) 403428d7b3dSmrg goto fallback; 404428d7b3dSmrg 405428d7b3dSmrg pbox++; 406428d7b3dSmrg } 407428d7b3dSmrg 408428d7b3dSmrg return; 409428d7b3dSmrg } 410428d7b3dSmrg 411428d7b3dSmrg if (uxa_pixmap_is_offscreen(pSrcPixmap)) { 412428d7b3dSmrg if (!(*uxa_screen->info->prepare_copy) (pSrcPixmap, pDstPixmap, 413428d7b3dSmrg reverse ? -1 : 1, 414428d7b3dSmrg upsidedown ? -1 : 1, 415428d7b3dSmrg pGC ? pGC->alu : GXcopy, 416428d7b3dSmrg pGC ? pGC-> 417428d7b3dSmrg planemask : FB_ALLONES)) 418428d7b3dSmrg goto fallback; 419428d7b3dSmrg 420428d7b3dSmrg while (nbox--) { 421428d7b3dSmrg (*uxa_screen->info->copy) (pDstPixmap, 422428d7b3dSmrg pbox->x1 + dx + src_off_x, 423428d7b3dSmrg pbox->y1 + dy + src_off_y, 424428d7b3dSmrg pbox->x1 + dst_off_x, 425428d7b3dSmrg pbox->y1 + dst_off_y, 426428d7b3dSmrg pbox->x2 - pbox->x1, 427428d7b3dSmrg pbox->y2 - pbox->y1); 428428d7b3dSmrg pbox++; 429428d7b3dSmrg } 430428d7b3dSmrg 431428d7b3dSmrg (*uxa_screen->info->done_copy) (pDstPixmap); 432428d7b3dSmrg } else { 433428d7b3dSmrg int stride, bpp; 434428d7b3dSmrg char *src; 435428d7b3dSmrg 436428d7b3dSmrg if (!uxa_screen->info->put_image) 437428d7b3dSmrg goto fallback; 438428d7b3dSmrg 439428d7b3dSmrg /* Don't bother with under 8bpp, XYPixmaps. */ 440428d7b3dSmrg bpp = pSrcPixmap->drawable.bitsPerPixel; 441428d7b3dSmrg if (bpp != pDstDrawable->bitsPerPixel || bpp < 8) 442428d7b3dSmrg goto fallback; 443428d7b3dSmrg 444428d7b3dSmrg /* Only accelerate copies: no rop or planemask. */ 445428d7b3dSmrg if (pGC && (!UXA_PM_IS_SOLID(pSrcDrawable, pGC->planemask) || pGC->alu != GXcopy)) 446428d7b3dSmrg goto fallback; 447428d7b3dSmrg 448428d7b3dSmrg src = pSrcPixmap->devPrivate.ptr; 449428d7b3dSmrg stride = pSrcPixmap->devKind; 450428d7b3dSmrg bpp /= 8; 451428d7b3dSmrg while (nbox--) { 452428d7b3dSmrg if (!uxa_screen->info->put_image(pDstPixmap, 453428d7b3dSmrg pbox->x1 + dst_off_x, 454428d7b3dSmrg pbox->y1 + dst_off_y, 455428d7b3dSmrg pbox->x2 - pbox->x1, 456428d7b3dSmrg pbox->y2 - pbox->y1, 457428d7b3dSmrg (char *) src + 458428d7b3dSmrg (pbox->y1 + dy + src_off_y) * stride + 459428d7b3dSmrg (pbox->x1 + dx + src_off_x) * bpp, 460428d7b3dSmrg stride)) 461428d7b3dSmrg goto fallback; 462428d7b3dSmrg 463428d7b3dSmrg pbox++; 464428d7b3dSmrg } 465428d7b3dSmrg } 466428d7b3dSmrg 467428d7b3dSmrg return; 468428d7b3dSmrg 469428d7b3dSmrgfallback: 470428d7b3dSmrg UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable, 471428d7b3dSmrg uxa_drawable_location(pSrcDrawable), 472428d7b3dSmrg uxa_drawable_location(pDstDrawable))); 473428d7b3dSmrg if (uxa_prepare_access(pDstDrawable, UXA_ACCESS_RW)) { 474428d7b3dSmrg if (pSrcDrawable == pDstDrawable || 475428d7b3dSmrg uxa_prepare_access(pSrcDrawable, UXA_ACCESS_RO)) { 476428d7b3dSmrg fbCopyNtoN(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, 477428d7b3dSmrg dx, dy, reverse, upsidedown, bitplane, 478428d7b3dSmrg closure); 479428d7b3dSmrg if (pSrcDrawable != pDstDrawable) 480428d7b3dSmrg uxa_finish_access(pSrcDrawable, UXA_ACCESS_RO); 481428d7b3dSmrg } 482428d7b3dSmrg uxa_finish_access(pDstDrawable, UXA_ACCESS_RW); 483428d7b3dSmrg } 484428d7b3dSmrg} 485428d7b3dSmrg 486428d7b3dSmrgRegionPtr 487428d7b3dSmrguxa_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, 488428d7b3dSmrg int srcx, int srcy, int width, int height, int dstx, int dsty) 489428d7b3dSmrg{ 490428d7b3dSmrg uxa_screen_t *uxa_screen = uxa_get_screen(pDstDrawable->pScreen); 491428d7b3dSmrg 492428d7b3dSmrg if (uxa_screen->force_fallback) { 493428d7b3dSmrg return uxa_check_copy_area(pSrcDrawable, pDstDrawable, pGC, 494428d7b3dSmrg srcx, srcy, width, height, dstx, 495428d7b3dSmrg dsty); 496428d7b3dSmrg } 497428d7b3dSmrg 498428d7b3dSmrg return miDoCopy(pSrcDrawable, pDstDrawable, pGC, 499428d7b3dSmrg srcx, srcy, width, height, 500428d7b3dSmrg dstx, dsty, uxa_copy_n_to_n, 0, NULL); 501428d7b3dSmrg} 502428d7b3dSmrg 503428d7b3dSmrgstatic void 504428d7b3dSmrguxa_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, 505428d7b3dSmrg DDXPointPtr ppt) 506428d7b3dSmrg{ 507428d7b3dSmrg int i; 508428d7b3dSmrg xRectangle *prect; 509428d7b3dSmrg 510428d7b3dSmrg /* If we can't reuse the current GC as is, don't bother accelerating the 511428d7b3dSmrg * points. 512428d7b3dSmrg */ 513428d7b3dSmrg if (pGC->fillStyle != FillSolid) { 514428d7b3dSmrg uxa_check_poly_point(pDrawable, pGC, mode, npt, ppt); 515428d7b3dSmrg return; 516428d7b3dSmrg } 517428d7b3dSmrg 518428d7b3dSmrg prect = malloc(sizeof(xRectangle) * npt); 519428d7b3dSmrg if (!prect) 520428d7b3dSmrg return; 521428d7b3dSmrg for (i = 0; i < npt; i++) { 522428d7b3dSmrg prect[i].x = ppt[i].x; 523428d7b3dSmrg prect[i].y = ppt[i].y; 524428d7b3dSmrg if (i > 0 && mode == CoordModePrevious) { 525428d7b3dSmrg prect[i].x += prect[i - 1].x; 526428d7b3dSmrg prect[i].y += prect[i - 1].y; 527428d7b3dSmrg } 528428d7b3dSmrg prect[i].width = 1; 529428d7b3dSmrg prect[i].height = 1; 530428d7b3dSmrg } 531428d7b3dSmrg pGC->ops->PolyFillRect(pDrawable, pGC, npt, prect); 532428d7b3dSmrg free(prect); 533428d7b3dSmrg} 534428d7b3dSmrg 535428d7b3dSmrg/** 536428d7b3dSmrg * uxa_poly_lines() checks if it can accelerate the lines as a group of 537428d7b3dSmrg * horizontal or vertical lines (rectangles), and uses existing rectangle fill 538428d7b3dSmrg * acceleration if so. 539428d7b3dSmrg */ 540428d7b3dSmrgstatic void 541428d7b3dSmrguxa_poly_lines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, 542428d7b3dSmrg DDXPointPtr ppt) 543428d7b3dSmrg{ 544428d7b3dSmrg xRectangle *prect; 545428d7b3dSmrg int x1, x2, y1, y2; 546428d7b3dSmrg int i; 547428d7b3dSmrg 548428d7b3dSmrg /* Don't try to do wide lines or non-solid fill style. */ 549428d7b3dSmrg if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid || 550428d7b3dSmrg pGC->fillStyle != FillSolid) { 551428d7b3dSmrg uxa_check_poly_lines(pDrawable, pGC, mode, npt, ppt); 552428d7b3dSmrg return; 553428d7b3dSmrg } 554428d7b3dSmrg 555428d7b3dSmrg prect = malloc(sizeof(xRectangle) * (npt - 1)); 556428d7b3dSmrg if (!prect) 557428d7b3dSmrg return; 558428d7b3dSmrg x1 = ppt[0].x; 559428d7b3dSmrg y1 = ppt[0].y; 560428d7b3dSmrg /* If we have any non-horizontal/vertical, fall back. */ 561428d7b3dSmrg for (i = 0; i < npt - 1; i++) { 562428d7b3dSmrg if (mode == CoordModePrevious) { 563428d7b3dSmrg x2 = x1 + ppt[i + 1].x; 564428d7b3dSmrg y2 = y1 + ppt[i + 1].y; 565428d7b3dSmrg } else { 566428d7b3dSmrg x2 = ppt[i + 1].x; 567428d7b3dSmrg y2 = ppt[i + 1].y; 568428d7b3dSmrg } 569428d7b3dSmrg 570428d7b3dSmrg if (x1 != x2 && y1 != y2) { 571428d7b3dSmrg free(prect); 572428d7b3dSmrg uxa_check_poly_lines(pDrawable, pGC, mode, npt, ppt); 573428d7b3dSmrg return; 574428d7b3dSmrg } 575428d7b3dSmrg 576428d7b3dSmrg if (x1 < x2) { 577428d7b3dSmrg prect[i].x = x1; 578428d7b3dSmrg prect[i].width = x2 - x1 + 1; 579428d7b3dSmrg } else { 580428d7b3dSmrg prect[i].x = x2; 581428d7b3dSmrg prect[i].width = x1 - x2 + 1; 582428d7b3dSmrg } 583428d7b3dSmrg if (y1 < y2) { 584428d7b3dSmrg prect[i].y = y1; 585428d7b3dSmrg prect[i].height = y2 - y1 + 1; 586428d7b3dSmrg } else { 587428d7b3dSmrg prect[i].y = y2; 588428d7b3dSmrg prect[i].height = y1 - y2 + 1; 589428d7b3dSmrg } 590428d7b3dSmrg 591428d7b3dSmrg x1 = x2; 592428d7b3dSmrg y1 = y2; 593428d7b3dSmrg } 594428d7b3dSmrg pGC->ops->PolyFillRect(pDrawable, pGC, npt - 1, prect); 595428d7b3dSmrg free(prect); 596428d7b3dSmrg} 597428d7b3dSmrg 598428d7b3dSmrgstatic BoxRec box_from_seg(const xSegment *seg, GCPtr gc) 599428d7b3dSmrg{ 600428d7b3dSmrg BoxRec b; 601428d7b3dSmrg 602428d7b3dSmrg if (seg->x1 == seg->x2) { 603428d7b3dSmrg if (seg->y1 > seg->y2) { 604428d7b3dSmrg b.y2 = seg->y1 + 1; 605428d7b3dSmrg b.y1 = seg->y2 + 1; 606428d7b3dSmrg if (gc->capStyle != CapNotLast) 607428d7b3dSmrg b.y1--; 608428d7b3dSmrg } else { 609428d7b3dSmrg b.y1 = seg->y1; 610428d7b3dSmrg b.y2 = seg->y2; 611428d7b3dSmrg if (gc->capStyle != CapNotLast) 612428d7b3dSmrg b.y2++; 613428d7b3dSmrg } 614428d7b3dSmrg b.x1 = seg->x1; 615428d7b3dSmrg b.x2 = seg->x1 + 1; 616428d7b3dSmrg } else { 617428d7b3dSmrg if (seg->x1 > seg->x2) { 618428d7b3dSmrg b.x2 = seg->x1 + 1; 619428d7b3dSmrg b.x1 = seg->x2 + 1; 620428d7b3dSmrg if (gc->capStyle != CapNotLast) 621428d7b3dSmrg b.x1--; 622428d7b3dSmrg } else { 623428d7b3dSmrg b.x1 = seg->x1; 624428d7b3dSmrg b.x2 = seg->x2; 625428d7b3dSmrg if (gc->capStyle != CapNotLast) 626428d7b3dSmrg b.x2++; 627428d7b3dSmrg } 628428d7b3dSmrg b.y1 = seg->y1; 629428d7b3dSmrg b.y2 = seg->y1 + 1; 630428d7b3dSmrg } 631428d7b3dSmrg 632428d7b3dSmrg return b; 633428d7b3dSmrg} 634428d7b3dSmrg 635428d7b3dSmrg/** 636428d7b3dSmrg * uxa_poly_segment() checks if it can accelerate the lines as a group of 637428d7b3dSmrg * horizontal or vertical lines (rectangles), and uses existing rectangle fill 638428d7b3dSmrg * acceleration if so. 639428d7b3dSmrg */ 640428d7b3dSmrgstatic void 641428d7b3dSmrguxa_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pSeg) 642428d7b3dSmrg{ 643428d7b3dSmrg xRectangle *prect; 644428d7b3dSmrg int i; 645428d7b3dSmrg 646428d7b3dSmrg /* Don't try to do wide lines or non-solid fill style. */ 647428d7b3dSmrg if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid || 648428d7b3dSmrg pGC->fillStyle != FillSolid) { 649428d7b3dSmrg uxa_check_poly_segment(pDrawable, pGC, nseg, pSeg); 650428d7b3dSmrg return; 651428d7b3dSmrg } 652428d7b3dSmrg 653428d7b3dSmrg /* If we have any non-horizontal/vertical, fall back. */ 654428d7b3dSmrg for (i = 0; i < nseg; i++) { 655428d7b3dSmrg if (pSeg[i].x1 != pSeg[i].x2 && pSeg[i].y1 != pSeg[i].y2) { 656428d7b3dSmrg uxa_check_poly_segment(pDrawable, pGC, nseg, pSeg); 657428d7b3dSmrg return; 658428d7b3dSmrg } 659428d7b3dSmrg } 660428d7b3dSmrg 661428d7b3dSmrg prect = malloc(sizeof(xRectangle) * nseg); 662428d7b3dSmrg if (!prect) 663428d7b3dSmrg return; 664428d7b3dSmrg for (i = 0; i < nseg; i++) { 665428d7b3dSmrg BoxRec b = box_from_seg(&pSeg[i], pGC); 666428d7b3dSmrg prect[i].x = b.x1; 667428d7b3dSmrg prect[i].y = b.y1; 668428d7b3dSmrg prect[i].width = b.x2 - b.x1; 669428d7b3dSmrg prect[i].height = b.y2 - b.y1; 670428d7b3dSmrg } 671428d7b3dSmrg pGC->ops->PolyFillRect(pDrawable, pGC, nseg, prect); 672428d7b3dSmrg free(prect); 673428d7b3dSmrg} 674428d7b3dSmrg 675428d7b3dSmrgstatic Bool uxa_fill_region_solid(DrawablePtr pDrawable, RegionPtr pRegion, 676428d7b3dSmrg Pixel pixel, CARD32 planemask, CARD32 alu); 677428d7b3dSmrg 678428d7b3dSmrgstatic void 679428d7b3dSmrguxa_poly_fill_rect(DrawablePtr pDrawable, 680428d7b3dSmrg GCPtr pGC, int nrect, xRectangle * prect) 681428d7b3dSmrg{ 682428d7b3dSmrg uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen); 683428d7b3dSmrg RegionPtr pClip = fbGetCompositeClip(pGC); 684428d7b3dSmrg PixmapPtr pPixmap; 685428d7b3dSmrg RegionPtr pReg; 686428d7b3dSmrg BoxPtr pbox; 687428d7b3dSmrg int fullX1, fullX2, fullY1, fullY2; 688428d7b3dSmrg int xoff, yoff; 689428d7b3dSmrg int xorg, yorg; 690428d7b3dSmrg int n; 691428d7b3dSmrg 692428d7b3dSmrg /* Compute intersection of rects and clip region */ 693428d7b3dSmrg pReg = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED); 694428d7b3dSmrg REGION_TRANSLATE(pScreen, pReg, pDrawable->x, pDrawable->y); 695428d7b3dSmrg REGION_INTERSECT(pScreen, pReg, pClip, pReg); 696428d7b3dSmrg 697428d7b3dSmrg if (!REGION_NUM_RECTS(pReg)) 698428d7b3dSmrg goto out; 699428d7b3dSmrg 700428d7b3dSmrg if (uxa_screen->force_fallback) 701428d7b3dSmrg goto fallback; 702428d7b3dSmrg 703428d7b3dSmrg pPixmap = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff); 704428d7b3dSmrg if (!pPixmap) 705428d7b3dSmrg goto fallback; 706428d7b3dSmrg 707428d7b3dSmrg /* For ROPs where overlaps don't matter, convert rectangles to region 708428d7b3dSmrg * and call uxa_fill_region_{solid,tiled}. 709428d7b3dSmrg */ 710428d7b3dSmrg if ((pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) && 711428d7b3dSmrg (nrect == 1 || pGC->alu == GXcopy || pGC->alu == GXclear || 712428d7b3dSmrg pGC->alu == GXnoop || pGC->alu == GXcopyInverted || 713428d7b3dSmrg pGC->alu == GXset)) { 714428d7b3dSmrg if (((pGC->fillStyle == FillSolid || pGC->tileIsPixel) && 715428d7b3dSmrg uxa_fill_region_solid(pDrawable, pReg, 716428d7b3dSmrg pGC->fillStyle == 717428d7b3dSmrg FillSolid ? pGC->fgPixel : pGC->tile. 718428d7b3dSmrg pixel, pGC->planemask, pGC->alu)) 719428d7b3dSmrg || (pGC->fillStyle == FillTiled && !pGC->tileIsPixel 720428d7b3dSmrg && uxa_fill_region_tiled(pDrawable, pReg, 721428d7b3dSmrg pGC->tile.pixmap, &pGC->patOrg, 722428d7b3dSmrg pGC->planemask, pGC->alu))) { 723428d7b3dSmrg goto out; 724428d7b3dSmrg } 725428d7b3dSmrg } 726428d7b3dSmrg 727428d7b3dSmrg if (pGC->fillStyle != FillSolid && 728428d7b3dSmrg !(pGC->tileIsPixel && pGC->fillStyle == FillTiled)) { 729428d7b3dSmrg goto fallback; 730428d7b3dSmrg } 731428d7b3dSmrg 732428d7b3dSmrg if (uxa_screen->info->check_solid && 733428d7b3dSmrg !uxa_screen->info->check_solid(pDrawable, pGC->alu, pGC->planemask)) { 734428d7b3dSmrg goto fallback; 735428d7b3dSmrg } 736428d7b3dSmrg 737428d7b3dSmrg if (!(*uxa_screen->info->prepare_solid) (pPixmap, 738428d7b3dSmrg pGC->alu, 739428d7b3dSmrg pGC->planemask, 740428d7b3dSmrg pGC->fgPixel)) { 741428d7b3dSmrgfallback: 742428d7b3dSmrg uxa_check_poly_fill_rect(pDrawable, pGC, nrect, prect); 743428d7b3dSmrg goto out; 744428d7b3dSmrg } 745428d7b3dSmrg 746428d7b3dSmrg xorg = pDrawable->x; 747428d7b3dSmrg yorg = pDrawable->y; 748428d7b3dSmrg 749428d7b3dSmrg while (nrect--) { 750428d7b3dSmrg fullX1 = prect->x + xorg; 751428d7b3dSmrg fullY1 = prect->y + yorg; 752428d7b3dSmrg fullX2 = fullX1 + (int)prect->width; 753428d7b3dSmrg fullY2 = fullY1 + (int)prect->height; 754428d7b3dSmrg prect++; 755428d7b3dSmrg 756428d7b3dSmrg n = REGION_NUM_RECTS(pClip); 757428d7b3dSmrg pbox = REGION_RECTS(pClip); 758428d7b3dSmrg /* 759428d7b3dSmrg * clip the rectangle to each box in the clip region 760428d7b3dSmrg * this is logically equivalent to calling Intersect(), 761428d7b3dSmrg * but rectangles may overlap each other here. 762428d7b3dSmrg */ 763428d7b3dSmrg while (n--) { 764428d7b3dSmrg int x1 = fullX1; 765428d7b3dSmrg int x2 = fullX2; 766428d7b3dSmrg int y1 = fullY1; 767428d7b3dSmrg int y2 = fullY2; 768428d7b3dSmrg 769428d7b3dSmrg if (pbox->x1 > x1) 770428d7b3dSmrg x1 = pbox->x1; 771428d7b3dSmrg if (pbox->x2 < x2) 772428d7b3dSmrg x2 = pbox->x2; 773428d7b3dSmrg if (pbox->y1 > y1) 774428d7b3dSmrg y1 = pbox->y1; 775428d7b3dSmrg if (pbox->y2 < y2) 776428d7b3dSmrg y2 = pbox->y2; 777428d7b3dSmrg pbox++; 778428d7b3dSmrg 779428d7b3dSmrg if (x1 >= x2 || y1 >= y2) 780428d7b3dSmrg continue; 781428d7b3dSmrg 782428d7b3dSmrg (*uxa_screen->info->solid) (pPixmap, 783428d7b3dSmrg x1 + xoff, 784428d7b3dSmrg y1 + yoff, 785428d7b3dSmrg x2 + xoff, 786428d7b3dSmrg y2 + yoff); 787428d7b3dSmrg } 788428d7b3dSmrg } 789428d7b3dSmrg (*uxa_screen->info->done_solid) (pPixmap); 790428d7b3dSmrg 791428d7b3dSmrgout: 792428d7b3dSmrg REGION_UNINIT(pScreen, pReg); 793428d7b3dSmrg REGION_DESTROY(pScreen, pReg); 794428d7b3dSmrg} 795428d7b3dSmrg 796428d7b3dSmrgvoid 797428d7b3dSmrguxa_get_spans(DrawablePtr pDrawable, 798428d7b3dSmrg int wMax, 799428d7b3dSmrg DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart) 800428d7b3dSmrg{ 801428d7b3dSmrg uxa_check_get_spans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart); 802428d7b3dSmrg} 803428d7b3dSmrg 804428d7b3dSmrgstatic void 805428d7b3dSmrguxa_set_spans(DrawablePtr pDrawable, GCPtr gc, char *src, 806428d7b3dSmrg DDXPointPtr points, int *widths, int n, int sorted) 807428d7b3dSmrg{ 808428d7b3dSmrg uxa_check_set_spans(pDrawable, gc, src, points, widths, n, sorted); 809428d7b3dSmrg} 810428d7b3dSmrg 811428d7b3dSmrgstatic RegionPtr 812428d7b3dSmrguxa_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, 813428d7b3dSmrg int srcx, int srcy, int w, int h, int dstx, int dsty, 814428d7b3dSmrg unsigned long bitPlane) 815428d7b3dSmrg{ 816428d7b3dSmrg return uxa_check_copy_plane(pSrc, pDst, pGC, srcx, srcy, w, h, 817428d7b3dSmrg dstx, dsty, bitPlane); 818428d7b3dSmrg} 819428d7b3dSmrg 820428d7b3dSmrgstatic void 821428d7b3dSmrguxa_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, 822428d7b3dSmrg int x, int y, unsigned int nglyph, 823428d7b3dSmrg CharInfoPtr * ppci, pointer pglyphBase) 824428d7b3dSmrg{ 825428d7b3dSmrg uxa_check_image_glyph_blt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); 826428d7b3dSmrg} 827428d7b3dSmrg 828428d7b3dSmrgstatic void 829428d7b3dSmrguxa_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC, 830428d7b3dSmrg int x, int y, unsigned int nglyph, 831428d7b3dSmrg CharInfoPtr * ppci, pointer pglyphBase) 832428d7b3dSmrg{ 833428d7b3dSmrg uxa_check_poly_glyph_blt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); 834428d7b3dSmrg} 835428d7b3dSmrg 836428d7b3dSmrgstatic void 837428d7b3dSmrguxa_push_pixels(GCPtr pGC, PixmapPtr pBitmap, 838428d7b3dSmrg DrawablePtr pDrawable, int w, int h, int x, int y) 839428d7b3dSmrg{ 840428d7b3dSmrg uxa_check_push_pixels(pGC, pBitmap, pDrawable, w, h, x, y); 841428d7b3dSmrg} 842428d7b3dSmrg 843428d7b3dSmrgconst GCOps uxa_ops = { 844428d7b3dSmrg uxa_fill_spans, 845428d7b3dSmrg uxa_set_spans, 846428d7b3dSmrg uxa_put_image, 847428d7b3dSmrg uxa_copy_area, 848428d7b3dSmrg uxa_copy_plane, 849428d7b3dSmrg uxa_poly_point, 850428d7b3dSmrg uxa_poly_lines, 851428d7b3dSmrg uxa_poly_segment, 852428d7b3dSmrg miPolyRectangle, 853428d7b3dSmrg uxa_check_poly_arc, 854428d7b3dSmrg miFillPolygon, 855428d7b3dSmrg uxa_poly_fill_rect, 856428d7b3dSmrg miPolyFillArc, 857428d7b3dSmrg miPolyText8, 858428d7b3dSmrg miPolyText16, 859428d7b3dSmrg miImageText8, 860428d7b3dSmrg miImageText16, 861428d7b3dSmrg uxa_image_glyph_blt, 862428d7b3dSmrg uxa_poly_glyph_blt, 863428d7b3dSmrg uxa_push_pixels, 864428d7b3dSmrg}; 865428d7b3dSmrg 866428d7b3dSmrgvoid uxa_copy_window(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 867428d7b3dSmrg{ 868428d7b3dSmrg RegionRec rgnDst; 869428d7b3dSmrg int dx, dy; 870428d7b3dSmrg PixmapPtr pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin); 871428d7b3dSmrg 872428d7b3dSmrg dx = ptOldOrg.x - pWin->drawable.x; 873428d7b3dSmrg dy = ptOldOrg.y - pWin->drawable.y; 874428d7b3dSmrg REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); 875428d7b3dSmrg 876428d7b3dSmrg REGION_INIT(pWin->drawable.pScreen, &rgnDst, NullBox, 0); 877428d7b3dSmrg 878428d7b3dSmrg REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, 879428d7b3dSmrg prgnSrc); 880428d7b3dSmrg#ifdef COMPOSITE 881428d7b3dSmrg if (pPixmap->screen_x || pPixmap->screen_y) 882428d7b3dSmrg REGION_TRANSLATE(pWin->drawable.pScreen, &rgnDst, 883428d7b3dSmrg -pPixmap->screen_x, -pPixmap->screen_y); 884428d7b3dSmrg#endif 885428d7b3dSmrg 886428d7b3dSmrg miCopyRegion(&pPixmap->drawable, &pPixmap->drawable, 887428d7b3dSmrg NULL, &rgnDst, dx, dy, uxa_copy_n_to_n, 0, NULL); 888428d7b3dSmrg 889428d7b3dSmrg REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); 890428d7b3dSmrg} 891428d7b3dSmrg 892428d7b3dSmrgstatic Bool 893428d7b3dSmrguxa_fill_region_solid(DrawablePtr pDrawable, 894428d7b3dSmrg RegionPtr pRegion, 895428d7b3dSmrg Pixel pixel, CARD32 planemask, CARD32 alu) 896428d7b3dSmrg{ 897428d7b3dSmrg ScreenPtr screen = pDrawable->pScreen; 898428d7b3dSmrg uxa_screen_t *uxa_screen = uxa_get_screen(screen); 899428d7b3dSmrg PixmapPtr pixmap; 900428d7b3dSmrg int xoff, yoff; 901428d7b3dSmrg int nbox; 902428d7b3dSmrg BoxPtr pBox; 903428d7b3dSmrg Bool ret = FALSE; 904428d7b3dSmrg 905428d7b3dSmrg pixmap = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff); 906428d7b3dSmrg if (!pixmap) 907428d7b3dSmrg return FALSE; 908428d7b3dSmrg 909428d7b3dSmrg REGION_TRANSLATE(screen, pRegion, xoff, yoff); 910428d7b3dSmrg 911428d7b3dSmrg nbox = REGION_NUM_RECTS(pRegion); 912428d7b3dSmrg pBox = REGION_RECTS(pRegion); 913428d7b3dSmrg 914428d7b3dSmrg if (uxa_screen->info->check_solid && 915428d7b3dSmrg !uxa_screen->info->check_solid(&pixmap->drawable, alu, planemask)) 916428d7b3dSmrg goto err; 917428d7b3dSmrg 918428d7b3dSmrg if (!uxa_screen->info->prepare_solid(pixmap, alu, planemask, pixel)) 919428d7b3dSmrg goto err; 920428d7b3dSmrg 921428d7b3dSmrg while (nbox--) { 922428d7b3dSmrg uxa_screen->info->solid(pixmap, 923428d7b3dSmrg pBox->x1, pBox->y1, 924428d7b3dSmrg pBox->x2, pBox->y2); 925428d7b3dSmrg pBox++; 926428d7b3dSmrg } 927428d7b3dSmrg uxa_screen->info->done_solid(pixmap); 928428d7b3dSmrg ret = TRUE; 929428d7b3dSmrg 930428d7b3dSmrgerr: 931428d7b3dSmrg REGION_TRANSLATE(screen, pRegion, -xoff, -yoff); 932428d7b3dSmrg return ret; 933428d7b3dSmrg} 934428d7b3dSmrg 935428d7b3dSmrg/* Try to do an accelerated tile of the pTile into pRegion of pDrawable. 936428d7b3dSmrg * Based on fbFillRegionTiled(), fbTile(). 937428d7b3dSmrg */ 938428d7b3dSmrgBool 939428d7b3dSmrguxa_fill_region_tiled(DrawablePtr pDrawable, 940428d7b3dSmrg RegionPtr pRegion, 941428d7b3dSmrg PixmapPtr pTile, 942428d7b3dSmrg DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu) 943428d7b3dSmrg{ 944428d7b3dSmrg uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen); 945428d7b3dSmrg PixmapPtr pPixmap; 946428d7b3dSmrg int xoff, yoff; 947428d7b3dSmrg int tileWidth, tileHeight; 948428d7b3dSmrg int nbox = REGION_NUM_RECTS(pRegion); 949428d7b3dSmrg BoxPtr pBox = REGION_RECTS(pRegion); 950428d7b3dSmrg Bool ret = FALSE; 951428d7b3dSmrg 952428d7b3dSmrg tileWidth = pTile->drawable.width; 953428d7b3dSmrg tileHeight = pTile->drawable.height; 954428d7b3dSmrg 955428d7b3dSmrg /* If we're filling with a solid color, grab it out and go to 956428d7b3dSmrg * FillRegionsolid, saving numerous copies. 957428d7b3dSmrg */ 958428d7b3dSmrg if (tileWidth == 1 && tileHeight == 1) 959428d7b3dSmrg return uxa_fill_region_solid(pDrawable, pRegion, 960428d7b3dSmrg uxa_get_pixmap_first_pixel(pTile), 961428d7b3dSmrg planemask, alu); 962428d7b3dSmrg 963428d7b3dSmrg pPixmap = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff); 964428d7b3dSmrg if (!pPixmap || !uxa_pixmap_is_offscreen(pTile)) 965428d7b3dSmrg goto out; 966428d7b3dSmrg 967428d7b3dSmrg if (uxa_screen->info->check_copy && 968428d7b3dSmrg !uxa_screen->info->check_copy(pTile, pPixmap, alu, planemask)) 969428d7b3dSmrg return FALSE; 970428d7b3dSmrg 971428d7b3dSmrg REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); 972428d7b3dSmrg 973428d7b3dSmrg if ((*uxa_screen->info->prepare_copy) (pTile, pPixmap, 1, 1, alu, 974428d7b3dSmrg planemask)) { 975428d7b3dSmrg while (nbox--) { 976428d7b3dSmrg int height = pBox->y2 - pBox->y1; 977428d7b3dSmrg int dstY = pBox->y1; 978428d7b3dSmrg int tileY; 979428d7b3dSmrg 980428d7b3dSmrg modulus(dstY - yoff - pDrawable->y - pPatOrg->y, 981428d7b3dSmrg tileHeight, tileY); 982428d7b3dSmrg 983428d7b3dSmrg while (height > 0) { 984428d7b3dSmrg int width = pBox->x2 - pBox->x1; 985428d7b3dSmrg int dstX = pBox->x1; 986428d7b3dSmrg int tileX; 987428d7b3dSmrg int h = tileHeight - tileY; 988428d7b3dSmrg 989428d7b3dSmrg if (h > height) 990428d7b3dSmrg h = height; 991428d7b3dSmrg height -= h; 992428d7b3dSmrg 993428d7b3dSmrg modulus(dstX - xoff - pDrawable->x - pPatOrg->x, 994428d7b3dSmrg tileWidth, tileX); 995428d7b3dSmrg 996428d7b3dSmrg while (width > 0) { 997428d7b3dSmrg int w = tileWidth - tileX; 998428d7b3dSmrg if (w > width) 999428d7b3dSmrg w = width; 1000428d7b3dSmrg width -= w; 1001428d7b3dSmrg 1002428d7b3dSmrg (*uxa_screen->info->copy) (pPixmap, 1003428d7b3dSmrg tileX, tileY, 1004428d7b3dSmrg dstX, dstY, 1005428d7b3dSmrg w, h); 1006428d7b3dSmrg dstX += w; 1007428d7b3dSmrg tileX = 0; 1008428d7b3dSmrg } 1009428d7b3dSmrg dstY += h; 1010428d7b3dSmrg tileY = 0; 1011428d7b3dSmrg } 1012428d7b3dSmrg pBox++; 1013428d7b3dSmrg } 1014428d7b3dSmrg (*uxa_screen->info->done_copy) (pPixmap); 1015428d7b3dSmrg 1016428d7b3dSmrg ret = TRUE; 1017428d7b3dSmrg } 1018428d7b3dSmrg 1019428d7b3dSmrgout: 1020428d7b3dSmrg REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); 1021428d7b3dSmrg 1022428d7b3dSmrg return ret; 1023428d7b3dSmrg} 1024428d7b3dSmrg 1025428d7b3dSmrg/** 1026428d7b3dSmrg * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory. 1027428d7b3dSmrg * 1028428d7b3dSmrg * This is probably the only case we actually care about. The rest fall through 1029428d7b3dSmrg * to migration and fbGetImage, which hopefully will result in migration pushing 1030428d7b3dSmrg * the pixmap out of framebuffer. 1031428d7b3dSmrg */ 1032428d7b3dSmrgvoid 1033428d7b3dSmrguxa_get_image(DrawablePtr pDrawable, int x, int y, int w, int h, 1034428d7b3dSmrg unsigned int format, unsigned long planeMask, char *d) 1035428d7b3dSmrg{ 1036428d7b3dSmrg ScreenPtr screen = pDrawable->pScreen; 1037428d7b3dSmrg uxa_screen_t *uxa_screen = uxa_get_screen(screen); 1038428d7b3dSmrg BoxRec Box; 1039428d7b3dSmrg PixmapPtr pPix = uxa_get_drawable_pixmap(pDrawable); 1040428d7b3dSmrg int xoff, yoff; 1041428d7b3dSmrg Bool ok; 1042428d7b3dSmrg 1043428d7b3dSmrg uxa_get_drawable_deltas(pDrawable, pPix, &xoff, &yoff); 1044428d7b3dSmrg 1045428d7b3dSmrg Box.x1 = pDrawable->y + x + xoff; 1046428d7b3dSmrg Box.y1 = pDrawable->y + y + yoff; 1047428d7b3dSmrg Box.x2 = Box.x1 + w; 1048428d7b3dSmrg Box.y2 = Box.y1 + h; 1049428d7b3dSmrg 1050428d7b3dSmrg if (uxa_screen->force_fallback) 1051428d7b3dSmrg goto fallback; 1052428d7b3dSmrg 1053428d7b3dSmrg pPix = uxa_get_offscreen_pixmap(pDrawable, &xoff, &yoff); 1054428d7b3dSmrg 1055428d7b3dSmrg if (pPix == NULL || uxa_screen->info->get_image == NULL) 1056428d7b3dSmrg goto fallback; 1057428d7b3dSmrg 1058428d7b3dSmrg /* Only cover the ZPixmap, solid copy case. */ 1059428d7b3dSmrg if (format != ZPixmap || !UXA_PM_IS_SOLID(pDrawable, planeMask)) 1060428d7b3dSmrg goto fallback; 1061428d7b3dSmrg 1062428d7b3dSmrg /* Only try to handle the 8bpp and up cases, since we don't want to 1063428d7b3dSmrg * think about <8bpp. 1064428d7b3dSmrg */ 1065428d7b3dSmrg if (pDrawable->bitsPerPixel < 8) 1066428d7b3dSmrg goto fallback; 1067428d7b3dSmrg 1068428d7b3dSmrg ok = uxa_screen->info->get_image(pPix, pDrawable->x + x + xoff, 1069428d7b3dSmrg pDrawable->y + y + yoff, w, h, d, 1070428d7b3dSmrg PixmapBytePad(w, pDrawable->depth)); 1071428d7b3dSmrg if (ok) 1072428d7b3dSmrg return; 1073428d7b3dSmrg 1074428d7b3dSmrgfallback: 1075428d7b3dSmrg UXA_FALLBACK(("from %p (%c)\n", pDrawable, 1076428d7b3dSmrg uxa_drawable_location(pDrawable))); 1077428d7b3dSmrg 1078428d7b3dSmrg if (uxa_prepare_access(pDrawable, UXA_ACCESS_RO)) { 1079428d7b3dSmrg fbGetImage(pDrawable, x, y, w, h, format, planeMask, d); 1080428d7b3dSmrg uxa_finish_access(pDrawable, UXA_ACCESS_RO); 1081428d7b3dSmrg } 1082428d7b3dSmrg 1083428d7b3dSmrg return; 1084428d7b3dSmrg} 1085