1fa225cbcSrjs/* 2fa225cbcSrjs * Copyright ® 2001 Keith Packard 3fa225cbcSrjs * 4fa225cbcSrjs * Partly based on code that is Copyright ® The XFree86 Project Inc. 5fa225cbcSrjs * 6fa225cbcSrjs * Permission to use, copy, modify, distribute, and sell this software and its 7fa225cbcSrjs * documentation for any purpose is hereby granted without fee, provided that 8fa225cbcSrjs * the above copyright notice appear in all copies and that both that 9fa225cbcSrjs * copyright notice and this permission notice appear in supporting 10fa225cbcSrjs * documentation, and that the name of Keith Packard not be used in 11fa225cbcSrjs * advertising or publicity pertaining to distribution of the software without 12fa225cbcSrjs * specific, written prior permission. Keith Packard makes no 13fa225cbcSrjs * representations about the suitability of this software for any purpose. It 14fa225cbcSrjs * is provided "as is" without express or implied warranty. 15fa225cbcSrjs * 16fa225cbcSrjs * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 17fa225cbcSrjs * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 18fa225cbcSrjs * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 19fa225cbcSrjs * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 20fa225cbcSrjs * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 21fa225cbcSrjs * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22fa225cbcSrjs * PERFORMANCE OF THIS SOFTWARE. 23fa225cbcSrjs * 24fa225cbcSrjs * Authors: 25fa225cbcSrjs * Eric Anholt <eric@anholt.net> 26fa225cbcSrjs * Michel Dänzer <michel@tungstengraphics.com> 27fa225cbcSrjs * 28fa225cbcSrjs */ 29fa225cbcSrjs 30fa225cbcSrjs#ifdef HAVE_DIX_CONFIG_H 31fa225cbcSrjs#include <dix-config.h> 32fa225cbcSrjs#endif 33fa225cbcSrjs#include "uxa-priv.h" 34fa225cbcSrjs#include <X11/fonts/fontstruct.h> 35fa225cbcSrjs#include "dixfontstr.h" 36fa225cbcSrjs#include "uxa.h" 37fa225cbcSrjs 38fa225cbcSrjsstatic void 39fa225cbcSrjsuxa_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n, 40fa225cbcSrjs DDXPointPtr ppt, int *pwidth, int fSorted) 41fa225cbcSrjs{ 42fa225cbcSrjs ScreenPtr pScreen = pDrawable->pScreen; 43fa225cbcSrjs uxa_screen_t *uxa_screen = uxa_get_screen(pScreen); 44fa225cbcSrjs RegionPtr pClip = fbGetCompositeClip(pGC); 45fa225cbcSrjs PixmapPtr pPixmap = uxa_get_drawable_pixmap (pDrawable); 46fa225cbcSrjs BoxPtr pextent, pbox; 47fa225cbcSrjs int nbox; 48fa225cbcSrjs int extentX1, extentX2, extentY1, extentY2; 49fa225cbcSrjs int fullX1, fullX2, fullY1; 50fa225cbcSrjs int partX1, partX2; 51fa225cbcSrjs int off_x, off_y; 52fa225cbcSrjs 53fa225cbcSrjs if (uxa_screen->swappedOut || pGC->fillStyle != FillSolid || 54fa225cbcSrjs !(pPixmap = uxa_get_offscreen_pixmap (pDrawable, &off_x, &off_y)) || 55fa225cbcSrjs !(*uxa_screen->info->prepare_solid) (pPixmap, 56fa225cbcSrjs pGC->alu, 57fa225cbcSrjs pGC->planemask, 58fa225cbcSrjs pGC->fgPixel)) 59fa225cbcSrjs { 60fa225cbcSrjs uxa_check_fill_spans (pDrawable, pGC, n, ppt, pwidth, fSorted); 61fa225cbcSrjs return; 62fa225cbcSrjs } 63fa225cbcSrjs 64fa225cbcSrjs pextent = REGION_EXTENTS(pGC->pScreen, pClip); 65fa225cbcSrjs extentX1 = pextent->x1; 66fa225cbcSrjs extentY1 = pextent->y1; 67fa225cbcSrjs extentX2 = pextent->x2; 68fa225cbcSrjs extentY2 = pextent->y2; 69fa225cbcSrjs while (n--) 70fa225cbcSrjs { 71fa225cbcSrjs fullX1 = ppt->x; 72fa225cbcSrjs fullY1 = ppt->y; 73fa225cbcSrjs fullX2 = fullX1 + (int) *pwidth; 74fa225cbcSrjs ppt++; 75fa225cbcSrjs pwidth++; 76fa225cbcSrjs 77fa225cbcSrjs if (fullY1 < extentY1 || extentY2 <= fullY1) 78fa225cbcSrjs continue; 79fa225cbcSrjs 80fa225cbcSrjs if (fullX1 < extentX1) 81fa225cbcSrjs fullX1 = extentX1; 82fa225cbcSrjs 83fa225cbcSrjs if (fullX2 > extentX2) 84fa225cbcSrjs fullX2 = extentX2; 85fa225cbcSrjs 86fa225cbcSrjs if (fullX1 >= fullX2) 87fa225cbcSrjs continue; 88fa225cbcSrjs 89fa225cbcSrjs nbox = REGION_NUM_RECTS (pClip); 90fa225cbcSrjs if (nbox == 1) 91fa225cbcSrjs { 92fa225cbcSrjs (*uxa_screen->info->solid) (pPixmap, 93fa225cbcSrjs fullX1 + off_x, fullY1 + off_y, 94fa225cbcSrjs fullX2 + off_x, fullY1 + 1 + off_y); 95fa225cbcSrjs } 96fa225cbcSrjs else 97fa225cbcSrjs { 98fa225cbcSrjs pbox = REGION_RECTS(pClip); 99fa225cbcSrjs while(nbox--) 100fa225cbcSrjs { 101fa225cbcSrjs if (pbox->y1 <= fullY1 && fullY1 < pbox->y2) 102fa225cbcSrjs { 103fa225cbcSrjs partX1 = pbox->x1; 104fa225cbcSrjs if (partX1 < fullX1) 105fa225cbcSrjs partX1 = fullX1; 106fa225cbcSrjs partX2 = pbox->x2; 107fa225cbcSrjs if (partX2 > fullX2) 108fa225cbcSrjs partX2 = fullX2; 109fa225cbcSrjs if (partX2 > partX1) { 110fa225cbcSrjs (*uxa_screen->info->solid) (pPixmap, 111fa225cbcSrjs partX1 + off_x, fullY1 + off_y, 112fa225cbcSrjs partX2 + off_x, fullY1 + 1 + off_y); 113fa225cbcSrjs } 114fa225cbcSrjs } 115fa225cbcSrjs pbox++; 116fa225cbcSrjs } 117fa225cbcSrjs } 118fa225cbcSrjs } 119fa225cbcSrjs (*uxa_screen->info->done_solid) (pPixmap); 120fa225cbcSrjs} 121fa225cbcSrjs 122fa225cbcSrjsstatic Bool 123fa225cbcSrjsuxa_do_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, 124fa225cbcSrjs int w, int h, int format, char *bits, int src_stride) 125fa225cbcSrjs{ 126fa225cbcSrjs uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen); 127fa225cbcSrjs PixmapPtr pPix = uxa_get_drawable_pixmap (pDrawable); 128fa225cbcSrjs RegionPtr pClip; 129fa225cbcSrjs BoxPtr pbox; 130fa225cbcSrjs int nbox; 131fa225cbcSrjs int xoff, yoff; 132fa225cbcSrjs int bpp = pDrawable->bitsPerPixel; 133fa225cbcSrjs Bool access_prepared = FALSE; 134fa225cbcSrjs 135fa225cbcSrjs /* Don't bother with under 8bpp, XYPixmaps. */ 136fa225cbcSrjs if (format != ZPixmap || bpp < 8) 137fa225cbcSrjs return FALSE; 138fa225cbcSrjs 139fa225cbcSrjs /* Only accelerate copies: no rop or planemask. */ 140fa225cbcSrjs if (!UXA_PM_IS_SOLID(pDrawable, pGC->planemask) || pGC->alu != GXcopy) 141fa225cbcSrjs return FALSE; 142fa225cbcSrjs 143fa225cbcSrjs if (uxa_screen->swappedOut) 144fa225cbcSrjs return FALSE; 145fa225cbcSrjs 146fa225cbcSrjs pPix = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff); 147fa225cbcSrjs 148fa225cbcSrjs if (!pPix || !uxa_screen->info->put_image) 149fa225cbcSrjs return FALSE; 150fa225cbcSrjs 151fa225cbcSrjs x += pDrawable->x; 152fa225cbcSrjs y += pDrawable->y; 153fa225cbcSrjs 154fa225cbcSrjs pClip = fbGetCompositeClip(pGC); 155fa225cbcSrjs for (nbox = REGION_NUM_RECTS(pClip), 156fa225cbcSrjs pbox = REGION_RECTS(pClip); 157fa225cbcSrjs nbox--; 158fa225cbcSrjs pbox++) 159fa225cbcSrjs { 160fa225cbcSrjs int x1 = x; 161fa225cbcSrjs int y1 = y; 162fa225cbcSrjs int x2 = x + w; 163fa225cbcSrjs int y2 = y + h; 164fa225cbcSrjs char *src; 165fa225cbcSrjs Bool ok; 166fa225cbcSrjs 167fa225cbcSrjs if (x1 < pbox->x1) 168fa225cbcSrjs x1 = pbox->x1; 169fa225cbcSrjs if (y1 < pbox->y1) 170fa225cbcSrjs y1 = pbox->y1; 171fa225cbcSrjs if (x2 > pbox->x2) 172fa225cbcSrjs x2 = pbox->x2; 173fa225cbcSrjs if (y2 > pbox->y2) 174fa225cbcSrjs y2 = pbox->y2; 175fa225cbcSrjs if (x1 >= x2 || y1 >= y2) 176fa225cbcSrjs continue; 177fa225cbcSrjs 178fa225cbcSrjs src = bits + (y1 - y) * src_stride + (x1 - x) * (bpp / 8); 179fa225cbcSrjs ok = uxa_screen->info->put_image(pPix, x1 + xoff, y1 + yoff, 180fa225cbcSrjs x2 - x1, y2 - y1, src, src_stride); 181fa225cbcSrjs /* If we fail to accelerate the upload, fall back to using unaccelerated 182fa225cbcSrjs * fb calls. 183fa225cbcSrjs */ 184fa225cbcSrjs if (!ok) { 185fa225cbcSrjs FbStip *dst; 186fa225cbcSrjs FbStride dst_stride; 187fa225cbcSrjs int dstBpp; 188fa225cbcSrjs int dstXoff, dstYoff; 189fa225cbcSrjs 190fa225cbcSrjs if (!access_prepared) { 191fa225cbcSrjs if (!uxa_prepare_access(pDrawable, UXA_ACCESS_RW)) 192fa225cbcSrjs return FALSE; 193fa225cbcSrjs access_prepared = TRUE; 194fa225cbcSrjs } 195fa225cbcSrjs 196fa225cbcSrjs fbGetStipDrawable(pDrawable, dst, dst_stride, dstBpp, 197fa225cbcSrjs dstXoff, dstYoff); 198fa225cbcSrjs 199fa225cbcSrjs fbBltStip((FbStip *)bits + (y1 - y) * (src_stride / sizeof(FbStip)), 200fa225cbcSrjs src_stride / sizeof(FbStip), 201fa225cbcSrjs (x1 - x) * dstBpp, 202fa225cbcSrjs dst + (y1 + dstYoff) * dst_stride, 203fa225cbcSrjs dst_stride, 204fa225cbcSrjs (x1 + dstXoff) * dstBpp, 205fa225cbcSrjs (x2 - x1) * dstBpp, 206fa225cbcSrjs y2 - y1, 207fa225cbcSrjs GXcopy, FB_ALLONES, dstBpp); 208fa225cbcSrjs } 209fa225cbcSrjs } 210fa225cbcSrjs 211fa225cbcSrjs if (access_prepared) 212fa225cbcSrjs uxa_finish_access(pDrawable); 213fa225cbcSrjs 214fa225cbcSrjs return TRUE; 215fa225cbcSrjs} 216fa225cbcSrjs 217fa225cbcSrjs#ifdef MITSHM 218fa225cbcSrjs 219fa225cbcSrjs#include "xorgVersion.h" 220fa225cbcSrjs 221fa225cbcSrjsstatic Bool 222fa225cbcSrjsuxa_do_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, 223fa225cbcSrjs unsigned int format, int w, int h, int sx, int sy, int sw, 224fa225cbcSrjs int sh, int dx, int dy, char *data) 225fa225cbcSrjs{ 226fa225cbcSrjs int src_stride = PixmapBytePad(w, depth); 227fa225cbcSrjs 228fa225cbcSrjs if (uxa_do_put_image(pDrawable, pGC, depth, dx, dy, sw, sh, format, data + 229fa225cbcSrjs sy * src_stride + sx * BitsPerPixel(depth) / 8, 230fa225cbcSrjs src_stride)) 231fa225cbcSrjs return TRUE; 232fa225cbcSrjs 233fa225cbcSrjs if (format == ZPixmap) 234fa225cbcSrjs { 235fa225cbcSrjs PixmapPtr pPixmap; 236fa225cbcSrjs 237fa225cbcSrjs pPixmap = GetScratchPixmapHeader(pDrawable->pScreen, w, h, depth, 238fa225cbcSrjs BitsPerPixel(depth), PixmapBytePad(w, depth), 239fa225cbcSrjs (pointer)data); 240fa225cbcSrjs if (!pPixmap) 241fa225cbcSrjs return FALSE; 242fa225cbcSrjs 243fa225cbcSrjs if (!uxa_prepare_access (pDrawable, UXA_ACCESS_RW)) 244fa225cbcSrjs return FALSE; 245fa225cbcSrjs fbCopyArea((DrawablePtr)pPixmap, pDrawable, pGC, sx, sy, sw, sh, dx, dy); 246fa225cbcSrjs uxa_finish_access(pDrawable); 247fa225cbcSrjs 248fa225cbcSrjs FreeScratchPixmapHeader(pPixmap); 249fa225cbcSrjs 250fa225cbcSrjs return TRUE; 251fa225cbcSrjs } 252fa225cbcSrjs 253fa225cbcSrjs return FALSE; 254fa225cbcSrjs} 255fa225cbcSrjs 256fa225cbcSrjs#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,5,99,0,0) 257fa225cbcSrjs 258fa225cbcSrjs/* The actual ShmPutImage isn't wrapped by the damage layer, so we need to 259fa225cbcSrjs * inform any interested parties of the damage incurred to the drawable. 260fa225cbcSrjs * 261fa225cbcSrjs * We also need to set the pending damage to ensure correct migration in all 262fa225cbcSrjs * cases. 263fa225cbcSrjs */ 264fa225cbcSrjsvoid 265fa225cbcSrjsuxa_shm_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, unsigned int format, 266fa225cbcSrjs int w, int h, int sx, int sy, int sw, int sh, int dx, int dy, 267fa225cbcSrjs char *data) 268fa225cbcSrjs{ 269fa225cbcSrjs if (!uxa_do_shm_put_image(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh, 270fa225cbcSrjs dx, dy, data)) { 271fa225cbcSrjs if (!uxa_prepare_access (pDrawable, UXA_ACCESS_RW)) 272fa225cbcSrjs return; 273fa225cbcSrjs fbShmPutImage(pDrawable, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, 274fa225cbcSrjs data); 275fa225cbcSrjs uxa_finish_access(pDrawable); 276fa225cbcSrjs } 277fa225cbcSrjs} 278fa225cbcSrjs#else 279fa225cbcSrjs#define uxa_shm_put_image NULL 280fa225cbcSrjs#endif 281fa225cbcSrjs 282fa225cbcSrjsShmFuncs uxa_shm_funcs = { NULL, uxa_shm_put_image }; 283fa225cbcSrjs 284fa225cbcSrjs#endif 285fa225cbcSrjs 286fa225cbcSrjsstatic void 287fa225cbcSrjsuxa_put_image (DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y, 288fa225cbcSrjs int w, int h, int leftPad, int format, char *bits) 289fa225cbcSrjs{ 290fa225cbcSrjs#ifdef MITSHM 291fa225cbcSrjs if (!uxa_do_shm_put_image(pDrawable, pGC, depth, format, w, h, 0, 0, w, h, x, y, 292fa225cbcSrjs bits)) 293fa225cbcSrjs#else 294fa225cbcSrjs if (!uxa_do_put_image(pDrawable, pGC, depth, x, y, w, h, format, bits, 295fa225cbcSrjs PixmapBytePad(w, pDrawable->depth))) 296fa225cbcSrjs#endif 297fa225cbcSrjs uxa_check_put_image(pDrawable, pGC, depth, x, y, w, h, leftPad, format, 298fa225cbcSrjs bits); 299fa225cbcSrjs} 300fa225cbcSrjs 301fa225cbcSrjsstatic Bool inline 302fa225cbcSrjsuxa_copy_n_to_n_two_dir (DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, 303fa225cbcSrjs GCPtr pGC, BoxPtr pbox, int nbox, int dx, int dy) 304fa225cbcSrjs{ 305fa225cbcSrjs uxa_screen_t *uxa_screen = uxa_get_screen(pDstDrawable->pScreen); 306fa225cbcSrjs PixmapPtr pSrcPixmap, pDstPixmap; 307fa225cbcSrjs int src_off_x, src_off_y, dst_off_x, dst_off_y; 308fa225cbcSrjs int dirsetup; 309fa225cbcSrjs 310fa225cbcSrjs /* Need to get both pixmaps to call the driver routines */ 311fa225cbcSrjs pSrcPixmap = uxa_get_offscreen_pixmap (pSrcDrawable, &src_off_x, &src_off_y); 312fa225cbcSrjs pDstPixmap = uxa_get_offscreen_pixmap (pDstDrawable, &dst_off_x, &dst_off_y); 313fa225cbcSrjs if (!pSrcPixmap || !pDstPixmap) 314fa225cbcSrjs return FALSE; 315fa225cbcSrjs 316fa225cbcSrjs /* 317fa225cbcSrjs * Now the case of a chip that only supports xdir = ydir = 1 or 318fa225cbcSrjs * xdir = ydir = -1, but we have xdir != ydir. 319fa225cbcSrjs */ 320fa225cbcSrjs dirsetup = 0; /* No direction set up yet. */ 321fa225cbcSrjs for (; nbox; pbox++, nbox--) { 322fa225cbcSrjs if (dx >= 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) { 323fa225cbcSrjs /* Do a xdir = ydir = -1 blit instead. */ 324fa225cbcSrjs if (dirsetup != -1) { 325fa225cbcSrjs if (dirsetup != 0) 326fa225cbcSrjs uxa_screen->info->done_copy(pDstPixmap); 327fa225cbcSrjs dirsetup = -1; 328fa225cbcSrjs if (!(*uxa_screen->info->prepare_copy)(pSrcPixmap, 329fa225cbcSrjs pDstPixmap, 330fa225cbcSrjs -1, -1, 331fa225cbcSrjs pGC ? pGC->alu : GXcopy, 332fa225cbcSrjs pGC ? pGC->planemask : 333fa225cbcSrjs FB_ALLONES)) 334fa225cbcSrjs return FALSE; 335fa225cbcSrjs } 336fa225cbcSrjs (*uxa_screen->info->copy)(pDstPixmap, 337fa225cbcSrjs src_off_x + pbox->x1 + dx, 338fa225cbcSrjs src_off_y + pbox->y1 + dy, 339fa225cbcSrjs dst_off_x + pbox->x1, 340fa225cbcSrjs dst_off_y + pbox->y1, 341fa225cbcSrjs pbox->x2 - pbox->x1, 342fa225cbcSrjs pbox->y2 - pbox->y1); 343fa225cbcSrjs } else if (dx < 0 && (src_off_y + pbox->y1 + dy) != pbox->y1) { 344fa225cbcSrjs /* Do a xdir = ydir = 1 blit instead. */ 345fa225cbcSrjs if (dirsetup != 1) { 346fa225cbcSrjs if (dirsetup != 0) 347fa225cbcSrjs uxa_screen->info->done_copy(pDstPixmap); 348fa225cbcSrjs dirsetup = 1; 349fa225cbcSrjs if (!(*uxa_screen->info->prepare_copy)(pSrcPixmap, 350fa225cbcSrjs pDstPixmap, 351fa225cbcSrjs 1, 1, 352fa225cbcSrjs pGC ? pGC->alu : GXcopy, 353fa225cbcSrjs pGC ? pGC->planemask : 354fa225cbcSrjs FB_ALLONES)) 355fa225cbcSrjs return FALSE; 356fa225cbcSrjs } 357fa225cbcSrjs (*uxa_screen->info->copy)(pDstPixmap, 358fa225cbcSrjs src_off_x + pbox->x1 + dx, 359fa225cbcSrjs src_off_y + pbox->y1 + dy, 360fa225cbcSrjs dst_off_x + pbox->x1, 361fa225cbcSrjs dst_off_y + pbox->y1, 362fa225cbcSrjs pbox->x2 - pbox->x1, 363fa225cbcSrjs pbox->y2 - pbox->y1); 364fa225cbcSrjs } else if (dx >= 0) { 365fa225cbcSrjs /* 366fa225cbcSrjs * xdir = 1, ydir = -1. 367fa225cbcSrjs * Perform line-by-line xdir = ydir = 1 blits, going up. 368fa225cbcSrjs */ 369fa225cbcSrjs int i; 370fa225cbcSrjs if (dirsetup != 1) { 371fa225cbcSrjs if (dirsetup != 0) 372fa225cbcSrjs uxa_screen->info->done_copy(pDstPixmap); 373fa225cbcSrjs dirsetup = 1; 374fa225cbcSrjs if (!(*uxa_screen->info->prepare_copy)(pSrcPixmap, 375fa225cbcSrjs pDstPixmap, 376fa225cbcSrjs 1, 1, 377fa225cbcSrjs pGC ? pGC->alu : GXcopy, 378fa225cbcSrjs pGC ? pGC->planemask : 379fa225cbcSrjs FB_ALLONES)) 380fa225cbcSrjs return FALSE; 381fa225cbcSrjs } 382fa225cbcSrjs for (i = pbox->y2 - pbox->y1 - 1; i >= 0; i--) 383fa225cbcSrjs (*uxa_screen->info->copy)(pDstPixmap, 384fa225cbcSrjs src_off_x + pbox->x1 + dx, 385fa225cbcSrjs src_off_y + pbox->y1 + dy + i, 386fa225cbcSrjs dst_off_x + pbox->x1, 387fa225cbcSrjs dst_off_y + pbox->y1 + i, 388fa225cbcSrjs pbox->x2 - pbox->x1, 1); 389fa225cbcSrjs } else { 390fa225cbcSrjs /* 391fa225cbcSrjs * xdir = -1, ydir = 1. 392fa225cbcSrjs * Perform line-by-line xdir = ydir = -1 blits, going down. 393fa225cbcSrjs */ 394fa225cbcSrjs int i; 395fa225cbcSrjs if (dirsetup != -1) { 396fa225cbcSrjs if (dirsetup != 0) 397fa225cbcSrjs uxa_screen->info->done_copy(pDstPixmap); 398fa225cbcSrjs dirsetup = -1; 399fa225cbcSrjs if (!(*uxa_screen->info->prepare_copy)(pSrcPixmap, 400fa225cbcSrjs pDstPixmap, 401fa225cbcSrjs -1, -1, 402fa225cbcSrjs pGC ? pGC->alu : GXcopy, 403fa225cbcSrjs pGC ? pGC->planemask : 404fa225cbcSrjs FB_ALLONES)) 405fa225cbcSrjs return FALSE; 406fa225cbcSrjs } 407fa225cbcSrjs for (i = 0; i < pbox->y2 - pbox->y1; i++) 408fa225cbcSrjs (*uxa_screen->info->copy)(pDstPixmap, 409fa225cbcSrjs src_off_x + pbox->x1 + dx, 410fa225cbcSrjs src_off_y + pbox->y1 + dy + i, 411fa225cbcSrjs dst_off_x + pbox->x1, 412fa225cbcSrjs dst_off_y + pbox->y1 + i, 413fa225cbcSrjs pbox->x2 - pbox->x1, 1); 414fa225cbcSrjs } 415fa225cbcSrjs } 416fa225cbcSrjs if (dirsetup != 0) 417fa225cbcSrjs uxa_screen->info->done_copy(pDstPixmap); 418fa225cbcSrjs return TRUE; 419fa225cbcSrjs} 420fa225cbcSrjs 421fa225cbcSrjsvoid 422fa225cbcSrjsuxa_copy_n_to_n (DrawablePtr pSrcDrawable, 423fa225cbcSrjs DrawablePtr pDstDrawable, 424fa225cbcSrjs GCPtr pGC, 425fa225cbcSrjs BoxPtr pbox, 426fa225cbcSrjs int nbox, 427fa225cbcSrjs int dx, 428fa225cbcSrjs int dy, 429fa225cbcSrjs Bool reverse, 430fa225cbcSrjs Bool upsidedown, 431fa225cbcSrjs Pixel bitplane, 432fa225cbcSrjs void *closure) 433fa225cbcSrjs{ 434fa225cbcSrjs ScreenPtr screen = pDstDrawable->pScreen; 435fa225cbcSrjs uxa_screen_t *uxa_screen = uxa_get_screen(screen); 436fa225cbcSrjs int src_off_x, src_off_y; 437fa225cbcSrjs int dst_off_x, dst_off_y; 438fa225cbcSrjs PixmapPtr pSrcPixmap, pDstPixmap; 439fa225cbcSrjs 440fa225cbcSrjs pSrcPixmap = uxa_get_drawable_pixmap (pSrcDrawable); 441fa225cbcSrjs pDstPixmap = uxa_get_drawable_pixmap (pDstDrawable); 442fa225cbcSrjs 443fa225cbcSrjs uxa_get_drawable_deltas (pSrcDrawable, pSrcPixmap, &src_off_x, &src_off_y); 444fa225cbcSrjs uxa_get_drawable_deltas (pDstDrawable, pDstPixmap, &dst_off_x, &dst_off_y); 445fa225cbcSrjs 446fa225cbcSrjs /* Mixed directions must be handled specially if the card is lame */ 447fa225cbcSrjs if ((uxa_screen->info->flags & UXA_TWO_BITBLT_DIRECTIONS) && 448fa225cbcSrjs reverse != upsidedown) { 449fa225cbcSrjs if (uxa_copy_n_to_n_two_dir(pSrcDrawable, pDstDrawable, pGC, pbox, nbox, 450fa225cbcSrjs dx, dy)) 451fa225cbcSrjs return; 452fa225cbcSrjs goto fallback; 453fa225cbcSrjs } 454fa225cbcSrjs 455fa225cbcSrjs if (!uxa_pixmap_is_offscreen(pSrcPixmap) || 456fa225cbcSrjs !uxa_pixmap_is_offscreen(pDstPixmap) || 457fa225cbcSrjs !(*uxa_screen->info->prepare_copy) (pSrcPixmap, pDstPixmap, reverse ? -1 : 1, 458fa225cbcSrjs upsidedown ? -1 : 1, 459fa225cbcSrjs pGC ? pGC->alu : GXcopy, 460fa225cbcSrjs pGC ? pGC->planemask : FB_ALLONES)) { 461fa225cbcSrjs goto fallback; 462fa225cbcSrjs } 463fa225cbcSrjs 464fa225cbcSrjs while (nbox--) 465fa225cbcSrjs { 466fa225cbcSrjs (*uxa_screen->info->copy) (pDstPixmap, 467fa225cbcSrjs pbox->x1 + dx + src_off_x, 468fa225cbcSrjs pbox->y1 + dy + src_off_y, 469fa225cbcSrjs pbox->x1 + dst_off_x, pbox->y1 + dst_off_y, 470fa225cbcSrjs pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); 471fa225cbcSrjs pbox++; 472fa225cbcSrjs } 473fa225cbcSrjs 474fa225cbcSrjs (*uxa_screen->info->done_copy) (pDstPixmap); 475fa225cbcSrjs 476fa225cbcSrjs return; 477fa225cbcSrjs 478fa225cbcSrjsfallback: 479fa225cbcSrjs UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable, 480fa225cbcSrjs uxa_drawable_location(pSrcDrawable), 481fa225cbcSrjs uxa_drawable_location(pDstDrawable))); 482fa225cbcSrjs if (uxa_prepare_access (pDstDrawable, UXA_ACCESS_RW)) { 483fa225cbcSrjs if (uxa_prepare_access (pSrcDrawable, UXA_ACCESS_RO)) { 484fa225cbcSrjs fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, 485fa225cbcSrjs reverse, upsidedown, bitplane, closure); 486fa225cbcSrjs uxa_finish_access (pSrcDrawable); 487fa225cbcSrjs } 488fa225cbcSrjs uxa_finish_access (pDstDrawable); 489fa225cbcSrjs } 490fa225cbcSrjs} 491fa225cbcSrjs 492fa225cbcSrjsRegionPtr 493fa225cbcSrjsuxa_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC, 494fa225cbcSrjs int srcx, int srcy, int width, int height, int dstx, int dsty) 495fa225cbcSrjs{ 496fa225cbcSrjs uxa_screen_t *uxa_screen = uxa_get_screen(pDstDrawable->pScreen); 497fa225cbcSrjs 498fa225cbcSrjs if (uxa_screen->swappedOut) { 499fa225cbcSrjs return uxa_check_copy_area(pSrcDrawable, pDstDrawable, pGC, 500fa225cbcSrjs srcx, srcy, width, height, dstx, dsty); 501fa225cbcSrjs } 502fa225cbcSrjs 503fa225cbcSrjs return miDoCopy (pSrcDrawable, pDstDrawable, pGC, 504fa225cbcSrjs srcx, srcy, width, height, 505fa225cbcSrjs dstx, dsty, uxa_copy_n_to_n, 0, NULL); 506fa225cbcSrjs} 507fa225cbcSrjs 508fa225cbcSrjsstatic void 509fa225cbcSrjsuxa_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, 510fa225cbcSrjs DDXPointPtr ppt) 511fa225cbcSrjs{ 512fa225cbcSrjs int i; 513fa225cbcSrjs xRectangle *prect; 514fa225cbcSrjs 515fa225cbcSrjs /* If we can't reuse the current GC as is, don't bother accelerating the 516fa225cbcSrjs * points. 517fa225cbcSrjs */ 518fa225cbcSrjs if (pGC->fillStyle != FillSolid) { 519fa225cbcSrjs uxa_check_poly_point(pDrawable, pGC, mode, npt, ppt); 520fa225cbcSrjs return; 521fa225cbcSrjs } 522fa225cbcSrjs 523fa225cbcSrjs prect = xalloc(sizeof(xRectangle) * npt); 524fa225cbcSrjs if (!prect) 525fa225cbcSrjs return; 526fa225cbcSrjs for (i = 0; i < npt; i++) { 527fa225cbcSrjs prect[i].x = ppt[i].x; 528fa225cbcSrjs prect[i].y = ppt[i].y; 529fa225cbcSrjs if (i > 0 && mode == CoordModePrevious) { 530fa225cbcSrjs prect[i].x += prect[i - 1].x; 531fa225cbcSrjs prect[i].y += prect[i - 1].y; 532fa225cbcSrjs } 533fa225cbcSrjs prect[i].width = 1; 534fa225cbcSrjs prect[i].height = 1; 535fa225cbcSrjs } 536fa225cbcSrjs pGC->ops->PolyFillRect(pDrawable, pGC, npt, prect); 537fa225cbcSrjs xfree(prect); 538fa225cbcSrjs} 539fa225cbcSrjs 540fa225cbcSrjs/** 541fa225cbcSrjs * uxa_poly_lines() checks if it can accelerate the lines as a group of 542fa225cbcSrjs * horizontal or vertical lines (rectangles), and uses existing rectangle fill 543fa225cbcSrjs * acceleration if so. 544fa225cbcSrjs */ 545fa225cbcSrjsstatic void 546fa225cbcSrjsuxa_poly_lines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt, 547fa225cbcSrjs DDXPointPtr ppt) 548fa225cbcSrjs{ 549fa225cbcSrjs xRectangle *prect; 550fa225cbcSrjs int x1, x2, y1, y2; 551fa225cbcSrjs int i; 552fa225cbcSrjs 553fa225cbcSrjs /* Don't try to do wide lines or non-solid fill style. */ 554fa225cbcSrjs if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid || 555fa225cbcSrjs pGC->fillStyle != FillSolid) { 556fa225cbcSrjs uxa_check_poly_lines(pDrawable, pGC, mode, npt, ppt); 557fa225cbcSrjs return; 558fa225cbcSrjs } 559fa225cbcSrjs 560fa225cbcSrjs prect = xalloc(sizeof(xRectangle) * (npt - 1)); 561fa225cbcSrjs if (!prect) 562fa225cbcSrjs return; 563fa225cbcSrjs x1 = ppt[0].x; 564fa225cbcSrjs y1 = ppt[0].y; 565fa225cbcSrjs /* If we have any non-horizontal/vertical, fall back. */ 566fa225cbcSrjs for (i = 0; i < npt - 1; i++) { 567fa225cbcSrjs if (mode == CoordModePrevious) { 568fa225cbcSrjs x2 = x1 + ppt[i + 1].x; 569fa225cbcSrjs y2 = y1 + ppt[i + 1].y; 570fa225cbcSrjs } else { 571fa225cbcSrjs x2 = ppt[i + 1].x; 572fa225cbcSrjs y2 = ppt[i + 1].y; 573fa225cbcSrjs } 574fa225cbcSrjs 575fa225cbcSrjs if (x1 != x2 && y1 != y2) { 576fa225cbcSrjs xfree(prect); 577fa225cbcSrjs uxa_check_poly_lines(pDrawable, pGC, mode, npt, ppt); 578fa225cbcSrjs return; 579fa225cbcSrjs } 580fa225cbcSrjs 581fa225cbcSrjs if (x1 < x2) { 582fa225cbcSrjs prect[i].x = x1; 583fa225cbcSrjs prect[i].width = x2 - x1 + 1; 584fa225cbcSrjs } else { 585fa225cbcSrjs prect[i].x = x2; 586fa225cbcSrjs prect[i].width = x1 - x2 + 1; 587fa225cbcSrjs } 588fa225cbcSrjs if (y1 < y2) { 589fa225cbcSrjs prect[i].y = y1; 590fa225cbcSrjs prect[i].height = y2 - y1 + 1; 591fa225cbcSrjs } else { 592fa225cbcSrjs prect[i].y = y2; 593fa225cbcSrjs prect[i].height = y1 - y2 + 1; 594fa225cbcSrjs } 595fa225cbcSrjs 596fa225cbcSrjs x1 = x2; 597fa225cbcSrjs y1 = y2; 598fa225cbcSrjs } 599fa225cbcSrjs pGC->ops->PolyFillRect(pDrawable, pGC, npt - 1, prect); 600fa225cbcSrjs xfree(prect); 601fa225cbcSrjs} 602fa225cbcSrjs 603fa225cbcSrjs/** 604fa225cbcSrjs * uxa_poly_segment() checks if it can accelerate the lines as a group of 605fa225cbcSrjs * horizontal or vertical lines (rectangles), and uses existing rectangle fill 606fa225cbcSrjs * acceleration if so. 607fa225cbcSrjs */ 608fa225cbcSrjsstatic void 609fa225cbcSrjsuxa_poly_segment (DrawablePtr pDrawable, GCPtr pGC, int nseg, 610fa225cbcSrjs xSegment *pSeg) 611fa225cbcSrjs{ 612fa225cbcSrjs xRectangle *prect; 613fa225cbcSrjs int i; 614fa225cbcSrjs 615fa225cbcSrjs /* Don't try to do wide lines or non-solid fill style. */ 616fa225cbcSrjs if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid || 617fa225cbcSrjs pGC->fillStyle != FillSolid) 618fa225cbcSrjs { 619fa225cbcSrjs uxa_check_poly_segment(pDrawable, pGC, nseg, pSeg); 620fa225cbcSrjs return; 621fa225cbcSrjs } 622fa225cbcSrjs 623fa225cbcSrjs /* If we have any non-horizontal/vertical, fall back. */ 624fa225cbcSrjs for (i = 0; i < nseg; i++) { 625fa225cbcSrjs if (pSeg[i].x1 != pSeg[i].x2 && pSeg[i].y1 != pSeg[i].y2) { 626fa225cbcSrjs uxa_check_poly_segment(pDrawable, pGC, nseg, pSeg); 627fa225cbcSrjs return; 628fa225cbcSrjs } 629fa225cbcSrjs } 630fa225cbcSrjs 631fa225cbcSrjs prect = xalloc(sizeof(xRectangle) * nseg); 632fa225cbcSrjs if (!prect) 633fa225cbcSrjs return; 634fa225cbcSrjs for (i = 0; i < nseg; i++) { 635fa225cbcSrjs if (pSeg[i].x1 < pSeg[i].x2) { 636fa225cbcSrjs prect[i].x = pSeg[i].x1; 637fa225cbcSrjs prect[i].width = pSeg[i].x2 - pSeg[i].x1 + 1; 638fa225cbcSrjs } else { 639fa225cbcSrjs prect[i].x = pSeg[i].x2; 640fa225cbcSrjs prect[i].width = pSeg[i].x1 - pSeg[i].x2 + 1; 641fa225cbcSrjs } 642fa225cbcSrjs if (pSeg[i].y1 < pSeg[i].y2) { 643fa225cbcSrjs prect[i].y = pSeg[i].y1; 644fa225cbcSrjs prect[i].height = pSeg[i].y2 - pSeg[i].y1 + 1; 645fa225cbcSrjs } else { 646fa225cbcSrjs prect[i].y = pSeg[i].y2; 647fa225cbcSrjs prect[i].height = pSeg[i].y1 - pSeg[i].y2 + 1; 648fa225cbcSrjs } 649fa225cbcSrjs 650fa225cbcSrjs /* don't paint last pixel */ 651fa225cbcSrjs if (pGC->capStyle == CapNotLast) { 652fa225cbcSrjs if (prect[i].width == 1) 653fa225cbcSrjs prect[i].height--; 654fa225cbcSrjs else 655fa225cbcSrjs prect[i].width--; 656fa225cbcSrjs } 657fa225cbcSrjs } 658fa225cbcSrjs pGC->ops->PolyFillRect(pDrawable, pGC, nseg, prect); 659fa225cbcSrjs xfree(prect); 660fa225cbcSrjs} 661fa225cbcSrjs 662fa225cbcSrjsstatic Bool uxa_fill_region_solid (DrawablePtr pDrawable, RegionPtr pRegion, 663fa225cbcSrjs Pixel pixel, CARD32 planemask, CARD32 alu); 664fa225cbcSrjs 665fa225cbcSrjsstatic void 666fa225cbcSrjsuxa_poly_fill_rect(DrawablePtr pDrawable, 667fa225cbcSrjs GCPtr pGC, 668fa225cbcSrjs int nrect, 669fa225cbcSrjs xRectangle *prect) 670fa225cbcSrjs{ 671fa225cbcSrjs uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen); 672fa225cbcSrjs RegionPtr pClip = fbGetCompositeClip(pGC); 673fa225cbcSrjs PixmapPtr pPixmap = uxa_get_drawable_pixmap(pDrawable); 674fa225cbcSrjs register BoxPtr pbox; 675fa225cbcSrjs BoxPtr pextent; 676fa225cbcSrjs int extentX1, extentX2, extentY1, extentY2; 677fa225cbcSrjs int fullX1, fullX2, fullY1, fullY2; 678fa225cbcSrjs int partX1, partX2, partY1, partY2; 679fa225cbcSrjs int xoff, yoff; 680fa225cbcSrjs int xorg, yorg; 681fa225cbcSrjs int n; 682fa225cbcSrjs RegionPtr pReg = RECTS_TO_REGION(pScreen, nrect, prect, CT_UNSORTED); 683fa225cbcSrjs 684fa225cbcSrjs /* Compute intersection of rects and clip region */ 685fa225cbcSrjs REGION_TRANSLATE(pScreen, pReg, pDrawable->x, pDrawable->y); 686fa225cbcSrjs REGION_INTERSECT(pScreen, pReg, pClip, pReg); 687fa225cbcSrjs 688fa225cbcSrjs if (!REGION_NUM_RECTS(pReg)) 689fa225cbcSrjs goto out; 690fa225cbcSrjs 691fa225cbcSrjs uxa_get_drawable_deltas(pDrawable, pPixmap, &xoff, &yoff); 692fa225cbcSrjs 693fa225cbcSrjs if (uxa_screen->swappedOut) 694fa225cbcSrjs goto fallback; 695fa225cbcSrjs 696fa225cbcSrjs /* For ROPs where overlaps don't matter, convert rectangles to region and 697fa225cbcSrjs * call uxa_fill_region_{solid,tiled}. 698fa225cbcSrjs */ 699fa225cbcSrjs if ((pGC->fillStyle == FillSolid || pGC->fillStyle == FillTiled) && 700fa225cbcSrjs (nrect == 1 || pGC->alu == GXcopy || pGC->alu == GXclear || 701fa225cbcSrjs pGC->alu == GXnoop || pGC->alu == GXcopyInverted || 702fa225cbcSrjs pGC->alu == GXset)) { 703fa225cbcSrjs if (((pGC->fillStyle == FillSolid || pGC->tileIsPixel) && 704fa225cbcSrjs uxa_fill_region_solid(pDrawable, pReg, pGC->fillStyle == FillSolid ? 705fa225cbcSrjs pGC->fgPixel : pGC->tile.pixel, pGC->planemask, 706fa225cbcSrjs pGC->alu)) || 707fa225cbcSrjs (pGC->fillStyle == FillTiled && !pGC->tileIsPixel && 708fa225cbcSrjs uxa_fill_region_tiled(pDrawable, pReg, pGC->tile.pixmap, &pGC->patOrg, 709fa225cbcSrjs pGC->planemask, pGC->alu))) { 710fa225cbcSrjs goto out; 711fa225cbcSrjs } 712fa225cbcSrjs } 713fa225cbcSrjs 714fa225cbcSrjs if (pGC->fillStyle != FillSolid && 715fa225cbcSrjs !(pGC->tileIsPixel && pGC->fillStyle == FillTiled)) 716fa225cbcSrjs { 717fa225cbcSrjs goto fallback; 718fa225cbcSrjs } 719fa225cbcSrjs 720fa225cbcSrjs if (!uxa_pixmap_is_offscreen (pPixmap) || 721fa225cbcSrjs !(*uxa_screen->info->prepare_solid) (pPixmap, 722fa225cbcSrjs pGC->alu, 723fa225cbcSrjs pGC->planemask, 724fa225cbcSrjs pGC->fgPixel)) 725fa225cbcSrjs { 726fa225cbcSrjsfallback: 727fa225cbcSrjs uxa_check_poly_fill_rect (pDrawable, pGC, nrect, prect); 728fa225cbcSrjs goto out; 729fa225cbcSrjs } 730fa225cbcSrjs 731fa225cbcSrjs xorg = pDrawable->x; 732fa225cbcSrjs yorg = pDrawable->y; 733fa225cbcSrjs 734fa225cbcSrjs pextent = REGION_EXTENTS(pGC->pScreen, pClip); 735fa225cbcSrjs extentX1 = pextent->x1; 736fa225cbcSrjs extentY1 = pextent->y1; 737fa225cbcSrjs extentX2 = pextent->x2; 738fa225cbcSrjs extentY2 = pextent->y2; 739fa225cbcSrjs while (nrect--) 740fa225cbcSrjs { 741fa225cbcSrjs fullX1 = prect->x + xorg; 742fa225cbcSrjs fullY1 = prect->y + yorg; 743fa225cbcSrjs fullX2 = fullX1 + (int) prect->width; 744fa225cbcSrjs fullY2 = fullY1 + (int) prect->height; 745fa225cbcSrjs prect++; 746fa225cbcSrjs 747fa225cbcSrjs if (fullX1 < extentX1) 748fa225cbcSrjs fullX1 = extentX1; 749fa225cbcSrjs 750fa225cbcSrjs if (fullY1 < extentY1) 751fa225cbcSrjs fullY1 = extentY1; 752fa225cbcSrjs 753fa225cbcSrjs if (fullX2 > extentX2) 754fa225cbcSrjs fullX2 = extentX2; 755fa225cbcSrjs 756fa225cbcSrjs if (fullY2 > extentY2) 757fa225cbcSrjs fullY2 = extentY2; 758fa225cbcSrjs 759fa225cbcSrjs if ((fullX1 >= fullX2) || (fullY1 >= fullY2)) 760fa225cbcSrjs continue; 761fa225cbcSrjs n = REGION_NUM_RECTS (pClip); 762fa225cbcSrjs if (n == 1) 763fa225cbcSrjs { 764fa225cbcSrjs (*uxa_screen->info->solid) (pPixmap, 765fa225cbcSrjs fullX1 + xoff, fullY1 + yoff, 766fa225cbcSrjs fullX2 + xoff, fullY2 + yoff); 767fa225cbcSrjs } 768fa225cbcSrjs else 769fa225cbcSrjs { 770fa225cbcSrjs pbox = REGION_RECTS(pClip); 771fa225cbcSrjs /* 772fa225cbcSrjs * clip the rectangle to each box in the clip region 773fa225cbcSrjs * this is logically equivalent to calling Intersect(), 774fa225cbcSrjs * but rectangles may overlap each other here. 775fa225cbcSrjs */ 776fa225cbcSrjs while(n--) 777fa225cbcSrjs { 778fa225cbcSrjs partX1 = pbox->x1; 779fa225cbcSrjs if (partX1 < fullX1) 780fa225cbcSrjs partX1 = fullX1; 781fa225cbcSrjs partY1 = pbox->y1; 782fa225cbcSrjs if (partY1 < fullY1) 783fa225cbcSrjs partY1 = fullY1; 784fa225cbcSrjs partX2 = pbox->x2; 785fa225cbcSrjs if (partX2 > fullX2) 786fa225cbcSrjs partX2 = fullX2; 787fa225cbcSrjs partY2 = pbox->y2; 788fa225cbcSrjs if (partY2 > fullY2) 789fa225cbcSrjs partY2 = fullY2; 790fa225cbcSrjs 791fa225cbcSrjs pbox++; 792fa225cbcSrjs 793fa225cbcSrjs if (partX1 < partX2 && partY1 < partY2) { 794fa225cbcSrjs (*uxa_screen->info->solid) (pPixmap, 795fa225cbcSrjs partX1 + xoff, partY1 + yoff, 796fa225cbcSrjs partX2 + xoff, partY2 + yoff); 797fa225cbcSrjs } 798fa225cbcSrjs } 799fa225cbcSrjs } 800fa225cbcSrjs } 801fa225cbcSrjs (*uxa_screen->info->done_solid) (pPixmap); 802fa225cbcSrjs 803fa225cbcSrjsout: 804fa225cbcSrjs REGION_UNINIT(pScreen, pReg); 805fa225cbcSrjs REGION_DESTROY(pScreen, pReg); 806fa225cbcSrjs} 807fa225cbcSrjs 808fa225cbcSrjsconst GCOps uxa_ops = { 809fa225cbcSrjs uxa_fill_spans, 810fa225cbcSrjs uxa_check_set_spans, 811fa225cbcSrjs uxa_put_image, 812fa225cbcSrjs uxa_copy_area, 813fa225cbcSrjs uxa_check_copy_plane, 814fa225cbcSrjs uxa_poly_point, 815fa225cbcSrjs uxa_poly_lines, 816fa225cbcSrjs uxa_poly_segment, 817fa225cbcSrjs miPolyRectangle, 818fa225cbcSrjs uxa_check_poly_arc, 819fa225cbcSrjs miFillPolygon, 820fa225cbcSrjs uxa_poly_fill_rect, 821fa225cbcSrjs miPolyFillArc, 822fa225cbcSrjs miPolyText8, 823fa225cbcSrjs miPolyText16, 824fa225cbcSrjs miImageText8, 825fa225cbcSrjs miImageText16, 826fa225cbcSrjs uxa_check_image_glyph_blt, 827fa225cbcSrjs uxa_check_poly_glyph_blt, 828fa225cbcSrjs uxa_check_push_pixels, 829fa225cbcSrjs}; 830fa225cbcSrjs 831fa225cbcSrjsvoid 832fa225cbcSrjsuxa_copy_window(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 833fa225cbcSrjs{ 834fa225cbcSrjs RegionRec rgnDst; 835fa225cbcSrjs int dx, dy; 836fa225cbcSrjs PixmapPtr pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin); 837fa225cbcSrjs 838fa225cbcSrjs dx = ptOldOrg.x - pWin->drawable.x; 839fa225cbcSrjs dy = ptOldOrg.y - pWin->drawable.y; 840fa225cbcSrjs REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); 841fa225cbcSrjs 842fa225cbcSrjs REGION_INIT (pWin->drawable.pScreen, &rgnDst, NullBox, 0); 843fa225cbcSrjs 844fa225cbcSrjs REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip, prgnSrc); 845fa225cbcSrjs#ifdef COMPOSITE 846fa225cbcSrjs if (pPixmap->screen_x || pPixmap->screen_y) 847fa225cbcSrjs REGION_TRANSLATE (pWin->drawable.pScreen, &rgnDst, 848fa225cbcSrjs -pPixmap->screen_x, -pPixmap->screen_y); 849fa225cbcSrjs#endif 850fa225cbcSrjs 851fa225cbcSrjs miCopyRegion (&pPixmap->drawable, &pPixmap->drawable, 852fa225cbcSrjs NULL, 853fa225cbcSrjs &rgnDst, dx, dy, uxa_copy_n_to_n, 0, NULL); 854fa225cbcSrjs 855fa225cbcSrjs REGION_UNINIT(pWin->drawable.pScreen, &rgnDst); 856fa225cbcSrjs} 857fa225cbcSrjs 858fa225cbcSrjsstatic Bool 859fa225cbcSrjsuxa_fill_region_solid (DrawablePtr pDrawable, 860fa225cbcSrjs RegionPtr pRegion, 861fa225cbcSrjs Pixel pixel, 862fa225cbcSrjs CARD32 planemask, 863fa225cbcSrjs CARD32 alu) 864fa225cbcSrjs{ 865fa225cbcSrjs uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen); 866fa225cbcSrjs PixmapPtr pPixmap = uxa_get_drawable_pixmap (pDrawable); 867fa225cbcSrjs int xoff, yoff; 868fa225cbcSrjs Bool ret = FALSE; 869fa225cbcSrjs 870fa225cbcSrjs uxa_get_drawable_deltas(pDrawable, pPixmap, &xoff, &yoff); 871fa225cbcSrjs REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); 872fa225cbcSrjs 873fa225cbcSrjs if (uxa_pixmap_is_offscreen (pPixmap) && 874fa225cbcSrjs (*uxa_screen->info->prepare_solid) (pPixmap, alu, planemask, pixel)) 875fa225cbcSrjs { 876fa225cbcSrjs int nbox; 877fa225cbcSrjs BoxPtr pBox; 878fa225cbcSrjs 879fa225cbcSrjs nbox = REGION_NUM_RECTS (pRegion); 880fa225cbcSrjs pBox = REGION_RECTS (pRegion); 881fa225cbcSrjs 882fa225cbcSrjs while (nbox--) 883fa225cbcSrjs { 884fa225cbcSrjs (*uxa_screen->info->solid) (pPixmap, pBox->x1, pBox->y1, pBox->x2, 885fa225cbcSrjs pBox->y2); 886fa225cbcSrjs pBox++; 887fa225cbcSrjs } 888fa225cbcSrjs (*uxa_screen->info->done_solid) (pPixmap); 889fa225cbcSrjs 890fa225cbcSrjs ret = TRUE; 891fa225cbcSrjs } 892fa225cbcSrjs 893fa225cbcSrjs REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); 894fa225cbcSrjs 895fa225cbcSrjs return ret; 896fa225cbcSrjs} 897fa225cbcSrjs 898fa225cbcSrjs/* Try to do an accelerated tile of the pTile into pRegion of pDrawable. 899fa225cbcSrjs * Based on fbFillRegionTiled(), fbTile(). 900fa225cbcSrjs */ 901fa225cbcSrjsBool 902fa225cbcSrjsuxa_fill_region_tiled (DrawablePtr pDrawable, 903fa225cbcSrjs RegionPtr pRegion, 904fa225cbcSrjs PixmapPtr pTile, 905fa225cbcSrjs DDXPointPtr pPatOrg, 906fa225cbcSrjs CARD32 planemask, 907fa225cbcSrjs CARD32 alu) 908fa225cbcSrjs{ 909fa225cbcSrjs uxa_screen_t *uxa_screen = uxa_get_screen(pDrawable->pScreen); 910fa225cbcSrjs PixmapPtr pPixmap; 911fa225cbcSrjs int xoff, yoff; 912fa225cbcSrjs int tileWidth, tileHeight; 913fa225cbcSrjs int nbox = REGION_NUM_RECTS (pRegion); 914fa225cbcSrjs BoxPtr pBox = REGION_RECTS (pRegion); 915fa225cbcSrjs Bool ret = FALSE; 916fa225cbcSrjs 917fa225cbcSrjs tileWidth = pTile->drawable.width; 918fa225cbcSrjs tileHeight = pTile->drawable.height; 919fa225cbcSrjs 920fa225cbcSrjs /* If we're filling with a solid color, grab it out and go to 921fa225cbcSrjs * FillRegionsolid, saving numerous copies. 922fa225cbcSrjs */ 923fa225cbcSrjs if (tileWidth == 1 && tileHeight == 1) 924fa225cbcSrjs return uxa_fill_region_solid(pDrawable, pRegion, 925fa225cbcSrjs uxa_get_pixmap_first_pixel (pTile), planemask, 926fa225cbcSrjs alu); 927fa225cbcSrjs 928fa225cbcSrjs pPixmap = uxa_get_drawable_pixmap (pDrawable); 929fa225cbcSrjs uxa_get_drawable_deltas(pDrawable, pPixmap, &xoff, &yoff); 930fa225cbcSrjs REGION_TRANSLATE(pScreen, pRegion, xoff, yoff); 931fa225cbcSrjs 932fa225cbcSrjs pPixmap = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff); 933fa225cbcSrjs 934fa225cbcSrjs if (!pPixmap || !uxa_pixmap_is_offscreen(pTile)) 935fa225cbcSrjs goto out; 936fa225cbcSrjs 937fa225cbcSrjs if ((*uxa_screen->info->prepare_copy) (pTile, pPixmap, 1, 1, alu, planemask)) 938fa225cbcSrjs { 939fa225cbcSrjs while (nbox--) 940fa225cbcSrjs { 941fa225cbcSrjs int height = pBox->y2 - pBox->y1; 942fa225cbcSrjs int dstY = pBox->y1; 943fa225cbcSrjs int tileY; 944fa225cbcSrjs 945fa225cbcSrjs modulus(dstY - yoff - pDrawable->y - pPatOrg->y, tileHeight, tileY); 946fa225cbcSrjs 947fa225cbcSrjs while (height > 0) { 948fa225cbcSrjs int width = pBox->x2 - pBox->x1; 949fa225cbcSrjs int dstX = pBox->x1; 950fa225cbcSrjs int tileX; 951fa225cbcSrjs int h = tileHeight - tileY; 952fa225cbcSrjs 953fa225cbcSrjs if (h > height) 954fa225cbcSrjs h = height; 955fa225cbcSrjs height -= h; 956fa225cbcSrjs 957fa225cbcSrjs modulus(dstX - xoff - pDrawable->x - pPatOrg->x, tileWidth, 958fa225cbcSrjs tileX); 959fa225cbcSrjs 960fa225cbcSrjs while (width > 0) { 961fa225cbcSrjs int w = tileWidth - tileX; 962fa225cbcSrjs if (w > width) 963fa225cbcSrjs w = width; 964fa225cbcSrjs width -= w; 965fa225cbcSrjs 966fa225cbcSrjs (*uxa_screen->info->copy) (pPixmap, tileX, tileY, dstX, dstY, 967fa225cbcSrjs w, h); 968fa225cbcSrjs dstX += w; 969fa225cbcSrjs tileX = 0; 970fa225cbcSrjs } 971fa225cbcSrjs dstY += h; 972fa225cbcSrjs tileY = 0; 973fa225cbcSrjs } 974fa225cbcSrjs pBox++; 975fa225cbcSrjs } 976fa225cbcSrjs (*uxa_screen->info->done_copy) (pPixmap); 977fa225cbcSrjs 978fa225cbcSrjs ret = TRUE; 979fa225cbcSrjs } 980fa225cbcSrjs 981fa225cbcSrjsout: 982fa225cbcSrjs REGION_TRANSLATE(pScreen, pRegion, -xoff, -yoff); 983fa225cbcSrjs 984fa225cbcSrjs return ret; 985fa225cbcSrjs} 986fa225cbcSrjs 987fa225cbcSrjs/** 988fa225cbcSrjs * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory. 989fa225cbcSrjs * 990fa225cbcSrjs * This is probably the only case we actually care about. The rest fall through 991fa225cbcSrjs * to migration and fbGetImage, which hopefully will result in migration pushing 992fa225cbcSrjs * the pixmap out of framebuffer. 993fa225cbcSrjs */ 994fa225cbcSrjsvoid 995fa225cbcSrjsuxa_get_image (DrawablePtr pDrawable, int x, int y, int w, int h, 996fa225cbcSrjs unsigned int format, unsigned long planeMask, char *d) 997fa225cbcSrjs{ 998fa225cbcSrjs ScreenPtr screen = pDrawable->pScreen; 999fa225cbcSrjs uxa_screen_t *uxa_screen = uxa_get_screen(screen); 1000fa225cbcSrjs BoxRec Box; 1001fa225cbcSrjs PixmapPtr pPix = uxa_get_drawable_pixmap (pDrawable); 1002fa225cbcSrjs int xoff, yoff; 1003fa225cbcSrjs Bool ok; 1004fa225cbcSrjs 1005fa225cbcSrjs uxa_get_drawable_deltas (pDrawable, pPix, &xoff, &yoff); 1006fa225cbcSrjs 1007fa225cbcSrjs Box.x1 = pDrawable->y + x + xoff; 1008fa225cbcSrjs Box.y1 = pDrawable->y + y + yoff; 1009fa225cbcSrjs Box.x2 = Box.x1 + w; 1010fa225cbcSrjs Box.y2 = Box.y1 + h; 1011fa225cbcSrjs 1012fa225cbcSrjs if (uxa_screen->swappedOut) 1013fa225cbcSrjs goto fallback; 1014fa225cbcSrjs 1015fa225cbcSrjs pPix = uxa_get_offscreen_pixmap (pDrawable, &xoff, &yoff); 1016fa225cbcSrjs 1017fa225cbcSrjs if (pPix == NULL || uxa_screen->info->get_image == NULL) 1018fa225cbcSrjs goto fallback; 1019fa225cbcSrjs 1020fa225cbcSrjs /* Only cover the ZPixmap, solid copy case. */ 1021fa225cbcSrjs if (format != ZPixmap || !UXA_PM_IS_SOLID(pDrawable, planeMask)) 1022fa225cbcSrjs goto fallback; 1023fa225cbcSrjs 1024fa225cbcSrjs /* Only try to handle the 8bpp and up cases, since we don't want to think 1025fa225cbcSrjs * about <8bpp. 1026fa225cbcSrjs */ 1027fa225cbcSrjs if (pDrawable->bitsPerPixel < 8) 1028fa225cbcSrjs goto fallback; 1029fa225cbcSrjs 1030fa225cbcSrjs ok = uxa_screen->info->get_image(pPix, pDrawable->x + x + xoff, 1031fa225cbcSrjs pDrawable->y + y + yoff, w, h, d, 1032fa225cbcSrjs PixmapBytePad(w, pDrawable->depth)); 1033fa225cbcSrjs if (ok) 1034fa225cbcSrjs return; 1035fa225cbcSrjs 1036fa225cbcSrjsfallback: 1037fa225cbcSrjs UXA_FALLBACK(("from %p (%c)\n", pDrawable, 1038fa225cbcSrjs uxa_drawable_location(pDrawable))); 1039fa225cbcSrjs 1040fa225cbcSrjs if (uxa_prepare_access (pDrawable, UXA_ACCESS_RO)) { 1041fa225cbcSrjs fbGetImage (pDrawable, x, y, w, h, format, planeMask, d); 1042fa225cbcSrjs uxa_finish_access (pDrawable); 1043fa225cbcSrjs } 1044fa225cbcSrjs 1045fa225cbcSrjs return; 1046fa225cbcSrjs} 1047