353 lines
8.9 KiB
C
353 lines
8.9 KiB
C
/* 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)
|
|
{
|
|
}
|