예제 #1
0
void
CreatorGetSpans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt,
		int *pwidth, int nspans, char *pchardstStart)
{
	FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
	ffb_fbcPtr ffb = pFfb->regs;
	char *addrp;

	FFBLOG(("CreatorGetSpans: wmax(%d) nspans(%d)\n", wMax, nspans));

	/* Punt early for this case. */
	if(pDrawable->bitsPerPixel == 1) {
		mfbGetSpans(pDrawable, wMax, ppt, pwidth,
			    nspans, pchardstStart);
		return;
	}

	/* This code only works when sucking bits directly from
	 * the framebuffer.
	 */
	if(pDrawable->type != DRAWABLE_WINDOW) {
		if (pDrawable->bitsPerPixel == 8)
			cfbGetSpans(pDrawable, wMax, ppt, pwidth,
				    nspans, pchardstStart);
		else
			cfb32GetSpans(pDrawable, wMax, ppt, pwidth,
				      nspans, pchardstStart);
		return;
	}

	/*
	 * XFree86 DDX empties the root borderClip when the VT is
	 * switched away; this checks for that case
	 */
	if (!cfbDrawableEnabled(pDrawable))
		return;
    
	/* We're just reading pixels from SFB, but we could be using
	 * a different read buffer when double-buffering.
	 */
	FFB_ATTR_SFB_VAR_WIN(pFfb, 0x00ffffff, GXcopy, (WindowPtr)pDrawable);
	FFBWait(pFfb, ffb);

	if (pDrawable->bitsPerPixel == 32) {
		unsigned int *pdst = (unsigned int *)pchardstStart;

		addrp = (char *) pFfb->sfb32;

		if ((nspans == 1) && (*pwidth == 1)) {
			*pdst = *(unsigned int *)(addrp + (ppt->y << 13) + (ppt->x << 2));
			return;
		}

		while(nspans--) {
			int w = min(ppt->x + *pwidth, 2048) - ppt->x;
			unsigned int *psrc = (unsigned int *) (addrp +
							       (ppt->y << 13) +
							       (ppt->x << 2));
			unsigned int *pdstNext = pdst + w;

			while (w--)
				*psrc++ = *pdst++;
			pdst = pdstNext;
			ppt++;
			pwidth++;
		}
	} else {
		unsigned char *pdst = (unsigned char *)pchardstStart;

		addrp = (char *) pFfb->sfb8r;

		if ((nspans == 1) && (*pwidth == 1)) {
			*pdst = *(unsigned char *)(addrp + (ppt->y << 11) + (ppt->x << 0));
			return;
		}

		while(nspans--) {
			int w = min(ppt->x + *pwidth, 2048) - ppt->x;
			unsigned char *psrc = (unsigned char *) (addrp +
							       (ppt->y << 11) +
							       (ppt->x << 0));
			unsigned char *pdstNext = pdst + w;

			while (w--)
				*psrc++ = *pdst++;
			pdst = pdstNext;
			ppt++;
			pwidth++;
		}
	}
}
예제 #2
0
RegionPtr
CreatorCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
		GCPtr pGC, int srcx, int srcy, int width, int height, int dstx, int dsty)
{
	FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDstDrawable->pScreen);
	ffb_fbcPtr ffb = pFfb->regs;
	RegionPtr ret;
	unsigned char *dptr, *sptr, *sfb;
	int garbage, all_planes;
	
	cfbGetByteWidthAndPointer (pDstDrawable, garbage, dptr);
	cfbGetByteWidthAndPointer (pSrcDrawable, garbage, sptr);
	if (pSrcDrawable->bitsPerPixel == 8) {
		sfb = (unsigned char *) pFfb->sfb8r;
		all_planes = 0xff;
	} else {
		sfb = (unsigned char *) pFfb->sfb32;
		all_planes = 0xffffff;
	}

	FFBLOG(("CreatorCopyArea: SFB(%p) s(%p) d(%p) alu(%x) pmsk(%08x) "
		"src(%08x:%08x) dst(%08x:%08x)\n",
		sfb, sptr, dptr, pGC->alu, pGC->planemask,
		srcx, srcy, dstx, dsty));
	if (((pGC->planemask & all_planes) != all_planes || pGC->alu != GXcopy) &&
	    dptr != sfb) {
		if(sptr == sfb) {
			WindowPtr pWin = (WindowPtr) pSrcDrawable;

			FFB_ATTR_SFB_VAR_WIN(pFfb, pGC->planemask, pGC->alu, pWin);
			FFBWait(pFfb, ffb);
		}
		if (pSrcDrawable->bitsPerPixel == 8)
			return cfbCopyArea (pSrcDrawable, pDstDrawable,
					    pGC, srcx, srcy, width, height, dstx, dsty);
		else
			return cfb32CopyArea (pSrcDrawable, pDstDrawable,
					      pGC, srcx, srcy, width, height, dstx, dsty);
	}

	/* Try to use hw VSCROLL if possible */
	if (!pFfb->disable_vscroll &&	/* must not be ffb1 in hires */
	    pGC->alu == GXcopy &&	/* it must be a copy */
	    dstx == srcx &&		/* X must be unchanging */
	    dsty != srcy &&		/* Y must be changing */
	    sptr == dptr &&		/* src and dst must be the framebuffer */
	    dptr == sfb) {
		WindowPtr pWin = (WindowPtr) pSrcDrawable;
		CreatorPrivWinPtr pFfbPrivWin = CreatorGetWindowPrivate(pWin);
		unsigned int fbc = pFfbPrivWin->fbc_base;
		int same_buffer;

		/* One last check, the read buffer and the write buffer
		 * must be the same.  VSCROLL only allows to move pixels
		 * within the same buffer.
		 */
		if (!pFfb->has_double_buffer) {
			same_buffer = 1;
		} else {
			same_buffer = 0;
			if ((((fbc & FFB_FBC_WB_MASK) == FFB_FBC_WB_A) &&
			     ((fbc & FFB_FBC_RB_MASK) == FFB_FBC_RB_A)) ||
			    (((fbc & FFB_FBC_WB_MASK) == FFB_FBC_WB_B) &&
			     ((fbc & FFB_FBC_RB_MASK) == FFB_FBC_RB_B)))
				same_buffer = 1;
		}

		if (same_buffer != 0) {
			FFB_ATTR_VSCROLL_WIN(pFfb, pGC->planemask, pWin);
			if (pSrcDrawable->bitsPerPixel == 8)
				ret = cfbBitBlt (pSrcDrawable, pDstDrawable,
						 pGC, srcx, srcy, width, height,
						 dstx, dsty,
						 (void (*)())CreatorDoVertBitblt, 0);
			else
				ret = cfb32BitBlt (pSrcDrawable, pDstDrawable,
						   pGC, srcx, srcy, width, height,
						   dstx, dsty,
						   (void (*)())CreatorDoVertBitblt, 0);
			FFBLOG(("CreatorCopyArea: Done, returning %p\n", ret));
			return ret;
		}
	}

	/* OK, we have to use GCOPY. */

	/* Even when we are only reading from the framebuffer, we must
	 * set the SFB_VAR attributes to handle double-buffering correctly.
	 */
	if(dptr == sfb || sptr == sfb) {
		WindowPtr pWin;

		if (dptr == sfb)
			pWin = (WindowPtr) pDstDrawable;
		else
			pWin = (WindowPtr) pSrcDrawable;
		FFB_ATTR_SFB_VAR_WIN(pFfb, pGC->planemask, pGC->alu, pWin);
		FFBWait(pFfb, ffb);
	}
	if (pSrcDrawable->bitsPerPixel == 8)
		ret = cfbBitBlt (pSrcDrawable, pDstDrawable,
				 pGC, srcx, srcy, width, height,
				 dstx, dsty, (void (*)())CreatorDoBitblt, 0);
	else
		ret = cfb32BitBlt (pSrcDrawable, pDstDrawable,
				   pGC, srcx, srcy, width, height,
				   dstx, dsty, (void (*)())CreatorDoBitblt, 0);

	FFBLOG(("CreatorCopyArea: Done, returning %p\n", ret));
	return ret;
}
예제 #3
0
void
CreatorSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *pcharsrc,
		DDXPointPtr ppt, int *pwidth, int nspans, int fSorted)
{
	WindowPtr pWin = (WindowPtr) pDrawable;
	FFBPtr pFfb = GET_FFB_FROM_SCREEN (pDrawable->pScreen);
	ffb_fbcPtr ffb = pFfb->regs;
	unsigned int *psrc = (unsigned int *)pcharsrc;
	BoxPtr pbox, pboxLast, pboxTest;
	DDXPointPtr pptLast;
	RegionPtr prgnDst;
	char *addrp;
	int xStart, xEnd, yMax;

	if(pDrawable->type != DRAWABLE_WINDOW) {
		if (pDrawable->bitsPerPixel == 8)
			cfbSetSpans(pDrawable, pGC, pcharsrc, ppt,
				    pwidth, nspans, fSorted);
		else
			cfb32SetSpans(pDrawable, pGC, pcharsrc, ppt,
				      pwidth, nspans, fSorted);
		return;
	}
	FFBLOG(("CreatorSetSpans: ALU(%x) PMSK(%08x) nspans(%d) fsorted(%d)\n",
		pGC->alu, pGC->planemask, nspans, fSorted));
	if (pGC->alu == GXnoop)
		return;

	/* Get SFB ready. */
	FFB_ATTR_SFB_VAR_WIN(pFfb, pGC->planemask, pGC->alu, pWin);
	FFBWait(pFfb, ffb);

	if (pGC->depth == 8)
		addrp = (char *) pFfb->sfb8r;
	else
		addrp = (char *) pFfb->sfb32;

	yMax = (int) pDrawable->y + (int) pDrawable->height;
	prgnDst = cfbGetCompositeClip(pGC);
	pbox = REGION_RECTS(prgnDst);
	pboxLast = pbox + REGION_NUM_RECTS(prgnDst);
	pptLast = ppt + nspans;
	if(fSorted) {
		pboxTest = pbox;
		while(ppt < pptLast) {
			pbox = pboxTest;
			if(ppt->y >= yMax)
				break;
			while(pbox < pboxLast) {
				if(pbox->y1 > ppt->y) {
					break;
				} else if(pbox->y2 <= ppt->y) {
					pboxTest = ++pbox;
					continue;
				} else if(pbox->x1 > ppt->x + *pwidth) {
					break;
				} else if(pbox->x2 <= ppt->x) {
					pbox++;
					continue;
				}
				xStart = max(pbox->x1, ppt->x);
				xEnd = min(ppt->x + *pwidth, pbox->x2);
				CreatorSetScanline(ppt->y, ppt->x, xStart, xEnd,
						   psrc, addrp, pGC->depth);
				if(ppt->x + *pwidth <= pbox->x2)
					break;
				else
					pbox++;
			}
			ppt++;
			psrc += *pwidth++;
		}
	} else {
		while(ppt < pptLast) {
			if(ppt->y >= 0 && ppt->y < yMax) {
				for(pbox = REGION_RECTS(prgnDst); pbox < pboxLast; pbox++) {
					if(pbox->y1 > ppt->y) {
						break;
					} else if(pbox->y2 <= ppt->y) {
						pbox++;
						break;
					}
					if(pbox->x1 <= ppt->x + *pwidth &&
					   pbox->x2 > ppt->x) {
						xStart = max(pbox->x1, ppt->x);
						xEnd = min(pbox->x2, ppt->x + *pwidth);
						CreatorSetScanline(ppt->y, ppt->x,
								   xStart, xEnd,
								   psrc, addrp, pGC->depth);
					}
				}
			}
			ppt++;
			psrc += *pwidth++;
		}
	}
}