You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
646 lines
20 KiB
646 lines
20 KiB
/******************************Module*Header**********************************\
|
|
*
|
|
* *******************
|
|
* * SAMPLE CODE *
|
|
* *******************
|
|
*
|
|
* Module Name: p2ctxt.c
|
|
*
|
|
* Content: Context switching for Permedia 2. Used to create and swap
|
|
* contexts in and out.
|
|
* The GDI, DDraw and D3D part each have another context.
|
|
*
|
|
* Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
|
|
* Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
|
|
\*****************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#include "p2ctxt.h"
|
|
#include "gdi.h"
|
|
#define ALLOC_TAG ALLOC_TAG_XC2P
|
|
static DWORD readableRegistersP2[] = {
|
|
__Permedia2TagStartXDom,
|
|
__Permedia2TagdXDom,
|
|
__Permedia2TagStartXSub,
|
|
__Permedia2TagdXSub,
|
|
__Permedia2TagStartY,
|
|
__Permedia2TagdY,
|
|
__Permedia2TagCount,
|
|
__Permedia2TagRasterizerMode,
|
|
__Permedia2TagYLimits,
|
|
__Permedia2TagXLimits,
|
|
__Permedia2TagScissorMode,
|
|
__Permedia2TagScissorMinXY,
|
|
__Permedia2TagScissorMaxXY,
|
|
__Permedia2TagScreenSize,
|
|
__Permedia2TagAreaStippleMode,
|
|
__Permedia2TagWindowOrigin,
|
|
__Permedia2TagAreaStipplePattern0,
|
|
__Permedia2TagAreaStipplePattern1,
|
|
__Permedia2TagAreaStipplePattern2,
|
|
__Permedia2TagAreaStipplePattern3,
|
|
__Permedia2TagAreaStipplePattern4,
|
|
__Permedia2TagAreaStipplePattern5,
|
|
__Permedia2TagAreaStipplePattern6,
|
|
__Permedia2TagAreaStipplePattern7,
|
|
__Permedia2TagTextureAddressMode,
|
|
__Permedia2TagSStart,
|
|
__Permedia2TagdSdx,
|
|
__Permedia2TagdSdyDom,
|
|
__Permedia2TagTStart,
|
|
__Permedia2TagdTdx,
|
|
__Permedia2TagdTdyDom,
|
|
__Permedia2TagQStart,
|
|
__Permedia2TagdQdx,
|
|
__Permedia2TagdQdyDom,
|
|
// texellutindex..transfer are treated seperately
|
|
__Permedia2TagTextureBaseAddress,
|
|
__Permedia2TagTextureMapFormat,
|
|
__Permedia2TagTextureDataFormat,
|
|
__Permedia2TagTexel0,
|
|
__Permedia2TagTextureReadMode,
|
|
__Permedia2TagTexelLUTMode,
|
|
__Permedia2TagTextureColorMode,
|
|
__Permedia2TagFogMode,
|
|
__Permedia2TagFogColor,
|
|
__Permedia2TagFStart,
|
|
__Permedia2TagdFdx,
|
|
__Permedia2TagdFdyDom,
|
|
__Permedia2TagKsStart,
|
|
__Permedia2TagdKsdx,
|
|
__Permedia2TagdKsdyDom,
|
|
__Permedia2TagKdStart,
|
|
__Permedia2TagdKddx,
|
|
__Permedia2TagdKddyDom,
|
|
__Permedia2TagRStart,
|
|
__Permedia2TagdRdx,
|
|
__Permedia2TagdRdyDom,
|
|
__Permedia2TagGStart,
|
|
__Permedia2TagdGdx,
|
|
__Permedia2TagdGdyDom,
|
|
__Permedia2TagBStart,
|
|
__Permedia2TagdBdx,
|
|
__Permedia2TagdBdyDom,
|
|
__Permedia2TagAStart,
|
|
__Permedia2TagColorDDAMode,
|
|
__Permedia2TagConstantColor,
|
|
__Permedia2TagAlphaBlendMode,
|
|
__Permedia2TagDitherMode,
|
|
__Permedia2TagFBSoftwareWriteMask,
|
|
__Permedia2TagLogicalOpMode,
|
|
__Permedia2TagLBReadMode,
|
|
__Permedia2TagLBReadFormat,
|
|
__Permedia2TagLBSourceOffset,
|
|
__Permedia2TagLBWindowBase,
|
|
__Permedia2TagLBWriteMode,
|
|
__Permedia2TagLBWriteFormat,
|
|
__Permedia2TagTextureDownloadOffset,
|
|
__Permedia2TagWindow,
|
|
__Permedia2TagStencilMode,
|
|
__Permedia2TagStencilData,
|
|
__Permedia2TagStencil,
|
|
__Permedia2TagDepthMode,
|
|
__Permedia2TagDepth,
|
|
__Permedia2TagZStartU,
|
|
__Permedia2TagZStartL,
|
|
__Permedia2TagdZdxU,
|
|
__Permedia2TagdZdxL,
|
|
__Permedia2TagdZdyDomU,
|
|
__Permedia2TagdZdyDomL,
|
|
__Permedia2TagFBReadMode,
|
|
__Permedia2TagFBSourceOffset,
|
|
__Permedia2TagFBPixelOffset,
|
|
__Permedia2TagFBWindowBase,
|
|
__Permedia2TagFBWriteMode,
|
|
__Permedia2TagFBHardwareWriteMask,
|
|
__Permedia2TagFBBlockColor,
|
|
__Permedia2TagFBReadPixel,
|
|
__Permedia2TagFilterMode,
|
|
__Permedia2TagStatisticMode,
|
|
__Permedia2TagMinRegion,
|
|
__Permedia2TagMaxRegion,
|
|
__Permedia2TagFBBlockColorU,
|
|
__Permedia2TagFBBlockColorL,
|
|
__Permedia2TagFBSourceBase,
|
|
__Permedia2TagTexelLUT0,
|
|
__Permedia2TagTexelLUT1,
|
|
__Permedia2TagTexelLUT2,
|
|
__Permedia2TagTexelLUT3,
|
|
__Permedia2TagTexelLUT4,
|
|
__Permedia2TagTexelLUT5,
|
|
__Permedia2TagTexelLUT6,
|
|
__Permedia2TagTexelLUT7,
|
|
__Permedia2TagTexelLUT8,
|
|
__Permedia2TagTexelLUT9,
|
|
__Permedia2TagTexelLUT10,
|
|
__Permedia2TagTexelLUT11,
|
|
__Permedia2TagTexelLUT12,
|
|
__Permedia2TagTexelLUT13,
|
|
__Permedia2TagTexelLUT14,
|
|
__Permedia2TagTexelLUT15,
|
|
|
|
__Permedia2TagYUVMode,
|
|
__Permedia2TagChromaUpperBound,
|
|
__Permedia2TagChromaLowerBound,
|
|
__Permedia2TagAlphaMapUpperBound,
|
|
__Permedia2TagAlphaMapLowerBound,
|
|
|
|
// delta tag values. must be at the end of this array
|
|
|
|
// v0/1/2 fixed are not used and for that reason not in the context
|
|
|
|
__Permedia2TagV0FloatS,
|
|
__Permedia2TagV0FloatT,
|
|
__Permedia2TagV0FloatQ,
|
|
__Permedia2TagV0FloatKs,
|
|
__Permedia2TagV0FloatKd,
|
|
__Permedia2TagV0FloatR,
|
|
__Permedia2TagV0FloatG,
|
|
__Permedia2TagV0FloatB,
|
|
__Permedia2TagV0FloatA,
|
|
__Permedia2TagV0FloatF,
|
|
__Permedia2TagV0FloatX,
|
|
__Permedia2TagV0FloatY,
|
|
__Permedia2TagV0FloatZ,
|
|
|
|
__Permedia2TagV1FloatS,
|
|
__Permedia2TagV1FloatT,
|
|
__Permedia2TagV1FloatQ,
|
|
__Permedia2TagV1FloatKs,
|
|
__Permedia2TagV1FloatKd,
|
|
__Permedia2TagV1FloatR,
|
|
__Permedia2TagV1FloatG,
|
|
__Permedia2TagV1FloatB,
|
|
__Permedia2TagV1FloatA,
|
|
__Permedia2TagV1FloatF,
|
|
__Permedia2TagV1FloatX,
|
|
__Permedia2TagV1FloatY,
|
|
__Permedia2TagV1FloatZ,
|
|
|
|
__Permedia2TagV2FloatS,
|
|
__Permedia2TagV2FloatT,
|
|
__Permedia2TagV2FloatQ,
|
|
__Permedia2TagV2FloatKs,
|
|
__Permedia2TagV2FloatKd,
|
|
__Permedia2TagV2FloatR,
|
|
__Permedia2TagV2FloatG,
|
|
__Permedia2TagV2FloatB,
|
|
__Permedia2TagV2FloatA,
|
|
__Permedia2TagV2FloatF,
|
|
__Permedia2TagV2FloatX,
|
|
__Permedia2TagV2FloatY,
|
|
__Permedia2TagV2FloatZ,
|
|
|
|
__Permedia2TagDeltaMode
|
|
|
|
};
|
|
|
|
#define N_READABLE_TAGSP2 (sizeof(readableRegistersP2) / sizeof(readableRegistersP2[0]))
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// P2AllocateNewContext:
|
|
//
|
|
// allocate a new context. If all registers are to be saved in the context then
|
|
// pTag is passed as null.
|
|
// ppdev--------ppdev
|
|
// pTag---------user can supply list of registers to save and restore on
|
|
// context switch. NULL defaults to all registers.
|
|
// Holds pointer to user function if dwCtxtType==P2CtxtUserFunc
|
|
// lTags--------number of tags in user supplied register list
|
|
// dwCtxtType---P2CtxtReadWrite (default)
|
|
// on a context switch, all Permedia 2 registers are
|
|
// saved and restored.
|
|
// P2CtxtWriteOnly
|
|
// registers of context will be saved once at the first
|
|
// context switch. After that they will always be restored
|
|
// to the state ate the very beginning. This method avoids
|
|
// readback of registers when switching away from context.
|
|
// P2CtxtUserFunc
|
|
// User can supply a user function to set context to a known
|
|
// state, to avoid readback when switching away from context.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
P2CtxtPtr
|
|
P2AllocateNewContext(PPDev ppdev,
|
|
DWORD *pTag,
|
|
LONG lTags,
|
|
P2CtxtType dwCtxtType
|
|
)
|
|
{
|
|
P2CtxtTablePtr pCtxtTable, pNewCtxtTable;
|
|
P2CtxtPtr pEntry;
|
|
P2CtxtData *pData;
|
|
LONG lEntries;
|
|
LONG lExtraSize;
|
|
LONG lSize;
|
|
LONG lCtxtId;
|
|
PERMEDIA_DECL;
|
|
PERMEDIA_DEFS(ppdev);
|
|
|
|
// first time round allocate the context table of pointers. We will
|
|
// grow this table as required.
|
|
//
|
|
if (permediaInfo->ContextTable == NULL)
|
|
{
|
|
DISPDBG((7, "creating context table"));
|
|
lSize = sizeof(P2CtxtTableRec);
|
|
pCtxtTable = (P2CtxtTableRec *)
|
|
ENGALLOCMEM( FL_ZERO_MEMORY, sizeof(P2CtxtTableRec), ALLOC_TAG);
|
|
|
|
if (pCtxtTable == NULL)
|
|
{
|
|
DISPDBG((0, "failed to allocate Permedia2 context table. out of memory"));
|
|
return(NULL);
|
|
}
|
|
pCtxtTable->lEntries = CTXT_CHUNK;
|
|
pCtxtTable->lSize = lSize;
|
|
permediaInfo->ContextTable = pCtxtTable;
|
|
permediaInfo->pCurrentCtxt = NULL;
|
|
}
|
|
|
|
// find an empty entry in the table
|
|
// I suppose if we have hundreds of contexts this could be a bit slow but then
|
|
// allocating the context isn't time critical, swapping in and out is.
|
|
//
|
|
|
|
pCtxtTable = (P2CtxtTablePtr) permediaInfo->ContextTable;
|
|
lEntries = pCtxtTable->lEntries;
|
|
|
|
for (lCtxtId = 0; lCtxtId < lEntries; ++lCtxtId)
|
|
if(pCtxtTable->pEntry[lCtxtId] == NULL)
|
|
break;
|
|
|
|
// if we found no free entries try to grow the table
|
|
if (lCtxtId == lEntries) {
|
|
DISPDBG((1, "context table full so enlarging"));
|
|
lSize = pCtxtTable->lSize + (CTXT_CHUNK * sizeof(P2CtxtPtr));
|
|
pNewCtxtTable =
|
|
(P2CtxtTablePtr) ENGALLOCMEM( FL_ZERO_MEMORY, sizeof(BYTE)*lSize, ALLOC_TAG);
|
|
|
|
if (pNewCtxtTable == NULL) {
|
|
DISPDBG((0, "failed to increase Permedia 2 context table. out of memory"));
|
|
return(NULL);
|
|
}
|
|
|
|
// copy the old table to the new one
|
|
RtlCopyMemory(pNewCtxtTable, pCtxtTable, pCtxtTable->lSize);
|
|
pNewCtxtTable->lSize = lSize;
|
|
pNewCtxtTable->lEntries = lEntries + CTXT_CHUNK;
|
|
permediaInfo->ContextTable = (PVOID)pNewCtxtTable;
|
|
|
|
// first of the newly allocated entries is next free one
|
|
lCtxtId = lEntries;
|
|
|
|
// free the old context table and reassign some variables
|
|
|
|
ENGFREEMEM(pCtxtTable);
|
|
|
|
pCtxtTable = pNewCtxtTable;
|
|
lEntries = pCtxtTable->lEntries;
|
|
}
|
|
|
|
// if pTag is passed as null then we are to add all readable registers to the
|
|
// context.
|
|
lExtraSize = 0;
|
|
if (dwCtxtType != P2CtxtUserFunc)
|
|
{
|
|
if (pTag == 0)
|
|
{
|
|
DISPDBG((7, "adding all readable registers to the context"));
|
|
DISPDBG((7, "Using PERMEDIA 2 register set for other context switch"));
|
|
pTag = readableRegistersP2;
|
|
lTags = N_READABLE_TAGSP2;
|
|
}
|
|
} else
|
|
{
|
|
lTags = 1;
|
|
}
|
|
|
|
// now allocate space for the new entry. We are given the number of tags to save
|
|
// when context switching. Allocate twice this much memory as we have to hold the
|
|
// data values as well.
|
|
|
|
DISPDBG((7, "Allocating space for context. lTags = %d", lTags));
|
|
|
|
lSize = sizeof(P2CtxtRec) + (lTags-1) * sizeof(P2CtxtData);
|
|
|
|
pEntry = (P2CtxtPtr)
|
|
ENGALLOCMEM( FL_ZERO_MEMORY, sizeof(BYTE)*(lSize+lExtraSize), ALLOC_TAG);
|
|
|
|
if (pEntry == NULL) {
|
|
DISPDBG((0, "out of memory trying to allocate space for new context"));
|
|
return(NULL);
|
|
}
|
|
|
|
DISPDBG((7, "Got pEntry 0x%x", pEntry));
|
|
|
|
pCtxtTable->pEntry[lCtxtId] = pEntry;
|
|
|
|
// allocate enough space for the Texel LUT: 256 entries
|
|
pEntry->dwCtxtType=dwCtxtType;
|
|
pEntry->bInitialized=FALSE;
|
|
pEntry->pTexelLUTCtxt = (PULONG)
|
|
ENGALLOCMEM( FL_ZERO_MEMORY, sizeof(ULONG)*256, ALLOC_TAG);
|
|
if (pEntry->pTexelLUTCtxt!=0)
|
|
{
|
|
pEntry->ulTexelLUTEntries = 256;
|
|
} else
|
|
{
|
|
pEntry->ulTexelLUTEntries = 0;
|
|
}
|
|
|
|
pEntry->lNumOfTags = lTags;
|
|
pEntry->P2UserFunc = NULL;
|
|
pData = pEntry->pData;
|
|
|
|
if (dwCtxtType != P2CtxtUserFunc)
|
|
{
|
|
// we must initialize the new context to something reasonable. We choose to
|
|
// initialize to the current state of the chip. We can't leave it uninitialized
|
|
// since the first thing the caller will do when he wants to draw is validate
|
|
// the new context which will load junk into the chip. At some point we
|
|
// should define a reasonable starting context which would mean we wouldn't
|
|
// have to do this readback.
|
|
|
|
// copy the tags and read the data back from the chip. We don't sync since we are
|
|
// only initialising the context to something reasonable. i.e. we don't care if
|
|
// the FIFO is still draining while we do this.
|
|
|
|
DISPDBG((7, "Reading current chip context back"));
|
|
while (--lTags >= 0) {
|
|
pData->dwTag = *pTag++;
|
|
READ_PERMEDIA_FIFO_REG(pData->dwTag, pData->dwData);
|
|
++pData;
|
|
}
|
|
|
|
// save the texel LUT
|
|
if(pEntry->ulTexelLUTEntries &&
|
|
pEntry->pTexelLUTCtxt!=NULL)
|
|
{
|
|
ULONG *pul;
|
|
INT i=0;
|
|
|
|
lEntries = pEntry->ulTexelLUTEntries;
|
|
pul = pEntry->pTexelLUTCtxt;
|
|
|
|
//special mechanism: reset readback index to 0
|
|
READ_PERMEDIA_FIFO_REG(__Permedia2TagTexelLUTIndex, i);
|
|
|
|
for(i = 0; i < lEntries; ++i, ++pul)
|
|
{
|
|
READ_PERMEDIA_FIFO_REG(__Permedia2TagTexelLUTData, *pul);
|
|
}
|
|
}
|
|
|
|
} else
|
|
{
|
|
pEntry->P2UserFunc = (PCtxtUserFunc) pTag;
|
|
}
|
|
|
|
DISPDBG((1, "Allocated context %lx", pEntry));
|
|
|
|
return(pEntry);
|
|
} // P2AllocateNewContext
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// P2FreeContext:
|
|
//
|
|
// free a previously allocated context.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
P2FreeContext( PPDev ppdev,
|
|
P2CtxtPtr pEntry)
|
|
{
|
|
PERMEDIA_DECL;
|
|
P2CtxtTablePtr pCtxtTable;
|
|
ULONG lCtxtId;
|
|
|
|
pCtxtTable = (P2CtxtTablePtr) permediaInfo->ContextTable;
|
|
|
|
for (lCtxtId = 0; lCtxtId < pCtxtTable->lEntries; ++lCtxtId)
|
|
if(pCtxtTable->pEntry[lCtxtId] == pEntry)
|
|
break;
|
|
|
|
ASSERTDD(lCtxtId != pCtxtTable->lEntries, "P2FreeContext: context not found");
|
|
|
|
// free LUT Table
|
|
if(pEntry->pTexelLUTCtxt)
|
|
{
|
|
ENGFREEMEM( pEntry->pTexelLUTCtxt);
|
|
}
|
|
|
|
ENGFREEMEM( pEntry);
|
|
|
|
pCtxtTable->pEntry[lCtxtId] = NULL;
|
|
|
|
// if this was the current context, mark the current context as invalid so we
|
|
// force a reload next time.
|
|
|
|
if (permediaInfo->pCurrentCtxt == pEntry)
|
|
{
|
|
permediaInfo->pCurrentCtxt = NULL;
|
|
}
|
|
|
|
DISPDBG((1, "Released context %lx", pEntry));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// VOID P2SwitchContext:
|
|
//
|
|
// load a new context into the hardware. We assume that this call is
|
|
// protected by a test that the given context is not the current one -
|
|
// hence the assertion.
|
|
// The code would work but the driver should never try to load an already
|
|
// loaded context so we trap it as an error.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
P2SwitchContext(
|
|
PPDev ppdev,
|
|
P2CtxtPtr pEntry)
|
|
{
|
|
P2CtxtTablePtr pCtxtTable;
|
|
P2CtxtData *pData;
|
|
P2CtxtPtr pOldCtxt;
|
|
LONG lTags;
|
|
LONG i;
|
|
ULONG *pul;
|
|
LONG lEntries;
|
|
PERMEDIA_DECL;
|
|
PERMEDIA_DEFS(ppdev);
|
|
|
|
//@@BEGIN_DDKSPLIT
|
|
#if MULTITHREADED
|
|
EngAcquireSemaphore(ppdev->hsemLock);
|
|
ASSERTDD(ppdev->ulLockCount, "P2SwitchContext: ulLockCount = 0\n Context could change as caller is NOT protected!");
|
|
ppdev->ulLockCount++;
|
|
#endif
|
|
//@@END_DDKSPLIT
|
|
|
|
pCtxtTable = (P2CtxtTablePtr)permediaInfo->ContextTable;
|
|
ASSERTDD(pCtxtTable, "Can't perform context switch: no contexts have been created!");
|
|
|
|
pOldCtxt = permediaInfo->pCurrentCtxt;
|
|
|
|
DISPDBG((3, "swapping from context %d to context %d", pOldCtxt, pEntry));
|
|
|
|
if(pOldCtxt == permediaInfo->pGDICtxt)
|
|
{
|
|
DISPDBG((6, "Switching from GDI context"));
|
|
|
|
ASSERTDD(ppdev->bNeedSync ||
|
|
(ppdev->pulInFifoPtr == ppdev->pulInFifoStart),
|
|
"P2SwitchContext: bNeedSync flag is wrong");
|
|
|
|
InputBufferSync(ppdev);
|
|
|
|
ppdev->bGdiContext = FALSE;
|
|
ppdev->pP2dma->bEnabled = TRUE;
|
|
|
|
}
|
|
|
|
// for each register in the old context, read it back
|
|
if (pOldCtxt != NULL) {
|
|
|
|
//
|
|
// P2CtxtWriteOnly will only be readback once after context initialization
|
|
//
|
|
if ((pOldCtxt->dwCtxtType==P2CtxtReadWrite) ||
|
|
(pOldCtxt->dwCtxtType==P2CtxtWriteOnly && !pOldCtxt->bInitialized)
|
|
)
|
|
{
|
|
// sync with the chip before reading back the current state. The flag
|
|
// is used to control context manipulation on lockup recovery.
|
|
|
|
SYNC_WITH_PERMEDIA;
|
|
|
|
pData = pOldCtxt->pData;
|
|
lTags = pOldCtxt->lNumOfTags;
|
|
while (--lTags >= 0) {
|
|
READ_PERMEDIA_FIFO_REG(pData->dwTag, pData->dwData);
|
|
++pData;
|
|
}
|
|
|
|
// save the texel LUT
|
|
if(pOldCtxt->ulTexelLUTEntries &&
|
|
pOldCtxt->pTexelLUTCtxt!=NULL)
|
|
{
|
|
lEntries = pOldCtxt->ulTexelLUTEntries;
|
|
pul = pOldCtxt->pTexelLUTCtxt;
|
|
|
|
//special mechanism: reset readback index to 0
|
|
READ_PERMEDIA_FIFO_REG(__Permedia2TagTexelLUTIndex, i);
|
|
|
|
for(i = 0; i < lEntries; ++i, ++pul)
|
|
{
|
|
READ_PERMEDIA_FIFO_REG(__Permedia2TagTexelLUTData, *pul);
|
|
}
|
|
}
|
|
|
|
pOldCtxt->bInitialized=TRUE;
|
|
}
|
|
}
|
|
|
|
// load the new context. We allow -1 to be passed so that we can force a
|
|
// save of the current context and force the current context to be
|
|
// undefined.
|
|
//
|
|
if (pEntry != NULL)
|
|
{
|
|
|
|
if (pEntry->dwCtxtType==P2CtxtUserFunc)
|
|
{
|
|
ASSERTDD(pEntry->P2UserFunc!=NULL,"supplied user function not initialized");
|
|
(*pEntry->P2UserFunc)(ppdev);
|
|
} else
|
|
if (pEntry->dwCtxtType==P2CtxtWriteOnly ||
|
|
pEntry->dwCtxtType==P2CtxtReadWrite)
|
|
{
|
|
lTags = pEntry->lNumOfTags;
|
|
pData = pEntry->pData;
|
|
|
|
while (lTags > 0) {
|
|
lEntries = MAX_P2_FIFO_ENTRIES;
|
|
lTags -= lEntries;
|
|
if (lTags < 0)
|
|
lEntries += lTags;
|
|
RESERVEDMAPTR(lEntries);
|
|
while (--lEntries >= 0) {
|
|
LD_INPUT_FIFO(pData->dwTag, pData->dwData);
|
|
DISPDBG((20, "loading tag 0x%x, data 0x%x", pData->dwTag, pData->dwData));
|
|
++pData;
|
|
}
|
|
COMMITDMAPTR();
|
|
}
|
|
|
|
// restore the texel LUT
|
|
if(pEntry->ulTexelLUTEntries &&
|
|
pEntry->pTexelLUTCtxt!=NULL )
|
|
{
|
|
lEntries = pEntry->ulTexelLUTEntries;
|
|
pul = pEntry->pTexelLUTCtxt;
|
|
|
|
RESERVEDMAPTR(lEntries+1);
|
|
LD_INPUT_FIFO(__Permedia2TagTexelLUTIndex, 0);
|
|
|
|
for(i = 0; i < lEntries; ++i, ++pul)
|
|
{
|
|
LD_INPUT_FIFO(__Permedia2TagTexelLUTData, *pul);
|
|
}
|
|
COMMITDMAPTR();
|
|
FLUSHDMA();
|
|
}
|
|
|
|
} else
|
|
{
|
|
ASSERTDD( FALSE, "undefined state for entry in context table");
|
|
}
|
|
}
|
|
|
|
if(pEntry == permediaInfo->pGDICtxt)
|
|
{
|
|
DISPDBG((6, "Switching to GDI context"));
|
|
|
|
//
|
|
// we have to do a full sync here, because GDI and DDraw
|
|
// share the same DMA buffer. To make sure nothing will be
|
|
// overridden, we do a complete sync
|
|
//
|
|
SYNC_WITH_PERMEDIA;
|
|
|
|
//
|
|
// Turn off permedia interrupt handler
|
|
//
|
|
|
|
WRITE_CTRL_REG( PREG_INTENABLE, 0);
|
|
|
|
ppdev->bGdiContext = TRUE;
|
|
ppdev->pP2dma->bEnabled = FALSE;
|
|
|
|
// invalidate the mono brush cache entry
|
|
// stipple unit was restored to default values
|
|
|
|
ppdev->abeMono.prbVerify = NULL;
|
|
|
|
}
|
|
|
|
DISPDBG((6, "context %lx now current", pEntry));
|
|
permediaInfo->pCurrentCtxt = pEntry;
|
|
|
|
//@@BEGIN_DDKSPLIT
|
|
#if MULTITHREADED
|
|
ppdev->ulLockCount--;
|
|
EngReleaseSemaphore(ppdev->hsemLock);
|
|
#endif
|
|
//@@END_DDKSPLIT
|
|
|
|
}
|
|
|