1706f2543Smrg/* 2706f2543Smrg * Copyright © 1998 Keith Packard 3706f2543Smrg * 4706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its 5706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that 6706f2543Smrg * the above copyright notice appear in all copies and that both that 7706f2543Smrg * copyright notice and this permission notice appear in supporting 8706f2543Smrg * documentation, and that the name of Keith Packard not be used in 9706f2543Smrg * advertising or publicity pertaining to distribution of the software without 10706f2543Smrg * specific, written prior permission. Keith Packard makes no 11706f2543Smrg * representations about the suitability of this software for any purpose. It 12706f2543Smrg * is provided "as is" without express or implied warranty. 13706f2543Smrg * 14706f2543Smrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16706f2543Smrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20706f2543Smrg * PERFORMANCE OF THIS SOFTWARE. 21706f2543Smrg */ 22706f2543Smrg 23706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 24706f2543Smrg#include <dix-config.h> 25706f2543Smrg#endif 26706f2543Smrg 27706f2543Smrg#include <string.h> 28706f2543Smrg 29706f2543Smrg#include "fb.h" 30706f2543Smrg 31706f2543Smrgvoid 32706f2543SmrgfbPutImage (DrawablePtr pDrawable, 33706f2543Smrg GCPtr pGC, 34706f2543Smrg int depth, 35706f2543Smrg int x, 36706f2543Smrg int y, 37706f2543Smrg int w, 38706f2543Smrg int h, 39706f2543Smrg int leftPad, 40706f2543Smrg int format, 41706f2543Smrg char *pImage) 42706f2543Smrg{ 43706f2543Smrg FbGCPrivPtr pPriv = fbGetGCPrivate(pGC); 44706f2543Smrg unsigned long i; 45706f2543Smrg FbStride srcStride; 46706f2543Smrg FbStip *src = (FbStip *) pImage; 47706f2543Smrg 48706f2543Smrg x += pDrawable->x; 49706f2543Smrg y += pDrawable->y; 50706f2543Smrg 51706f2543Smrg switch (format) 52706f2543Smrg { 53706f2543Smrg case XYBitmap: 54706f2543Smrg srcStride = BitmapBytePad(w + leftPad) / sizeof (FbStip); 55706f2543Smrg fbPutXYImage (pDrawable, 56706f2543Smrg fbGetCompositeClip(pGC), 57706f2543Smrg pPriv->fg, 58706f2543Smrg pPriv->bg, 59706f2543Smrg pPriv->pm, 60706f2543Smrg pGC->alu, 61706f2543Smrg TRUE, 62706f2543Smrg x, y, w, h, 63706f2543Smrg src, 64706f2543Smrg srcStride, 65706f2543Smrg leftPad); 66706f2543Smrg break; 67706f2543Smrg case XYPixmap: 68706f2543Smrg srcStride = BitmapBytePad(w + leftPad) / sizeof (FbStip); 69706f2543Smrg for (i = (unsigned long)1 << (pDrawable->depth - 1); i; i >>= 1) 70706f2543Smrg { 71706f2543Smrg if (i & pGC->planemask) 72706f2543Smrg { 73706f2543Smrg fbPutXYImage (pDrawable, 74706f2543Smrg fbGetCompositeClip(pGC), 75706f2543Smrg FB_ALLONES, 76706f2543Smrg 0, 77706f2543Smrg fbReplicatePixel (i, pDrawable->bitsPerPixel), 78706f2543Smrg pGC->alu, 79706f2543Smrg TRUE, 80706f2543Smrg x, y, w, h, 81706f2543Smrg src, 82706f2543Smrg srcStride, 83706f2543Smrg leftPad); 84706f2543Smrg src += srcStride * h; 85706f2543Smrg } 86706f2543Smrg } 87706f2543Smrg break; 88706f2543Smrg case ZPixmap: 89706f2543Smrg#ifdef FB_24_32BIT 90706f2543Smrg if (pDrawable->bitsPerPixel != BitsPerPixel(pDrawable->depth)) 91706f2543Smrg { 92706f2543Smrg srcStride = PixmapBytePad(w, pDrawable->depth); 93706f2543Smrg fb24_32PutZImage (pDrawable, 94706f2543Smrg fbGetCompositeClip(pGC), 95706f2543Smrg pGC->alu, 96706f2543Smrg (FbBits) pGC->planemask, 97706f2543Smrg x, y, w, h, 98706f2543Smrg (CARD8 *) pImage, 99706f2543Smrg srcStride); 100706f2543Smrg } 101706f2543Smrg else 102706f2543Smrg#endif 103706f2543Smrg { 104706f2543Smrg srcStride = PixmapBytePad(w, pDrawable->depth) / sizeof (FbStip); 105706f2543Smrg fbPutZImage (pDrawable, 106706f2543Smrg fbGetCompositeClip(pGC), 107706f2543Smrg pGC->alu, 108706f2543Smrg pPriv->pm, 109706f2543Smrg x, y, w, h, 110706f2543Smrg src, srcStride); 111706f2543Smrg } 112706f2543Smrg } 113706f2543Smrg} 114706f2543Smrg 115706f2543Smrgvoid 116706f2543SmrgfbPutZImage (DrawablePtr pDrawable, 117706f2543Smrg RegionPtr pClip, 118706f2543Smrg int alu, 119706f2543Smrg FbBits pm, 120706f2543Smrg int x, 121706f2543Smrg int y, 122706f2543Smrg int width, 123706f2543Smrg int height, 124706f2543Smrg FbStip *src, 125706f2543Smrg FbStride srcStride) 126706f2543Smrg{ 127706f2543Smrg FbStip *dst; 128706f2543Smrg FbStride dstStride; 129706f2543Smrg int dstBpp; 130706f2543Smrg int dstXoff, dstYoff; 131706f2543Smrg int nbox; 132706f2543Smrg BoxPtr pbox; 133706f2543Smrg int x1, y1, x2, y2; 134706f2543Smrg 135706f2543Smrg fbGetStipDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); 136706f2543Smrg 137706f2543Smrg for (nbox = RegionNumRects (pClip), 138706f2543Smrg pbox = RegionRects(pClip); 139706f2543Smrg nbox--; 140706f2543Smrg pbox++) 141706f2543Smrg { 142706f2543Smrg x1 = x; 143706f2543Smrg y1 = y; 144706f2543Smrg x2 = x + width; 145706f2543Smrg y2 = y + height; 146706f2543Smrg if (x1 < pbox->x1) 147706f2543Smrg x1 = pbox->x1; 148706f2543Smrg if (y1 < pbox->y1) 149706f2543Smrg y1 = pbox->y1; 150706f2543Smrg if (x2 > pbox->x2) 151706f2543Smrg x2 = pbox->x2; 152706f2543Smrg if (y2 > pbox->y2) 153706f2543Smrg y2 = pbox->y2; 154706f2543Smrg if (x1 >= x2 || y1 >= y2) 155706f2543Smrg continue; 156706f2543Smrg fbBltStip (src + (y1 - y) * srcStride, 157706f2543Smrg srcStride, 158706f2543Smrg (x1 - x) * dstBpp, 159706f2543Smrg 160706f2543Smrg dst + (y1 + dstYoff) * dstStride, 161706f2543Smrg dstStride, 162706f2543Smrg (x1 + dstXoff) * dstBpp, 163706f2543Smrg 164706f2543Smrg (x2 - x1) * dstBpp, 165706f2543Smrg (y2 - y1), 166706f2543Smrg 167706f2543Smrg alu, 168706f2543Smrg pm, 169706f2543Smrg dstBpp); 170706f2543Smrg } 171706f2543Smrg 172706f2543Smrg fbFinishAccess (pDrawable); 173706f2543Smrg} 174706f2543Smrg 175706f2543Smrgvoid 176706f2543SmrgfbPutXYImage (DrawablePtr pDrawable, 177706f2543Smrg RegionPtr pClip, 178706f2543Smrg FbBits fg, 179706f2543Smrg FbBits bg, 180706f2543Smrg FbBits pm, 181706f2543Smrg int alu, 182706f2543Smrg Bool opaque, 183706f2543Smrg 184706f2543Smrg int x, 185706f2543Smrg int y, 186706f2543Smrg int width, 187706f2543Smrg int height, 188706f2543Smrg 189706f2543Smrg FbStip *src, 190706f2543Smrg FbStride srcStride, 191706f2543Smrg int srcX) 192706f2543Smrg{ 193706f2543Smrg FbBits *dst; 194706f2543Smrg FbStride dstStride; 195706f2543Smrg int dstBpp; 196706f2543Smrg int dstXoff, dstYoff; 197706f2543Smrg int nbox; 198706f2543Smrg BoxPtr pbox; 199706f2543Smrg int x1, y1, x2, y2; 200706f2543Smrg FbBits fgand = 0, fgxor = 0, bgand = 0, bgxor = 0; 201706f2543Smrg 202706f2543Smrg fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff); 203706f2543Smrg 204706f2543Smrg if (dstBpp == 1) 205706f2543Smrg { 206706f2543Smrg if (opaque) 207706f2543Smrg alu = FbOpaqueStipple1Rop(alu,fg,bg); 208706f2543Smrg else 209706f2543Smrg alu = FbStipple1Rop(alu,fg); 210706f2543Smrg } 211706f2543Smrg else 212706f2543Smrg { 213706f2543Smrg fgand = fbAnd(alu,fg,pm); 214706f2543Smrg fgxor = fbXor(alu,fg,pm); 215706f2543Smrg if (opaque) 216706f2543Smrg { 217706f2543Smrg bgand = fbAnd(alu,bg,pm); 218706f2543Smrg bgxor = fbXor(alu,bg,pm); 219706f2543Smrg } 220706f2543Smrg else 221706f2543Smrg { 222706f2543Smrg bgand = fbAnd(GXnoop,(FbBits)0,FB_ALLONES); 223706f2543Smrg bgxor = fbXor(GXnoop,(FbBits)0,FB_ALLONES); 224706f2543Smrg } 225706f2543Smrg } 226706f2543Smrg 227706f2543Smrg for (nbox = RegionNumRects (pClip), 228706f2543Smrg pbox = RegionRects(pClip); 229706f2543Smrg nbox--; 230706f2543Smrg pbox++) 231706f2543Smrg { 232706f2543Smrg x1 = x; 233706f2543Smrg y1 = y; 234706f2543Smrg x2 = x + width; 235706f2543Smrg y2 = y + height; 236706f2543Smrg if (x1 < pbox->x1) 237706f2543Smrg x1 = pbox->x1; 238706f2543Smrg if (y1 < pbox->y1) 239706f2543Smrg y1 = pbox->y1; 240706f2543Smrg if (x2 > pbox->x2) 241706f2543Smrg x2 = pbox->x2; 242706f2543Smrg if (y2 > pbox->y2) 243706f2543Smrg y2 = pbox->y2; 244706f2543Smrg if (x1 >= x2 || y1 >= y2) 245706f2543Smrg continue; 246706f2543Smrg if (dstBpp == 1) 247706f2543Smrg { 248706f2543Smrg fbBltStip (src + (y1 - y) * srcStride, 249706f2543Smrg srcStride, 250706f2543Smrg (x1 - x) + srcX, 251706f2543Smrg 252706f2543Smrg (FbStip *) (dst + (y1 + dstYoff) * dstStride), 253706f2543Smrg FbBitsStrideToStipStride(dstStride), 254706f2543Smrg (x1 + dstXoff) * dstBpp, 255706f2543Smrg 256706f2543Smrg (x2 - x1) * dstBpp, 257706f2543Smrg (y2 - y1), 258706f2543Smrg 259706f2543Smrg alu, 260706f2543Smrg pm, 261706f2543Smrg dstBpp); 262706f2543Smrg } 263706f2543Smrg else 264706f2543Smrg { 265706f2543Smrg fbBltOne (src + (y1 - y) * srcStride, 266706f2543Smrg srcStride, 267706f2543Smrg (x1 - x) + srcX, 268706f2543Smrg 269706f2543Smrg dst + (y1 + dstYoff) * dstStride, 270706f2543Smrg dstStride, 271706f2543Smrg (x1 + dstXoff) * dstBpp, 272706f2543Smrg dstBpp, 273706f2543Smrg 274706f2543Smrg (x2 - x1) * dstBpp, 275706f2543Smrg (y2 - y1), 276706f2543Smrg 277706f2543Smrg fgand, fgxor, bgand, bgxor); 278706f2543Smrg } 279706f2543Smrg } 280706f2543Smrg 281706f2543Smrg fbFinishAccess (pDrawable); 282706f2543Smrg} 283706f2543Smrg 284706f2543Smrgvoid 285706f2543SmrgfbGetImage (DrawablePtr pDrawable, 286706f2543Smrg int x, 287706f2543Smrg int y, 288706f2543Smrg int w, 289706f2543Smrg int h, 290706f2543Smrg unsigned int format, 291706f2543Smrg unsigned long planeMask, 292706f2543Smrg char *d) 293706f2543Smrg{ 294706f2543Smrg FbBits *src; 295706f2543Smrg FbStride srcStride; 296706f2543Smrg int srcBpp; 297706f2543Smrg int srcXoff, srcYoff; 298706f2543Smrg FbStip *dst; 299706f2543Smrg FbStride dstStride; 300706f2543Smrg 301706f2543Smrg /* 302706f2543Smrg * XFree86 DDX empties the root borderClip when the VT is 303706f2543Smrg * switched away; this checks for that case 304706f2543Smrg */ 305706f2543Smrg if (!fbDrawableEnabled(pDrawable)) 306706f2543Smrg return; 307706f2543Smrg 308706f2543Smrg#ifdef FB_24_32BIT 309706f2543Smrg if (format == ZPixmap && 310706f2543Smrg pDrawable->bitsPerPixel != BitsPerPixel (pDrawable->depth)) 311706f2543Smrg { 312706f2543Smrg fb24_32GetImage (pDrawable, x, y, w, h, format, planeMask, d); 313706f2543Smrg return; 314706f2543Smrg } 315706f2543Smrg#endif 316706f2543Smrg 317706f2543Smrg fbGetDrawable (pDrawable, src, srcStride, srcBpp, srcXoff, srcYoff); 318706f2543Smrg 319706f2543Smrg x += pDrawable->x; 320706f2543Smrg y += pDrawable->y; 321706f2543Smrg 322706f2543Smrg dst = (FbStip *) d; 323706f2543Smrg if (format == ZPixmap || srcBpp == 1) 324706f2543Smrg { 325706f2543Smrg FbBits pm; 326706f2543Smrg 327706f2543Smrg pm = fbReplicatePixel (planeMask, srcBpp); 328706f2543Smrg dstStride = PixmapBytePad(w, pDrawable->depth); 329706f2543Smrg if (pm != FB_ALLONES) 330706f2543Smrg memset (d, 0, dstStride * h); 331706f2543Smrg dstStride /= sizeof (FbStip); 332706f2543Smrg fbBltStip ((FbStip *) (src + (y + srcYoff) * srcStride), 333706f2543Smrg FbBitsStrideToStipStride(srcStride), 334706f2543Smrg (x + srcXoff) * srcBpp, 335706f2543Smrg 336706f2543Smrg dst, 337706f2543Smrg dstStride, 338706f2543Smrg 0, 339706f2543Smrg 340706f2543Smrg w * srcBpp, h, 341706f2543Smrg 342706f2543Smrg GXcopy, 343706f2543Smrg pm, 344706f2543Smrg srcBpp); 345706f2543Smrg } 346706f2543Smrg else 347706f2543Smrg { 348706f2543Smrg dstStride = BitmapBytePad(w) / sizeof (FbStip); 349706f2543Smrg fbBltPlane (src + (y + srcYoff) * srcStride, 350706f2543Smrg srcStride, 351706f2543Smrg (x + srcXoff) * srcBpp, 352706f2543Smrg srcBpp, 353706f2543Smrg 354706f2543Smrg dst, 355706f2543Smrg dstStride, 356706f2543Smrg 0, 357706f2543Smrg 358706f2543Smrg w * srcBpp, h, 359706f2543Smrg 360706f2543Smrg fbAndStip(GXcopy,FB_STIP_ALLONES,FB_STIP_ALLONES), 361706f2543Smrg fbXorStip(GXcopy,FB_STIP_ALLONES,FB_STIP_ALLONES), 362706f2543Smrg fbAndStip(GXcopy,0,FB_STIP_ALLONES), 363706f2543Smrg fbXorStip(GXcopy,0,FB_STIP_ALLONES), 364706f2543Smrg planeMask); 365706f2543Smrg } 366706f2543Smrg 367706f2543Smrg fbFinishAccess (pDrawable); 368706f2543Smrg} 369