#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "apm.h" #include "miline.h" #ifdef HAVE_XAA_H /* Defines */ #define MAXLOOP 1000000 /* Translation from X ROP's to APM ROP's. */ static unsigned char apmROP[] = { 0, 0x88, 0x44, 0xCC, 0x22, 0xAA, 0x66, 0xEE, 0x11, 0x99, 0x55, 0xDD, 0x33, 0xBB, 0x77, 0xFF }; #include "apm_funcs.c" #define PSZ 24 #include "apm_funcs.c" static void ApmRemoveStipple(FBAreaPtr area) { ((struct ApmStippleCacheRec *)area->devPrivate.ptr)->apmStippleCached = FALSE; } static void ApmMoveStipple(FBAreaPtr from, FBAreaPtr to) { struct ApmStippleCacheRec *pApm = (struct ApmStippleCacheRec *)to->devPrivate.ptr; pApm->apmStippleCache.x = to->box.x1; pApm->apmStippleCache.y += to->box.y1 - from->box.y1; /* TODO : move data */ } /* * ApmCacheMonoStipple * because my poor AT3D needs stipples stored linearly in memory. */ static XAACacheInfoPtr ApmCacheMonoStipple(ScrnInfoPtr pScrn, PixmapPtr pPix) { APMDECL(pScrn); int w = pPix->drawable.width, W = (w + 31) & ~31; int h = pPix->drawable.height; int i, j, dwords, mem, width, funcNo; FBAreaPtr draw; struct ApmStippleCacheRec *pCache; unsigned char *srcPtr; CARD32 *dstPtr; static StippleScanlineProcPtr *StippleTab = NULL; if (!StippleTab) StippleTab = XAAGetStippleScanlineFuncMSBFirst(); for (i = 0; i < APM_CACHE_NUMBER; i++) if ((pApm->apmCache[i].apmStippleCache.serialNumber == pPix->drawable.serialNumber) && pApm->apmCache[i].apmStippleCached && (pApm->apmCache[i].apmStippleCache.fg == -1) && (pApm->apmCache[i].apmStippleCache.bg == -1)) { pApm->apmCache[i].apmStippleCache.trans_color = -1; return &pApm->apmCache[i].apmStippleCache; } if ((i = ++pApm->apmCachePtr) >= APM_CACHE_NUMBER) i = pApm->apmCachePtr = 0; pCache = &pApm->apmCache[i]; if (pCache->apmStippleCached) { pCache->apmStippleCached = FALSE; xf86FreeOffscreenArea(pCache->area); } draw = xf86AllocateLinearOffscreenArea(pApm->pScreen, (W * h + 7) / 8, (pApm->CurrentLayout.mask32 + 1) << 1, ApmMoveStipple, ApmRemoveStipple, pCache); if (!draw) return NULL; /* Let's hope this will never happen... */ pCache->area = draw; pCache->apmStippleCache.serialNumber = pPix->drawable.serialNumber; pCache->apmStippleCache.trans_color = pCache->apmStippleCache.bg = pCache->apmStippleCache.fg = -1; pCache->apmStippleCache.orig_w = w; pCache->apmStippleCache.orig_h = h; pCache->apmStippleCache.x = draw->box.x1; pCache->apmStippleCache.y = draw->box.y1 + ((pCache - pApm->apmCache) + 1) * pApm->CurrentLayout.Scanlines; mem = ((draw->box.x2 - draw->box.x1) * (draw->box.y2 - draw->box.y1) * pScrn->bitsPerPixel) / (W * h); width = 2; while (width * width <= mem) width++; width--; pCache->apmStippleCache.w = (width * W + pScrn->bitsPerPixel - 1) / pScrn->bitsPerPixel; pCache->apmStippleCache.h = ((draw->box.x2 - draw->box.x1) * (draw->box.y2 - draw->box.y1)) / pCache->apmStippleCache.w; pCache->apmStippleCached = TRUE; if (w < 32) { if (w & (w - 1)) funcNo = 1; else funcNo = 0; } else funcNo = 2; dstPtr = ((CARD32 *)pApm->FbBase) + (draw->box.x1 + draw->box.y1*pApm->CurrentLayout.bytesPerScanline) / 4; j = 0; dwords = (pCache->apmStippleCache.w * pScrn->bitsPerPixel) / 32; while (j + h <= pCache->apmStippleCache.h) { srcPtr = (unsigned char *)pPix->devPrivate.ptr; for (i = h; --i >= 0; ) { StippleTab[funcNo](dstPtr, (CARD32 *)srcPtr, 0, w, dwords); srcPtr += pPix->devKind; dstPtr += dwords; } j += h; } srcPtr = (unsigned char *)pPix->devPrivate.ptr; for (i = pCache->apmStippleCache.h - j ; --i >= 0; ) { StippleTab[funcNo](dstPtr, (CARD32 *)srcPtr, 0, w, dwords); srcPtr += pPix->devKind; dstPtr += dwords; } return &pCache->apmStippleCache; } #if 0 extern GCOps XAAPixmapOps; static RegionPtr (*SaveCopyAreaPixmap)(DrawablePtr, DrawablePtr, GC *, int, int, int, int, int, int); static RegionPtr ApmCopyAreaPixmap(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GC *pGC, int srcx, int srcy, int width, int height, int dstx, int dsty ) { register int Scanlines; int is; int id; int sx = 0, sy = 0, dx = 0, dy = 0, pitch; RegionPtr pReg; if (APMPTR(xf86Screens[(pGC)->pScreen->myNum])->Chipset == AT3D) { Scanlines = APMPTR(xf86Screens[(pGC)->pScreen->myNum])->CurrentLayout.Scanlines; is = (pSrcDrawable->type == DRAWABLE_PIXMAP) ? APM_GET_PIXMAP_PRIVATE(pSrcDrawable)->num : 0; id = (pDstDrawable->type == DRAWABLE_PIXMAP) ? APM_GET_PIXMAP_PRIVATE(pDstDrawable)->num : 0; if (is) { sx = pSrcDrawable->x; sy = pSrcDrawable->y % Scanlines; pitch = 2 * pSrcDrawable->width; pSrcDrawable->x = (sx + ((PixmapPtr)pSrcDrawable)->devKind * sy) % pitch; pSrcDrawable->y = (sx + ((PixmapPtr)pSrcDrawable)->devKind * sy) / pitch; ((PixmapPtr)pSrcDrawable)->devKind = pitch; pSrcDrawable->depth = 16; } if (id) { dx = pDstDrawable->x; dy = pDstDrawable->y % Scanlines; pitch = 2 * pDstDrawable->width; pDstDrawable->x = (dx + ((PixmapPtr)pDstDrawable)->devKind * dy) % pitch; pDstDrawable->y = (dx + ((PixmapPtr)pDstDrawable)->devKind * dy) / pitch; ((PixmapPtr)pDstDrawable)->devKind = pitch; pDstDrawable->depth = 16; } pReg = (*SaveCopyAreaPixmap)(pSrcDrawable, pDstDrawable, pGC, srcx, srcy % Scanlines, width, height, dstx, dsty % Scanlines); if (is) { pSrcDrawable->x = sx; pSrcDrawable->y = sy + is * Scanlines; } if (id) { pDstDrawable->x = dx; pDstDrawable->y = dy + id * Scanlines; } return pReg; } return (*SaveCopyAreaPixmap)(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height, dstx, dsty); } #endif void ApmAccelReserveSpace(ApmPtr pApm) { memType mem, ScratchMemOffset; mem = xf86ScreenToScrn(pApm->pScreen)->videoRam << 10; /* * Reserve at least four lines for mono to color expansion */ ScratchMemOffset = ((mem - pApm->OffscreenReserved) / pApm->CurrentLayout.bytesPerScanline - 4) * pApm->CurrentLayout.bytesPerScanline; pApm->ScratchMemSize= mem - ScratchMemOffset - pApm->OffscreenReserved; pApm->ScratchMemPtr = pApm->ScratchMemOffset = (memType)pApm->FbBase + ScratchMemOffset; pApm->ScratchMemEnd = (memType)pApm->FbBase + mem - pApm->OffscreenReserved; } /*********************************************************************************************/ int ApmAccelInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); APMDECL(pScrn); XAAInfoRecPtr pXAAinfo; BoxRec AvailFBArea; memType mem, ScratchMemOffset; int i, stat; pApm->AccelInfoRec = pXAAinfo = XAACreateInfoRec(); if (!pXAAinfo) return FALSE; mem = pScrn->videoRam << 10; ScratchMemOffset = pApm->ScratchMemOffset - (memType)pApm->FbBase; switch (pApm->CurrentLayout.bitsPerPixel) { case 8: case 24: pApm->ScratchMemWidth = (mem - ScratchMemOffset - pApm->OffscreenReserved) / 1; pApm->ScratchMem = ((ScratchMemOffset & 0xFFF000) << 4) | (ScratchMemOffset & 0xFFF); break; case 16: pApm->ScratchMemWidth = (mem - ScratchMemOffset - pApm->OffscreenReserved) / 2; pApm->ScratchMem = ((ScratchMemOffset & 0xFFE000) << 3) | ((ScratchMemOffset & 0x1FFE) >> 1); break; case 32: pApm->ScratchMemWidth = (mem - ScratchMemOffset - pApm->OffscreenReserved) / 4; pApm->ScratchMem = ((ScratchMemOffset & 0xFFC000) << 2) | ((ScratchMemOffset & 0x3FFC) >> 2); break; } pApm->OffscreenReserved = mem - ScratchMemOffset; /* * Abort */ if (pApm->Chipset == AP6422) i = 4; else i = 8; stat = RDXL_M(0x1FC); while ((stat & (STATUS_HOSTBLTBUSY | STATUS_ENGINEBUSY)) || ((stat & STATUS_FIFO) < i)) { WRXB_M(0x1FC, 0); stat = RDXL_M(0x1FC); } /* Setup current register values */ for (i = 0; i < sizeof(pApm->regcurr) / 4; i++) ((CARD32 *)curr)[i] = RDXL(0x30 + 4*i); SETCLIP_CTRL(1); SETCLIP_CTRL(0); SETBYTEMASK(0x00); SETBYTEMASK(0xFF); SETROP(ROP_S_xor_D); SETROP(ROP_S); #if 0 if (XAAPixmapOps.CopyArea != ApmCopyAreaPixmap) { SaveCopyAreaPixmap = XAAPixmapOps.CopyArea; XAAPixmapOps.CopyArea = ApmCopyAreaPixmap; } #endif ApmSetupXAAInfo(pApm, pXAAinfo); pApm->SetupForSolidFill = ApmSetupForSolidFill; pApm->SubsequentSolidFillRect = ApmSubsequentSolidFillRect; pApm->SetupForSolidFill24 = ApmSetupForSolidFill24; pApm->SubsequentSolidFillRect24 = ApmSubsequentSolidFillRect24; pApm->SetupForScreenToScreenCopy = ApmSetupForScreenToScreenCopy; pApm->SubsequentScreenToScreenCopy = ApmSubsequentScreenToScreenCopy; pApm->SetupForScreenToScreenCopy24 = ApmSetupForScreenToScreenCopy24; pApm->SubsequentScreenToScreenCopy24= ApmSubsequentScreenToScreenCopy24; /* * Init Rush extension. * Must be initialized once per generation. */ #ifdef XF86RUSH_EXT if (!pApm->CreatePixmap) { pApm->CreatePixmap = pScreen->CreatePixmap; pApm->DestroyPixmap = pScreen->DestroyPixmap; } XFree86RushExtensionInit(pScreen); #endif /* Pixmap cache setup */ pXAAinfo->CachePixelGranularity = (pApm->CurrentLayout.mask32 + 1) << 1; AvailFBArea.x1 = 0; AvailFBArea.y1 = 0; AvailFBArea.x2 = pScrn->displayWidth; AvailFBArea.y2 = (pScrn->videoRam * 1024 - pApm->OffscreenReserved) / (pScrn->displayWidth * ((pScrn->bitsPerPixel + 7) >> 3)); xf86InitFBManager(pScreen, &AvailFBArea); bzero(pApm->apmCache, sizeof pApm->apmCache); return XAAInit(pScreen, pXAAinfo); } void ApmSetupXAAInfo(ApmPtr pApm, XAAInfoRecPtr pXAAinfo) { pApm->CurrentLayout.Setup_DEC = 0; switch(pApm->CurrentLayout.bitsPerPixel) { case 8: pApm->CurrentLayout.Setup_DEC |= DEC_BITDEPTH_8; break; case 16: pApm->CurrentLayout.Setup_DEC |= DEC_BITDEPTH_16; break; case 24: /* Note : in 24 bpp, the accelerator wants linear coordinates */ pApm->CurrentLayout.Setup_DEC |= DEC_BITDEPTH_24 | DEC_SOURCE_LINEAR | DEC_DEST_LINEAR; break; case 32: pApm->CurrentLayout.Setup_DEC |= DEC_BITDEPTH_32; break; default: xf86DrvMsg(xf86ScreenToScrn(pApm->pScreen)->scrnIndex, X_WARNING, "Cannot set up drawing engine control for bpp = %d\n", pApm->CurrentLayout.bitsPerPixel); break; } switch(pApm->CurrentLayout.displayWidth) { case 640: pApm->CurrentLayout.Setup_DEC |= DEC_WIDTH_640; break; case 800: pApm->CurrentLayout.Setup_DEC |= DEC_WIDTH_800; break; case 1024: pApm->CurrentLayout.Setup_DEC |= DEC_WIDTH_1024; break; case 1152: pApm->CurrentLayout.Setup_DEC |= DEC_WIDTH_1152; break; case 1280: pApm->CurrentLayout.Setup_DEC |= DEC_WIDTH_1280; break; case 1600: pApm->CurrentLayout.Setup_DEC |= DEC_WIDTH_1600; break; default: xf86DrvMsg(xf86ScreenToScrn(pApm->pScreen)->scrnIndex, X_WARNING, "Cannot set up drawing engine control " "for screen width = %d\n", pApm->CurrentLayout.displayWidth); break; } if (!pXAAinfo) return; /* * Set up the main acceleration flags. */ pXAAinfo->Flags = PIXMAP_CACHE | LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS; pXAAinfo->CacheMonoStipple = ApmCacheMonoStipple; if (pApm->CurrentLayout.bitsPerPixel != 24) { #define XAA(s) pXAAinfo->s = Apm##s if (pApm->Chipset < AT24) pXAAinfo->Sync = ApmSync6422; else XAA(Sync); /* Accelerated filled rectangles */ pXAAinfo->SolidFillFlags = NO_PLANEMASK; XAA(SetupForSolidFill); XAA(SubsequentSolidFillRect); /* Accelerated screen to screen color expansion */ pXAAinfo->ScreenToScreenColorExpandFillFlags = NO_PLANEMASK; XAA(SetupForScreenToScreenColorExpandFill); XAA(SubsequentScreenToScreenColorExpandFill); #if 0 The constraints of the transfer range are incompatible with the XAA architecture. I rewrote the XAA functions using ImageWrite /* Accelerated CPU to screen color expansion */ if ((pApm->Chipset == AT24 && pApm->ChipRev >= 4) || pApm->Chipset == AT3D) { pXAAinfo->CPUToScreenColorExpandFillFlags = NO_PLANEMASK | SCANLINE_PAD_DWORD | CPU_TRANSFER_PAD_QWORD | BIT_ORDER_IN_BYTE_MSBFIRST | LEFT_EDGE_CLIPPING | LEFT_EDGE_CLIPPING_NEGATIVE_X | SYNC_AFTER_COLOR_EXPAND; XAA(SetupForCPUToScreenColorExpandFill); XAA(SubsequentCPUToScreenColorExpandFill); pXAAinfo->ColorExpandBase = pApm->BltMap; pXAAinfo->ColorExpandRange = (pApm->Chipset >= AT3D) ? 32*1024 : 30*1024; } /* Accelerated image transfers */ pXAAinfo->ImageWriteFlags = LEFT_EDGE_CLIPPING | NO_PLANEMASK | SCANLINE_PAD_DWORD | CPU_TRANSFER_PAD_QWORD | LEFT_EDGE_CLIPPING_NEGATIVE_X | SYNC_AFTER_IMAGE_WRITE; pXAAinfo->ImageWriteBase = pApm->BltMap; pXAAinfo->ImageWriteRange = (pApm->Chipset >= AT3D) ? 32*1024 : 30*1024; XAA(SetupForImageWrite); XAA(SubsequentImageWriteRect); #endif pXAAinfo->WritePixmapFlags = LEFT_EDGE_CLIPPING | NO_PLANEMASK | LEFT_EDGE_CLIPPING_NEGATIVE_X; XAA(WritePixmap); pXAAinfo->FillImageWriteRectsFlags = LEFT_EDGE_CLIPPING | NO_PLANEMASK | LEFT_EDGE_CLIPPING_NEGATIVE_X; XAA(FillImageWriteRects); pXAAinfo->WriteBitmapFlags = LEFT_EDGE_CLIPPING | NO_PLANEMASK | LEFT_EDGE_CLIPPING_NEGATIVE_X | BIT_ORDER_IN_BYTE_LSBFIRST; XAA(WriteBitmap); pXAAinfo->TEGlyphRendererFlags = LEFT_EDGE_CLIPPING | NO_PLANEMASK | LEFT_EDGE_CLIPPING_NEGATIVE_X; XAA(TEGlyphRenderer); /* Accelerated screen-screen bitblts */ pXAAinfo->ScreenToScreenCopyFlags = NO_PLANEMASK; XAA(SetupForScreenToScreenCopy); XAA(SubsequentScreenToScreenCopy); /* Accelerated Line drawing */ pXAAinfo->SolidLineFlags = NO_PLANEMASK | HARDWARE_CLIP_LINE; XAA(SetClippingRectangle); pXAAinfo->SolidBresenhamLineErrorTermBits = 15; if (pApm->Chipset >= AT24) { XAA(SubsequentSolidBresenhamLine); /* Pattern fill */ pXAAinfo->Mono8x8PatternFillFlags = NO_PLANEMASK | HARDWARE_PATTERN_PROGRAMMED_BITS | HARDWARE_PATTERN_SCREEN_ORIGIN; XAA(SetupForMono8x8PatternFill); XAA(SubsequentMono8x8PatternFillRect); if (pApm->CurrentLayout.bitsPerPixel == 8) { pXAAinfo->Color8x8PatternFillFlags = NO_PLANEMASK | HARDWARE_PATTERN_SCREEN_ORIGIN; XAA(SetupForColor8x8PatternFill); XAA(SubsequentColor8x8PatternFillRect); } } else pXAAinfo->SubsequentSolidBresenhamLine = ApmSubsequentSolidBresenhamLine6422; #undef XAA } else { #define XAA(s) pXAAinfo->s = Apm##s##24 XAA(Sync); /* Accelerated filled rectangles */ pXAAinfo->SolidFillFlags = NO_PLANEMASK; XAA(SetupForSolidFill); XAA(SubsequentSolidFillRect); #if 0 /* Accelerated screen to screen color expansion */ pXAAinfo->ScreenToScreenColorExpandFillFlags = NO_PLANEMASK; XAA(SetupForScreenToScreenColorExpandFill); XAA(SubsequentScreenToScreenColorExpandFill); #if 0 The constraints of the transfer range are incompatible with the XAA architecture. I rewrote the XAA functions using ImageWrite /* Accelerated CPU to screen color expansion */ if (pApm->Chipset == AT3D && pApm->ChipRev >= 4) { pXAAinfo->CPUToScreenColorExpandFillFlags = NO_PLANEMASK | SCANLINE_PAD_DWORD | CPU_TRANSFER_PAD_QWORD | BIT_ORDER_IN_BYTE_MSBFIRST | LEFT_EDGE_CLIPPING | LEFT_EDGE_CLIPPING_NEGATIVE_X | SYNC_AFTER_COLOR_EXPAND; XAA(SetupForCPUToScreenColorExpandFill); XAA(SubsequentCPUToScreenColorExpandFill); pXAAinfo->ColorExpandBase = pApm->BltMap; pXAAinfo->ColorExpandRange = 32*1024; } /* Accelerated image transfers */ pXAAinfo->ImageWriteFlags = LEFT_EDGE_CLIPPING | NO_PLANEMASK | SCANLINE_PAD_DWORD | CPU_TRANSFER_PAD_QWORD | SYNC_AFTER_IMAGE_WRITE; pXAAinfo->ImageWriteBase = pApm->BltMap; pXAAinfo->ImageWriteRange = 32*1024; XAA(SetupForImageWrite); XAA(SubsequentImageWriteRect); #endif pXAAinfo->WritePixmapFlags = LEFT_EDGE_CLIPPING | NO_PLANEMASK | LEFT_EDGE_CLIPPING_NEGATIVE_X; XAA(WritePixmap); pXAAinfo->FillImageWriteRectsFlags = LEFT_EDGE_CLIPPING | NO_PLANEMASK | LEFT_EDGE_CLIPPING_NEGATIVE_X; XAA(FillImageWriteRects); pXAAinfo->WriteBitmapFlags = LEFT_EDGE_CLIPPING | NO_PLANEMASK | LEFT_EDGE_CLIPPING_NEGATIVE_X | BIT_ORDER_IN_BYTE_LSBFIRST; XAA(WriteBitmap); pXAAinfo->TEGlyphRendererFlags = LEFT_EDGE_CLIPPING | NO_PLANEMASK | LEFT_EDGE_CLIPPING_NEGATIVE_X; XAA(TEGlyphRenderer); /* Accelerated Line drawing */ pXAAinfo->SolidLineFlags = NO_PLANEMASK | HARDWARE_CLIP_LINE; XAA(SubsequentSolidBresenhamLine); XAA(SetClippingRectangle); pXAAinfo->SolidBresenhamLineErrorTermBits = 15; /* Pattern fill */ pXAAinfo->Mono8x8PatternFillFlags = NO_PLANEMASK | NO_TRANSPARENCY | HARDWARE_PATTERN_PROGRAMMED_BITS | HARDWARE_PATTERN_SCREEN_ORIGIN; XAA(SetupForMono8x8PatternFill); XAA(SubsequentMono8x8PatternFillRect); #endif /* Accelerated screen-screen bitblts */ pXAAinfo->ScreenToScreenCopyFlags = NO_PLANEMASK | NO_TRANSPARENCY; XAA(SetupForScreenToScreenCopy); XAA(SubsequentScreenToScreenCopy); #undef XAA } } #endif