1/* 2 * Copyright © 1998 Keith Packard 3 * Copyright © 2012 Intel Corporation 4 * 5 * Permission to use, copy, modify, distribute, and sell this software and its 6 * documentation for any purpose is hereby granted without fee, provided that 7 * the above copyright notice appear in all copies and that both that 8 * copyright notice and this permission notice appear in supporting 9 * documentation, and that the name of Keith Packard not be used in 10 * advertising or publicity pertaining to distribution of the software without 11 * specific, written prior permission. Keith Packard makes no 12 * representations about the suitability of this software for any purpose. It 13 * is provided "as is" without express or implied warranty. 14 * 15 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 17 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21 * PERFORMANCE OF THIS SOFTWARE. 22 */ 23 24#include "fb.h" 25#include <gcstruct.h> 26#include <scrnintstr.h> 27 28/* 29 * Pad pixmap to FB_UNIT bits wide 30 */ 31void 32fbPadPixmap(PixmapPtr pPixmap) 33{ 34 int width; 35 FbBits *bits; 36 FbBits b; 37 FbBits mask; 38 int height; 39 int w; 40 int stride; 41 int bpp; 42 _X_UNUSED int xOff, yOff; 43 44 fbGetDrawable(&pPixmap->drawable, bits, stride, bpp, xOff, yOff); 45 46 width = pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel; 47 height = pPixmap->drawable.height; 48 mask = FbBitsMask(0, width); 49 while (height--) { 50 b = READ(bits) & mask; 51 w = width; 52 while (w < FB_UNIT) { 53 b = b | FbScrRight(b, w); 54 w <<= 1; 55 } 56 WRITE(bits, b); 57 bits += stride; 58 } 59} 60 61/* 62 * Verify that 'bits' repeats every 'len' bits 63 */ 64static Bool 65fbBitsRepeat(FbBits bits, int len, int width) 66{ 67 FbBits mask = FbBitsMask(0, len); 68 FbBits orig = bits & mask; 69 int i; 70 71 if (width > FB_UNIT) 72 width = FB_UNIT; 73 for (i = 0; i < width / len; i++) { 74 if ((bits & mask) != orig) 75 return FALSE; 76 bits = FbScrLeft(bits, len); 77 } 78 return TRUE; 79} 80 81/* 82 * Check whether an entire bitmap line is a repetition of 83 * the first 'len' bits 84 */ 85static Bool 86fbLineRepeat(FbBits * bits, int len, int width) 87{ 88 FbBits first = bits[0]; 89 90 if (!fbBitsRepeat(first, len, width)) 91 return FALSE; 92 width = (width + FB_UNIT - 1) >> FB_SHIFT; 93 bits++; 94 while (--width) 95 if (READ(bits) != first) 96 return FALSE; 97 return TRUE; 98} 99 100/* 101 * The even stipple code wants the first FB_UNIT/bpp bits on 102 * each scanline to represent the entire stipple 103 */ 104static Bool 105fbCanEvenStipple(PixmapPtr pStipple, int bpp) 106{ 107 int len = FB_UNIT / bpp; 108 FbBits *bits; 109 int stride; 110 int stip_bpp; 111 _X_UNUSED int stipXoff, stipYoff; 112 int h; 113 114 /* make sure the stipple width is a multiple of the even stipple width */ 115 if (pStipple->drawable.width % len != 0) 116 return FALSE; 117 118 fbGetDrawable(&pStipple->drawable, bits, stride, stip_bpp, stipXoff, 119 stipYoff); 120 h = pStipple->drawable.height; 121 /* check to see that the stipple repeats horizontally */ 122 while (h--) { 123 if (!fbLineRepeat(bits, len, pStipple->drawable.width)) 124 return FALSE; 125 126 bits += stride; 127 } 128 return TRUE; 129} 130 131void 132fbValidateGC(GCPtr gc, unsigned long changes, DrawablePtr drawable) 133{ 134 FbGCPrivPtr pgc = fb_gc(gc); 135 FbBits mask; 136 137 DBG(("%s changes=%lx\n", __FUNCTION__, changes)); 138 139 if (changes & GCStipple) { 140 pgc->evenStipple = FALSE; 141 142 if (gc->stipple) { 143 /* can we do an even stipple ?? */ 144 if (FbEvenStip(gc->stipple->drawable.width, 145 drawable->bitsPerPixel) && 146 (fbCanEvenStipple(gc->stipple, drawable->bitsPerPixel))) 147 pgc->evenStipple = TRUE; 148 } 149 } 150 151 /* 152 * Recompute reduced rop values 153 */ 154 if (changes & (GCForeground | GCBackground | GCPlaneMask | GCFunction)) { 155 int s; 156 FbBits depthMask; 157 158 mask = FbFullMask(drawable->bitsPerPixel); 159 depthMask = FbFullMask(drawable->depth); 160 161 DBG(("%s: computing rrop mask=%08x, depthMask=%08x, fg=%08x, bg=%08x, planemask=%08x\n", 162 __FUNCTION__, mask, depthMask, (int)gc->fgPixel, (int)gc->bgPixel, (int)gc->planemask)); 163 164 pgc->fg = gc->fgPixel & mask; 165 pgc->bg = gc->bgPixel & mask; 166 167 if ((gc->planemask & depthMask) == depthMask) 168 pgc->pm = mask; 169 else 170 pgc->pm = gc->planemask & mask; 171 172 s = drawable->bitsPerPixel; 173 while (s < FB_UNIT) { 174 pgc->fg |= pgc->fg << s; 175 pgc->bg |= pgc->bg << s; 176 pgc->pm |= pgc->pm << s; 177 s <<= 1; 178 } 179 pgc->and = fbAnd(gc->alu, pgc->fg, pgc->pm); 180 pgc->xor = fbXor(gc->alu, pgc->fg, pgc->pm); 181 pgc->bgand = fbAnd(gc->alu, pgc->bg, pgc->pm); 182 pgc->bgxor = fbXor(gc->alu, pgc->bg, pgc->pm); 183 184 DBG(("%s: rrop fg=%08x, bg=%08x, pm=%08x, and=%08x, xor=%08x, bgand=%08x, bgxor=%08x\n", 185 __FUNCTION__, pgc->fg, pgc->bg, pgc->pm, pgc->and, pgc->xor, pgc->bgand, pgc->bgxor)); 186 } 187 188 if (changes & GCDashList) { 189 unsigned short n = gc->numInDashList; 190 unsigned char *dash = gc->dash; 191 unsigned int dashLength = 0; 192 193 while (n--) 194 dashLength += (unsigned int) *dash++; 195 pgc->dashLength = dashLength; 196 } 197} 198