mirror of
https://github.com/Stichting-MINIX-Research-Foundation/xsrc.git
synced 2025-09-16 08:05:30 -04:00
2911 lines
70 KiB
C
2911 lines
70 KiB
C
/*
|
|
static char *rid="$Xorg: sunGX.c,v 1.5 2001/02/09 02:04:44 xorgcvs Exp $";
|
|
*/
|
|
/*
|
|
Copyright 1991, 1998 The Open Group
|
|
|
|
Permission to use, copy, modify, distribute, and sell this software and its
|
|
documentation for any purpose is hereby granted without fee, provided that
|
|
the above copyright notice appear in all copies and that both that
|
|
copyright notice and this permission notice appear in supporting
|
|
documentation.
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
Except as contained in this notice, the name of The Open Group shall not be
|
|
used in advertising or otherwise to promote the sale, use or other dealings
|
|
in this Software without prior written authorization from The Open Group.
|
|
*
|
|
* Author: Keith Packard, MIT X Consortium
|
|
*/
|
|
|
|
/* $XFree86: xc/programs/Xserver/hw/sun/sunGX.c,v 1.9 2003/11/17 22:20:36 dawes Exp $ */
|
|
|
|
#include "sun.h"
|
|
|
|
#include "Xmd.h"
|
|
#include "gcstruct.h"
|
|
#include "scrnintstr.h"
|
|
#include "pixmapstr.h"
|
|
#include "regionstr.h"
|
|
#include "mistruct.h"
|
|
#include "fontstruct.h"
|
|
#include "dixfontstr.h"
|
|
#include "cfb/cfb.h"
|
|
#include "cfb/cfbmskbits.h"
|
|
#include "cfb/cfb8bit.h"
|
|
#include "fastblt.h"
|
|
#include "mergerop.h"
|
|
#include "sunGX.h"
|
|
#include "migc.h"
|
|
#include "mispans.h"
|
|
|
|
#define sunGXFillSpan(gx,y,x1,x2,r) {\
|
|
(gx)->apointy = (y); \
|
|
(gx)->apointx = (x1); \
|
|
(gx)->arectx = (x2); \
|
|
GXDrawDone(gx,r); \
|
|
}
|
|
|
|
#define GXSetClip(gx,pbox) {\
|
|
(gx)->clipminx = (pbox)->x1; \
|
|
(gx)->clipminy = (pbox)->y1; \
|
|
(gx)->clipmaxx = (pbox)->x2 - 1; \
|
|
(gx)->clipmaxy = (pbox)->y2 - 1; \
|
|
}
|
|
|
|
#define GXSetOff(gx,x,y) {\
|
|
(gx)->offx = (x); \
|
|
(gx)->offy = (y); \
|
|
}
|
|
|
|
#define GXResetClip(gx,pScreen) { \
|
|
(gx)->clipminx = 0; \
|
|
(gx)->clipminy = 0; \
|
|
(gx)->clipmaxx = (pScreen)->width - 1; \
|
|
(gx)->clipmaxy = (pScreen)->height - 1; \
|
|
}
|
|
|
|
#define GXResetOff(gx) {\
|
|
(gx)->offx = 0; \
|
|
(gx)->offy = 0; \
|
|
}
|
|
|
|
#define sunGXGetAddrRange(pDrawable,extents,base,lo,hi) {\
|
|
int __x__; \
|
|
cfbGetWindowByteWidthAndPointer((WindowPtr)pDrawable,__x__,base); \
|
|
lo = (base) + WIDTH_MUL((extents)->y1) + (extents)->x1; \
|
|
hi = (base) + WIDTH_MUL((extents)->y2 - 1) + (extents)->x2 - 1; \
|
|
(base) = (base) + WIDTH_MUL(pDrawable->y) + pDrawable->x; \
|
|
}
|
|
|
|
/*
|
|
rop_tables
|
|
==========
|
|
lookup tables for GX raster ops, with the plane_mask,pixel_mask,pattern_mask
|
|
,attrib_sel, polygon_draw,raster_mode encoded into the top half.
|
|
There is a lookup table for each commonly used combination.
|
|
*/
|
|
|
|
/* rops for bit blit / copy area
|
|
with:
|
|
Plane Mask - use plane mask reg.
|
|
Pixel Mask - use all ones.
|
|
Patt Mask - use all ones.
|
|
*/
|
|
|
|
#define POLY_O GX_POLYG_OVERLAP
|
|
#define POLY_N GX_POLYG_NONOVERLAP
|
|
|
|
#define ROP_STANDARD (GX_PLANE_MASK |\
|
|
GX_PIXEL_ONES |\
|
|
GX_ATTR_SUPP |\
|
|
GX_RAST_BOOL |\
|
|
GX_PLOT_PLOT)
|
|
|
|
/* fg = don't care bg = don't care */
|
|
|
|
#define ROP_BLIT(O,I) (ROP_STANDARD | \
|
|
GX_PATTERN_ONES |\
|
|
GX_ROP_11_1(I) |\
|
|
GX_ROP_11_0(O) |\
|
|
GX_ROP_10_1(I) |\
|
|
GX_ROP_10_0(O) |\
|
|
GX_ROP_01_1(I) |\
|
|
GX_ROP_01_0(O) |\
|
|
GX_ROP_00_1(I) |\
|
|
GX_ROP_00_0(O))
|
|
|
|
/* fg = fgPixel bg = don't care */
|
|
|
|
#define ROP_FILL(O,I) (ROP_STANDARD | \
|
|
GX_PATTERN_ONES |\
|
|
GX_ROP_11_1(I) |\
|
|
GX_ROP_11_0(I) |\
|
|
GX_ROP_10_1(I) |\
|
|
GX_ROP_10_0(I) | \
|
|
GX_ROP_01_1(O) |\
|
|
GX_ROP_01_0(O) |\
|
|
GX_ROP_00_1(O) |\
|
|
GX_ROP_00_0(O))
|
|
|
|
/* fg = fgPixel bg = don't care */
|
|
|
|
#define ROP_STIP(O,I) (ROP_STANDARD |\
|
|
GX_ROP_11_1(I) |\
|
|
GX_ROP_11_0(GX_ROP_NOOP) |\
|
|
GX_ROP_10_1(I) |\
|
|
GX_ROP_10_0(GX_ROP_NOOP) | \
|
|
GX_ROP_01_1(O) |\
|
|
GX_ROP_01_0(GX_ROP_NOOP) |\
|
|
GX_ROP_00_1(O) |\
|
|
GX_ROP_00_0(GX_ROP_NOOP))
|
|
|
|
/* fg = fgPixel bg = bgPixel */
|
|
|
|
#define ROP_OSTP(O,I) (ROP_STANDARD |\
|
|
GX_ROP_11_1(I) |\
|
|
GX_ROP_11_0(I) |\
|
|
GX_ROP_10_1(I) |\
|
|
GX_ROP_10_0(O) |\
|
|
GX_ROP_01_1(O) |\
|
|
GX_ROP_01_0(I) |\
|
|
GX_ROP_00_1(O) |\
|
|
GX_ROP_00_0(O))
|
|
|
|
#define ROP_ITXT(O,I) (ROP_STANDARD |\
|
|
GX_PATTERN_ONES |\
|
|
GX_ROP_11_1(I) |\
|
|
GX_ROP_11_0(I) |\
|
|
GX_ROP_10_1(I) |\
|
|
GX_ROP_10_0(O) |\
|
|
GX_ROP_01_1(O) |\
|
|
GX_ROP_01_0(I) |\
|
|
GX_ROP_00_1(O) |\
|
|
GX_ROP_00_0(O))
|
|
|
|
#define ROP_PTXT(O,I) (ROP_STANDARD |\
|
|
GX_PATTERN_ONES |\
|
|
GX_ROP_11_1(I) |\
|
|
GX_ROP_11_0(GX_ROP_NOOP) |\
|
|
GX_ROP_10_1(I) |\
|
|
GX_ROP_10_0(GX_ROP_NOOP) | \
|
|
GX_ROP_01_1(O) |\
|
|
GX_ROP_01_0(GX_ROP_NOOP) |\
|
|
GX_ROP_00_1(O) |\
|
|
GX_ROP_00_0(GX_ROP_NOOP))
|
|
|
|
static Uint gx_blit_rop_table[16]={
|
|
ROP_BLIT(GX_ROP_CLEAR, GX_ROP_CLEAR), /* GXclear */
|
|
ROP_BLIT(GX_ROP_CLEAR, GX_ROP_NOOP), /* GXand */
|
|
ROP_BLIT(GX_ROP_CLEAR, GX_ROP_INVERT), /* GXandReverse */
|
|
ROP_BLIT(GX_ROP_CLEAR, GX_ROP_SET), /* GXcopy */
|
|
ROP_BLIT(GX_ROP_NOOP, GX_ROP_CLEAR), /* GXandInverted */
|
|
ROP_BLIT(GX_ROP_NOOP, GX_ROP_NOOP), /* GXnoop */
|
|
ROP_BLIT(GX_ROP_NOOP, GX_ROP_INVERT), /* GXxor */
|
|
ROP_BLIT(GX_ROP_NOOP, GX_ROP_SET), /* GXor */
|
|
ROP_BLIT(GX_ROP_INVERT, GX_ROP_CLEAR), /* GXnor */
|
|
ROP_BLIT(GX_ROP_INVERT, GX_ROP_NOOP), /* GXequiv */
|
|
ROP_BLIT(GX_ROP_INVERT, GX_ROP_INVERT), /* GXinvert */
|
|
ROP_BLIT(GX_ROP_INVERT, GX_ROP_SET), /* GXorReverse */
|
|
ROP_BLIT(GX_ROP_SET, GX_ROP_CLEAR), /* GXcopyInverted */
|
|
ROP_BLIT(GX_ROP_SET, GX_ROP_NOOP), /* GXorInverted */
|
|
ROP_BLIT(GX_ROP_SET, GX_ROP_INVERT), /* GXnand */
|
|
ROP_BLIT(GX_ROP_SET, GX_ROP_SET), /* GXset */
|
|
};
|
|
|
|
/* rops for solid drawing
|
|
with:
|
|
Plane Mask - use plane mask reg.
|
|
Pixel Mask - use all ones.
|
|
Patt Mask - use all ones.
|
|
*/
|
|
|
|
static Uint gx_solid_rop_table[16]={
|
|
ROP_FILL(GX_ROP_CLEAR, GX_ROP_CLEAR), /* GXclear */
|
|
ROP_FILL(GX_ROP_CLEAR, GX_ROP_NOOP), /* GXand */
|
|
ROP_FILL(GX_ROP_CLEAR, GX_ROP_INVERT), /* GXandReverse */
|
|
ROP_FILL(GX_ROP_CLEAR, GX_ROP_SET), /* GXcopy */
|
|
ROP_FILL(GX_ROP_NOOP, GX_ROP_CLEAR), /* GXandInverted */
|
|
ROP_FILL(GX_ROP_NOOP, GX_ROP_NOOP), /* GXnoop */
|
|
ROP_FILL(GX_ROP_NOOP, GX_ROP_INVERT), /* GXxor */
|
|
ROP_FILL(GX_ROP_NOOP, GX_ROP_SET), /* GXor */
|
|
ROP_FILL(GX_ROP_INVERT, GX_ROP_CLEAR), /* GXnor */
|
|
ROP_FILL(GX_ROP_INVERT, GX_ROP_NOOP), /* GXequiv */
|
|
ROP_FILL(GX_ROP_INVERT, GX_ROP_INVERT), /* GXinvert */
|
|
ROP_FILL(GX_ROP_INVERT, GX_ROP_SET), /* GXorReverse */
|
|
ROP_FILL(GX_ROP_SET, GX_ROP_CLEAR), /* GXcopyInverted */
|
|
ROP_FILL(GX_ROP_SET, GX_ROP_NOOP), /* GXorInverted */
|
|
ROP_FILL(GX_ROP_SET, GX_ROP_INVERT), /* GXnand */
|
|
ROP_FILL(GX_ROP_SET, GX_ROP_SET), /* GXset */
|
|
};
|
|
|
|
static Uint gx_stipple_rop_table[16]={
|
|
ROP_STIP(GX_ROP_CLEAR, GX_ROP_CLEAR), /* GXclear */
|
|
ROP_STIP(GX_ROP_CLEAR, GX_ROP_NOOP), /* GXand */
|
|
ROP_STIP(GX_ROP_CLEAR, GX_ROP_INVERT), /* GXandReverse */
|
|
ROP_STIP(GX_ROP_CLEAR, GX_ROP_SET), /* GXcopy */
|
|
ROP_STIP(GX_ROP_NOOP, GX_ROP_CLEAR), /* GXandInverted */
|
|
ROP_STIP(GX_ROP_NOOP, GX_ROP_NOOP), /* GXnoop */
|
|
ROP_STIP(GX_ROP_NOOP, GX_ROP_INVERT), /* GXxor */
|
|
ROP_STIP(GX_ROP_NOOP, GX_ROP_SET), /* GXor */
|
|
ROP_STIP(GX_ROP_INVERT, GX_ROP_CLEAR), /* GXnor */
|
|
ROP_STIP(GX_ROP_INVERT, GX_ROP_NOOP), /* GXequiv */
|
|
ROP_STIP(GX_ROP_INVERT, GX_ROP_INVERT), /* GXinvert */
|
|
ROP_STIP(GX_ROP_INVERT, GX_ROP_SET), /* GXorReverse */
|
|
ROP_STIP(GX_ROP_SET, GX_ROP_CLEAR), /* GXcopyInverted */
|
|
ROP_STIP(GX_ROP_SET, GX_ROP_NOOP), /* GXorInverted */
|
|
ROP_STIP(GX_ROP_SET, GX_ROP_INVERT), /* GXnand */
|
|
ROP_STIP(GX_ROP_SET, GX_ROP_SET), /* GXset */
|
|
};
|
|
|
|
static Uint gx_opaque_stipple_rop_table[16]={
|
|
ROP_OSTP(GX_ROP_CLEAR, GX_ROP_CLEAR), /* GXclear */
|
|
ROP_OSTP(GX_ROP_CLEAR, GX_ROP_NOOP), /* GXand */
|
|
ROP_OSTP(GX_ROP_CLEAR, GX_ROP_INVERT), /* GXandReverse */
|
|
ROP_OSTP(GX_ROP_CLEAR, GX_ROP_SET), /* GXcopy */
|
|
ROP_OSTP(GX_ROP_NOOP, GX_ROP_CLEAR), /* GXandInverted */
|
|
ROP_OSTP(GX_ROP_NOOP, GX_ROP_NOOP), /* GXnoop */
|
|
ROP_OSTP(GX_ROP_NOOP, GX_ROP_INVERT), /* GXxor */
|
|
ROP_OSTP(GX_ROP_NOOP, GX_ROP_SET), /* GXor */
|
|
ROP_OSTP(GX_ROP_INVERT, GX_ROP_CLEAR), /* GXnor */
|
|
ROP_OSTP(GX_ROP_INVERT, GX_ROP_NOOP), /* GXequiv */
|
|
ROP_OSTP(GX_ROP_INVERT, GX_ROP_INVERT), /* GXinvert */
|
|
ROP_OSTP(GX_ROP_INVERT, GX_ROP_SET), /* GXorReverse */
|
|
ROP_OSTP(GX_ROP_SET, GX_ROP_CLEAR), /* GXcopyInverted */
|
|
ROP_OSTP(GX_ROP_SET, GX_ROP_NOOP), /* GXorInverted */
|
|
ROP_OSTP(GX_ROP_SET, GX_ROP_INVERT), /* GXnand */
|
|
ROP_OSTP(GX_ROP_SET, GX_ROP_SET), /* GXset */
|
|
};
|
|
|
|
int sunGXScreenPrivateIndex;
|
|
int sunGXGCPrivateIndex;
|
|
int sunGXWindowPrivateIndex;
|
|
int sunGXGeneration;
|
|
|
|
/*
|
|
sunGXDoBitBlt
|
|
=============
|
|
Bit Blit for all window to window blits.
|
|
*/
|
|
static void
|
|
sunGXDoBitblt(pSrc, pDst, alu, prgnDst, pptSrc, planemask)
|
|
DrawablePtr pSrc, pDst;
|
|
int alu;
|
|
RegionPtr prgnDst;
|
|
DDXPointPtr pptSrc;
|
|
unsigned long planemask;
|
|
{
|
|
register sunGXPtr gx = sunGXGetScreenPrivate (pSrc->pScreen);
|
|
register long r;
|
|
register BoxPtr pboxTmp;
|
|
register DDXPointPtr pptTmp;
|
|
register int nbox;
|
|
BoxPtr pboxNext,pboxBase,pbox;
|
|
|
|
/* setup GX ( need fg of 0xff for blits ) */
|
|
GXBlitInit(gx,gx_blit_rop_table[alu]|POLY_O,planemask);
|
|
|
|
pbox = REGION_RECTS(prgnDst);
|
|
nbox = REGION_NUM_RECTS(prgnDst);
|
|
|
|
/* need to blit rectangles in different orders, depending on the direction of copy
|
|
so that an area isnt overwritten before it is blitted */
|
|
if( (pptSrc->y < pbox->y1) && (nbox > 1) ){
|
|
|
|
if( (pptSrc->x < pbox->x1) && (nbox > 1) ){
|
|
|
|
/* reverse order of bands and rects in each band */
|
|
pboxTmp=pbox+nbox;
|
|
pptTmp=pptSrc+nbox;
|
|
|
|
while (nbox--){
|
|
pboxTmp--;
|
|
pptTmp--;
|
|
gx->x0=pptTmp->x;
|
|
gx->y0=pptTmp->y;
|
|
gx->x1=pptTmp->x+(pboxTmp->x2-pboxTmp->x1)-1;
|
|
gx->y1=pptTmp->y+(pboxTmp->y2-pboxTmp->y1)-1;
|
|
gx->x2=pboxTmp->x1;
|
|
gx->y2=pboxTmp->y1;
|
|
gx->x3=pboxTmp->x2-1;
|
|
gx->y3=pboxTmp->y2-1;
|
|
GXBlitDone(gx,r);
|
|
}
|
|
}
|
|
else{
|
|
|
|
/* keep ordering in each band, reverse order of bands */
|
|
pboxBase = pboxNext = pbox+nbox-1;
|
|
|
|
while (pboxBase >= pbox){ /* for each band */
|
|
|
|
/* find first box in band */
|
|
while ((pboxNext >= pbox) &&
|
|
(pboxBase->y1 == pboxNext->y1))
|
|
pboxNext--;
|
|
|
|
pboxTmp = pboxNext+1; /* first box in band */
|
|
pptTmp = pptSrc + (pboxTmp - pbox); /* first point in band */
|
|
|
|
while (pboxTmp <= pboxBase){ /* for each box in band */
|
|
gx->x0=pptTmp->x;
|
|
gx->y0=pptTmp->y;
|
|
gx->x1=pptTmp->x+(pboxTmp->x2-pboxTmp->x1)-1;
|
|
gx->y1=pptTmp->y+(pboxTmp->y2-pboxTmp->y1)-1;
|
|
gx->x2=pboxTmp->x1;
|
|
gx->y2=pboxTmp->y1;
|
|
gx->x3=pboxTmp->x2-1;
|
|
gx->y3=pboxTmp->y2-1;
|
|
++pboxTmp;
|
|
++pptTmp;
|
|
GXBlitDone(gx,r);
|
|
}
|
|
pboxBase = pboxNext;
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
|
|
if( (pptSrc->x < pbox->x1) && (nbox > 1) ){
|
|
|
|
/* reverse order of rects in each band */
|
|
pboxBase = pboxNext = pbox;
|
|
|
|
while (pboxBase < pbox+nbox){ /* for each band */
|
|
|
|
/* find last box in band */
|
|
while ((pboxNext < pbox+nbox) &&
|
|
(pboxNext->y1 == pboxBase->y1))
|
|
pboxNext++;
|
|
|
|
pboxTmp = pboxNext; /* last box in band */
|
|
pptTmp = pptSrc + (pboxTmp - pbox); /* last point in band */
|
|
|
|
while (pboxTmp != pboxBase){ /* for each box in band */
|
|
--pboxTmp;
|
|
--pptTmp;
|
|
gx->x0=pptTmp->x;
|
|
gx->y0=pptTmp->y;
|
|
gx->x1=pptTmp->x+(pboxTmp->x2-pboxTmp->x1)-1;
|
|
gx->y1=pptTmp->y+(pboxTmp->y2-pboxTmp->y1)-1;
|
|
gx->x2=pboxTmp->x1;
|
|
gx->y2=pboxTmp->y1;
|
|
gx->x3=pboxTmp->x2-1;
|
|
gx->y3=pboxTmp->y2-1;
|
|
GXBlitDone(gx,r);
|
|
}
|
|
pboxBase = pboxNext;
|
|
}
|
|
}
|
|
else{
|
|
|
|
/* dont need to change order of anything */
|
|
pptTmp=pptSrc;
|
|
pboxTmp=pbox;
|
|
|
|
while(nbox--){
|
|
gx->x0=pptTmp->x;
|
|
gx->y0=pptTmp->y;
|
|
gx->x1=pptTmp->x+(pboxTmp->x2-pboxTmp->x1)-1;
|
|
gx->y1=pptTmp->y+(pboxTmp->y2-pboxTmp->y1)-1;
|
|
gx->x2=pboxTmp->x1;
|
|
gx->y2=pboxTmp->y1;
|
|
gx->x3=pboxTmp->x2-1;
|
|
gx->y3=pboxTmp->y2-1;
|
|
pboxTmp++;
|
|
pptTmp++;
|
|
GXBlitDone(gx,r);
|
|
}
|
|
}
|
|
}
|
|
GXWait(gx,r);
|
|
}
|
|
|
|
RegionPtr
|
|
sunGXCopyArea(pSrcDrawable, pDstDrawable,
|
|
pGC, srcx, srcy, width, height, dstx, dsty)
|
|
register DrawablePtr pSrcDrawable;
|
|
register DrawablePtr pDstDrawable;
|
|
GC *pGC;
|
|
int srcx, srcy;
|
|
int width, height;
|
|
int dstx, dsty;
|
|
{
|
|
if (pSrcDrawable->type != DRAWABLE_WINDOW)
|
|
return cfbCopyArea (pSrcDrawable, pDstDrawable,
|
|
pGC, srcx, srcy, width, height, dstx, dsty);
|
|
return cfbBitBlt (pSrcDrawable, pDstDrawable,
|
|
pGC, srcx, srcy, width, height, dstx, dsty, sunGXDoBitblt, 0);
|
|
}
|
|
|
|
static unsigned long copyPlaneFG, copyPlaneBG;
|
|
|
|
static void
|
|
sunGXCopyPlane1to8 (pSrcDrawable, pDstDrawable, rop, prgnDst, pptSrc, planemask, bitPlane)
|
|
DrawablePtr pSrcDrawable;
|
|
DrawablePtr pDstDrawable;
|
|
int rop;
|
|
RegionPtr prgnDst;
|
|
DDXPointPtr pptSrc;
|
|
unsigned long planemask;
|
|
unsigned long bitPlane;
|
|
{
|
|
register sunGXPtr gx = sunGXGetScreenPrivate (pDstDrawable->pScreen);
|
|
int srcx, srcy, dstx, dsty, width, height;
|
|
int dstLastx, dstRightx;
|
|
int xoffSrc, widthSrc, widthRest;
|
|
int widthLast;
|
|
unsigned long *psrcBase, *psrc;
|
|
unsigned long bits, tmp;
|
|
register int leftShift, rightShift;
|
|
register int nl, nlMiddle;
|
|
int nbox;
|
|
BoxPtr pbox;
|
|
register long r;
|
|
|
|
GXDrawInit (gx, copyPlaneFG,
|
|
gx_opaque_stipple_rop_table[rop]|GX_PATTERN_ONES,
|
|
planemask);
|
|
gx->bg = copyPlaneBG;
|
|
gx->mode = GX_BLIT_NOSRC | GX_MODE_COLOR1;
|
|
|
|
cfbGetLongWidthAndPointer (pSrcDrawable, widthSrc, psrcBase)
|
|
|
|
nbox = REGION_NUM_RECTS(prgnDst);
|
|
pbox = REGION_RECTS(prgnDst);
|
|
gx->incx = BITMAP_SCANLINE_UNIT;
|
|
gx->incy = 0;
|
|
while (nbox--)
|
|
{
|
|
dstx = pbox->x1;
|
|
dsty = pbox->y1;
|
|
srcx = pptSrc->x;
|
|
srcy = pptSrc->y;
|
|
dstLastx = pbox->x2;
|
|
width = dstLastx - dstx;
|
|
height = pbox->y2 - dsty;
|
|
pbox++;
|
|
pptSrc++;
|
|
if (!width)
|
|
continue;
|
|
psrc = psrcBase + srcy * widthSrc + (srcx >> LOG2_BITMAP_PAD);
|
|
dstLastx--;
|
|
dstRightx = dstx + BITMAP_SCANLINE_UNIT - 1;
|
|
nlMiddle = (width + BITMAP_SCANLINE_UNIT - 1) >> LOG2_BITMAP_PAD;
|
|
widthLast = width & (BITMAP_SCANLINE_UNIT - 1);
|
|
xoffSrc = srcx & ((1 << LOG2_BITMAP_PAD) - 1);
|
|
leftShift = xoffSrc;
|
|
rightShift = BITMAP_SCANLINE_UNIT - leftShift;
|
|
widthRest = widthSrc - nlMiddle;
|
|
if (widthLast)
|
|
nlMiddle--;
|
|
if (leftShift == 0)
|
|
{
|
|
while (height--)
|
|
{
|
|
gx->x0 = dstx;
|
|
gx->x1 = dstRightx;
|
|
gx->y0 = dsty++;
|
|
nl = nlMiddle;
|
|
while (nl--)
|
|
gx->font = *psrc++;
|
|
if (widthLast)
|
|
{
|
|
gx->x1 = dstLastx;
|
|
#if BITMAP_SCANLINE_UNIT == 64
|
|
gx->font = (int)((*psrc++)>>32);
|
|
#else
|
|
gx->font = *psrc++;
|
|
#endif
|
|
}
|
|
psrc += widthRest;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
widthRest--;
|
|
while (height--)
|
|
{
|
|
gx->x0 = dstx;
|
|
gx->x1 = dstRightx;
|
|
gx->y0 = dsty++;
|
|
bits = *psrc++;
|
|
nl = nlMiddle;
|
|
while (nl--)
|
|
{
|
|
tmp = BitLeft(bits, leftShift);
|
|
bits = *psrc++;
|
|
tmp |= BitRight(bits, rightShift);
|
|
gx->font = tmp;
|
|
}
|
|
if (widthLast)
|
|
{
|
|
tmp = BitLeft(bits, leftShift);
|
|
bits = *psrc++;
|
|
tmp |= BitRight(bits, rightShift);
|
|
gx->x1 = dstLastx;
|
|
gx->font = tmp;
|
|
}
|
|
psrc += widthRest;
|
|
}
|
|
}
|
|
}
|
|
GXWait (gx, r);
|
|
gx->incx = 0;
|
|
gx->incy = 0;
|
|
gx->mode = GX_BLIT_SRC | GX_MODE_COLOR8;
|
|
}
|
|
|
|
RegionPtr sunGXCopyPlane(pSrcDrawable, pDstDrawable,
|
|
pGC, srcx, srcy, width, height, dstx, dsty, bitPlane)
|
|
DrawablePtr pSrcDrawable;
|
|
DrawablePtr pDstDrawable;
|
|
GCPtr pGC;
|
|
int srcx, srcy;
|
|
int width, height;
|
|
int dstx, dsty;
|
|
unsigned long bitPlane;
|
|
{
|
|
RegionPtr ret;
|
|
|
|
if (pSrcDrawable->bitsPerPixel == 1 && pDstDrawable->bitsPerPixel == 8)
|
|
{
|
|
if (bitPlane == 1)
|
|
{
|
|
copyPlaneFG = pGC->fgPixel;
|
|
copyPlaneBG = pGC->bgPixel;
|
|
ret = cfbBitBlt (pSrcDrawable, pDstDrawable,
|
|
pGC, srcx, srcy, width, height, dstx, dsty, sunGXCopyPlane1to8, bitPlane);
|
|
}
|
|
else
|
|
ret = miHandleExposures (pSrcDrawable, pDstDrawable,
|
|
pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
|
|
}
|
|
else if (pSrcDrawable->bitsPerPixel == 8 && pDstDrawable->bitsPerPixel == 1)
|
|
{
|
|
extern int InverseAlu[16];
|
|
int oldalu;
|
|
|
|
oldalu = pGC->alu;
|
|
if ((pGC->fgPixel & 1) == 0 && (pGC->bgPixel&1) == 1)
|
|
pGC->alu = InverseAlu[pGC->alu];
|
|
else if ((pGC->fgPixel & 1) == (pGC->bgPixel & 1))
|
|
pGC->alu = mfbReduceRop(pGC->alu, pGC->fgPixel);
|
|
ret = cfbCopyPlaneReduce (pSrcDrawable, pDstDrawable,
|
|
pGC, srcx, srcy, width, height, dstx, dsty, cfbCopyPlane8to1, bitPlane);
|
|
pGC->alu = oldalu;
|
|
}
|
|
else
|
|
{
|
|
PixmapPtr pBitmap;
|
|
ScreenPtr pScreen = pSrcDrawable->pScreen;
|
|
GCPtr pGC1;
|
|
|
|
pBitmap = (*pScreen->CreatePixmap) (pScreen, width, height, 1);
|
|
if (!pBitmap)
|
|
return NULL;
|
|
pGC1 = GetScratchGC (1, pScreen);
|
|
if (!pGC1)
|
|
{
|
|
(*pScreen->DestroyPixmap) (pBitmap);
|
|
return NULL;
|
|
}
|
|
/*
|
|
* don't need to set pGC->fgPixel,bgPixel as copyPlane8to1
|
|
* ignores pixel values, expecting the rop to "do the
|
|
* right thing", which GXcopy will.
|
|
*/
|
|
ValidateGC ((DrawablePtr) pBitmap, pGC1);
|
|
/* no exposures here, scratch GC's don't get graphics expose */
|
|
(void) cfbCopyPlaneReduce (pSrcDrawable, (DrawablePtr) pBitmap,
|
|
pGC1, srcx, srcy, width, height, 0, 0, cfbCopyPlane8to1, bitPlane);
|
|
copyPlaneFG = pGC->fgPixel;
|
|
copyPlaneBG = pGC->bgPixel;
|
|
(void) cfbBitBlt ((DrawablePtr) pBitmap, pDstDrawable, pGC,
|
|
0, 0, width, height, dstx, dsty, sunGXCopyPlane1to8, 1);
|
|
FreeScratchGC (pGC1);
|
|
(*pScreen->DestroyPixmap) (pBitmap);
|
|
/* compute resultant exposures */
|
|
ret = miHandleExposures (pSrcDrawable, pDstDrawable, pGC,
|
|
srcx, srcy, width, height,
|
|
dstx, dsty, bitPlane);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void
|
|
sunGXFillRectAll (pDrawable, pGC, nBox, pBox)
|
|
DrawablePtr pDrawable;
|
|
GCPtr pGC;
|
|
int nBox;
|
|
BoxPtr pBox;
|
|
{
|
|
register sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen);
|
|
register sunGXPrivGCPtr gxPriv = sunGXGetGCPrivate (pGC);
|
|
register int r;
|
|
|
|
GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu]|POLY_N,pGC->planemask);
|
|
if (gxPriv->stipple)
|
|
GXStippleInit(gx,gxPriv->stipple);
|
|
while (nBox--) {
|
|
gx->arecty = pBox->y1;
|
|
gx->arectx = pBox->x1;
|
|
gx->arecty = pBox->y2;
|
|
gx->arectx = pBox->x2;
|
|
pBox++;
|
|
GXDrawDone(gx,r);
|
|
}
|
|
GXWait(gx,r);
|
|
}
|
|
|
|
#define NUM_STACK_RECTS 1024
|
|
|
|
void
|
|
sunGXPolyFillRect(pDrawable, pGC, nrectFill, prectInit)
|
|
DrawablePtr pDrawable;
|
|
register GCPtr pGC;
|
|
int nrectFill; /* number of rectangles to fill */
|
|
xRectangle *prectInit; /* Pointer to first rectangle to fill */
|
|
{
|
|
xRectangle *prect;
|
|
RegionPtr prgnClip;
|
|
register BoxPtr pbox;
|
|
register BoxPtr pboxClipped;
|
|
BoxPtr pboxClippedBase;
|
|
BoxPtr pextent;
|
|
BoxRec stackRects[NUM_STACK_RECTS];
|
|
int numRects;
|
|
int n;
|
|
int xorg, yorg;
|
|
|
|
prgnClip = pGC->pCompositeClip;
|
|
prect = prectInit;
|
|
xorg = pDrawable->x;
|
|
yorg = pDrawable->y;
|
|
if (xorg || yorg)
|
|
{
|
|
prect = prectInit;
|
|
n = nrectFill;
|
|
while(n--)
|
|
{
|
|
prect->x += xorg;
|
|
prect->y += yorg;
|
|
prect++;
|
|
}
|
|
}
|
|
|
|
prect = prectInit;
|
|
|
|
numRects = REGION_NUM_RECTS(prgnClip) * nrectFill;
|
|
if (numRects > NUM_STACK_RECTS)
|
|
{
|
|
pboxClippedBase = (BoxPtr)ALLOCATE_LOCAL(numRects * sizeof(BoxRec));
|
|
if (!pboxClippedBase)
|
|
return;
|
|
}
|
|
else
|
|
pboxClippedBase = stackRects;
|
|
|
|
pboxClipped = pboxClippedBase;
|
|
|
|
if (REGION_NUM_RECTS(prgnClip) == 1)
|
|
{
|
|
int x1, y1, x2, y2, bx2, by2;
|
|
|
|
pextent = REGION_RECTS(prgnClip);
|
|
x1 = pextent->x1;
|
|
y1 = pextent->y1;
|
|
x2 = pextent->x2;
|
|
y2 = pextent->y2;
|
|
while (nrectFill--)
|
|
{
|
|
if ((pboxClipped->x1 = prect->x) < x1)
|
|
pboxClipped->x1 = x1;
|
|
|
|
if ((pboxClipped->y1 = prect->y) < y1)
|
|
pboxClipped->y1 = y1;
|
|
|
|
bx2 = (int) prect->x + (int) prect->width;
|
|
if (bx2 > x2)
|
|
bx2 = x2;
|
|
pboxClipped->x2 = bx2;
|
|
|
|
by2 = (int) prect->y + (int) prect->height;
|
|
if (by2 > y2)
|
|
by2 = y2;
|
|
pboxClipped->y2 = by2;
|
|
|
|
prect++;
|
|
if ((pboxClipped->x1 < pboxClipped->x2) &&
|
|
(pboxClipped->y1 < pboxClipped->y2))
|
|
{
|
|
pboxClipped++;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int x1, y1, x2, y2, bx2, by2;
|
|
|
|
pextent = REGION_EXTENTS(pGC->pScreen, prgnClip);
|
|
x1 = pextent->x1;
|
|
y1 = pextent->y1;
|
|
x2 = pextent->x2;
|
|
y2 = pextent->y2;
|
|
while (nrectFill--)
|
|
{
|
|
BoxRec box;
|
|
|
|
if ((box.x1 = prect->x) < x1)
|
|
box.x1 = x1;
|
|
|
|
if ((box.y1 = prect->y) < y1)
|
|
box.y1 = y1;
|
|
|
|
bx2 = (int) prect->x + (int) prect->width;
|
|
if (bx2 > x2)
|
|
bx2 = x2;
|
|
box.x2 = bx2;
|
|
|
|
by2 = (int) prect->y + (int) prect->height;
|
|
if (by2 > y2)
|
|
by2 = y2;
|
|
box.y2 = by2;
|
|
|
|
prect++;
|
|
|
|
if ((box.x1 >= box.x2) || (box.y1 >= box.y2))
|
|
continue;
|
|
|
|
n = REGION_NUM_RECTS (prgnClip);
|
|
pbox = REGION_RECTS(prgnClip);
|
|
|
|
/* clip the rectangle to each box in the clip region
|
|
this is logically equivalent to calling Intersect()
|
|
*/
|
|
while(n--)
|
|
{
|
|
pboxClipped->x1 = max(box.x1, pbox->x1);
|
|
pboxClipped->y1 = max(box.y1, pbox->y1);
|
|
pboxClipped->x2 = min(box.x2, pbox->x2);
|
|
pboxClipped->y2 = min(box.y2, pbox->y2);
|
|
pbox++;
|
|
|
|
/* see if clipping left anything */
|
|
if(pboxClipped->x1 < pboxClipped->x2 &&
|
|
pboxClipped->y1 < pboxClipped->y2)
|
|
{
|
|
pboxClipped++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (pboxClipped != pboxClippedBase)
|
|
sunGXFillRectAll(pDrawable, pGC,
|
|
pboxClipped-pboxClippedBase, pboxClippedBase);
|
|
if (pboxClippedBase != stackRects)
|
|
DEALLOCATE_LOCAL(pboxClippedBase);
|
|
}
|
|
|
|
void
|
|
sunGXFillSpans (pDrawable, pGC, n, ppt, pwidth, fSorted)
|
|
DrawablePtr pDrawable;
|
|
GCPtr pGC;
|
|
int n; /* number of spans to fill */
|
|
DDXPointPtr ppt; /* pointer to list of start points */
|
|
int *pwidth; /* pointer to list of n widths */
|
|
int fSorted;
|
|
{
|
|
int x, y;
|
|
int width;
|
|
/* next three parameters are post-clip */
|
|
int nTmp;
|
|
int *pwidthFree;/* copies of the pointers to free */
|
|
DDXPointPtr pptFree;
|
|
register sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen);
|
|
cfbPrivGCPtr devPriv = cfbGetGCPrivate(pGC);
|
|
register sunGXPrivGCPtr gxPriv = sunGXGetGCPrivate (pGC);
|
|
register int r;
|
|
BoxPtr extents;
|
|
|
|
GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu]|POLY_O,pGC->planemask)
|
|
if (gxPriv->stipple)
|
|
GXStippleInit(gx,gxPriv->stipple);
|
|
if (devPriv->oneRect)
|
|
{
|
|
extents = &pGC->pCompositeClip->extents;
|
|
GXSetClip (gx, extents);
|
|
}
|
|
else
|
|
{
|
|
nTmp = n * miFindMaxBand(pGC->pCompositeClip);
|
|
pwidthFree = (int *)ALLOCATE_LOCAL(nTmp * sizeof(int));
|
|
pptFree = (DDXPointRec *)ALLOCATE_LOCAL(nTmp * sizeof(DDXPointRec));
|
|
if(!pptFree || !pwidthFree)
|
|
{
|
|
if (pptFree) DEALLOCATE_LOCAL(pptFree);
|
|
if (pwidthFree) DEALLOCATE_LOCAL(pwidthFree);
|
|
return;
|
|
}
|
|
n = miClipSpans(pGC->pCompositeClip, ppt, pwidth, n,
|
|
pptFree, pwidthFree, fSorted);
|
|
pwidth = pwidthFree;
|
|
ppt = pptFree;
|
|
}
|
|
while (n--)
|
|
{
|
|
x = ppt->x;
|
|
y = ppt->y;
|
|
ppt++;
|
|
width = *pwidth++;
|
|
if (width)
|
|
{
|
|
sunGXFillSpan(gx,y,x,x + width - 1,r);
|
|
}
|
|
}
|
|
GXWait(gx,r);
|
|
if (devPriv->oneRect)
|
|
{
|
|
GXResetClip (gx, pDrawable->pScreen);
|
|
}
|
|
else
|
|
{
|
|
DEALLOCATE_LOCAL(pptFree);
|
|
DEALLOCATE_LOCAL(pwidthFree);
|
|
}
|
|
}
|
|
|
|
#ifdef NOTDEF
|
|
/* cfb is faster for dots */
|
|
void
|
|
sunGXPolyPoint(pDrawable, pGC, mode, npt, pptInit)
|
|
DrawablePtr pDrawable;
|
|
GCPtr pGC;
|
|
int mode;
|
|
int npt;
|
|
xPoint *pptInit;
|
|
{
|
|
register sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen);
|
|
RegionPtr cclip;
|
|
int nbox;
|
|
register int i;
|
|
register BoxPtr pbox;
|
|
cfbPrivGCPtr devPriv;
|
|
xPoint *ppt;
|
|
int x, y;
|
|
int r;
|
|
int off;
|
|
|
|
devPriv = (cfbPrivGC *)(pGC->devPrivates[cfbGCPrivateIndex].ptr);
|
|
if (devPriv->rop == GXnoop)
|
|
return;
|
|
cclip = pGC->pCompositeClip;
|
|
GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu],pGC->planemask);
|
|
gx->offx = pDrawable->x;
|
|
gx->offy = pDrawable->y;
|
|
for (nbox = REGION_NUM_RECTS(cclip), pbox = REGION_RECTS(cclip);
|
|
--nbox >= 0;
|
|
pbox++)
|
|
{
|
|
sunGXSetClip(gx,pbox);
|
|
if (mode != CoordModeOrigin)
|
|
{
|
|
x = 0;
|
|
y = 0;
|
|
for (ppt = pptInit, i = npt; --i >= 0;)
|
|
{
|
|
gx->apointy = y += ppt->y;
|
|
gx->apointx = x += ppt->x;
|
|
++ppt;
|
|
GXDrawDone(gx,r);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (ppt = pptInit, i = npt; --i >= 0;)
|
|
{
|
|
gx->apointy = ppt->y;
|
|
gx->apointx = ppt->x;
|
|
++ppt;
|
|
GXDrawDone(gx,r);
|
|
}
|
|
}
|
|
}
|
|
GXWait(gx,r);
|
|
GXResetOff (gx);
|
|
GXResetClip(gx,pDrawable->pScreen);
|
|
}
|
|
#endif
|
|
|
|
#include "mifillarc.h"
|
|
|
|
#define FILLSPAN(gx,y,x1,x2,r) {\
|
|
if (x2 >= x1) {\
|
|
sunGXFillSpan(gx,y,x1,x2,r) \
|
|
} \
|
|
}
|
|
|
|
#define FILLSLICESPANS(flip,y) \
|
|
if (!flip) \
|
|
{ \
|
|
FILLSPAN(gx,y,xl,xr,r) \
|
|
} \
|
|
else \
|
|
{ \
|
|
xc = xorg - x; \
|
|
FILLSPAN(gx, y, xc, xr, r) \
|
|
xc += slw - 1; \
|
|
FILLSPAN(gx, y, xl, xc, r) \
|
|
}
|
|
|
|
static void
|
|
sunGXFillEllipse (pDraw, gx, arc)
|
|
DrawablePtr pDraw;
|
|
sunGXPtr gx;
|
|
xArc *arc;
|
|
{
|
|
int x, y, e;
|
|
int yk, xk, ym, xm, dx, dy, xorg, yorg;
|
|
int y_top, y_bot;
|
|
miFillArcRec info;
|
|
register int xpos;
|
|
int r;
|
|
int slw;
|
|
|
|
miFillArcSetup(arc, &info);
|
|
MIFILLARCSETUP();
|
|
y_top = yorg - y;
|
|
y_bot = yorg + y + dy;
|
|
while (y)
|
|
{
|
|
y_top++;
|
|
y_bot--;
|
|
MIFILLARCSTEP(slw);
|
|
if (!slw)
|
|
continue;
|
|
xpos = xorg - x;
|
|
sunGXFillSpan (gx,y_top,xpos,xpos+slw - 1,r);
|
|
if (miFillArcLower(slw))
|
|
sunGXFillSpan (gx,y_bot,xpos,xpos+slw - 1,r);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
sunGXFillArcSlice (pDraw, pGC, gx, arc)
|
|
DrawablePtr pDraw;
|
|
GCPtr pGC;
|
|
sunGXPtr gx;
|
|
xArc *arc;
|
|
{
|
|
int yk, xk, ym, xm, dx, dy, xorg, yorg, slw;
|
|
register int x, y, e;
|
|
miFillArcRec info;
|
|
miArcSliceRec slice;
|
|
int xl, xr, xc;
|
|
int y_top, y_bot;
|
|
int r;
|
|
|
|
miFillArcSetup(arc, &info);
|
|
miFillArcSliceSetup(arc, &slice, pGC);
|
|
MIFILLARCSETUP();
|
|
y_top = yorg - y;
|
|
y_bot = yorg + y + dy;
|
|
while (y > 0)
|
|
{
|
|
y_top++;
|
|
y_bot--;
|
|
MIFILLARCSTEP(slw);
|
|
MIARCSLICESTEP(slice.edge1);
|
|
MIARCSLICESTEP(slice.edge2);
|
|
if (miFillSliceUpper(slice))
|
|
{
|
|
MIARCSLICEUPPER(xl, xr, slice, slw);
|
|
FILLSLICESPANS(slice.flip_top, y_top);
|
|
}
|
|
if (miFillSliceLower(slice))
|
|
{
|
|
MIARCSLICELOWER(xl, xr, slice, slw);
|
|
FILLSLICESPANS(slice.flip_bot, y_bot);
|
|
}
|
|
}
|
|
}
|
|
|
|
#define FAST_CIRCLES
|
|
#ifdef FAST_CIRCLES
|
|
#if (BITMAP_BIT_ORDER == MSBFirst)
|
|
#define Bits32(v) (v)
|
|
#define Bits16(v) (v)
|
|
#define Bits8(v) (v)
|
|
#else
|
|
#define FlipBits2(a) ((((a) & 0x1) << 1) | (((a) & 0x2) >> 1))
|
|
#define FlipBits4(a) ((FlipBits2(a) << 2) | FlipBits2(a >> 2))
|
|
#define FlipBits8(a) ((FlipBits4(a) << 4) | FlipBits4(a >> 4))
|
|
#define FlipBits16(a) ((FlipBits8(a) << 8) | FlipBits8(a >> 8))
|
|
#define FlipBits32(a) ((FlipBits16(a) << 16) | FlipBits16(a >> 16))
|
|
#define Bits32(v) FlipBits32(v)
|
|
#define Bits16(v) FlipBits16(v)
|
|
#define Bits8(v) FlipBits8(v)
|
|
#endif
|
|
|
|
#define B(x) Bits16(x)
|
|
#define DO_FILLED_ARCS
|
|
#include "circleset.h"
|
|
#undef B
|
|
#undef Bits8
|
|
#undef Bits16
|
|
#undef Bits32
|
|
#define UNSET_CIRCLE if (old_width) \
|
|
{ \
|
|
gx->alu = gx_solid_rop_table[pGC->alu]; \
|
|
old_width = -old_width; \
|
|
}
|
|
|
|
#else
|
|
#define UNSET_CIRCLE
|
|
#endif
|
|
|
|
void
|
|
sunGXPolyFillArc (pDraw, pGC, narcs, parcs)
|
|
DrawablePtr pDraw;
|
|
GCPtr pGC;
|
|
int narcs;
|
|
xArc *parcs;
|
|
{
|
|
register xArc *arc;
|
|
register int i;
|
|
int x, y;
|
|
BoxRec box;
|
|
BoxPtr extents = NULL;
|
|
RegionPtr cclip;
|
|
register sunGXPtr gx = sunGXGetScreenPrivate (pDraw->pScreen);
|
|
sunGXPrivGCPtr gxPriv = sunGXGetGCPrivate (pGC);
|
|
cfbPrivGCPtr devPriv;
|
|
register int r;
|
|
#ifdef FAST_CIRCLES
|
|
int old_width = 0;
|
|
#endif
|
|
|
|
GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu]|POLY_O,pGC->planemask);
|
|
if (gxPriv->stipple)
|
|
GXStippleInit(gx,gxPriv->stipple);
|
|
devPriv = (cfbPrivGC *)(pGC->devPrivates[cfbGCPrivateIndex].ptr);
|
|
cclip = pGC->pCompositeClip;
|
|
GXSetOff(gx,pDraw->x,pDraw->y)
|
|
if (devPriv->oneRect) {
|
|
extents = &cclip->extents;
|
|
GXSetClip(gx,extents);
|
|
}
|
|
for (arc = parcs, i = narcs; --i >= 0; arc++)
|
|
{
|
|
if (miFillArcEmpty(arc))
|
|
continue;
|
|
if (miCanFillArc(arc))
|
|
{
|
|
x = arc->x;
|
|
y = arc->y;
|
|
if (!devPriv->oneRect)
|
|
{
|
|
box.x1 = x + pDraw->x;
|
|
box.y1 = y + pDraw->y;
|
|
box.x2 = box.x1 + (int)arc->width + 1;
|
|
box.y2 = box.y1 + (int)arc->height + 1;
|
|
}
|
|
if (devPriv->oneRect ||
|
|
RECT_IN_REGION(pDraw->pScreen, cclip, &box) == rgnIN)
|
|
{
|
|
if ((arc->angle2 >= FULLCIRCLE) ||
|
|
(arc->angle2 <= -FULLCIRCLE))
|
|
{
|
|
#ifdef FAST_CIRCLES
|
|
/* who really needs fast filled circles? */
|
|
if (arc->width == arc->height && arc->width <= 16 &&
|
|
!gxPriv->stipple)
|
|
{
|
|
int offx, offy;
|
|
if (arc->width != old_width)
|
|
{
|
|
int i;
|
|
Uint *sp;
|
|
VUint *dp;
|
|
|
|
if (old_width != -arc->width)
|
|
{
|
|
sp = (Uint *) filled_arcs[arc->width-1];
|
|
dp = gx->pattern;
|
|
i = 8;
|
|
while (i--)
|
|
dp[i] = sp[i];
|
|
}
|
|
gx->alu = gx_stipple_rop_table[pGC->alu]|GX_PATTERN_MASK;
|
|
old_width = arc->width;
|
|
}
|
|
offx = 16 - ((x + pDraw->x) & 0x0f);
|
|
offy = 16 - ((y + pDraw->y) & 0x0f);
|
|
gx->patalign = (offx << 16) | offy;
|
|
gx->arecty = y;
|
|
gx->arectx = x;
|
|
gx->arecty = y + old_width-1;
|
|
gx->arectx = x + old_width-1;
|
|
GXDrawDone (gx, r);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
UNSET_CIRCLE
|
|
sunGXFillEllipse (pDraw, gx, arc);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UNSET_CIRCLE
|
|
sunGXFillArcSlice (pDraw, pGC, gx, arc);
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
UNSET_CIRCLE
|
|
GXWait (gx,r);
|
|
GXResetOff (gx);
|
|
if (devPriv->oneRect)
|
|
GXResetClip (gx, pDraw->pScreen);
|
|
miPolyFillArc(pDraw, pGC, 1, arc);
|
|
GXSetOff (gx, pDraw->x, pDraw->y);
|
|
if (devPriv->oneRect)
|
|
GXSetClip (gx, extents);
|
|
}
|
|
GXWait (gx, r);
|
|
GXResetOff (gx);
|
|
if (devPriv->oneRect)
|
|
GXResetClip (gx, pDraw->pScreen);
|
|
}
|
|
|
|
void
|
|
sunGXFillPoly1Rect (pDrawable, pGC, shape, mode, count, ptsIn)
|
|
DrawablePtr pDrawable;
|
|
GCPtr pGC;
|
|
int count;
|
|
DDXPointPtr ptsIn;
|
|
{
|
|
BoxPtr extents;
|
|
int x1, x2, x3, x4;
|
|
int y1, y2, y3, y4;
|
|
sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen);
|
|
sunGXPrivGCPtr gxPriv = sunGXGetGCPrivate (pGC);
|
|
int r;
|
|
typedef struct {
|
|
Uint x;
|
|
Uint y;
|
|
Uint z;
|
|
} GXPointRec, *GXPointPtr;
|
|
GXPointPtr tri, qua;
|
|
|
|
if (count < 3)
|
|
return;
|
|
if (shape != Convex && count > 4)
|
|
{
|
|
miFillPolygon (pDrawable, pGC, shape, mode, count, ptsIn);
|
|
return;
|
|
}
|
|
GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu]|POLY_N,pGC->planemask);
|
|
if (gxPriv->stipple)
|
|
GXStippleInit(gx,gxPriv->stipple);
|
|
extents = &pGC->pCompositeClip->extents;
|
|
GXSetOff(gx,pDrawable->x, pDrawable->y);
|
|
GXSetClip(gx,extents);
|
|
if (mode == CoordModeOrigin)
|
|
{
|
|
tri = (GXPointPtr) &gx->atrix;
|
|
qua = (GXPointPtr) &gx->aquadx;
|
|
}
|
|
else
|
|
{
|
|
tri = (GXPointPtr) &gx->rtrix;
|
|
qua = (GXPointPtr) &gx->rquadx;
|
|
}
|
|
if (count == 3) {
|
|
gx->apointy = ptsIn[0].y;
|
|
gx->apointx = ptsIn[0].x;
|
|
tri->y = ptsIn[1].y;
|
|
tri->x = ptsIn[1].x;
|
|
tri->y = ptsIn[2].y;
|
|
tri->x = ptsIn[2].x;
|
|
GXDrawDone (gx, r);
|
|
}
|
|
else if (count == 4)
|
|
{
|
|
gx->apointy = ptsIn[0].y;
|
|
gx->apointx = ptsIn[0].x;
|
|
qua->y = ptsIn[1].y;
|
|
qua->x = ptsIn[1].x;
|
|
qua->y = ptsIn[2].y;
|
|
qua->x = ptsIn[2].x;
|
|
qua->y = ptsIn[3].y;
|
|
qua->x = ptsIn[3].x;
|
|
GXDrawDone (gx, r);
|
|
if (r < 0 && shape != Convex)
|
|
{
|
|
GXWait(gx,r);
|
|
GXResetOff(gx);
|
|
GXResetClip(gx,pDrawable->pScreen);
|
|
miFillPolygon (pDrawable, pGC, shape, mode, count, ptsIn);
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
y1 = ptsIn[0].y;
|
|
x1 = ptsIn[0].x;
|
|
y2 = ptsIn[1].y;
|
|
x2 = ptsIn[1].x;
|
|
count -= 2;
|
|
ptsIn += 2;
|
|
while (count) {
|
|
x3 = ptsIn->x;
|
|
y3 = ptsIn->y;
|
|
ptsIn++;
|
|
count--;
|
|
gx->apointy = y1;
|
|
gx->apointx = x1;
|
|
if (count == 0) {
|
|
tri->y = y2;
|
|
tri->x = x2;
|
|
tri->y = y3;
|
|
tri->x = x3;
|
|
}
|
|
else
|
|
{
|
|
y4 = ptsIn->y;
|
|
x4 = ptsIn->x;
|
|
ptsIn++;
|
|
count--;
|
|
qua->y = y2;
|
|
qua->x = x2;
|
|
qua->y = y3;
|
|
qua->x = x3;
|
|
qua->y = y4;
|
|
qua->x = x4;
|
|
if (mode == CoordModeOrigin)
|
|
{
|
|
x2 = x4;
|
|
y2 = y4;
|
|
}
|
|
else
|
|
{
|
|
x2 = x2 + x3 + x4;
|
|
y2 = y2 + y3 + y4;
|
|
}
|
|
}
|
|
GXDrawDone (gx, r);
|
|
}
|
|
}
|
|
GXWait(gx,r);
|
|
GXResetOff(gx);
|
|
GXResetClip(gx,pDrawable->pScreen);
|
|
}
|
|
|
|
/*
|
|
* Note that the GX does not allow CapNotLast, so the code fakes it. This is
|
|
* expensive to do as the GX is asynchronous and must be synced with GXWait
|
|
* before fetching and storing the final line point. If only the hardware was
|
|
* designed for X.
|
|
*/
|
|
|
|
/* hard code the screen width; otherwise we'd have to check or mul */
|
|
|
|
#define WIDTH_MUL(y) (((y) << 10) + ((y) << 7))
|
|
#define GX_WIDTH 1152
|
|
#define WID_OK(s) ((s)->width == GX_WIDTH)
|
|
|
|
void
|
|
sunGXPolySeg1Rect (pDrawable, pGC, nseg, pSeg)
|
|
DrawablePtr pDrawable;
|
|
GCPtr pGC;
|
|
int nseg;
|
|
xSegment *pSeg;
|
|
{
|
|
sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen);
|
|
sunGXPrivGCPtr gxPriv = sunGXGetGCPrivate (pGC);
|
|
BoxPtr extents;
|
|
int x, y;
|
|
int r;
|
|
unsigned char *baseAddr, *loAddr, *hiAddr, *saveAddr = 0, save = 0;
|
|
|
|
GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu]|POLY_O,pGC->planemask);
|
|
if (gxPriv->stipple)
|
|
GXStippleInit(gx,gxPriv->stipple);
|
|
GXSetOff (gx, pDrawable->x, pDrawable->y);
|
|
|
|
extents = &pGC->pCompositeClip->extents;
|
|
GXSetClip (gx, extents);
|
|
if (pGC->capStyle == CapNotLast)
|
|
{
|
|
sunGXGetAddrRange(pDrawable,extents,baseAddr,loAddr,hiAddr);
|
|
while (nseg--)
|
|
{
|
|
gx->aliney = pSeg->y1;
|
|
gx->alinex = pSeg->x1;
|
|
y = pSeg->y2;
|
|
x = pSeg->x2;
|
|
saveAddr = baseAddr + WIDTH_MUL(y) + x;
|
|
if (saveAddr < loAddr || hiAddr < saveAddr)
|
|
saveAddr = 0;
|
|
else
|
|
save = *saveAddr;
|
|
gx->aliney = y;
|
|
gx->alinex = x;
|
|
GXDrawDone (gx, r);
|
|
if (saveAddr)
|
|
{
|
|
GXWait(gx,r);
|
|
*saveAddr = save;
|
|
}
|
|
pSeg++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (nseg--)
|
|
{
|
|
gx->aliney = pSeg->y1;
|
|
gx->alinex = pSeg->x1;
|
|
gx->aliney = pSeg->y2;
|
|
gx->alinex = pSeg->x2;
|
|
pSeg++;
|
|
GXDrawDone (gx, r);
|
|
}
|
|
}
|
|
GXWait (gx, r);
|
|
GXResetOff (gx);
|
|
GXResetClip (gx, pDrawable->pScreen);
|
|
}
|
|
|
|
void
|
|
sunGXPolylines1Rect (pDrawable, pGC, mode, npt, ppt)
|
|
DrawablePtr pDrawable;
|
|
GCPtr pGC;
|
|
int mode;
|
|
int npt;
|
|
DDXPointPtr ppt;
|
|
{
|
|
sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen);
|
|
sunGXPrivGCPtr gxPriv = sunGXGetGCPrivate (pGC);
|
|
BoxPtr extents;
|
|
unsigned char *baseAddr, *loAddr, *hiAddr, *saveAddr, save = 0;
|
|
int r;
|
|
Bool careful;
|
|
Bool capNotLast;
|
|
|
|
if (!--npt)
|
|
return;
|
|
GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu]|POLY_O,pGC->planemask);
|
|
if (gxPriv->stipple)
|
|
GXStippleInit(gx,gxPriv->stipple);
|
|
careful = ((pGC->alu & 0xc) == 0x8 || (pGC->alu & 0x3) == 0x2);
|
|
capNotLast = pGC->capStyle == CapNotLast;
|
|
|
|
extents = &pGC->pCompositeClip->extents;
|
|
GXSetOff (gx, pDrawable->x, pDrawable->y);
|
|
GXSetClip (gx, extents);
|
|
if (careful)
|
|
{
|
|
int x, y;
|
|
sunGXGetAddrRange (pDrawable, extents, baseAddr, loAddr, hiAddr);
|
|
gx->apointy = y = ppt->y;
|
|
gx->apointx = x = ppt->x;
|
|
ppt++;
|
|
while (npt--)
|
|
{
|
|
if (mode == CoordModeOrigin)
|
|
{
|
|
y = ppt->y;
|
|
x = ppt->x;
|
|
}
|
|
else
|
|
{
|
|
y += ppt->y;
|
|
x += ppt->x;
|
|
}
|
|
ppt++;
|
|
saveAddr = baseAddr + WIDTH_MUL(y) + x;
|
|
if (saveAddr < loAddr || hiAddr < saveAddr)
|
|
saveAddr = 0;
|
|
else
|
|
save = *saveAddr;
|
|
gx->aliney = y;
|
|
gx->alinex = x;
|
|
GXDrawDone (gx, r);
|
|
if (saveAddr)
|
|
{
|
|
GXWait(gx,r);
|
|
*saveAddr = save;
|
|
}
|
|
}
|
|
GXWait(gx,r);
|
|
}
|
|
else
|
|
{
|
|
int x, y;
|
|
if (capNotLast)
|
|
npt--;
|
|
if (mode == CoordModeOrigin)
|
|
{
|
|
x = y = 0;
|
|
gx->apointy = ppt->y;
|
|
gx->apointx = ppt->x;
|
|
ppt++;
|
|
while (npt--)
|
|
{
|
|
gx->aliney = ppt->y;
|
|
gx->alinex = ppt->x;
|
|
++ppt;
|
|
GXDrawDone(gx,r);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
y = gx->apointy = ppt->y;
|
|
x = gx->apointx = ppt->x;
|
|
ppt++;
|
|
while (npt--)
|
|
{
|
|
y += gx->rliney = ppt->y;
|
|
x += gx->rlinex = ppt->x;
|
|
++ppt;
|
|
GXDrawDone(gx,r);
|
|
}
|
|
}
|
|
if (capNotLast)
|
|
{
|
|
sunGXGetAddrRange (pDrawable, extents, baseAddr, loAddr, hiAddr);
|
|
x += ppt->x;
|
|
y += ppt->y;
|
|
saveAddr = baseAddr + WIDTH_MUL(y) + x;
|
|
if (saveAddr < loAddr || hiAddr < saveAddr)
|
|
saveAddr = 0;
|
|
else
|
|
save = *saveAddr;
|
|
gx->aliney = y;
|
|
gx->alinex = x;
|
|
GXDrawDone(gx,r);
|
|
GXWait(gx,r);
|
|
if (saveAddr)
|
|
*saveAddr = save;
|
|
}
|
|
else
|
|
{
|
|
GXWait(gx,r);
|
|
}
|
|
}
|
|
GXResetOff (gx);
|
|
GXResetClip (gx, pDrawable->pScreen);
|
|
}
|
|
|
|
void
|
|
sunGXPolyFillRect1Rect (pDrawable, pGC, nrect, prect)
|
|
DrawablePtr pDrawable;
|
|
GCPtr pGC;
|
|
int nrect;
|
|
xRectangle *prect;
|
|
{
|
|
sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen);
|
|
sunGXPrivGCPtr gxPriv = sunGXGetGCPrivate (pGC);
|
|
BoxPtr extents = &pGC->pCompositeClip->extents;
|
|
int r;
|
|
int x, y;
|
|
|
|
GXDrawInit(gx,pGC->fgPixel,gx_solid_rop_table[pGC->alu]|POLY_N,pGC->planemask);
|
|
if (gxPriv->stipple)
|
|
GXStippleInit(gx,gxPriv->stipple);
|
|
GXSetOff (gx, pDrawable->x, pDrawable->y);
|
|
GXSetClip (gx, extents);
|
|
while (nrect--)
|
|
{
|
|
gx->arecty = y = prect->y;
|
|
gx->arectx = x = prect->x;
|
|
gx->arecty = y + (int) prect->height;
|
|
gx->arectx = x + (int) prect->width;
|
|
prect++;
|
|
GXDrawDone (gx, r);
|
|
}
|
|
GXWait (gx, r);
|
|
GXResetOff (gx);
|
|
GXResetClip (gx, pDrawable->pScreen);
|
|
}
|
|
|
|
static void
|
|
sunGXPolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
|
|
DrawablePtr pDrawable;
|
|
GCPtr pGC;
|
|
int x, y;
|
|
unsigned int nglyph;
|
|
CharInfoPtr *ppci; /* array of character info */
|
|
pointer pglyphBase;
|
|
{
|
|
sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen);
|
|
int h;
|
|
int w;
|
|
CharInfoPtr pci;
|
|
unsigned int *bits;
|
|
register int r;
|
|
RegionPtr clip;
|
|
BoxPtr extents;
|
|
BoxRec box;
|
|
|
|
clip = pGC->pCompositeClip;
|
|
extents = &clip->extents;
|
|
|
|
if (REGION_NUM_RECTS(clip) == 1)
|
|
{
|
|
GXSetClip (gx, extents);
|
|
}
|
|
else
|
|
{
|
|
/* compute an approximate (but covering) bounding box */
|
|
box.x1 = 0;
|
|
if ((ppci[0]->metrics.leftSideBearing < 0))
|
|
box.x1 = ppci[0]->metrics.leftSideBearing;
|
|
h = nglyph - 1;
|
|
w = ppci[h]->metrics.rightSideBearing;
|
|
while (--h >= 0)
|
|
w += ppci[h]->metrics.characterWidth;
|
|
box.x2 = w;
|
|
box.y1 = -FONTMAXBOUNDS(pGC->font,ascent);
|
|
box.y2 = FONTMAXBOUNDS(pGC->font,descent);
|
|
|
|
box.x1 += pDrawable->x + x;
|
|
box.x2 += pDrawable->x + x;
|
|
box.y1 += pDrawable->y + y;
|
|
box.y2 += pDrawable->y + y;
|
|
|
|
switch (RECT_IN_REGION(pGC->pScreen, clip, &box))
|
|
{
|
|
case rgnPART:
|
|
cfbPolyGlyphBlt8 (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
|
|
case rgnOUT:
|
|
return;
|
|
}
|
|
}
|
|
|
|
GXDrawInit (gx, pGC->fgPixel,
|
|
gx_stipple_rop_table[pGC->alu]|GX_PATTERN_ONES|POLY_N,
|
|
pGC->planemask);
|
|
gx->mode = GX_BLIT_NOSRC | GX_MODE_COLOR1;
|
|
x += pDrawable->x;
|
|
y += pDrawable->y;
|
|
|
|
while (nglyph--)
|
|
{
|
|
pci = *ppci++;
|
|
gx->incx = 0;
|
|
gx->incy = 1;
|
|
gx->x0 = x + pci->metrics.leftSideBearing;
|
|
gx->x1 = (x + pci->metrics.rightSideBearing) - 1;
|
|
gx->y0 = y - pci->metrics.ascent;
|
|
h = pci->metrics.ascent + pci->metrics.descent;
|
|
bits = (unsigned int *) pci->bits;
|
|
while (h--) {
|
|
gx->font = *bits++;
|
|
}
|
|
x += pci->metrics.characterWidth;
|
|
}
|
|
GXWait (gx, r);
|
|
gx->mode = GX_BLIT_SRC | GX_MODE_COLOR8;
|
|
GXResetClip (gx, pDrawable->pScreen);
|
|
}
|
|
|
|
static void
|
|
sunGXTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
|
|
DrawablePtr pDrawable;
|
|
GCPtr pGC;
|
|
int x, y;
|
|
unsigned int nglyph;
|
|
CharInfoPtr *ppci; /* array of character info */
|
|
pointer pglyphBase; /* start of array of glyphs */
|
|
{
|
|
sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen);
|
|
int h, hTmp;
|
|
FontPtr pfont = pGC->font;
|
|
register int r;
|
|
unsigned int *char1, *char2, *char3, *char4;
|
|
int widthGlyphs, widthGlyph;
|
|
BoxRec bbox;
|
|
BoxPtr extents;
|
|
RegionPtr clip;
|
|
unsigned long rop;
|
|
|
|
widthGlyph = FONTMAXBOUNDS(pfont,characterWidth);
|
|
h = FONTASCENT(pfont) + FONTDESCENT(pfont);
|
|
clip = pGC->pCompositeClip;
|
|
extents = &clip->extents;
|
|
|
|
if (REGION_NUM_RECTS(clip) == 1)
|
|
{
|
|
GXSetClip (gx, extents);
|
|
}
|
|
else
|
|
{
|
|
bbox.x1 = x + pDrawable->x;
|
|
bbox.x2 = bbox.x1 + (widthGlyph * nglyph);
|
|
bbox.y1 = y + pDrawable->y - FONTASCENT(pfont);
|
|
bbox.y2 = bbox.y1 + h;
|
|
|
|
switch (RECT_IN_REGION(pGC->pScreen, clip, &bbox))
|
|
{
|
|
case rgnPART:
|
|
if (pglyphBase)
|
|
cfbPolyGlyphBlt8(pDrawable, pGC, x, y, nglyph, ppci, NULL);
|
|
else
|
|
miImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
|
|
case rgnOUT:
|
|
return;
|
|
}
|
|
}
|
|
|
|
rop = gx_opaque_stipple_rop_table[GXcopy] | GX_PATTERN_ONES;
|
|
if (pglyphBase)
|
|
rop = gx_stipple_rop_table[pGC->alu] | GX_PATTERN_ONES;
|
|
GXDrawInit (gx, pGC->fgPixel, rop, pGC->planemask);
|
|
gx->bg = pGC->bgPixel;
|
|
gx->mode = GX_BLIT_NOSRC | GX_MODE_COLOR1;
|
|
|
|
y = y + pDrawable->y - FONTASCENT(pfont);
|
|
x += pDrawable->x;
|
|
|
|
#define LoopIt(count, w, loadup, fetch) \
|
|
while (nglyph >= count) \
|
|
{ \
|
|
nglyph -= count; \
|
|
gx->incx = 0; \
|
|
gx->incy = 1; \
|
|
gx->x0 = x; \
|
|
gx->x1 = (x += w) - 1; \
|
|
gx->y0 = y; \
|
|
loadup \
|
|
hTmp = h; \
|
|
while (hTmp--) \
|
|
gx->font = fetch; \
|
|
}
|
|
|
|
if (widthGlyph <= 8)
|
|
{
|
|
widthGlyphs = widthGlyph << 2;
|
|
LoopIt(4, widthGlyphs,
|
|
char1 = (unsigned int *) (*ppci++)->bits;
|
|
char2 = (unsigned int *) (*ppci++)->bits;
|
|
char3 = (unsigned int *) (*ppci++)->bits;
|
|
char4 = (unsigned int *) (*ppci++)->bits;,
|
|
(*char1++ | ((*char2++ | ((*char3++ | (*char4++
|
|
>> widthGlyph))
|
|
>> widthGlyph))
|
|
>> widthGlyph)))
|
|
}
|
|
else if (widthGlyph <= 10)
|
|
{
|
|
widthGlyphs = (widthGlyph << 1) + widthGlyph;
|
|
LoopIt(3, widthGlyphs,
|
|
char1 = (unsigned int *) (*ppci++)->bits;
|
|
char2 = (unsigned int *) (*ppci++)->bits;
|
|
char3 = (unsigned int *) (*ppci++)->bits;,
|
|
(*char1++ | ((*char2++ | (*char3++ >> widthGlyph)) >> widthGlyph)))
|
|
}
|
|
else if (widthGlyph <= 16)
|
|
{
|
|
widthGlyphs = widthGlyph << 1;
|
|
LoopIt(2, widthGlyphs,
|
|
char1 = (unsigned int *) (*ppci++)->bits;
|
|
char2 = (unsigned int *) (*ppci++)->bits;,
|
|
(*char1++ | (*char2++ >> widthGlyph)))
|
|
}
|
|
while (nglyph--) {
|
|
gx->incx = 0;
|
|
gx->incy = 1;
|
|
gx->x0 = x;
|
|
gx->x1 = (x += widthGlyph) - 1;
|
|
gx->y0 = y;
|
|
char1 = (unsigned int *) (*ppci++)->bits;
|
|
hTmp = h;
|
|
while (hTmp--)
|
|
gx->font = *char1++;
|
|
}
|
|
gx->incx = 0;
|
|
gx->incy = 0;
|
|
GXWait (gx, r);
|
|
gx->mode = GX_BLIT_SRC | GX_MODE_COLOR8;
|
|
GXResetClip (gx, pDrawable->pScreen);
|
|
}
|
|
|
|
static void
|
|
sunGXPolyTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
|
|
DrawablePtr pDrawable;
|
|
GCPtr pGC;
|
|
int x, y;
|
|
unsigned int nglyph;
|
|
CharInfoPtr *ppci; /* array of character info */
|
|
pointer pglyphBase; /* start of array of glyphs */
|
|
{
|
|
sunGXTEGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, (char *) 1);
|
|
}
|
|
|
|
static void
|
|
sunGXFillBoxSolid (pDrawable, nBox, pBox, pixel)
|
|
DrawablePtr pDrawable;
|
|
int nBox;
|
|
BoxPtr pBox;
|
|
unsigned long pixel;
|
|
{
|
|
register sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen);
|
|
register int r;
|
|
|
|
GXDrawInit(gx,pixel,gx_solid_rop_table[GXcopy]|POLY_N,~0);
|
|
while (nBox--) {
|
|
gx->arecty = pBox->y1;
|
|
gx->arectx = pBox->x1;
|
|
gx->arecty = pBox->y2;
|
|
gx->arectx = pBox->x2;
|
|
pBox++;
|
|
GXDrawDone(gx,r);
|
|
}
|
|
GXWait(gx,r);
|
|
}
|
|
|
|
void
|
|
sunGXFillBoxStipple (pDrawable, nBox, pBox, stipple)
|
|
DrawablePtr pDrawable;
|
|
int nBox;
|
|
BoxPtr pBox;
|
|
sunGXStipplePtr stipple;
|
|
{
|
|
register sunGXPtr gx = sunGXGetScreenPrivate (pDrawable->pScreen);
|
|
register int r;
|
|
int patx, paty;
|
|
|
|
patx = 16 - (pDrawable->x & 0xf);
|
|
paty = 16 - (pDrawable->y & 0xf);
|
|
stipple->patalign = (patx << 16) | paty;
|
|
GXDrawInit(gx,0,gx_solid_rop_table[GXcopy]|POLY_N,~0);
|
|
GXStippleInit(gx, stipple);
|
|
while (nBox--) {
|
|
gx->arecty = pBox->y1;
|
|
gx->arectx = pBox->x1;
|
|
gx->arecty = pBox->y2;
|
|
gx->arectx = pBox->x2;
|
|
pBox++;
|
|
GXDrawDone(gx,r);
|
|
}
|
|
GXWait(gx,r);
|
|
}
|
|
|
|
Bool
|
|
sunGXCheckTile (pPixmap, stipple)
|
|
PixmapPtr pPixmap;
|
|
sunGXStipplePtr stipple;
|
|
{
|
|
unsigned short *sbits;
|
|
unsigned int fg = (unsigned int)~0, bg = (unsigned int)~0;
|
|
unsigned char *tilebitsLine, *tilebits, tilebit;
|
|
unsigned short sbit, mask;
|
|
int nbwidth;
|
|
int h, w;
|
|
int x, y;
|
|
int s_y, s_x;
|
|
|
|
h = pPixmap->drawable.height;
|
|
if (h > 16 || (h & (h - 1)))
|
|
return FALSE;
|
|
w = pPixmap->drawable.width;
|
|
if (w > 16 || (w & (w - 1)))
|
|
return FALSE;
|
|
sbits = (unsigned short *) stipple->bits;
|
|
tilebitsLine = (unsigned char *) pPixmap->devPrivate.ptr;
|
|
nbwidth = pPixmap->devKind;
|
|
for (y = 0; y < h; y++) {
|
|
tilebits = tilebitsLine;
|
|
tilebitsLine += nbwidth;
|
|
sbit = 0;
|
|
mask = 1 << 15;
|
|
for (x = 0; x < w; x++)
|
|
{
|
|
tilebit = *tilebits++;
|
|
if (tilebit == fg)
|
|
sbit |= mask;
|
|
else if (tilebit != bg)
|
|
{
|
|
if (fg == ~0)
|
|
{
|
|
fg = tilebit;
|
|
sbit |= mask;
|
|
}
|
|
else if (bg == ~0)
|
|
{
|
|
bg = tilebit;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
mask >>= 1;
|
|
}
|
|
for (s_x = w; s_x < 16; s_x <<= 1)
|
|
sbit = sbit | (sbit >> s_x);
|
|
for (s_y = y; s_y < 16; s_y += h)
|
|
sbits[s_y] = sbit;
|
|
}
|
|
stipple->fore = fg;
|
|
stipple->back = bg;
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
sunGXCheckStipple (pPixmap, stipple)
|
|
PixmapPtr pPixmap;
|
|
sunGXStipplePtr stipple;
|
|
{
|
|
unsigned short *sbits;
|
|
unsigned int *stippleBits;
|
|
unsigned long sbit, mask;
|
|
int h, w;
|
|
int y;
|
|
int s_y, s_x;
|
|
|
|
h = pPixmap->drawable.height;
|
|
if (h > 16 || (h & (h - 1)))
|
|
return FALSE;
|
|
w = pPixmap->drawable.width;
|
|
if (w > 16 || (w & (w - 1)))
|
|
return FALSE;
|
|
sbits = (unsigned short *) stipple->bits;
|
|
stippleBits = (unsigned int *) pPixmap->devPrivate.ptr;
|
|
mask = ((1 << w) - 1) << (16 - w);
|
|
for (y = 0; y < h; y++) {
|
|
sbit = (*stippleBits++ >> 16) & mask;
|
|
for (s_x = w; s_x < 16; s_x <<= 1)
|
|
sbit = sbit | (sbit >> s_x);
|
|
for (s_y = y; s_y < 16; s_y += h)
|
|
sbits[s_y] = sbit;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/* cache one stipple; figuring out if we can use the stipple is as hard as
|
|
* computing it, so we just use this one and leave it here if it
|
|
* can't be used this time
|
|
*/
|
|
|
|
static sunGXStipplePtr tmpStipple;
|
|
|
|
Bool
|
|
sunGXCheckFill (pGC, pDrawable)
|
|
GCPtr pGC;
|
|
DrawablePtr pDrawable;
|
|
{
|
|
sunGXPrivGCPtr gxPriv = sunGXGetGCPrivate (pGC);
|
|
sunGXStipplePtr stipple;
|
|
Uint alu;
|
|
int xrot, yrot;
|
|
|
|
if (pGC->fillStyle == FillSolid)
|
|
{
|
|
if (gxPriv->stipple)
|
|
{
|
|
xfree (gxPriv->stipple);
|
|
gxPriv->stipple = 0;
|
|
}
|
|
return TRUE;
|
|
}
|
|
if (!(stipple = gxPriv->stipple))
|
|
{
|
|
if (!tmpStipple)
|
|
{
|
|
tmpStipple = (sunGXStipplePtr) xalloc (sizeof *tmpStipple);
|
|
if (!tmpStipple)
|
|
return FALSE;
|
|
}
|
|
stipple = tmpStipple;
|
|
}
|
|
alu = gx_opaque_stipple_rop_table[pGC->alu]|GX_PATTERN_MASK;
|
|
switch (pGC->fillStyle) {
|
|
case FillTiled:
|
|
if (!sunGXCheckTile (pGC->tile.pixmap, stipple))
|
|
{
|
|
if (gxPriv->stipple)
|
|
{
|
|
xfree (gxPriv->stipple);
|
|
gxPriv->stipple = 0;
|
|
}
|
|
return FALSE;
|
|
}
|
|
break;
|
|
case FillStippled:
|
|
alu = gx_stipple_rop_table[pGC->alu]|GX_PATTERN_MASK;
|
|
case FillOpaqueStippled:
|
|
if (!sunGXCheckStipple (pGC->stipple, stipple))
|
|
{
|
|
if (gxPriv->stipple)
|
|
{
|
|
xfree (gxPriv->stipple);
|
|
gxPriv->stipple = 0;
|
|
}
|
|
return FALSE;
|
|
}
|
|
stipple->fore = pGC->fgPixel;
|
|
stipple->back = pGC->bgPixel;
|
|
break;
|
|
}
|
|
xrot = (pGC->patOrg.x + pDrawable->x) & 0xf;
|
|
yrot = (pGC->patOrg.y + pDrawable->y) & 0xf;
|
|
/*
|
|
stipple->patalign = ((16 - (xrot & 0xf)) << 16) | (16 - (yrot & 0xf));
|
|
*/
|
|
xrot = 16 - xrot;
|
|
yrot = 16 - yrot;
|
|
stipple->patalign = (xrot << 16) | yrot;
|
|
stipple->alu = alu;
|
|
gxPriv->stipple = stipple;
|
|
if (stipple == tmpStipple)
|
|
tmpStipple = 0;
|
|
return TRUE;
|
|
}
|
|
|
|
void sunGXValidateGC ();
|
|
void sunGXDestroyGC ();
|
|
|
|
GCFuncs sunGXGCFuncs = {
|
|
sunGXValidateGC,
|
|
miChangeGC,
|
|
miCopyGC,
|
|
sunGXDestroyGC,
|
|
miChangeClip,
|
|
miDestroyClip,
|
|
miCopyClip
|
|
};
|
|
|
|
GCOps sunGXTEOps1Rect = {
|
|
sunGXFillSpans,
|
|
cfbSetSpans,
|
|
cfbPutImage,
|
|
sunGXCopyArea,
|
|
sunGXCopyPlane,
|
|
cfbPolyPoint,
|
|
sunGXPolylines1Rect,
|
|
sunGXPolySeg1Rect,
|
|
miPolyRectangle,
|
|
cfbZeroPolyArcSS8Copy,
|
|
sunGXFillPoly1Rect,
|
|
sunGXPolyFillRect1Rect,
|
|
sunGXPolyFillArc,
|
|
miPolyText8,
|
|
miPolyText16,
|
|
miImageText8,
|
|
miImageText16,
|
|
sunGXTEGlyphBlt,
|
|
sunGXPolyTEGlyphBlt,
|
|
cfbPushPixels8
|
|
#ifdef NEED_LINEHELPER
|
|
,NULL
|
|
#endif
|
|
};
|
|
|
|
GCOps sunGXTEOps = {
|
|
sunGXFillSpans,
|
|
cfbSetSpans,
|
|
cfbPutImage,
|
|
sunGXCopyArea,
|
|
sunGXCopyPlane,
|
|
cfbPolyPoint,
|
|
cfbLineSS,
|
|
cfbSegmentSS,
|
|
miPolyRectangle,
|
|
cfbZeroPolyArcSS8Copy,
|
|
miFillPolygon,
|
|
sunGXPolyFillRect,
|
|
sunGXPolyFillArc,
|
|
miPolyText8,
|
|
miPolyText16,
|
|
miImageText8,
|
|
miImageText16,
|
|
sunGXTEGlyphBlt,
|
|
sunGXPolyTEGlyphBlt,
|
|
cfbPushPixels8
|
|
#ifdef NEED_LINEHELPER
|
|
,NULL
|
|
#endif
|
|
};
|
|
|
|
GCOps sunGXNonTEOps1Rect = {
|
|
sunGXFillSpans,
|
|
cfbSetSpans,
|
|
cfbPutImage,
|
|
sunGXCopyArea,
|
|
sunGXCopyPlane,
|
|
cfbPolyPoint,
|
|
sunGXPolylines1Rect,
|
|
sunGXPolySeg1Rect,
|
|
miPolyRectangle,
|
|
cfbZeroPolyArcSS8Copy,
|
|
sunGXFillPoly1Rect,
|
|
sunGXPolyFillRect1Rect,
|
|
sunGXPolyFillArc,
|
|
miPolyText8,
|
|
miPolyText16,
|
|
miImageText8,
|
|
miImageText16,
|
|
miImageGlyphBlt,
|
|
sunGXPolyGlyphBlt,
|
|
cfbPushPixels8
|
|
#ifdef NEED_LINEHELPER
|
|
,NULL
|
|
#endif
|
|
};
|
|
|
|
GCOps sunGXNonTEOps = {
|
|
sunGXFillSpans,
|
|
cfbSetSpans,
|
|
cfbPutImage,
|
|
sunGXCopyArea,
|
|
sunGXCopyPlane,
|
|
cfbPolyPoint,
|
|
cfbLineSS,
|
|
cfbSegmentSS,
|
|
miPolyRectangle,
|
|
cfbZeroPolyArcSS8Copy,
|
|
miFillPolygon,
|
|
sunGXPolyFillRect,
|
|
sunGXPolyFillArc,
|
|
miPolyText8,
|
|
miPolyText16,
|
|
miImageText8,
|
|
miImageText16,
|
|
miImageGlyphBlt,
|
|
sunGXPolyGlyphBlt,
|
|
cfbPushPixels8
|
|
#ifdef NEED_LINEHELPER
|
|
,NULL
|
|
#endif
|
|
};
|
|
|
|
#define FONTWIDTH(font) (FONTMAXBOUNDS(font,rightSideBearing) - \
|
|
FONTMINBOUNDS(font,leftSideBearing))
|
|
|
|
GCOps *
|
|
sunGXMatchCommon (pGC, devPriv)
|
|
GCPtr pGC;
|
|
cfbPrivGCPtr devPriv;
|
|
{
|
|
if (pGC->lineWidth != 0)
|
|
return 0;
|
|
if (pGC->lineStyle != LineSolid)
|
|
return 0;
|
|
if (pGC->fillStyle != FillSolid)
|
|
return 0;
|
|
if (devPriv->rop != GXcopy)
|
|
return 0;
|
|
if (!WID_OK(pGC->pScreen))
|
|
return 0;
|
|
if (pGC->font &&
|
|
FONTWIDTH (pGC->font) <= 32 &&
|
|
FONTMINBOUNDS(pGC->font,characterWidth) >= 0)
|
|
{
|
|
if (TERMINALFONT(pGC->font))
|
|
if (devPriv->oneRect)
|
|
return &sunGXTEOps1Rect;
|
|
else
|
|
return &sunGXTEOps;
|
|
else
|
|
if (devPriv->oneRect)
|
|
return &sunGXNonTEOps1Rect;
|
|
else
|
|
return &sunGXNonTEOps;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
sunGXValidateGC (pGC, changes, pDrawable)
|
|
GCPtr pGC;
|
|
Mask changes;
|
|
DrawablePtr pDrawable;
|
|
{
|
|
int mask; /* stateChanges */
|
|
int index; /* used for stepping through bitfields */
|
|
int new_rrop;
|
|
int new_line, new_text, new_fillspans, new_fillarea;
|
|
int new_rotate;
|
|
int xrot, yrot;
|
|
/* flags for changing the proc vector */
|
|
cfbPrivGCPtr devPriv;
|
|
sunGXPrivGCPtr gxPriv;
|
|
int oneRect;
|
|
int canGX;
|
|
int widOK;
|
|
|
|
gxPriv = sunGXGetGCPrivate (pGC);
|
|
widOK = WID_OK(pGC->pScreen);
|
|
if (pDrawable->type != DRAWABLE_WINDOW)
|
|
{
|
|
if (gxPriv->type == DRAWABLE_WINDOW)
|
|
{
|
|
extern GCOps cfbNonTEOps;
|
|
|
|
miDestroyGCOps (pGC->ops);
|
|
pGC->ops = &cfbNonTEOps;
|
|
changes = (1 << (GCLastBit + 1)) - 1;
|
|
pGC->stateChanges = changes;
|
|
gxPriv->type = pDrawable->type;
|
|
}
|
|
cfbValidateGC (pGC, changes, pDrawable);
|
|
return;
|
|
}
|
|
if (gxPriv->type != DRAWABLE_WINDOW)
|
|
{
|
|
changes = (1 << (GCLastBit + 1)) - 1;
|
|
gxPriv->type = DRAWABLE_WINDOW;
|
|
}
|
|
|
|
new_rotate = pGC->lastWinOrg.x != pDrawable->x ||
|
|
pGC->lastWinOrg.y != pDrawable->y;
|
|
|
|
pGC->lastWinOrg.x = pDrawable->x;
|
|
pGC->lastWinOrg.y = pDrawable->y;
|
|
|
|
devPriv = ((cfbPrivGCPtr) (pGC->devPrivates[cfbGCPrivateIndex].ptr));
|
|
|
|
new_rrop = FALSE;
|
|
new_line = FALSE;
|
|
new_text = FALSE;
|
|
new_fillspans = FALSE;
|
|
new_fillarea = FALSE;
|
|
|
|
/*
|
|
* if the client clip is different or moved OR the subwindowMode has
|
|
* changed OR the window's clip has changed since the last validation
|
|
* we need to recompute the composite clip
|
|
*/
|
|
|
|
if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) ||
|
|
(pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS))
|
|
)
|
|
{
|
|
miComputeCompositeClip(pGC, pDrawable);
|
|
oneRect = REGION_NUM_RECTS(pGC->pCompositeClip) == 1;
|
|
if (oneRect != devPriv->oneRect)
|
|
{
|
|
new_line = TRUE;
|
|
new_fillarea = TRUE;
|
|
devPriv->oneRect = oneRect;
|
|
}
|
|
}
|
|
|
|
mask = changes;
|
|
while (mask) {
|
|
index = lowbit (mask);
|
|
mask &= ~index;
|
|
|
|
/*
|
|
* this switch acculmulates a list of which procedures might have
|
|
* to change due to changes in the GC. in some cases (e.g.
|
|
* changing one 16 bit tile for another) we might not really need
|
|
* a change, but the code is being paranoid. this sort of batching
|
|
* wins if, for example, the alu and the font have been changed,
|
|
* or any other pair of items that both change the same thing.
|
|
*/
|
|
switch (index) {
|
|
case GCFunction:
|
|
case GCForeground:
|
|
new_rrop = TRUE;
|
|
break;
|
|
case GCPlaneMask:
|
|
new_rrop = TRUE;
|
|
new_text = TRUE;
|
|
break;
|
|
case GCBackground:
|
|
break;
|
|
case GCLineStyle:
|
|
case GCLineWidth:
|
|
new_line = TRUE;
|
|
break;
|
|
case GCCapStyle:
|
|
break;
|
|
case GCJoinStyle:
|
|
break;
|
|
case GCFillStyle:
|
|
new_text = TRUE;
|
|
new_fillspans = TRUE;
|
|
new_line = TRUE;
|
|
new_fillarea = TRUE;
|
|
break;
|
|
case GCFillRule:
|
|
break;
|
|
case GCTile:
|
|
new_fillspans = TRUE;
|
|
new_fillarea = TRUE;
|
|
break;
|
|
|
|
case GCStipple:
|
|
new_fillspans = TRUE;
|
|
new_fillarea = TRUE;
|
|
break;
|
|
|
|
case GCTileStipXOrigin:
|
|
new_rotate = TRUE;
|
|
break;
|
|
|
|
case GCTileStipYOrigin:
|
|
new_rotate = TRUE;
|
|
break;
|
|
|
|
case GCFont:
|
|
new_text = TRUE;
|
|
break;
|
|
case GCSubwindowMode:
|
|
break;
|
|
case GCGraphicsExposures:
|
|
break;
|
|
case GCClipXOrigin:
|
|
break;
|
|
case GCClipYOrigin:
|
|
break;
|
|
case GCClipMask:
|
|
break;
|
|
case GCDashOffset:
|
|
break;
|
|
case GCDashList:
|
|
break;
|
|
case GCArcMode:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If the drawable has changed, check its depth & ensure suitable
|
|
* entries are in the proc vector.
|
|
*/
|
|
if (pDrawable->serialNumber != (pGC->serialNumber & (DRAWABLE_SERIAL_BITS))) {
|
|
new_fillspans = TRUE; /* deal with FillSpans later */
|
|
}
|
|
|
|
if ((new_rotate || new_fillspans))
|
|
{
|
|
Bool new_pix = FALSE;
|
|
xrot = pGC->patOrg.x + pDrawable->x;
|
|
yrot = pGC->patOrg.y + pDrawable->y;
|
|
|
|
if (!sunGXCheckFill (pGC, pDrawable))
|
|
{
|
|
switch (pGC->fillStyle)
|
|
{
|
|
case FillTiled:
|
|
if (!pGC->tileIsPixel)
|
|
{
|
|
int width = pGC->tile.pixmap->drawable.width * PSZ;
|
|
|
|
if ((width <= 32) && !(width & (width - 1)))
|
|
{
|
|
cfbCopyRotatePixmap(pGC->tile.pixmap,
|
|
&pGC->pRotatedPixmap,
|
|
xrot, yrot);
|
|
new_pix = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
case FillStippled:
|
|
case FillOpaqueStippled:
|
|
{
|
|
int width = pGC->stipple->drawable.width;
|
|
|
|
if ((width <= 32) && !(width & (width - 1)))
|
|
{
|
|
mfbCopyRotatePixmap(pGC->stipple,
|
|
&pGC->pRotatedPixmap, xrot, yrot);
|
|
new_pix = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (!new_pix && pGC->pRotatedPixmap)
|
|
{
|
|
cfbDestroyPixmap(pGC->pRotatedPixmap);
|
|
pGC->pRotatedPixmap = (PixmapPtr) NULL;
|
|
}
|
|
}
|
|
|
|
if (new_rrop)
|
|
{
|
|
int old_rrop;
|
|
|
|
if (gxPriv->stipple)
|
|
{
|
|
if (pGC->fillStyle == FillStippled)
|
|
gxPriv->stipple->alu = gx_stipple_rop_table[pGC->alu]|GX_PATTERN_MASK;
|
|
else
|
|
gxPriv->stipple->alu = gx_opaque_stipple_rop_table[pGC->alu]|GX_PATTERN_MASK;
|
|
if (pGC->fillStyle != FillTiled)
|
|
{
|
|
gxPriv->stipple->fore = pGC->fgPixel;
|
|
gxPriv->stipple->back = pGC->bgPixel;
|
|
}
|
|
}
|
|
old_rrop = devPriv->rop;
|
|
devPriv->rop = cfbReduceRasterOp (pGC->alu, pGC->fgPixel,
|
|
pGC->planemask,
|
|
&devPriv->and, &devPriv->xor);
|
|
if (old_rrop == devPriv->rop)
|
|
new_rrop = FALSE;
|
|
else
|
|
{
|
|
new_line = TRUE;
|
|
new_text = TRUE;
|
|
new_fillspans = TRUE;
|
|
new_fillarea = TRUE;
|
|
}
|
|
}
|
|
|
|
if (new_rrop || new_fillspans || new_text || new_fillarea || new_line)
|
|
{
|
|
GCOps *newops;
|
|
|
|
if ((newops = sunGXMatchCommon (pGC, devPriv)))
|
|
{
|
|
if (pGC->ops->devPrivate.val)
|
|
miDestroyGCOps (pGC->ops);
|
|
pGC->ops = newops;
|
|
new_rrop = new_line = new_fillspans = new_text = new_fillarea = 0;
|
|
}
|
|
else
|
|
{
|
|
if (!pGC->ops->devPrivate.val)
|
|
{
|
|
pGC->ops = miCreateGCOps (pGC->ops);
|
|
pGC->ops->devPrivate.val = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
canGX = pGC->fillStyle == FillSolid || gxPriv->stipple;
|
|
|
|
/* deal with the changes we've collected */
|
|
if (new_line)
|
|
{
|
|
pGC->ops->FillPolygon = miFillPolygon;
|
|
if (devPriv->oneRect && canGX)
|
|
pGC->ops->FillPolygon = sunGXFillPoly1Rect;
|
|
if (pGC->lineWidth == 0)
|
|
{
|
|
if ((pGC->lineStyle == LineSolid) && (pGC->fillStyle == FillSolid))
|
|
{
|
|
switch (devPriv->rop)
|
|
{
|
|
case GXxor:
|
|
pGC->ops->PolyArc = cfbZeroPolyArcSS8Xor;
|
|
break;
|
|
case GXcopy:
|
|
pGC->ops->PolyArc = cfbZeroPolyArcSS8Copy;
|
|
break;
|
|
default:
|
|
pGC->ops->PolyArc = cfbZeroPolyArcSS8General;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
pGC->ops->PolyArc = miZeroPolyArc;
|
|
}
|
|
else
|
|
pGC->ops->PolyArc = miPolyArc;
|
|
pGC->ops->PolySegment = miPolySegment;
|
|
switch (pGC->lineStyle)
|
|
{
|
|
case LineSolid:
|
|
if(pGC->lineWidth == 0)
|
|
{
|
|
if (devPriv->oneRect && canGX && widOK)
|
|
{
|
|
pGC->ops->PolySegment = sunGXPolySeg1Rect;
|
|
pGC->ops->Polylines = sunGXPolylines1Rect;
|
|
}
|
|
else if (pGC->fillStyle == FillSolid)
|
|
{
|
|
if (devPriv->oneRect)
|
|
{
|
|
pGC->ops->Polylines = cfb8LineSS1Rect;
|
|
pGC->ops->PolySegment = cfb8SegmentSS1Rect;
|
|
}
|
|
else
|
|
{
|
|
pGC->ops->Polylines = cfbLineSS;
|
|
pGC->ops->PolySegment = cfbSegmentSS;
|
|
}
|
|
}
|
|
else
|
|
pGC->ops->Polylines = miZeroLine;
|
|
}
|
|
else
|
|
pGC->ops->Polylines = miWideLine;
|
|
break;
|
|
case LineOnOffDash:
|
|
case LineDoubleDash:
|
|
if (pGC->lineWidth == 0 && pGC->fillStyle == FillSolid)
|
|
{
|
|
pGC->ops->Polylines = cfbLineSD;
|
|
pGC->ops->PolySegment = cfbSegmentSD;
|
|
} else
|
|
pGC->ops->Polylines = miWideDash;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (new_text && (pGC->font))
|
|
{
|
|
if (FONTWIDTH(pGC->font) > 32 ||
|
|
FONTMINBOUNDS(pGC->font,characterWidth) < 0)
|
|
{
|
|
pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
|
|
pGC->ops->ImageGlyphBlt = miImageGlyphBlt;
|
|
}
|
|
else
|
|
{
|
|
if (pGC->fillStyle == FillSolid)
|
|
{
|
|
if (TERMINALFONT (pGC->font))
|
|
pGC->ops->PolyGlyphBlt = sunGXPolyTEGlyphBlt;
|
|
else
|
|
pGC->ops->PolyGlyphBlt = sunGXPolyGlyphBlt;
|
|
}
|
|
else
|
|
pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
|
|
/* special case ImageGlyphBlt for terminal emulator fonts */
|
|
if (TERMINALFONT(pGC->font))
|
|
pGC->ops->ImageGlyphBlt = sunGXTEGlyphBlt;
|
|
else
|
|
pGC->ops->ImageGlyphBlt = miImageGlyphBlt;
|
|
}
|
|
}
|
|
|
|
|
|
if (new_fillspans) {
|
|
if (canGX)
|
|
pGC->ops->FillSpans = sunGXFillSpans;
|
|
else switch (pGC->fillStyle) {
|
|
case FillTiled:
|
|
if (pGC->pRotatedPixmap)
|
|
{
|
|
if (pGC->alu == GXcopy && (pGC->planemask & PMSK) == PMSK)
|
|
pGC->ops->FillSpans = cfbTile32FSCopy;
|
|
else
|
|
pGC->ops->FillSpans = cfbTile32FSGeneral;
|
|
}
|
|
else
|
|
pGC->ops->FillSpans = cfbUnnaturalTileFS;
|
|
break;
|
|
case FillStippled:
|
|
if (pGC->pRotatedPixmap)
|
|
pGC->ops->FillSpans = cfb8Stipple32FS;
|
|
else
|
|
pGC->ops->FillSpans = cfbUnnaturalStippleFS;
|
|
break;
|
|
case FillOpaqueStippled:
|
|
if (pGC->pRotatedPixmap)
|
|
pGC->ops->FillSpans = cfb8OpaqueStipple32FS;
|
|
else
|
|
pGC->ops->FillSpans = cfbUnnaturalStippleFS;
|
|
break;
|
|
default:
|
|
FatalError("cfbValidateGC: illegal fillStyle\n");
|
|
}
|
|
} /* end of new_fillspans */
|
|
|
|
if (new_fillarea) {
|
|
pGC->ops->PolyFillRect = cfbPolyFillRect;
|
|
pGC->ops->PolyFillArc = miPolyFillArc;
|
|
if (canGX)
|
|
{
|
|
pGC->ops->PolyFillArc = sunGXPolyFillArc;
|
|
pGC->ops->PolyFillRect = sunGXPolyFillRect;
|
|
if (devPriv->oneRect)
|
|
pGC->ops->PolyFillRect = sunGXPolyFillRect1Rect;
|
|
}
|
|
pGC->ops->PushPixels = mfbPushPixels;
|
|
if (pGC->fillStyle == FillSolid && devPriv->rop == GXcopy)
|
|
pGC->ops->PushPixels = cfbPushPixels8;
|
|
}
|
|
}
|
|
|
|
void
|
|
sunGXDestroyGC (pGC)
|
|
GCPtr pGC;
|
|
{
|
|
sunGXPrivGCPtr gxPriv = sunGXGetGCPrivate (pGC);
|
|
|
|
if (gxPriv->stipple)
|
|
xfree (gxPriv->stipple);
|
|
miDestroyGC (pGC);
|
|
}
|
|
|
|
Bool
|
|
sunGXCreateGC (pGC)
|
|
GCPtr pGC;
|
|
{
|
|
sunGXPrivGCPtr gxPriv;
|
|
if (pGC->depth == 1)
|
|
return mfbCreateGC (pGC);
|
|
if (!cfbCreateGC (pGC))
|
|
return FALSE;
|
|
pGC->ops = &sunGXNonTEOps;
|
|
pGC->funcs = &sunGXGCFuncs;
|
|
gxPriv = sunGXGetGCPrivate(pGC);
|
|
gxPriv->type = DRAWABLE_WINDOW;
|
|
gxPriv->stipple = 0;
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
sunGXCreateWindow (pWin)
|
|
WindowPtr pWin;
|
|
{
|
|
if (!cfbCreateWindow (pWin))
|
|
return FALSE;
|
|
pWin->devPrivates[sunGXWindowPrivateIndex].ptr = 0;
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
sunGXDestroyWindow (pWin)
|
|
WindowPtr pWin;
|
|
{
|
|
sunGXStipplePtr stipple = sunGXGetWindowPrivate(pWin);
|
|
xfree (stipple);
|
|
return cfbDestroyWindow (pWin);
|
|
}
|
|
|
|
Bool
|
|
sunGXChangeWindowAttributes (pWin, mask)
|
|
WindowPtr pWin;
|
|
Mask mask;
|
|
{
|
|
sunGXStipplePtr stipple;
|
|
Mask index;
|
|
WindowPtr pBgWin;
|
|
register cfbPrivWin *pPrivWin;
|
|
int width;
|
|
|
|
pPrivWin = (cfbPrivWin *)(pWin->devPrivates[cfbWindowPrivateIndex].ptr);
|
|
/*
|
|
* When background state changes from ParentRelative and
|
|
* we had previously rotated the fast border pixmap to match
|
|
* the parent relative origin, rerotate to match window
|
|
*/
|
|
if (mask & (CWBackPixmap | CWBackPixel) &&
|
|
pWin->backgroundState != ParentRelative &&
|
|
pPrivWin->fastBorder &&
|
|
(pPrivWin->oldRotate.x != pWin->drawable.x ||
|
|
pPrivWin->oldRotate.y != pWin->drawable.y))
|
|
{
|
|
cfbXRotatePixmap(pPrivWin->pRotatedBorder,
|
|
pWin->drawable.x - pPrivWin->oldRotate.x);
|
|
cfbYRotatePixmap(pPrivWin->pRotatedBorder,
|
|
pWin->drawable.y - pPrivWin->oldRotate.y);
|
|
pPrivWin->oldRotate.x = pWin->drawable.x;
|
|
pPrivWin->oldRotate.y = pWin->drawable.y;
|
|
}
|
|
while (mask)
|
|
{
|
|
index = lowbit(mask);
|
|
mask &= ~index;
|
|
switch (index)
|
|
{
|
|
case CWBackPixmap:
|
|
stipple = sunGXGetWindowPrivate(pWin);
|
|
if (pWin->backgroundState == None ||
|
|
pWin->backgroundState == ParentRelative)
|
|
{
|
|
pPrivWin->fastBackground = FALSE;
|
|
if (stipple)
|
|
{
|
|
xfree (stipple);
|
|
sunGXSetWindowPrivate(pWin,0);
|
|
}
|
|
/* Rotate border to match parent origin */
|
|
if (pWin->backgroundState == ParentRelative &&
|
|
pPrivWin->pRotatedBorder)
|
|
{
|
|
for (pBgWin = pWin->parent;
|
|
pBgWin->backgroundState == ParentRelative;
|
|
pBgWin = pBgWin->parent);
|
|
cfbXRotatePixmap(pPrivWin->pRotatedBorder,
|
|
pBgWin->drawable.x - pPrivWin->oldRotate.x);
|
|
cfbYRotatePixmap(pPrivWin->pRotatedBorder,
|
|
pBgWin->drawable.y - pPrivWin->oldRotate.y);
|
|
}
|
|
|
|
break;
|
|
}
|
|
if (!stipple)
|
|
{
|
|
if (!tmpStipple)
|
|
tmpStipple = (sunGXStipplePtr) xalloc (sizeof *tmpStipple);
|
|
stipple = tmpStipple;
|
|
}
|
|
if (stipple && sunGXCheckTile (pWin->background.pixmap, stipple))
|
|
{
|
|
stipple->alu = gx_opaque_stipple_rop_table[GXcopy]|GX_PATTERN_MASK;
|
|
pPrivWin->fastBackground = FALSE;
|
|
if (stipple == tmpStipple)
|
|
{
|
|
sunGXSetWindowPrivate(pWin, stipple);
|
|
tmpStipple = 0;
|
|
}
|
|
break;
|
|
}
|
|
if ((stipple = sunGXGetWindowPrivate(pWin)))
|
|
{
|
|
xfree (stipple);
|
|
sunGXSetWindowPrivate(pWin,0);
|
|
}
|
|
if (((width = (pWin->background.pixmap->drawable.width * PSZ)) <= BITMAP_SCANLINE_UNIT) &&
|
|
!(width & (width - 1)))
|
|
{
|
|
cfbCopyRotatePixmap(pWin->background.pixmap,
|
|
&pPrivWin->pRotatedBackground,
|
|
pWin->drawable.x,
|
|
pWin->drawable.y);
|
|
if (pPrivWin->pRotatedBackground)
|
|
{
|
|
pPrivWin->fastBackground = TRUE;
|
|
pPrivWin->oldRotate.x = pWin->drawable.x;
|
|
pPrivWin->oldRotate.y = pWin->drawable.y;
|
|
}
|
|
else
|
|
{
|
|
pPrivWin->fastBackground = FALSE;
|
|
}
|
|
break;
|
|
}
|
|
pPrivWin->fastBackground = FALSE;
|
|
break;
|
|
|
|
case CWBackPixel:
|
|
pPrivWin->fastBackground = FALSE;
|
|
break;
|
|
|
|
case CWBorderPixmap:
|
|
/* don't bother with accelerator for border tiles (just lazy) */
|
|
if (((width = (pWin->border.pixmap->drawable.width * PSZ)) <= BITMAP_SCANLINE_UNIT) &&
|
|
!(width & (width - 1)))
|
|
{
|
|
for (pBgWin = pWin;
|
|
pBgWin->backgroundState == ParentRelative;
|
|
pBgWin = pBgWin->parent);
|
|
cfbCopyRotatePixmap(pWin->border.pixmap,
|
|
&pPrivWin->pRotatedBorder,
|
|
pBgWin->drawable.x,
|
|
pBgWin->drawable.y);
|
|
if (pPrivWin->pRotatedBorder)
|
|
{
|
|
pPrivWin->fastBorder = TRUE;
|
|
pPrivWin->oldRotate.x = pBgWin->drawable.x;
|
|
pPrivWin->oldRotate.y = pBgWin->drawable.y;
|
|
}
|
|
else
|
|
{
|
|
pPrivWin->fastBorder = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pPrivWin->fastBorder = FALSE;
|
|
}
|
|
break;
|
|
case CWBorderPixel:
|
|
pPrivWin->fastBorder = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
return (TRUE);
|
|
}
|
|
|
|
void
|
|
sunGXPaintWindow(pWin, pRegion, what)
|
|
WindowPtr pWin;
|
|
RegionPtr pRegion;
|
|
int what;
|
|
{
|
|
register cfbPrivWin *pPrivWin;
|
|
sunGXStipplePtr stipple;
|
|
WindowPtr pBgWin;
|
|
pPrivWin = (cfbPrivWin *)(pWin->devPrivates[cfbWindowPrivateIndex].ptr);
|
|
|
|
switch (what) {
|
|
case PW_BACKGROUND:
|
|
stipple = sunGXGetWindowPrivate(pWin);
|
|
switch (pWin->backgroundState) {
|
|
case None:
|
|
return;
|
|
case ParentRelative:
|
|
do {
|
|
pWin = pWin->parent;
|
|
} while (pWin->backgroundState == ParentRelative);
|
|
(*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion,
|
|
what);
|
|
return;
|
|
case BackgroundPixmap:
|
|
if (stipple)
|
|
{
|
|
sunGXFillBoxStipple ((DrawablePtr)pWin,
|
|
(int)REGION_NUM_RECTS(pRegion),
|
|
REGION_RECTS(pRegion),
|
|
stipple);
|
|
}
|
|
else if (pPrivWin->fastBackground)
|
|
{
|
|
cfbFillBoxTile32 ((DrawablePtr)pWin,
|
|
(int)REGION_NUM_RECTS(pRegion),
|
|
REGION_RECTS(pRegion),
|
|
pPrivWin->pRotatedBackground);
|
|
}
|
|
else
|
|
{
|
|
cfbFillBoxTileOdd ((DrawablePtr)pWin,
|
|
(int)REGION_NUM_RECTS(pRegion),
|
|
REGION_RECTS(pRegion),
|
|
pWin->background.pixmap,
|
|
(int) pWin->drawable.x, (int) pWin->drawable.y);
|
|
}
|
|
return;
|
|
case BackgroundPixel:
|
|
sunGXFillBoxSolid((DrawablePtr)pWin,
|
|
(int)REGION_NUM_RECTS(pRegion),
|
|
REGION_RECTS(pRegion),
|
|
pWin->background.pixel);
|
|
return;
|
|
}
|
|
break;
|
|
case PW_BORDER:
|
|
if (pWin->borderIsPixel)
|
|
{
|
|
sunGXFillBoxSolid((DrawablePtr)pWin,
|
|
(int)REGION_NUM_RECTS(pRegion),
|
|
REGION_RECTS(pRegion),
|
|
pWin->border.pixel);
|
|
return;
|
|
}
|
|
else if (pPrivWin->fastBorder)
|
|
{
|
|
cfbFillBoxTile32 ((DrawablePtr)pWin,
|
|
(int)REGION_NUM_RECTS(pRegion),
|
|
REGION_RECTS(pRegion),
|
|
pPrivWin->pRotatedBorder);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
for (pBgWin = pWin;
|
|
pBgWin->backgroundState == ParentRelative;
|
|
pBgWin = pBgWin->parent);
|
|
|
|
cfbFillBoxTileOdd ((DrawablePtr)pWin,
|
|
(int)REGION_NUM_RECTS(pRegion),
|
|
REGION_RECTS(pRegion),
|
|
pWin->border.pixmap,
|
|
(int) pBgWin->drawable.x,
|
|
(int) pBgWin->drawable.y);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
sunGXCopyWindow(pWin, ptOldOrg, prgnSrc)
|
|
WindowPtr pWin;
|
|
DDXPointRec ptOldOrg;
|
|
RegionPtr prgnSrc;
|
|
{
|
|
DDXPointPtr pptSrc;
|
|
register DDXPointPtr ppt;
|
|
RegionPtr prgnDst;
|
|
register BoxPtr pbox;
|
|
register int dx, dy;
|
|
register int i, nbox;
|
|
WindowPtr pwinRoot;
|
|
extern WindowPtr *WindowTable;
|
|
|
|
pwinRoot = WindowTable[pWin->drawable.pScreen->myNum];
|
|
|
|
prgnDst = REGION_CREATE(pWin->drawable.pScreen, NULL, 1);
|
|
|
|
dx = ptOldOrg.x - pWin->drawable.x;
|
|
dy = ptOldOrg.y - pWin->drawable.y;
|
|
REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
|
|
REGION_INTERSECT(pWin->drawable.pScreen, prgnDst, &pWin->borderClip, prgnSrc);
|
|
|
|
pbox = REGION_RECTS(prgnDst);
|
|
nbox = REGION_NUM_RECTS(prgnDst);
|
|
if(!(pptSrc = (DDXPointPtr )ALLOCATE_LOCAL(nbox * sizeof(DDXPointRec))))
|
|
return;
|
|
ppt = pptSrc;
|
|
|
|
for (i = nbox; --i >= 0; ppt++, pbox++)
|
|
{
|
|
ppt->x = pbox->x1 + dx;
|
|
ppt->y = pbox->y1 + dy;
|
|
}
|
|
|
|
sunGXDoBitblt ((DrawablePtr)pwinRoot, (DrawablePtr)pwinRoot,
|
|
GXcopy, prgnDst, pptSrc, ~0L);
|
|
DEALLOCATE_LOCAL(pptSrc);
|
|
REGION_DESTROY(pWin->drawable.pScreen, prgnDst);
|
|
}
|
|
|
|
Bool
|
|
sunGXInit (
|
|
ScreenPtr pScreen,
|
|
fbFd *fb)
|
|
{
|
|
sunGXPtr gx;
|
|
Uint mode;
|
|
register long r;
|
|
|
|
if (serverGeneration != sunGXGeneration)
|
|
{
|
|
sunGXScreenPrivateIndex = AllocateScreenPrivateIndex();
|
|
if (sunGXScreenPrivateIndex == -1)
|
|
return FALSE;
|
|
sunGXGCPrivateIndex = AllocateGCPrivateIndex ();
|
|
sunGXWindowPrivateIndex = AllocateWindowPrivateIndex ();
|
|
sunGXGeneration = serverGeneration;
|
|
}
|
|
if (!AllocateGCPrivate(pScreen, sunGXGCPrivateIndex, sizeof (sunGXPrivGCRec)))
|
|
return FALSE;
|
|
if (!AllocateWindowPrivate(pScreen, sunGXWindowPrivateIndex, 0))
|
|
return FALSE;
|
|
gx = (sunGXPtr) fb->fb;
|
|
mode = gx->mode;
|
|
GXWait(gx,r);
|
|
mode &= ~( GX_BLIT_ALL |
|
|
GX_MODE_ALL |
|
|
GX_DRAW_ALL |
|
|
GX_BWRITE0_ALL |
|
|
GX_BWRITE1_ALL |
|
|
GX_BREAD_ALL |
|
|
GX_BDISP_ALL);
|
|
mode |= GX_BLIT_SRC |
|
|
GX_MODE_COLOR8 |
|
|
GX_DRAW_RENDER |
|
|
GX_BWRITE0_ENABLE |
|
|
GX_BWRITE1_DISABLE |
|
|
GX_BREAD_0 |
|
|
GX_BDISP_0;
|
|
gx->mode = mode;
|
|
gx->clip = 0;
|
|
gx->offx = 0;
|
|
gx->offy = 0;
|
|
gx->clipminx = 0;
|
|
gx->clipminy = 0;
|
|
gx->clipmaxx = fb->info.fb_width - 1;
|
|
gx->clipmaxy = fb->info.fb_height - 1;
|
|
pScreen->devPrivates[sunGXScreenPrivateIndex].ptr = (pointer) gx;
|
|
/*
|
|
* Replace various screen functions
|
|
*/
|
|
pScreen->CreateGC = sunGXCreateGC;
|
|
pScreen->CreateWindow = sunGXCreateWindow;
|
|
pScreen->ChangeWindowAttributes = sunGXChangeWindowAttributes;
|
|
pScreen->DestroyWindow = sunGXDestroyWindow;
|
|
pScreen->PaintWindowBackground = sunGXPaintWindow;
|
|
pScreen->PaintWindowBorder = sunGXPaintWindow;
|
|
pScreen->CopyWindow = sunGXCopyWindow;
|
|
return TRUE;
|
|
}
|