1428d7b3dSmrg/* 2428d7b3dSmrg * Copyright © 1998 Keith Packard 3428d7b3dSmrg * Copyright © 2012 Intel Corporation 4428d7b3dSmrg * 5428d7b3dSmrg * Permission to use, copy, modify, distribute, and sell this software and its 6428d7b3dSmrg * documentation for any purpose is hereby granted without fee, provided that 7428d7b3dSmrg * the above copyright notice appear in all copies and that both that 8428d7b3dSmrg * copyright notice and this permission notice appear in supporting 9428d7b3dSmrg * documentation, and that the name of Keith Packard not be used in 10428d7b3dSmrg * advertising or publicity pertaining to distribution of the software without 11428d7b3dSmrg * specific, written prior permission. Keith Packard makes no 12428d7b3dSmrg * representations about the suitability of this software for any purpose. It 13428d7b3dSmrg * is provided "as is" without express or implied warranty. 14428d7b3dSmrg * 15428d7b3dSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16428d7b3dSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 17428d7b3dSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 18428d7b3dSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 19428d7b3dSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 20428d7b3dSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21428d7b3dSmrg * PERFORMANCE OF THIS SOFTWARE. 22428d7b3dSmrg */ 23428d7b3dSmrg 24428d7b3dSmrg#include "fb.h" 25428d7b3dSmrg#include <gcstruct.h> 26428d7b3dSmrg#include <scrnintstr.h> 27428d7b3dSmrg 28428d7b3dSmrg/* 29428d7b3dSmrg * Pad pixmap to FB_UNIT bits wide 30428d7b3dSmrg */ 31428d7b3dSmrgvoid 32428d7b3dSmrgfbPadPixmap(PixmapPtr pPixmap) 33428d7b3dSmrg{ 34428d7b3dSmrg int width; 35428d7b3dSmrg FbBits *bits; 36428d7b3dSmrg FbBits b; 37428d7b3dSmrg FbBits mask; 38428d7b3dSmrg int height; 39428d7b3dSmrg int w; 40428d7b3dSmrg int stride; 41428d7b3dSmrg int bpp; 42428d7b3dSmrg _X_UNUSED int xOff, yOff; 43428d7b3dSmrg 44428d7b3dSmrg fbGetDrawable(&pPixmap->drawable, bits, stride, bpp, xOff, yOff); 45428d7b3dSmrg 46428d7b3dSmrg width = pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel; 47428d7b3dSmrg height = pPixmap->drawable.height; 48428d7b3dSmrg mask = FbBitsMask(0, width); 49428d7b3dSmrg while (height--) { 50428d7b3dSmrg b = READ(bits) & mask; 51428d7b3dSmrg w = width; 52428d7b3dSmrg while (w < FB_UNIT) { 53428d7b3dSmrg b = b | FbScrRight(b, w); 54428d7b3dSmrg w <<= 1; 55428d7b3dSmrg } 56428d7b3dSmrg WRITE(bits, b); 57428d7b3dSmrg bits += stride; 58428d7b3dSmrg } 59428d7b3dSmrg} 60428d7b3dSmrg 61428d7b3dSmrg/* 62428d7b3dSmrg * Verify that 'bits' repeats every 'len' bits 63428d7b3dSmrg */ 64428d7b3dSmrgstatic Bool 65428d7b3dSmrgfbBitsRepeat(FbBits bits, int len, int width) 66428d7b3dSmrg{ 67428d7b3dSmrg FbBits mask = FbBitsMask(0, len); 68428d7b3dSmrg FbBits orig = bits & mask; 69428d7b3dSmrg int i; 70428d7b3dSmrg 71428d7b3dSmrg if (width > FB_UNIT) 72428d7b3dSmrg width = FB_UNIT; 73428d7b3dSmrg for (i = 0; i < width / len; i++) { 74428d7b3dSmrg if ((bits & mask) != orig) 75428d7b3dSmrg return FALSE; 76428d7b3dSmrg bits = FbScrLeft(bits, len); 77428d7b3dSmrg } 78428d7b3dSmrg return TRUE; 79428d7b3dSmrg} 80428d7b3dSmrg 81428d7b3dSmrg/* 82428d7b3dSmrg * Check whether an entire bitmap line is a repetition of 83428d7b3dSmrg * the first 'len' bits 84428d7b3dSmrg */ 85428d7b3dSmrgstatic Bool 86428d7b3dSmrgfbLineRepeat(FbBits * bits, int len, int width) 87428d7b3dSmrg{ 88428d7b3dSmrg FbBits first = bits[0]; 89428d7b3dSmrg 90428d7b3dSmrg if (!fbBitsRepeat(first, len, width)) 91428d7b3dSmrg return FALSE; 92428d7b3dSmrg width = (width + FB_UNIT - 1) >> FB_SHIFT; 93428d7b3dSmrg bits++; 94428d7b3dSmrg while (--width) 95428d7b3dSmrg if (READ(bits) != first) 96428d7b3dSmrg return FALSE; 97428d7b3dSmrg return TRUE; 98428d7b3dSmrg} 99428d7b3dSmrg 100428d7b3dSmrg/* 101428d7b3dSmrg * The even stipple code wants the first FB_UNIT/bpp bits on 102428d7b3dSmrg * each scanline to represent the entire stipple 103428d7b3dSmrg */ 104428d7b3dSmrgstatic Bool 105428d7b3dSmrgfbCanEvenStipple(PixmapPtr pStipple, int bpp) 106428d7b3dSmrg{ 107428d7b3dSmrg int len = FB_UNIT / bpp; 108428d7b3dSmrg FbBits *bits; 109428d7b3dSmrg int stride; 110428d7b3dSmrg int stip_bpp; 111428d7b3dSmrg _X_UNUSED int stipXoff, stipYoff; 112428d7b3dSmrg int h; 113428d7b3dSmrg 114428d7b3dSmrg /* make sure the stipple width is a multiple of the even stipple width */ 115428d7b3dSmrg if (pStipple->drawable.width % len != 0) 116428d7b3dSmrg return FALSE; 117428d7b3dSmrg 118428d7b3dSmrg fbGetDrawable(&pStipple->drawable, bits, stride, stip_bpp, stipXoff, 119428d7b3dSmrg stipYoff); 120428d7b3dSmrg h = pStipple->drawable.height; 121428d7b3dSmrg /* check to see that the stipple repeats horizontally */ 122428d7b3dSmrg while (h--) { 123428d7b3dSmrg if (!fbLineRepeat(bits, len, pStipple->drawable.width)) 124428d7b3dSmrg return FALSE; 125428d7b3dSmrg 126428d7b3dSmrg bits += stride; 127428d7b3dSmrg } 128428d7b3dSmrg return TRUE; 129428d7b3dSmrg} 130428d7b3dSmrg 131428d7b3dSmrgvoid 132428d7b3dSmrgfbValidateGC(GCPtr gc, unsigned long changes, DrawablePtr drawable) 133428d7b3dSmrg{ 134428d7b3dSmrg FbGCPrivPtr pgc = fb_gc(gc); 135428d7b3dSmrg FbBits mask; 136428d7b3dSmrg 137428d7b3dSmrg DBG(("%s changes=%lx\n", __FUNCTION__, changes)); 138428d7b3dSmrg 139428d7b3dSmrg if (changes & GCStipple) { 140428d7b3dSmrg pgc->evenStipple = FALSE; 141428d7b3dSmrg 142428d7b3dSmrg if (gc->stipple) { 143428d7b3dSmrg /* can we do an even stipple ?? */ 144428d7b3dSmrg if (FbEvenStip(gc->stipple->drawable.width, 145428d7b3dSmrg drawable->bitsPerPixel) && 146428d7b3dSmrg (fbCanEvenStipple(gc->stipple, drawable->bitsPerPixel))) 147428d7b3dSmrg pgc->evenStipple = TRUE; 148428d7b3dSmrg } 149428d7b3dSmrg } 150428d7b3dSmrg 151428d7b3dSmrg /* 152428d7b3dSmrg * Recompute reduced rop values 153428d7b3dSmrg */ 154428d7b3dSmrg if (changes & (GCForeground | GCBackground | GCPlaneMask | GCFunction)) { 155428d7b3dSmrg int s; 156428d7b3dSmrg FbBits depthMask; 157428d7b3dSmrg 158428d7b3dSmrg mask = FbFullMask(drawable->bitsPerPixel); 159428d7b3dSmrg depthMask = FbFullMask(drawable->depth); 160428d7b3dSmrg 161428d7b3dSmrg DBG(("%s: computing rrop mask=%08x, depthMask=%08x, fg=%08x, bg=%08x, planemask=%08x\n", 162428d7b3dSmrg __FUNCTION__, mask, depthMask, (int)gc->fgPixel, (int)gc->bgPixel, (int)gc->planemask)); 163428d7b3dSmrg 164428d7b3dSmrg pgc->fg = gc->fgPixel & mask; 165428d7b3dSmrg pgc->bg = gc->bgPixel & mask; 166428d7b3dSmrg 167428d7b3dSmrg if ((gc->planemask & depthMask) == depthMask) 168428d7b3dSmrg pgc->pm = mask; 169428d7b3dSmrg else 170428d7b3dSmrg pgc->pm = gc->planemask & mask; 171428d7b3dSmrg 172428d7b3dSmrg s = drawable->bitsPerPixel; 173428d7b3dSmrg while (s < FB_UNIT) { 174428d7b3dSmrg pgc->fg |= pgc->fg << s; 175428d7b3dSmrg pgc->bg |= pgc->bg << s; 176428d7b3dSmrg pgc->pm |= pgc->pm << s; 177428d7b3dSmrg s <<= 1; 178428d7b3dSmrg } 179428d7b3dSmrg pgc->and = fbAnd(gc->alu, pgc->fg, pgc->pm); 180428d7b3dSmrg pgc->xor = fbXor(gc->alu, pgc->fg, pgc->pm); 181428d7b3dSmrg pgc->bgand = fbAnd(gc->alu, pgc->bg, pgc->pm); 182428d7b3dSmrg pgc->bgxor = fbXor(gc->alu, pgc->bg, pgc->pm); 183428d7b3dSmrg 184428d7b3dSmrg DBG(("%s: rrop fg=%08x, bg=%08x, pm=%08x, and=%08x, xor=%08x, bgand=%08x, bgxor=%08x\n", 185428d7b3dSmrg __FUNCTION__, pgc->fg, pgc->bg, pgc->pm, pgc->and, pgc->xor, pgc->bgand, pgc->bgxor)); 186428d7b3dSmrg } 187428d7b3dSmrg 188428d7b3dSmrg if (changes & GCDashList) { 189428d7b3dSmrg unsigned short n = gc->numInDashList; 190428d7b3dSmrg unsigned char *dash = gc->dash; 191428d7b3dSmrg unsigned int dashLength = 0; 192428d7b3dSmrg 193428d7b3dSmrg while (n--) 194428d7b3dSmrg dashLength += (unsigned int) *dash++; 195428d7b3dSmrg pgc->dashLength = dashLength; 196428d7b3dSmrg } 197428d7b3dSmrg} 198