diff options
Diffstat (limited to 'xorg-server/hw/kdrive/i810/i810draw.c')
-rw-r--r-- | xorg-server/hw/kdrive/i810/i810draw.c | 352 |
1 files changed, 352 insertions, 0 deletions
diff --git a/xorg-server/hw/kdrive/i810/i810draw.c b/xorg-server/hw/kdrive/i810/i810draw.c new file mode 100644 index 000000000..b571efbe0 --- /dev/null +++ b/xorg-server/hw/kdrive/i810/i810draw.c @@ -0,0 +1,352 @@ +/* COPYRIGHT AND PERMISSION NOTICE + +Copyright (c) 2000, 2001 Nokia Home Communications + +All rights reserved. + +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, and/or sell copies of the Software, and to permit persons +to whom the Software is furnished to do so, provided that the above +copyright notice(s) and this permission notice appear in all copies of +the Software and that both the above copyright notice(s) and this +permission notice appear in supporting documentation. + +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 +OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY +SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER +RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF +CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +Except as contained in this notice, the name of a copyright holder +shall not be used in advertising or otherwise to promote the sale, use +or other dealings in this Software without prior written authorization +of the copyright holder. + +X Window System is a trademark of The Open Group */ + +/* Hardware accelerated drawing for KDrive i810 driver. + Author: Pontus Lidman <pontus.lidman@nokia.com> +*/ + +#ifdef HAVE_CONFIG_H +#include <kdrive-config.h> +#endif +#include "kdrive.h" +#include "kaa.h" +#ifdef XV +#include "kxv.h" +#endif +#include "i810.h" +#include "i810_reg.h" + +//#include "Xmd.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "mistruct.h" +#include "dixfontstr.h" +#include "fb.h" +#include "migc.h" +#include "miline.h" +#include "picturestr.h" + +#define NUM_STACK_RECTS 1024 + +i810ScreenInfo *accel_i810s; + +static int +i810WaitLpRing(i810ScreenInfo *i810s, int n, int timeout_millis) +{ + i810CardInfo *i810c = i810s->i810c; + I810RingBuffer *ring = &(i810c->LpRing); + int iters = 0; + int start = 0; + int now = 0; + int last_head = 0; + int first = 0; + + /* If your system hasn't moved the head pointer in 2 seconds, I'm going to + * call it crashed. + */ + if (timeout_millis == 0) + timeout_millis = 2000; + + if (I810_DEBUG) { + fprintf(stderr, "i810WaitLpRing %d\n", n); + first = GetTimeInMillis(); + } + + while (ring->space < n) + { + int i; + + ring->head = INREG(LP_RING + RING_HEAD) & HEAD_ADDR; + ring->space = ring->head - (ring->tail+8); + + if (ring->space < 0) + ring->space += ring->mem.Size; + + iters++; + now = GetTimeInMillis(); + if ( start == 0 || now < start || ring->head != last_head) { + if (I810_DEBUG) + if (now > start) + fprintf(stderr, "space: %d wanted %d\n", ring->space, n ); + start = now; + last_head = ring->head; + } else if ( now - start > timeout_millis ) { + + i810PrintErrorState(i810c); + fprintf(stderr, "space: %d wanted %d\n", ring->space, n ); + FatalError("lockup\n"); + } + + for (i = 0 ; i < 2000 ; i++) + ; + } + + if (I810_DEBUG) + { + now = GetTimeInMillis(); + if (now - first) { + fprintf(stderr,"Elapsed %d ms\n", now - first); + fprintf(stderr, "space: %d wanted %d\n", ring->space, n ); + } + } + + return iters; +} + +static void +i810Sync(i810ScreenInfo *i810s) +{ + i810CardInfo *i810c = i810s->i810c; + LP_RING_LOCALS; + + if (I810_DEBUG) + fprintf(stderr, "i810Sync\n"); + + /* Send a flush instruction and then wait till the ring is empty. + * This is stronger than waiting for the blitter to finish as it also + * flushes the internal graphics caches. + */ + BEGIN_LP_RING(2); + OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE ); + OUT_RING( 0 ); /* pad to quadword */ + ADVANCE_LP_RING(); + + i810WaitLpRing(i810s, i810c->LpRing.mem.Size - 8, 0); + + i810c->LpRing.space = i810c->LpRing.mem.Size - 8; + i810c->nextColorExpandBuf = 0; +} + +static void +i810WaitMarker(ScreenPtr pScreen, int marker) +{ + KdScreenPriv(pScreen); + i810ScreenInfo(pScreenPriv); + + i810Sync(i810s); +} + +#if 0 +static void +i810EmitInvarientState(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + i810CardInfo(pScreenPriv); + i810ScreenInfo(pScreenPriv); + LP_RING_LOCALS; + + BEGIN_LP_RING( 10 ); + + OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE ); + OUT_RING( GFX_CMD_CONTEXT_SEL | CS_UPDATE_USE | CS_USE_CTX0 ); + OUT_RING( INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE); + OUT_RING( 0 ); + + + OUT_RING( GFX_OP_COLOR_CHROMA_KEY ); + OUT_RING( CC1_UPDATE_KILL_WRITE | + CC1_DISABLE_KILL_WRITE | + CC1_UPDATE_COLOR_IDX | + CC1_UPDATE_CHROMA_LOW | + CC1_UPDATE_CHROMA_HI | + 0); + OUT_RING( 0 ); + OUT_RING( 0 ); + + /* No depth buffer in KDrive yet */ + /* OUT_RING( CMD_OP_Z_BUFFER_INFO ); */ + /* OUT_RING( pI810->DepthBuffer.Start | pI810->auxPitchBits); */ + + ADVANCE_LP_RING(); +} +#endif + +static unsigned int i810PatternRop[16] = { + 0x00, /* GXclear */ + 0xA0, /* GXand */ + 0x50, /* GXandReverse */ + 0xF0, /* GXcopy */ + 0x0A, /* GXandInvert */ + 0xAA, /* GXnoop */ + 0x5A, /* GXxor */ + 0xFA, /* GXor */ + 0x05, /* GXnor */ + 0xA5, /* GXequiv */ + 0x55, /* GXinvert */ + 0xF5, /* GXorReverse */ + 0x0F, /* GXcopyInvert */ + 0xAF, /* GXorInverted */ + 0x5F, /* GXnand */ + 0xFF /* GXset */ +}; + +static Bool +i810PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg) +{ + KdScreenPriv(pPix->drawable.pScreen); + i810ScreenInfo(pScreenPriv); + i810CardInfo(pScreenPriv); + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF( "i810PrepareSolid color: %x rop: %x mask: %x\n", + fg, alu, pm); + + /* Color blit, p166 */ + i810c->BR[13] = BR13_SOLID_PATTERN | + (i810PatternRop[alu] << 16) | + (pPix->drawable.pScreen->width * i810c->cpp); + i810c->BR[16] = fg; + + accel_i810s = i810s; + + return TRUE; +} + +static void +i810Solid(int x1, int y1, int x2, int y2) +{ + I810ScreenInfo *i810s = accel_i810s; + I810CardInfo *i810c = i810s->i810c; + LP_RING_LOCALS; + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF( "i810SubsequentFillRectSolid %d,%d %d,%d\n", x1, y1, x2, y2); + + BEGIN_LP_RING(6); + + OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3 ); + OUT_RING( i810c->BR[13] ); + OUT_RING( ((y2 - y1) << 16) | ((x2 - x1) * i810c->cpp)); + OUT_RING( i810c->bufferOffset + y1 * i810s->pitch + x1 * i810c->cpp ); + + OUT_RING( i810c->BR[16]); + OUT_RING( 0 ); /* pad to quadword */ + + ADVANCE_LP_RING(); +} + +static void +i810DoneSolid(void) +{ +} + +static Bool +i810PrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, int dx, int dy, int alu, Pixel pm) +{ + return FALSE; +} + +static void +i810RefreshRing(i810CardInfo *i810c) +{ + i810c->LpRing.head = INREG(LP_RING + RING_HEAD) & HEAD_ADDR; + i810c->LpRing.tail = INREG(LP_RING + RING_TAIL); + i810c->LpRing.space = i810c->LpRing.head - (i810c->LpRing.tail+8); + if (i810c->LpRing.space < 0) + i810c->LpRing.space += i810c->LpRing.mem.Size; +} + + +static void +i810SetRingRegs(i810CardInfo *i810c) +{ + unsigned int itemp; + + OUTREG(LP_RING + RING_TAIL, 0 ); + OUTREG(LP_RING + RING_HEAD, 0 ); + + itemp = INREG(LP_RING + RING_START); + itemp &= ~(START_ADDR); + itemp |= i810c->LpRing.mem.Start; + OUTREG(LP_RING + RING_START, itemp ); + + itemp = INREG(LP_RING + RING_LEN); + itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK); + itemp |= ((i810c->LpRing.mem.Size-4096) | RING_NO_REPORT | RING_VALID); + OUTREG(LP_RING + RING_LEN, itemp ); +} + +Bool +i810InitAccel(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + i810ScreenInfo(pScreenPriv); + i810CardInfo(pScreenPriv); + + memset(&i810s->kaa, 0, sizeof(KaaScreenInfoRec)); + i810s->kaa.waitMarker = i810WaitMarker; + i810s->kaa.PrepareSolid = i810PrepareSolid; + i810s->kaa.Solid = i810Solid; + i810s->kaa.DoneSolid = i810DoneSolid; + i810s->kaa.PrepareCopy = i810PrepareCopy; + i810s->kaa.Copy = NULL; + i810s->kaa.DoneCopy = NULL; + + i810s->pitch = pScreen->width * i810c->cpp; + + return FALSE; +} + +void +i810EnableAccel(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + i810CardInfo(pScreenPriv); + + if (i810c->LpRing.mem.Size == 0) { + ErrorF("No memory for LpRing!! Acceleration not functional!!\n"); + } + + i810SetRingRegs(i810c); + + kaaMarkSync (pScreen); +} + + +void +i810DisableAccel(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + i810CardInfo(pScreenPriv); + i810ScreenInfo(pScreenPriv); + + i810RefreshRing(i810c); + i810Sync(i810s); +} + +void +i810FiniAccel(ScreenPtr pScreen) +{ +} |