#include "dri_util.h"
#include "context.h"
#include "utils.h"
#include "imports.h"
#include "sis_context.h"
#include "sis_dri.h"
#include "sis_lock.h"
static sisScreenPtr
sisCreateScreen( __DRIscreenPrivate *sPriv )
{
sisScreenPtr sisScreen;
SISDRIPtr sisDRIPriv = (SISDRIPtr)sPriv->pDevPriv;
if ( !driCheckDriDdxDrmVersions( sPriv, "SiS", 4, 0, 0, 1, 1, 0 ) )
return NULL;
sisScreen = (sisScreenPtr)CALLOC( sizeof(*sisScreen) );
if ( sisScreen == NULL )
return NULL;
sisScreen->screenX = sisDRIPriv->width;
sisScreen->screenY = sisDRIPriv->height;
sisScreen->cpp = sisDRIPriv->bytesPerPixel;
sisScreen->irqEnabled = sisDRIPriv->bytesPerPixel;
sisScreen->deviceID = sisDRIPriv->deviceID;
sisScreen->AGPCmdBufOffset = sisDRIPriv->AGPCmdBufOffset;
sisScreen->AGPCmdBufSize = sisDRIPriv->AGPCmdBufSize;
sisScreen->sarea_priv_offset = sizeof(XF86DRISAREARec);
sisScreen->mmio.handle = sisDRIPriv->regs.handle;
sisScreen->mmio.size = sisDRIPriv->regs.size;
if ( drmMap( sPriv->fd, sisScreen->mmio.handle, sisScreen->mmio.size,
&sisScreen->mmio.map ) )
{
FREE( sisScreen );
return NULL;
}
if (sisDRIPriv->agp.size) {
sisScreen->agp.handle = sisDRIPriv->agp.handle;
sisScreen->agp.size = sisDRIPriv->agp.size;
if ( drmMap( sPriv->fd, sisScreen->agp.handle, sisScreen->agp.size,
&sisScreen->agp.map ) )
{
sisScreen->agp.size = 0;
}
}
sisScreen->driScreen = sPriv;
return sisScreen;
}
static void
sisDestroyScreen( __DRIscreenPrivate *sPriv )
{
sisScreenPtr sisScreen = (sisScreenPtr)sPriv->private;
if ( sisScreen == NULL )
return;
if (sisScreen->agp.size != 0)
drmUnmap( sisScreen->agp.map, sisScreen->agp.size );
drmUnmap( sisScreen->mmio.map, sisScreen->mmio.size );
FREE( sisScreen );
sPriv->private = NULL;
}
static GLboolean
sisCreateBuffer( __DRIscreenPrivate *driScrnPriv,
__DRIdrawablePrivate *driDrawPriv,
const __GLcontextModes *mesaVis,
GLboolean isPixmap )
{
if (isPixmap)
return GL_FALSE;
driDrawPriv->driverPrivate = (void *)_mesa_create_framebuffer(
mesaVis,
GL_FALSE,
mesaVis->stencilBits > 0,
mesaVis->accumRedBits > 0,
mesaVis->alphaBits > 0 );
return (driDrawPriv->driverPrivate != NULL);
}
static void
sisDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
{
_mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
}
__inline__ static void
sis_bitblt_copy_cmd (sisContextPtr smesa, ENGPACKET * pkt)
{
GLint *lpdwDest, *lpdwSrc;
int i;
lpdwSrc = (GLint *) pkt;
lpdwDest = (GLint *) (GET_IOBase (smesa) + REG_SRC_ADDR);
mWait3DCmdQueue (10);
for (i = 0; i < 7; i++)
*lpdwDest++ = *lpdwSrc++;
MMIO(REG_CMD0, *(GLint *)&pkt->stdwCmd);
MMIO(REG_CommandQueue, -1);
}
static void sisCopyBuffer( __DRIdrawablePrivate *dPriv )
{
sisContextPtr smesa = (sisContextPtr)dPriv->driContextPriv->driverPrivate;
int i;
ENGPACKET stEngPacket;
while ((*smesa->FrameCountPtr) - MMIO_READ(0x8a2c) > SIS_MAX_FRAME_LENGTH)
;
LOCK_HARDWARE();
stEngPacket.dwSrcBaseAddr = smesa->backOffset;
stEngPacket.dwSrcPitch = smesa->backPitch |
((smesa->bytesPerPixel == 2) ? 0x80000000 : 0xc0000000);
stEngPacket.dwDestBaseAddr = 0;
stEngPacket.wDestPitch = smesa->frontPitch;
stEngPacket.wDestHeight = smesa->virtualY;
stEngPacket.stdwCmd.cRop = 0xcc;
if (smesa->blockWrite)
stEngPacket.stdwCmd.cCmd0 = CMD0_PAT_FG_COLOR;
else
stEngPacket.stdwCmd.cCmd0 = 0;
stEngPacket.stdwCmd.cCmd1 = CMD1_DIR_X_INC | CMD1_DIR_Y_INC;
for (i = 0; i < dPriv->numClipRects; i++) {
XF86DRIClipRectPtr box = &dPriv->pClipRects[i];
stEngPacket.stdwSrcPos.wY = box->y1 - dPriv->y;
stEngPacket.stdwSrcPos.wX = box->x1 - dPriv->x;
stEngPacket.stdwDestPos.wY = box->y1;
stEngPacket.stdwDestPos.wX = box->x1;
stEngPacket.stdwDim.wWidth = (GLshort) box->x2 - box->x1;
stEngPacket.stdwDim.wHeight = (GLshort) box->y2 - box->y1;
sis_bitblt_copy_cmd( smesa, &stEngPacket );
}
*(GLint *)(smesa->IOBase+0x8a2c) = *smesa->FrameCountPtr;
(*smesa->FrameCountPtr)++;
UNLOCK_HARDWARE ();
}
static void
sisSwapBuffers(__DRIdrawablePrivate *dPriv)
{
if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
sisContextPtr smesa = (sisContextPtr) dPriv->driContextPriv->driverPrivate;
GLcontext *ctx = smesa->glCtx;
if (ctx->Visual.doubleBufferMode) {
_mesa_notifySwapBuffers( ctx );
sisCopyBuffer( dPriv );
}
} else {
_mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
}
}
static GLboolean
sisInitDriver( __DRIscreenPrivate *sPriv )
{
sPriv->private = (void *) sisCreateScreen( sPriv );
if ( !sPriv->private ) {
sisDestroyScreen( sPriv );
return GL_FALSE;
}
return GL_TRUE;
}
static GLboolean
sisOpenCloseFullScreen( __DRIcontextPrivate *driContextPriv )
{
return GL_TRUE;
}
static struct __DriverAPIRec sisAPI = {
.InitDriver = sisInitDriver,
.DestroyScreen = sisDestroyScreen,
.CreateContext = sisCreateContext,
.DestroyContext = sisDestroyContext,
.CreateBuffer = sisCreateBuffer,
.DestroyBuffer = sisDestroyBuffer,
.SwapBuffers = sisSwapBuffers,
.MakeCurrent = sisMakeCurrent,
.UnbindContext = sisUnbindContext,
.OpenFullScreen = sisOpenCloseFullScreen,
.CloseFullScreen = sisOpenCloseFullScreen,
.GetSwapInfo = NULL,
.GetMSC = NULL,
.WaitForMSC = NULL,
.WaitForSBC = NULL,
.SwapBuffersMSC = NULL
};
void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
int numConfigs, __GLXvisualConfig *config)
{
__DRIscreenPrivate *psp;
psp = __driUtilCreateScreen( dpy, scrn, psc, numConfigs, config, &sisAPI );
return (void *)psp;
}