103b705cfSriastradh/* 203b705cfSriastradh * Copyright © 1998 Keith Packard 303b705cfSriastradh * Copyright © 2012 Intel Corporation 403b705cfSriastradh * 503b705cfSriastradh * Permission to use, copy, modify, distribute, and sell this software and its 603b705cfSriastradh * documentation for any purpose is hereby granted without fee, provided that 703b705cfSriastradh * the above copyright notice appear in all copies and that both that 803b705cfSriastradh * copyright notice and this permission notice appear in supporting 903b705cfSriastradh * documentation, and that the name of Keith Packard not be used in 1003b705cfSriastradh * advertising or publicity pertaining to distribution of the software without 1103b705cfSriastradh * specific, written prior permission. Keith Packard makes no 1203b705cfSriastradh * representations about the suitability of this software for any purpose. It 1303b705cfSriastradh * is provided "as is" without express or implied warranty. 1403b705cfSriastradh * 1503b705cfSriastradh * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1603b705cfSriastradh * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1703b705cfSriastradh * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1803b705cfSriastradh * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1903b705cfSriastradh * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 2003b705cfSriastradh * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2103b705cfSriastradh * PERFORMANCE OF THIS SOFTWARE. 2203b705cfSriastradh */ 2303b705cfSriastradh 2403b705cfSriastradh#include "fb.h" 2503b705cfSriastradh#include <gcstruct.h> 2603b705cfSriastradh#include <scrnintstr.h> 2703b705cfSriastradh 2803b705cfSriastradh/* 2903b705cfSriastradh * Pad pixmap to FB_UNIT bits wide 3003b705cfSriastradh */ 3103b705cfSriastradhvoid 3203b705cfSriastradhfbPadPixmap(PixmapPtr pPixmap) 3303b705cfSriastradh{ 3403b705cfSriastradh int width; 3503b705cfSriastradh FbBits *bits; 3603b705cfSriastradh FbBits b; 3703b705cfSriastradh FbBits mask; 3803b705cfSriastradh int height; 3903b705cfSriastradh int w; 4003b705cfSriastradh int stride; 4103b705cfSriastradh int bpp; 4203b705cfSriastradh _X_UNUSED int xOff, yOff; 4303b705cfSriastradh 4403b705cfSriastradh fbGetDrawable(&pPixmap->drawable, bits, stride, bpp, xOff, yOff); 4503b705cfSriastradh 4603b705cfSriastradh width = pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel; 4703b705cfSriastradh height = pPixmap->drawable.height; 4803b705cfSriastradh mask = FbBitsMask(0, width); 4903b705cfSriastradh while (height--) { 5003b705cfSriastradh b = READ(bits) & mask; 5103b705cfSriastradh w = width; 5203b705cfSriastradh while (w < FB_UNIT) { 5303b705cfSriastradh b = b | FbScrRight(b, w); 5403b705cfSriastradh w <<= 1; 5503b705cfSriastradh } 5603b705cfSriastradh WRITE(bits, b); 5703b705cfSriastradh bits += stride; 5803b705cfSriastradh } 5903b705cfSriastradh} 6003b705cfSriastradh 6103b705cfSriastradh/* 6203b705cfSriastradh * Verify that 'bits' repeats every 'len' bits 6303b705cfSriastradh */ 6403b705cfSriastradhstatic Bool 6503b705cfSriastradhfbBitsRepeat(FbBits bits, int len, int width) 6603b705cfSriastradh{ 6703b705cfSriastradh FbBits mask = FbBitsMask(0, len); 6803b705cfSriastradh FbBits orig = bits & mask; 6903b705cfSriastradh int i; 7003b705cfSriastradh 7103b705cfSriastradh if (width > FB_UNIT) 7203b705cfSriastradh width = FB_UNIT; 7303b705cfSriastradh for (i = 0; i < width / len; i++) { 7403b705cfSriastradh if ((bits & mask) != orig) 7503b705cfSriastradh return FALSE; 7603b705cfSriastradh bits = FbScrLeft(bits, len); 7703b705cfSriastradh } 7803b705cfSriastradh return TRUE; 7903b705cfSriastradh} 8003b705cfSriastradh 8103b705cfSriastradh/* 8203b705cfSriastradh * Check whether an entire bitmap line is a repetition of 8303b705cfSriastradh * the first 'len' bits 8403b705cfSriastradh */ 8503b705cfSriastradhstatic Bool 8603b705cfSriastradhfbLineRepeat(FbBits * bits, int len, int width) 8703b705cfSriastradh{ 8803b705cfSriastradh FbBits first = bits[0]; 8903b705cfSriastradh 9003b705cfSriastradh if (!fbBitsRepeat(first, len, width)) 9103b705cfSriastradh return FALSE; 9203b705cfSriastradh width = (width + FB_UNIT - 1) >> FB_SHIFT; 9303b705cfSriastradh bits++; 9403b705cfSriastradh while (--width) 9503b705cfSriastradh if (READ(bits) != first) 9603b705cfSriastradh return FALSE; 9703b705cfSriastradh return TRUE; 9803b705cfSriastradh} 9903b705cfSriastradh 10003b705cfSriastradh/* 10103b705cfSriastradh * The even stipple code wants the first FB_UNIT/bpp bits on 10203b705cfSriastradh * each scanline to represent the entire stipple 10303b705cfSriastradh */ 10403b705cfSriastradhstatic Bool 10503b705cfSriastradhfbCanEvenStipple(PixmapPtr pStipple, int bpp) 10603b705cfSriastradh{ 10703b705cfSriastradh int len = FB_UNIT / bpp; 10803b705cfSriastradh FbBits *bits; 10903b705cfSriastradh int stride; 11003b705cfSriastradh int stip_bpp; 11103b705cfSriastradh _X_UNUSED int stipXoff, stipYoff; 11203b705cfSriastradh int h; 11303b705cfSriastradh 11403b705cfSriastradh /* make sure the stipple width is a multiple of the even stipple width */ 11503b705cfSriastradh if (pStipple->drawable.width % len != 0) 11603b705cfSriastradh return FALSE; 11703b705cfSriastradh 11803b705cfSriastradh fbGetDrawable(&pStipple->drawable, bits, stride, stip_bpp, stipXoff, 11903b705cfSriastradh stipYoff); 12003b705cfSriastradh h = pStipple->drawable.height; 12103b705cfSriastradh /* check to see that the stipple repeats horizontally */ 12203b705cfSriastradh while (h--) { 12303b705cfSriastradh if (!fbLineRepeat(bits, len, pStipple->drawable.width)) 12403b705cfSriastradh return FALSE; 12503b705cfSriastradh 12603b705cfSriastradh bits += stride; 12703b705cfSriastradh } 12803b705cfSriastradh return TRUE; 12903b705cfSriastradh} 13003b705cfSriastradh 13103b705cfSriastradhvoid 13203b705cfSriastradhfbValidateGC(GCPtr gc, unsigned long changes, DrawablePtr drawable) 13303b705cfSriastradh{ 13403b705cfSriastradh FbGCPrivPtr pgc = fb_gc(gc); 13503b705cfSriastradh FbBits mask; 13603b705cfSriastradh 13703b705cfSriastradh DBG(("%s changes=%lx\n", __FUNCTION__, changes)); 13803b705cfSriastradh 13903b705cfSriastradh if (changes & GCStipple) { 14003b705cfSriastradh pgc->evenStipple = FALSE; 14103b705cfSriastradh 14203b705cfSriastradh if (gc->stipple) { 14303b705cfSriastradh /* can we do an even stipple ?? */ 14403b705cfSriastradh if (FbEvenStip(gc->stipple->drawable.width, 14503b705cfSriastradh drawable->bitsPerPixel) && 14603b705cfSriastradh (fbCanEvenStipple(gc->stipple, drawable->bitsPerPixel))) 14703b705cfSriastradh pgc->evenStipple = TRUE; 14803b705cfSriastradh } 14903b705cfSriastradh } 15003b705cfSriastradh 15103b705cfSriastradh /* 15203b705cfSriastradh * Recompute reduced rop values 15303b705cfSriastradh */ 15403b705cfSriastradh if (changes & (GCForeground | GCBackground | GCPlaneMask | GCFunction)) { 15503b705cfSriastradh int s; 15603b705cfSriastradh FbBits depthMask; 15703b705cfSriastradh 15803b705cfSriastradh mask = FbFullMask(drawable->bitsPerPixel); 15903b705cfSriastradh depthMask = FbFullMask(drawable->depth); 16003b705cfSriastradh 16103b705cfSriastradh DBG(("%s: computing rrop mask=%08x, depthMask=%08x, fg=%08x, bg=%08x, planemask=%08x\n", 16203b705cfSriastradh __FUNCTION__, mask, depthMask, (int)gc->fgPixel, (int)gc->bgPixel, (int)gc->planemask)); 16303b705cfSriastradh 16403b705cfSriastradh pgc->fg = gc->fgPixel & mask; 16503b705cfSriastradh pgc->bg = gc->bgPixel & mask; 16603b705cfSriastradh 16703b705cfSriastradh if ((gc->planemask & depthMask) == depthMask) 16803b705cfSriastradh pgc->pm = mask; 16903b705cfSriastradh else 17003b705cfSriastradh pgc->pm = gc->planemask & mask; 17103b705cfSriastradh 17203b705cfSriastradh s = drawable->bitsPerPixel; 17303b705cfSriastradh while (s < FB_UNIT) { 17403b705cfSriastradh pgc->fg |= pgc->fg << s; 17503b705cfSriastradh pgc->bg |= pgc->bg << s; 17603b705cfSriastradh pgc->pm |= pgc->pm << s; 17703b705cfSriastradh s <<= 1; 17803b705cfSriastradh } 17903b705cfSriastradh pgc->and = fbAnd(gc->alu, pgc->fg, pgc->pm); 18003b705cfSriastradh pgc->xor = fbXor(gc->alu, pgc->fg, pgc->pm); 18103b705cfSriastradh pgc->bgand = fbAnd(gc->alu, pgc->bg, pgc->pm); 18203b705cfSriastradh pgc->bgxor = fbXor(gc->alu, pgc->bg, pgc->pm); 18303b705cfSriastradh 18403b705cfSriastradh DBG(("%s: rrop fg=%08x, bg=%08x, pm=%08x, and=%08x, xor=%08x, bgand=%08x, bgxor=%08x\n", 18503b705cfSriastradh __FUNCTION__, pgc->fg, pgc->bg, pgc->pm, pgc->and, pgc->xor, pgc->bgand, pgc->bgxor)); 18603b705cfSriastradh } 18703b705cfSriastradh 18803b705cfSriastradh if (changes & GCDashList) { 18903b705cfSriastradh unsigned short n = gc->numInDashList; 19003b705cfSriastradh unsigned char *dash = gc->dash; 19103b705cfSriastradh unsigned int dashLength = 0; 19203b705cfSriastradh 19303b705cfSriastradh while (n--) 19403b705cfSriastradh dashLength += (unsigned int) *dash++; 19503b705cfSriastradh pgc->dashLength = dashLength; 19603b705cfSriastradh } 19703b705cfSriastradh} 198