559 lines
14 KiB
C
559 lines
14 KiB
C
/*
|
|
* Copyright (c) 2007 NVIDIA, Corporation
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the
|
|
* "Software"), to deal in the Software without restriction, including
|
|
* without limitation the rights to use, copy, modify, merge, publish,
|
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
* permit persons to whom the Software is furnished to do so, subject to
|
|
* the following conditions:
|
|
*
|
|
* 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 AUTHORS OR COPYRIGHT HOLDERS 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.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <miline.h>
|
|
|
|
#include "g80_type.h"
|
|
#include "g80_dma.h"
|
|
#include "g80_xaa.h"
|
|
|
|
void
|
|
G80Sync(ScrnInfoPtr pScrn)
|
|
{
|
|
G80Ptr pNv = G80PTR(pScrn);
|
|
volatile CARD16 *pSync = (volatile CARD16*)&pNv->reg[0x00711008/4] + 1;
|
|
|
|
G80DmaStart(pNv, 0x104, 1);
|
|
G80DmaNext (pNv, 0);
|
|
G80DmaStart(pNv, 0x100, 1);
|
|
G80DmaNext (pNv, 0);
|
|
|
|
*pSync = 0x8000;
|
|
G80DmaKickoff(pNv);
|
|
while(*pSync);
|
|
}
|
|
|
|
void
|
|
G80DMAKickoffCallback(ScrnInfoPtr pScrn)
|
|
{
|
|
G80Ptr pNv = G80PTR(pScrn);
|
|
|
|
G80DmaKickoff(pNv);
|
|
pNv->DMAKickoffCallback = NULL;
|
|
}
|
|
|
|
void
|
|
G80SetPattern(G80Ptr pNv, int bg, int fg, int pat0, int pat1)
|
|
{
|
|
G80DmaStart(pNv, 0x2f0, 4);
|
|
G80DmaNext (pNv, bg);
|
|
G80DmaNext (pNv, fg);
|
|
G80DmaNext (pNv, pat0);
|
|
G80DmaNext (pNv, pat1);
|
|
}
|
|
|
|
void
|
|
G80SetRopSolid(G80Ptr pNv, CARD32 rop, CARD32 planemask)
|
|
{
|
|
static const int rops[] = {
|
|
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0,
|
|
0x30, 0xB0, 0x70, 0xF0
|
|
};
|
|
|
|
if(planemask != ~0) {
|
|
G80SetPattern(pNv, 0, planemask, ~0, ~0);
|
|
if(pNv->currentRop != (rop + 32)) {
|
|
pNv->currentRop = rop + 32;
|
|
|
|
rop = rops[rop] | 0xA;
|
|
G80DmaStart(pNv, 0x2a0, 1);
|
|
G80DmaNext (pNv, rop);
|
|
}
|
|
} else if(pNv->currentRop != rop) {
|
|
if(pNv->currentRop >= 16)
|
|
G80SetPattern(pNv, ~0, ~0, ~0, ~0);
|
|
pNv->currentRop = rop;
|
|
|
|
rop = rops[rop];
|
|
rop |= rop >> 4;
|
|
G80DmaStart(pNv, 0x2a0, 1);
|
|
G80DmaNext (pNv, rop);
|
|
}
|
|
}
|
|
|
|
inline void
|
|
G80SetClip(G80Ptr pNv, int x, int y, int w, int h)
|
|
{
|
|
G80DmaStart(pNv, 0x280, 4);
|
|
G80DmaNext (pNv, x);
|
|
G80DmaNext (pNv, y);
|
|
G80DmaNext (pNv, w);
|
|
G80DmaNext (pNv, h);
|
|
}
|
|
|
|
#ifdef HAVE_XAA_H
|
|
/* Screen to screen copies */
|
|
|
|
static void
|
|
G80SetupForScreenToScreenCopy(
|
|
ScrnInfoPtr pScrn,
|
|
int xdir, int ydir,
|
|
int rop,
|
|
unsigned planemask,
|
|
int transparency_color
|
|
)
|
|
{
|
|
G80Ptr pNv = G80PTR(pScrn);
|
|
|
|
planemask |= ~0 << pScrn->depth;
|
|
|
|
G80SetClip(pNv, 0, 0, 0x7fff, 0x7fff);
|
|
G80DmaStart(pNv, 0x2ac, 1);
|
|
if(rop == GXcopy && planemask == ~0) {
|
|
G80DmaNext (pNv, 3);
|
|
} else {
|
|
G80DmaNext (pNv, 4);
|
|
G80SetRopSolid(pNv, rop, planemask);
|
|
}
|
|
pNv->DMAKickoffCallback = G80DMAKickoffCallback;
|
|
}
|
|
|
|
static void
|
|
G80SubsequentScreenToScreenCopy(
|
|
ScrnInfoPtr pScrn,
|
|
int x1, int y1,
|
|
int x2, int y2,
|
|
int w, int h
|
|
)
|
|
{
|
|
G80Ptr pNv = G80PTR(pScrn);
|
|
|
|
G80DmaStart(pNv, 0x110, 1);
|
|
G80DmaNext (pNv, 0);
|
|
G80DmaStart(pNv, 0x8b0, 12);
|
|
G80DmaNext (pNv, x2);
|
|
G80DmaNext (pNv, y2);
|
|
G80DmaNext (pNv, w);
|
|
G80DmaNext (pNv, h);
|
|
G80DmaNext (pNv, 0);
|
|
G80DmaNext (pNv, 1);
|
|
G80DmaNext (pNv, 0);
|
|
G80DmaNext (pNv, 1);
|
|
G80DmaNext (pNv, 0);
|
|
G80DmaNext (pNv, x1);
|
|
G80DmaNext (pNv, 0);
|
|
G80DmaNext (pNv, y1);
|
|
|
|
if(w * h >= 512)
|
|
G80DmaKickoff(pNv);
|
|
}
|
|
|
|
/* Solid fills */
|
|
|
|
static void
|
|
G80SetupForSolidFill(
|
|
ScrnInfoPtr pScrn,
|
|
int color,
|
|
int rop,
|
|
unsigned planemask
|
|
)
|
|
{
|
|
G80Ptr pNv = G80PTR(pScrn);
|
|
|
|
planemask |= ~0 << pScrn->depth;
|
|
|
|
G80SetClip(pNv, 0, 0, 0x7fff, 0x7fff);
|
|
G80DmaStart(pNv, 0x2ac, 1);
|
|
G80DmaNext (pNv, 4);
|
|
G80SetRopSolid(pNv, rop, planemask);
|
|
G80DmaStart(pNv, 0x580, 1);
|
|
G80DmaNext (pNv, 4);
|
|
G80DmaStart(pNv, 0x588, 1);
|
|
G80DmaNext (pNv, color);
|
|
|
|
pNv->DMAKickoffCallback = G80DMAKickoffCallback;
|
|
}
|
|
|
|
static void
|
|
G80SubsequentFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
|
|
{
|
|
G80Ptr pNv = G80PTR(pScrn);
|
|
|
|
G80DmaStart(pNv, 0x600, 4);
|
|
G80DmaNext (pNv, x);
|
|
G80DmaNext (pNv, y);
|
|
G80DmaNext (pNv, x + w);
|
|
G80DmaNext (pNv, y + h);
|
|
|
|
if(w * h >= 512)
|
|
G80DmaKickoff(pNv);
|
|
}
|
|
|
|
/* 8x8 pattern fills */
|
|
|
|
static void
|
|
G80SetupForMono8x8PatternFill(
|
|
ScrnInfoPtr pScrn,
|
|
int patternx, int patterny,
|
|
int fg, int bg,
|
|
int rop,
|
|
unsigned planemask
|
|
)
|
|
{
|
|
G80Ptr pNv = G80PTR(pScrn);
|
|
static const int rops[] = {
|
|
0x00, 0xA0, 0x50, 0xF0, 0x0A, 0xAA, 0x5A, 0xFA, 0x05, 0xA5, 0x55, 0xF5,
|
|
0x0F, 0xAF, 0x5F, 0xFF
|
|
};
|
|
|
|
planemask = ~0 << pScrn->depth;
|
|
|
|
fg |= planemask;
|
|
if(bg == -1) bg = 0;
|
|
else bg |= planemask;
|
|
|
|
if(pNv->currentRop != (rop + 16)) {
|
|
G80DmaStart(pNv, 0x2a0, 1);
|
|
G80DmaNext (pNv, rops[rop]);
|
|
pNv->currentRop = rop + 16;
|
|
}
|
|
|
|
G80SetClip(pNv, 0, 0, 0x7fff, 0x7fff);
|
|
G80SetPattern(pNv, bg, fg, patternx, patterny);
|
|
|
|
G80DmaStart(pNv, 0x2ac, 1);
|
|
G80DmaNext (pNv, 4);
|
|
G80DmaStart(pNv, 0x580, 1);
|
|
G80DmaNext (pNv, 4);
|
|
G80DmaStart(pNv, 0x588, 1);
|
|
G80DmaNext (pNv, fg);
|
|
|
|
pNv->DMAKickoffCallback = G80DMAKickoffCallback;
|
|
}
|
|
|
|
static void
|
|
G80SubsequentMono8x8PatternFillRect(
|
|
ScrnInfoPtr pScrn,
|
|
int patternx, int patterny,
|
|
int x, int y,
|
|
int w, int h
|
|
)
|
|
{
|
|
G80SubsequentFillRect(pScrn, x, y, w, h);
|
|
}
|
|
|
|
/* Color expansion fills */
|
|
|
|
static CARD32 _color_expand_dwords;
|
|
static int _remaining;
|
|
static unsigned char *_storage_buffer[1];
|
|
|
|
static void
|
|
G80SetupForScanlineCPUToScreenColorExpandFill(
|
|
ScrnInfoPtr pScrn,
|
|
int fg, int bg,
|
|
int rop,
|
|
unsigned int planemask
|
|
)
|
|
{
|
|
G80Ptr pNv = G80PTR(pScrn);
|
|
CARD32 mask = ~0 << pScrn->depth;
|
|
|
|
planemask |= mask;
|
|
|
|
G80DmaStart(pNv, 0x2ac, 1);
|
|
G80DmaNext (pNv, 1);
|
|
G80SetRopSolid(pNv, rop, planemask);
|
|
G80DmaStart(pNv, 0x800, 1);
|
|
G80DmaNext (pNv, 1);
|
|
G80DmaStart(pNv, 0x808, 6);
|
|
G80DmaNext (pNv, 0);
|
|
G80DmaNext (pNv, 1);
|
|
G80DmaNext (pNv, 0);
|
|
G80DmaNext (pNv, bg | mask);
|
|
G80DmaNext (pNv, fg | mask);
|
|
G80DmaNext (pNv, (bg == -1) ? 0 : 1);
|
|
}
|
|
|
|
static void
|
|
G80SubsequentScanlineCPUToScreenColorExpandFill(
|
|
ScrnInfoPtr pScrn,
|
|
int x, int y,
|
|
int w, int h,
|
|
int skipleft
|
|
)
|
|
{
|
|
G80Ptr pNv = G80PTR(pScrn);
|
|
int bw = (w + 31) & ~31;
|
|
|
|
_color_expand_dwords = bw >> 5;
|
|
_remaining = h;
|
|
|
|
G80SetClip(pNv, x + skipleft, y, w - skipleft, h);
|
|
|
|
G80DmaStart(pNv, 0x838, 10);
|
|
G80DmaNext (pNv, bw);
|
|
G80DmaNext (pNv, h);
|
|
G80DmaNext (pNv, 0);
|
|
G80DmaNext (pNv, 1);
|
|
G80DmaNext (pNv, 0);
|
|
G80DmaNext (pNv, 1);
|
|
G80DmaNext (pNv, 0);
|
|
G80DmaNext (pNv, x);
|
|
G80DmaNext (pNv, 0);
|
|
G80DmaNext (pNv, y);
|
|
|
|
G80DmaStart(pNv, 0x40000860, _color_expand_dwords);
|
|
_storage_buffer[0] = (unsigned char*)&pNv->dmaBase[pNv->dmaCurrent];
|
|
}
|
|
|
|
static void
|
|
G80SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
|
|
{
|
|
G80Ptr pNv = G80PTR(pScrn);
|
|
|
|
pNv->dmaCurrent += _color_expand_dwords;
|
|
|
|
if(--_remaining) {
|
|
G80DmaStart(pNv, 0x40000860, _color_expand_dwords);
|
|
_storage_buffer[0] = (unsigned char*)&pNv->dmaBase[pNv->dmaCurrent];
|
|
} else {
|
|
G80DmaKickoff(pNv);
|
|
}
|
|
}
|
|
|
|
/* Scaline image write */
|
|
|
|
static void
|
|
G80SetupForScanlineImageWrite(
|
|
ScrnInfoPtr pScrn, int rop,
|
|
unsigned int planemask,
|
|
int trans_color,
|
|
int bpp, int depth
|
|
)
|
|
{
|
|
G80Ptr pNv = G80PTR(pScrn);
|
|
|
|
planemask |= ~0 << pScrn->depth;
|
|
|
|
G80DmaStart(pNv, 0x2ac, 1);
|
|
if(rop == GXcopy && planemask == ~0) {
|
|
G80DmaNext (pNv, 3);
|
|
} else {
|
|
G80DmaNext (pNv, 4);
|
|
G80SetRopSolid(pNv, rop, planemask);
|
|
}
|
|
|
|
G80DmaStart(pNv, 0x800, 1);
|
|
G80DmaNext (pNv, 0);
|
|
}
|
|
|
|
static CARD32 _image_dwords;
|
|
|
|
static void
|
|
G80SubsequentScanlineImageWriteRect(
|
|
ScrnInfoPtr pScrn,
|
|
int x, int y,
|
|
int w, int h,
|
|
int skipleft
|
|
)
|
|
{
|
|
G80Ptr pNv = G80PTR(pScrn);
|
|
int Bpp = pScrn->bitsPerPixel >> 3;
|
|
|
|
_remaining = h;
|
|
_image_dwords = (w * Bpp + 3) / 4;
|
|
|
|
G80SetClip(pNv, x + skipleft, y, w - skipleft, h);
|
|
|
|
G80DmaStart(pNv, 0x838, 10);
|
|
G80DmaNext (pNv, w);
|
|
G80DmaNext (pNv, h);
|
|
G80DmaNext (pNv, 0);
|
|
G80DmaNext (pNv, 1);
|
|
G80DmaNext (pNv, 0);
|
|
G80DmaNext (pNv, 1);
|
|
G80DmaNext (pNv, 0);
|
|
G80DmaNext (pNv, x);
|
|
G80DmaNext (pNv, 0);
|
|
G80DmaNext (pNv, y);
|
|
|
|
G80DmaStart(pNv, 0x40000860, _image_dwords);
|
|
_storage_buffer[0] = (unsigned char*)&pNv->dmaBase[pNv->dmaCurrent];
|
|
}
|
|
|
|
static void G80SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno)
|
|
{
|
|
G80Ptr pNv = G80PTR(pScrn);
|
|
|
|
pNv->dmaCurrent += _image_dwords;
|
|
|
|
if(--_remaining) {
|
|
G80DmaStart(pNv, 0x40000860, _image_dwords);
|
|
_storage_buffer[0] = (unsigned char*)&pNv->dmaBase[pNv->dmaCurrent];
|
|
} else {
|
|
G80DmaKickoff(pNv);
|
|
}
|
|
}
|
|
|
|
/* Solid lines */
|
|
|
|
static void
|
|
G80SetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop, unsigned planemask)
|
|
{
|
|
G80Ptr pNv = G80PTR(pScrn);
|
|
|
|
planemask |= ~0 << pScrn->depth;
|
|
|
|
G80SetClip(pNv, 0, 0, 0x7fff, 0x7fff);
|
|
G80DmaStart(pNv, 0x2ac, 1);
|
|
G80DmaNext (pNv, 4);
|
|
G80SetRopSolid(pNv, rop, planemask);
|
|
G80DmaStart(pNv, 0x580, 1);
|
|
G80DmaNext (pNv, 1);
|
|
G80DmaStart(pNv, 0x588, 1);
|
|
G80DmaNext (pNv, color);
|
|
|
|
pNv->DMAKickoffCallback = G80DMAKickoffCallback;
|
|
}
|
|
|
|
static void
|
|
G80SubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len, int dir)
|
|
{
|
|
G80Ptr pNv = G80PTR(pScrn);
|
|
|
|
G80DmaStart(pNv, 0x400005e0, 2);
|
|
G80DmaNext (pNv, (y << 16) | (x & 0xffff));
|
|
if(dir == DEGREES_0) {
|
|
G80DmaNext (pNv, (y << 16) | ((x + len) & 0xffff));
|
|
} else {
|
|
G80DmaNext (pNv, ((y + len) << 16) | (x & 0xffff));
|
|
}
|
|
}
|
|
|
|
static void
|
|
G80SubsequentSolidTwoPointLine(
|
|
ScrnInfoPtr pScrn,
|
|
int x1, int y1,
|
|
int x2, int y2,
|
|
int flags
|
|
)
|
|
{
|
|
G80Ptr pNv = G80PTR(pScrn);
|
|
Bool drawLast = !(flags & OMIT_LAST);
|
|
|
|
G80DmaStart(pNv, 0x400005e0, drawLast ? 4 : 2);
|
|
G80DmaNext (pNv, (y1 << 16) | (x1 & 0xffff));
|
|
G80DmaNext (pNv, (y2 << 16) | (x2 & 0xffff));
|
|
if(drawLast) {
|
|
G80DmaNext (pNv, (y2 << 16) | (x2 & 0xffff));
|
|
G80DmaNext (pNv, ((y2 + 1) << 16) | (x2 & 0xffff));
|
|
}
|
|
}
|
|
|
|
static void
|
|
G80SetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2)
|
|
{
|
|
G80Ptr pNv = G80PTR(pScrn);
|
|
int h = y2 - y1 + 1;
|
|
int w = x2 - x1 + 1;
|
|
|
|
G80SetClip(pNv, x1, y1, w, h);
|
|
}
|
|
|
|
static void
|
|
G80DisableClipping(ScrnInfoPtr pScrn)
|
|
{
|
|
G80Ptr pNv = G80PTR(pScrn);
|
|
|
|
G80SetClip(pNv, 0, 0, 0x7fff, 0x7fff);
|
|
}
|
|
#endif
|
|
|
|
Bool
|
|
G80XAAInit(ScreenPtr pScreen)
|
|
{
|
|
#ifdef HAVE_XAA_H
|
|
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
|
|
G80Ptr pNv = G80PTR(pScrn);
|
|
XAAInfoRecPtr xaa;
|
|
|
|
xaa = pNv->xaa = XAACreateInfoRec();
|
|
if(!xaa) return FALSE;
|
|
|
|
xaa->Flags = LINEAR_FRAMEBUFFER | PIXMAP_CACHE | OFFSCREEN_PIXMAPS;
|
|
xaa->Sync = G80Sync;
|
|
|
|
/* Screen to screen copies */
|
|
xaa->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
|
|
xaa->SetupForScreenToScreenCopy = G80SetupForScreenToScreenCopy;
|
|
xaa->SubsequentScreenToScreenCopy = G80SubsequentScreenToScreenCopy;
|
|
|
|
/* Solid fills */
|
|
xaa->SolidFillFlags = 0;
|
|
xaa->SetupForSolidFill = G80SetupForSolidFill;
|
|
xaa->SubsequentSolidFillRect = G80SubsequentFillRect;
|
|
|
|
/* 8x8 pattern fills */
|
|
xaa->Mono8x8PatternFillFlags = HARDWARE_PATTERN_SCREEN_ORIGIN |
|
|
HARDWARE_PATTERN_PROGRAMMED_BITS |
|
|
NO_PLANEMASK;
|
|
xaa->SetupForMono8x8PatternFill = G80SetupForMono8x8PatternFill;
|
|
xaa->SubsequentMono8x8PatternFillRect = G80SubsequentMono8x8PatternFillRect;
|
|
|
|
/* Color expansion fills */
|
|
xaa->ScanlineCPUToScreenColorExpandFillFlags =
|
|
BIT_ORDER_IN_BYTE_LSBFIRST |
|
|
CPU_TRANSFER_PAD_DWORD |
|
|
LEFT_EDGE_CLIPPING |
|
|
LEFT_EDGE_CLIPPING_NEGATIVE_X;
|
|
xaa->NumScanlineColorExpandBuffers = 1;
|
|
xaa->SetupForScanlineCPUToScreenColorExpandFill =
|
|
G80SetupForScanlineCPUToScreenColorExpandFill;
|
|
xaa->SubsequentScanlineCPUToScreenColorExpandFill =
|
|
G80SubsequentScanlineCPUToScreenColorExpandFill;
|
|
xaa->SubsequentColorExpandScanline =
|
|
G80SubsequentColorExpandScanline;
|
|
xaa->ScanlineColorExpandBuffers = _storage_buffer;
|
|
|
|
/* Scaline image write */
|
|
xaa->ScanlineImageWriteFlags = NO_GXCOPY |
|
|
NO_TRANSPARENCY |
|
|
LEFT_EDGE_CLIPPING |
|
|
LEFT_EDGE_CLIPPING_NEGATIVE_X;
|
|
xaa->NumScanlineImageWriteBuffers = 1;
|
|
xaa->SetupForScanlineImageWrite = G80SetupForScanlineImageWrite;
|
|
xaa->SubsequentScanlineImageWriteRect = G80SubsequentScanlineImageWriteRect;
|
|
xaa->SubsequentImageWriteScanline = G80SubsequentImageWriteScanline;
|
|
xaa->ScanlineImageWriteBuffers = _storage_buffer;
|
|
|
|
/* Solid lines */
|
|
xaa->SolidLineFlags = 0;
|
|
xaa->SetupForSolidLine = G80SetupForSolidLine;
|
|
xaa->SubsequentSolidHorVertLine = G80SubsequentSolidHorVertLine;
|
|
xaa->SubsequentSolidTwoPointLine = G80SubsequentSolidTwoPointLine;
|
|
xaa->SetClippingRectangle = G80SetClippingRectangle;
|
|
xaa->DisableClipping = G80DisableClipping;
|
|
xaa->ClippingFlags = HARDWARE_CLIP_SOLID_LINE;
|
|
|
|
miSetZeroLineBias(pScreen, OCTANT1 | OCTANT3 | OCTANT4 | OCTANT6);
|
|
|
|
return XAAInit(pScreen, xaa);
|
|
#else
|
|
return FALSE;
|
|
#endif
|
|
}
|