mirror of https://github.com/lianthony/NT4.0
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.
3619 lines
118 KiB
3619 lines
118 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: genaccel.c *
|
|
* *
|
|
* This module provides support routines for span acceleration. *
|
|
* *
|
|
* Created: 18-Feb-1994 *
|
|
* Author: Otto Berkes [ottob] *
|
|
* *
|
|
* Copyright (c) 1994 Microsoft Corporation *
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#include "genline.h"
|
|
|
|
#define MAX_SPAN_SIZE (sizeof(RXSPAN))
|
|
#define MAX_SPAN_WIDTH 2048
|
|
#define PIX_BUFFER_SIZE ((sizeof(DWORD) * MAX_SPAN_WIDTH) +\
|
|
sizeof(RXCMD) + sizeof(RXREADRECT))
|
|
|
|
#define INIT_NEXT_CMD_BUFFER(pDrvAccel)\
|
|
if (pDrvAccel->pStartCmd == pDrvAccel->pCmdBuffer1) {\
|
|
pDrvAccel->pStartCmd = pDrvAccel->pCmdBuffer2;\
|
|
RxLockExecMem(pDrvAccel->hrxExecBuffer2);\
|
|
RxUnlockExecMem(pDrvAccel->hrxExecBuffer2);\
|
|
pDrvAccel->rxExecute.hrxMem = pDrvAccel->hrxExecBuffer2;\
|
|
} else {\
|
|
pDrvAccel->pStartCmd = pDrvAccel->pCmdBuffer1;\
|
|
RxLockExecMem(pDrvAccel->hrxExecBuffer1);\
|
|
RxUnlockExecMem(pDrvAccel->hrxExecBuffer1);\
|
|
pDrvAccel->rxExecute.hrxMem = pDrvAccel->hrxExecBuffer1;\
|
|
}\
|
|
pDrvAccel->rxExecute.pCmd = pDrvAccel->pCmd = pDrvAccel->pStartCmd;\
|
|
pDrvAccel->rxExecute.pVertex = pDrvAccel->pVertex = \
|
|
pDrvAccel->pStartVertex = \
|
|
pDrvAccel->pCmd + pDrvAccel->vertexStartOffset;\
|
|
pDrvAccel->pEndVertex = pDrvAccel->pCmd + pDrvAccel->vertexEndOffset;\
|
|
pDrvAccel->vIndex = 0;
|
|
|
|
|
|
|
|
#define SET_DRV_STATE(state, value)\
|
|
{\
|
|
RXCMD *prxCmd;\
|
|
RXSETSTATE *prxSetState;\
|
|
\
|
|
GenDrvFlush((__GLGENcontext *)gc);\
|
|
prxCmd = (RXCMD *)(pDrvAccel->pCmd);\
|
|
prxCmd->command = RXCMD_SET_STATE;\
|
|
prxCmd->size = sizeof(RXSETSTATE);\
|
|
prxCmd->count = 1;\
|
|
\
|
|
prxSetState = (RXSETSTATE *)(prxCmd + 1);\
|
|
prxSetState->stateToChange = state;\
|
|
prxSetState->newState[0] = (ULONG)(value);\
|
|
pDrvAccel->rxExecute.cmdSize = (char *)(prxSetState + 1) - \
|
|
pDrvAccel->pCmd;\
|
|
pDrvAccel->rxExecute.vertexSize = 0;\
|
|
RxExecute(&pDrvAccel->rxExecute, TRUE);\
|
|
}
|
|
|
|
|
|
#define BATCHED_DRV_STATE(state, value)\
|
|
{\
|
|
RXCMD *prxCmd;\
|
|
RXSETSTATE *prxSetState;\
|
|
\
|
|
if ((pDrvAccel->pCmd + sizeof(RXCMD) + sizeof(RXSETSTATE))\
|
|
> pDrvAccel->pStartVertex) {\
|
|
GenDrvFlush((__GLGENcontext *)gc);\
|
|
}\
|
|
\
|
|
prxCmd = (RXCMD *)(pDrvAccel->pCmd);\
|
|
prxCmd->command = RXCMD_SET_STATE;\
|
|
prxCmd->size = sizeof(RXSETSTATE);\
|
|
prxCmd->count = 1;\
|
|
\
|
|
prxSetState = (RXSETSTATE *)(prxCmd + 1);\
|
|
prxSetState->stateToChange = state;\
|
|
prxSetState->newState[0] = (ULONG)(value);\
|
|
pDrvAccel->pCmd += (sizeof(RXSETSTATE) + sizeof(RXCMD));\
|
|
}
|
|
|
|
|
|
|
|
#define DRV_STATE_STRUCT(state, value, sizeValue)\
|
|
{\
|
|
RXCMD *prxCmd;\
|
|
RXSETSTATE *prxSetState;\
|
|
\
|
|
GenDrvFlush((__GLGENcontext *)gc);\
|
|
\
|
|
prxCmd = (RXCMD *)(pDrvAccel->pCmd);\
|
|
prxCmd->command = RXCMD_SET_STATE;\
|
|
prxCmd->size = sizeValue - sizeof(RXSETSTATE);\
|
|
prxCmd->count = 1;\
|
|
\
|
|
prxSetState = (RXSETSTATE *)(prxCmd + 1);\
|
|
prxSetState->stateToChange = state;\
|
|
RtlCopyMemory(prxSetState->newState, &value, sizeValue);\
|
|
pDrvAccel->pCmd += (sizeof(RXCMD) + sizeof(RXSETSTATE) + \
|
|
sizeValue - sizeof(ULONG));\
|
|
\
|
|
GenDrvFlush((__GLGENcontext *)gc);\
|
|
}
|
|
|
|
|
|
BYTE __GLtoGDIRop[] = {R2_BLACK, // GL_CLEAR (0)
|
|
R2_MASKPEN, // GL_AND
|
|
R2_MASKPENNOT, // GL_AND_REVERSE
|
|
R2_COPYPEN, // GL_COPY
|
|
R2_MASKNOTPEN, // GL_AND_INVERTED
|
|
R2_NOP, // GL_NOOP
|
|
R2_XORPEN, // GL_XOR
|
|
R2_MERGEPEN, // GL_OR
|
|
R2_NOTMERGEPEN, // GL_NOR
|
|
R2_NOTXORPEN, // GL_EQUIV
|
|
R2_NOT, // GL_INVERT
|
|
R2_MERGEPENNOT, // GL_OR_REVERSE
|
|
R2_NOTCOPYPEN, // GL_COPY_INVERTED
|
|
R2_MERGENOTPEN, // GL_OR_INVERTED
|
|
R2_NOTMASKPEN, // GL_NAND
|
|
R2_WHITE // GL_SET
|
|
};
|
|
|
|
static ULONG internalSolidTexture[4] = {0xffffffff, 0xffffffff,
|
|
0xffffffff, 0xffffffff};
|
|
|
|
|
|
void APIENTRY glsrvCopyDriverInfo(WNDOBJ *pwo, PVOID *pso, PVOID *pfnDrvEscape,
|
|
BOOL bSet)
|
|
{
|
|
__GLdrawablePrivate *dp;
|
|
GENDRVACCEL *pDrvAccel;
|
|
__GLGENbuffers *buffers;
|
|
|
|
if ((dp = (__GLdrawablePrivate *)pwo->pvConsumer)) {
|
|
__GLGENbuffers *buffers = (__GLGENbuffers *)dp->data;
|
|
|
|
if (buffers && (pDrvAccel = buffers->pDrvAccel)) {
|
|
if (bSet) {
|
|
pDrvAccel->pso = *pso;
|
|
pDrvAccel->pfnDrvEscape = *pfnDrvEscape;
|
|
} else {
|
|
*pso = pDrvAccel->pso;
|
|
*pfnDrvEscape = pDrvAccel->pfnDrvEscape;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#if DEAD_3DDDI
|
|
|
|
void GenDrvFlush(__GLGENcontext *gengc)
|
|
{
|
|
GENDRVACCEL *pDrvAccel;
|
|
RXCMD *ddiCmd;
|
|
ULONG nBytes;
|
|
|
|
if (!(pDrvAccel = gengc->pDrvAccel))
|
|
return;
|
|
|
|
if ((nBytes = (pDrvAccel->pCmd - pDrvAccel->pStartCmd)) == 0)
|
|
return;
|
|
|
|
pDrvAccel->rxExecute.cmdSize = nBytes;
|
|
pDrvAccel->rxExecute.vertexSize = pDrvAccel->pVertex -
|
|
pDrvAccel->pStartVertex;
|
|
|
|
if (!RxExecute(&pDrvAccel->rxExecute, 0))
|
|
{
|
|
WARNING("GenDrvFlush failed\n");
|
|
}
|
|
|
|
INIT_NEXT_CMD_BUFFER(pDrvAccel);
|
|
}
|
|
|
|
void FASTCALL GenDrvClearFunc(__GLcontext *gc, void *pBuffer, ULONG flags)
|
|
{
|
|
__GLGENcontext *gengc = (__GLGENcontext *)gc;
|
|
PIXELFORMATDESCRIPTOR *pfmt;
|
|
RXCMD *ddiCmd;
|
|
RXFILLRECT *ddiRectCmd;
|
|
RXSETSTATE *ddiStateCmd;
|
|
GENDRVACCEL *pDrvAccel = ((__GLGENcontext *)gc)->pDrvAccel;
|
|
ULONG *pZVal;
|
|
GLint x0, y0, x1, y1;
|
|
|
|
pfmt = &gengc->CurrentFormat;
|
|
|
|
GenDrvFlush((__GLGENcontext *)gc);
|
|
|
|
ddiCmd = (RXCMD *)pDrvAccel->pCmd;
|
|
ddiCmd->command = RXCMD_SET_STATE;
|
|
ddiCmd->size = sizeof(RXSETSTATE);
|
|
ddiCmd->count = 1;
|
|
|
|
ddiStateCmd = (RXSETSTATE *)(ddiCmd + 1);
|
|
|
|
if (flags == RXFILLRECT_COLOR)
|
|
ddiStateCmd->stateToChange = RXSTATE_FILL_COLOR;
|
|
else
|
|
ddiStateCmd->stateToChange = RXSTATE_FILL_Z;
|
|
//XXX!!! BUG
|
|
if (flags == RXFILLRECT_COLOR) {
|
|
__GLcolorBuffer *cfb = (__GLcolorBuffer *)pBuffer;
|
|
RXCOLOR *pRxColor = (RXCOLOR *)ddiStateCmd->newState;
|
|
|
|
if(pfmt->iPixelType == PFD_TYPE_RGBA) {
|
|
*pRxColor =
|
|
(((ULONG)(gc->state.raster.clear.a * ACCEL_COLOR_SCALE) << 24) |
|
|
((ULONG)(gc->state.raster.clear.r * ACCEL_COLOR_SCALE) << 16) |
|
|
((ULONG)(gc->state.raster.clear.g * ACCEL_COLOR_SCALE) << 8) |
|
|
((ULONG)(gc->state.raster.clear.b * ACCEL_COLOR_SCALE)));
|
|
} else {
|
|
*pRxColor =
|
|
((ULONG)(gc->state.raster.clear.r * ACCEL_COLOR_SCALE) << 16);
|
|
}
|
|
} else {
|
|
ddiStateCmd->newState[0] =
|
|
(ULONG)(gc->state.depth.clear * gc->depthBuffer.scale);
|
|
}
|
|
|
|
ddiCmd = (RXCMD *)(ddiStateCmd + 1);
|
|
ddiCmd->command = RXCMD_FILL_RECT;
|
|
ddiCmd->size = sizeof(RXFILLRECT);
|
|
ddiCmd->count = 1;
|
|
|
|
ddiRectCmd = (RXFILLRECT *)(ddiCmd + 1);
|
|
ddiRectCmd->fillType = flags;
|
|
|
|
x0 = __GL_UNBIAS_X(gc, gc->transform.clipX0);
|
|
y0 = __GL_UNBIAS_Y(gc, gc->transform.clipY0);
|
|
x1 = __GL_UNBIAS_X(gc, gc->transform.clipX1);
|
|
y1 = __GL_UNBIAS_Y(gc, gc->transform.clipY1);
|
|
if ((x1 == x0) || (y1 == y0))
|
|
return;
|
|
|
|
ddiRectCmd->fillRect.x = x0;
|
|
ddiRectCmd->fillRect.y = y0;
|
|
ddiRectCmd->fillRect.width = x1 - x0;
|
|
ddiRectCmd->fillRect.height = y1 - y0;
|
|
|
|
pDrvAccel->rxExecute.cmdSize = (char *)(ddiRectCmd + 1) -
|
|
(char *)pDrvAccel->pCmd;
|
|
pDrvAccel->rxExecute.vertexSize = 0;
|
|
|
|
if (!RxExecute(&pDrvAccel->rxExecute, 0))
|
|
{
|
|
WARNING("GenDrvClearFunc failed\n");
|
|
}
|
|
|
|
INIT_NEXT_CMD_BUFFER(pDrvAccel);
|
|
}
|
|
|
|
BOOL APIENTRY GenPixelVisible(HDC hdc, LONG x, LONG y)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
void GenDrvCopyPixels(__GLGENcontext *gengc, __GLcolorBuffer *cfb, GLint x, GLint y,
|
|
GLint cx, BOOL bIn)
|
|
{
|
|
GENDRVACCEL *pDrvAccel;
|
|
ULONG nBytes;
|
|
RXEXECUTE rxExecute;
|
|
|
|
GenDrvFlush(gengc);
|
|
|
|
pDrvAccel = gengc->pDrvAccel;
|
|
|
|
rxExecute.hrxRC = pDrvAccel->rxExecute.hrxRC;
|
|
rxExecute.hdc = pDrvAccel->rxExecute.hdc;
|
|
rxExecute.hrxMem = pDrvAccel->hrxMemC;
|
|
rxExecute.pCmd = pDrvAccel->pCRWBase;
|
|
|
|
if (bIn) {
|
|
RXCMD *pCmd;
|
|
RXWRITERECT *ddiRect;
|
|
|
|
if (gengc->gc.state.raster.drawBuffer == GL_FRONT_AND_BACK) {
|
|
RXSETSTATE *ddiState;
|
|
|
|
pCmd = (RXCMD *)pDrvAccel->pCRWBase;
|
|
pCmd->command = RXCMD_SET_STATE;
|
|
pCmd->size = sizeof(RXSETSTATE);
|
|
pCmd->count = 1;
|
|
|
|
ddiState = (RXSETSTATE *)(pCmd + 1);
|
|
ddiState->stateToChange = RXSTATE_ACTIVE_BUFFER;
|
|
ddiState->newState[0] = ((cfb == gengc->gc.front) ? RX_FRONT_LEFT :
|
|
RX_BACK_LEFT);
|
|
pCmd = (RXCMD *)(ddiState + 1);
|
|
} else {
|
|
pCmd = (RXCMD *)pDrvAccel->pCRWBase;
|
|
}
|
|
|
|
pCmd->command = RXCMD_WRITE_RECT;
|
|
pCmd->size = sizeof(RXWRITERECT);
|
|
pCmd->count = 1;
|
|
|
|
ddiRect = (RXWRITERECT *)(pCmd + 1);
|
|
ddiRect->destBuffer = RXWRITERECT_PIX;
|
|
ddiRect->sourceX = 0;
|
|
ddiRect->sourceY = 0;
|
|
ddiRect->destRect.x = x;
|
|
ddiRect->destRect.y = y;
|
|
ddiRect->destRect.width = cx;
|
|
ddiRect->destRect.height = 1;
|
|
ddiRect->pMem = (VOID *)pDrvAccel->pCDrv;
|
|
ddiRect->pitch = cx; // set to something reasonable...
|
|
ddiRect++;
|
|
|
|
pDrvAccel->rxExecute.cmdSize = (char *)ddiRect - pDrvAccel->pCRWBase;
|
|
pDrvAccel->rxExecute.vertexSize = 0;
|
|
if (!RxExecute(&rxExecute, TRUE))
|
|
{
|
|
WARNING("GenDrvCopyPixels in failed\n");
|
|
}
|
|
|
|
} else {
|
|
RXCMD *pCmd = (RXCMD *)pDrvAccel->pCRWBase;
|
|
RXREADRECT *ddiRect = (RXREADRECT *)(pCmd + 1);
|
|
|
|
pCmd->command = RXCMD_WRITE_RECT;
|
|
pCmd->size = sizeof(RXWRITERECT);
|
|
pCmd->count = 1;
|
|
|
|
ddiRect->sourceBuffer =
|
|
((cfb == gengc->gc.front) ? RXREADRECT_FRONT_LEFT :
|
|
RXREADRECT_BACK_LEFT);
|
|
ddiRect->sourceX = x;
|
|
ddiRect->sourceY = y;
|
|
ddiRect->destRect.x = 0;
|
|
ddiRect->destRect.y = 0;
|
|
ddiRect->destRect.width = cx;
|
|
ddiRect->destRect.height = 1;
|
|
ddiRect->pMem = (VOID *)pDrvAccel->pCDrv;
|
|
ddiRect->pitch = cx; // set to something reasonable...
|
|
ddiRect++;
|
|
|
|
pDrvAccel->rxExecute.cmdSize = (char *)ddiRect - pDrvAccel->pCRWBase;
|
|
pDrvAccel->rxExecute.vertexSize = 0;
|
|
if (!RxExecute(&rxExecute, TRUE))
|
|
{
|
|
WARNING("GenDrvCopyPixels out failed\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
BOOL FASTCALL GenDrvSwapBuffers(GENDRVACCEL *pDrvAccel, HDC hdc, WNDOBJ *pwo)
|
|
{
|
|
RXSWAPBUFFERS *prxSwapBuffers;
|
|
RXCMD *ddiCmd;
|
|
ULONG nBytes;
|
|
BOOL retVal;
|
|
|
|
if ((nBytes = (pDrvAccel->pCmd - pDrvAccel->pStartCmd)) != 0) {
|
|
pDrvAccel->rxExecute.cmdSize = nBytes;
|
|
pDrvAccel->rxExecute.vertexSize = pDrvAccel->pVertex -
|
|
pDrvAccel->pStartVertex;
|
|
RxExecute(&pDrvAccel->rxExecute, 0);
|
|
INIT_NEXT_CMD_BUFFER(pDrvAccel);
|
|
}
|
|
|
|
ddiCmd = (RXCMD *)pDrvAccel->pCmd;
|
|
ddiCmd->command = RXCMD_SWAP_BUFFERS;
|
|
ddiCmd->size = sizeof(RXSWAPBUFFERS);
|
|
ddiCmd->count = 1;
|
|
|
|
prxSwapBuffers = (RXSWAPBUFFERS *)(ddiCmd + 1);
|
|
prxSwapBuffers->flags = 0;
|
|
|
|
pDrvAccel->rxExecute.cmdSize = (char *)(prxSwapBuffers + 1) -
|
|
pDrvAccel->pStartCmd;
|
|
pDrvAccel->rxExecute.vertexSize = 0;
|
|
|
|
retVal = (BOOL)RxExecute(&pDrvAccel->rxExecute, FALSE);
|
|
|
|
INIT_NEXT_CMD_BUFFER(pDrvAccel);
|
|
|
|
return retVal;
|
|
}
|
|
|
|
void FASTCALL GenDrvClearDepth(__GLdepthBuffer *dfb)
|
|
{
|
|
GenDrvClearFunc(dfb->buf.gc, (void *)dfb, RXFILLRECT_Z);
|
|
}
|
|
|
|
|
|
void FASTCALL GenDrvClear(__GLcolorBuffer *cfb)
|
|
{
|
|
//XXX do we need to check dithering caps?
|
|
//!!! Check mask caps!
|
|
|
|
if ((GLuint)cfb->buf.other & COLORMASK_ON) {
|
|
__GLGENcontext *gengc = (__GLGENcontext *)cfb->buf.gc;
|
|
|
|
(*gengc->pDrvAccel->softClearFuncPtr)(cfb);
|
|
} else
|
|
GenDrvClearFunc(cfb->buf.gc, (void *)cfb, RXFILLRECT_COLOR);
|
|
}
|
|
|
|
void FASTCALL GenDrvDeltaSpan(__GLcontext *gc)
|
|
{
|
|
GENDRVACCEL *pDrvAccel = ((__GLGENcontext *)gc)->pDrvAccel;
|
|
RXSPAN *pSpan;
|
|
|
|
if (((pDrvAccel->pCmd + sizeof(RXCMD) + (2 * MAX_SPAN_SIZE)) >
|
|
pDrvAccel->pStartVertex) ||
|
|
(pDrvAccel->pCmd !=
|
|
(pDrvAccel->pStartCmd + sizeof(RXCMD)) ||
|
|
(((RXCMD *)pDrvAccel->pStartCmd)->command !=
|
|
RXCMD_POLY_DRAW_SPAN))) {
|
|
GenDrvFlush((__GLGENcontext *)gc);
|
|
}
|
|
|
|
if (pDrvAccel->pCmd == pDrvAccel->pStartCmd) {
|
|
RXCMD *ddiCmd;
|
|
RXSPAN *prxDrawSpan;
|
|
|
|
ddiCmd = (RXCMD *)pDrvAccel->pCmd;
|
|
|
|
ddiCmd = (RXCMD *)pDrvAccel->pCmd;
|
|
ddiCmd->command = RXCMD_POLY_DRAW_SPAN;
|
|
ddiCmd->size = sizeof(RXSPAN);
|
|
ddiCmd->count = 0;
|
|
|
|
pDrvAccel->pCmd = (char *)(ddiCmd + 1);
|
|
|
|
if (!(gc->polygon.shader.modeFlags &
|
|
(__GL_SHADE_TEXTURE | __GL_SHADE_SMOOTH))) {
|
|
ddiCmd->count = 1;
|
|
pSpan = (RXSPAN *)pDrvAccel->pCmd;
|
|
pSpan->flags = RXSPAN_DELTA;
|
|
pSpan->r = 0;
|
|
pSpan->g = 0;
|
|
pSpan->b = 0;
|
|
pSpan->a = 0;
|
|
pDrvAccel->pCmd += pDrvAccel->spanStride;
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (gc->polygon.shader.modeFlags & __GL_SHADE_SMOOTH) {
|
|
((RXCMD *)pDrvAccel->pCmd - 1)->count++;
|
|
pSpan = (RXSPAN *)pDrvAccel->pCmd;
|
|
pSpan->flags = RXSPAN_DELTA;
|
|
pSpan->r = GENACCEL(gc).spanDelta.r;
|
|
pSpan->g = GENACCEL(gc).spanDelta.g;
|
|
pSpan->b = GENACCEL(gc).spanDelta.b;
|
|
pSpan->a = GENACCEL(gc).spanDelta.a;
|
|
pDrvAccel->pCmd += pDrvAccel->spanStride;
|
|
}
|
|
}
|
|
|
|
void FASTCALL GenDrvSpan(__GLGENcontext *gengc)
|
|
{
|
|
__GLcontext *gc = (__GLcontext *)gengc;
|
|
ULONG stippleLength = ((gc->polygon.shader.length + 31) >> 3) & (~0x3);
|
|
GENDRVACCEL *pDrvAccel = ((__GLGENcontext *)gc)->pDrvAccel;
|
|
RXSPAN *pSpan;
|
|
|
|
if ((pDrvAccel->pCmd + MAX_SPAN_SIZE +
|
|
stippleLength) > pDrvAccel->pStartVertex) {
|
|
GenDrvFlush(gengc);
|
|
|
|
// We need to re-issue the delta/color if we've broken the
|
|
// batch
|
|
|
|
GenDrvDeltaSpan((__GLcontext *)gengc);
|
|
} else if (pDrvAccel->pCmd == pDrvAccel->pStartCmd) {
|
|
|
|
// This could happen if we do read/write spans with the z-buffer.
|
|
// Unfortunately, we have to re-start the span, including the delta...
|
|
|
|
GenDrvDeltaSpan((__GLcontext *)gengc);
|
|
}
|
|
|
|
((RXCMD *)pDrvAccel->pCmd - 1)->count++;
|
|
|
|
pSpan = (RXSPAN *)pDrvAccel->pCmd;
|
|
pSpan->flags = 0;
|
|
|
|
pSpan->x = (USHORT)(gc->polygon.shader.frag.x -
|
|
gc->constants.viewportXAdjust);
|
|
|
|
pSpan->y = (USHORT)(gc->polygon.shader.frag.y -
|
|
gc->constants.viewportYAdjust);
|
|
|
|
pSpan->count = (USHORT)gc->polygon.shader.length;
|
|
|
|
pSpan->r = GENACCEL(gc).spanValue.r;
|
|
pSpan->g = GENACCEL(gc).spanValue.g;
|
|
pSpan->b = GENACCEL(gc).spanValue.b;
|
|
pSpan->a = GENACCEL(gc).spanValue.a;
|
|
|
|
pDrvAccel->pCmd += pDrvAccel->spanStride;
|
|
|
|
if (GENACCEL(gc).flags & HAVE_STIPPLE) {
|
|
pSpan->flags = RXSPAN_MASK;
|
|
RtlCopyMemory(pDrvAccel->pCmd, gc->polygon.shader.stipplePat,
|
|
stippleLength);
|
|
pDrvAccel->pCmd += stippleLength;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL FASTCALL GenDrvLoadTexImage(__GLcontext *gc, __GLtexture *tex)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
void FASTCALL GenDrvDestroy(WNDOBJ *pwo, __GLGENbuffers *buffer)
|
|
{
|
|
GENDRVACCEL *pDrvAccel;
|
|
|
|
if (!buffer)
|
|
return;
|
|
|
|
if (!(pDrvAccel = buffer->pDrvAccel))
|
|
return;
|
|
|
|
RxDeleteResource((RXHANDLE)pDrvAccel->hrxRC);
|
|
|
|
if (pDrvAccel->pZDrv) {
|
|
if (pDrvAccel->pZDrv != pDrvAccel->pShMemZ)
|
|
GenFree(pDrvAccel->pShMemZ);
|
|
buffer->depthBuffer.base = NULL;
|
|
}
|
|
|
|
GenFree(pDrvAccel->pExecBuffer);
|
|
GenFree(pDrvAccel->pZRWBase);
|
|
GenFree(pDrvAccel->pCRWBase);
|
|
|
|
buffer->pDrvAccel = NULL;
|
|
}
|
|
|
|
|
|
ULONG FASTCALL GenDrvBuffersUsed(__GLGENcontext *genGc)
|
|
{
|
|
ULONG buffersEnabled;
|
|
__GLcontextModes *modes = &genGc->gc.modes;
|
|
GENDRVACCEL *pDrvAccel = genGc->pDrvAccel;
|
|
ULONG zDepth;
|
|
|
|
buffersEnabled = 0;
|
|
|
|
if (modes->doubleBufferMode)
|
|
buffersEnabled |= RXENABLE_BACK_LEFT_BUFFER;
|
|
|
|
zDepth = pDrvAccel->rxSurfaceInfo.zDepth;
|
|
|
|
// Make sure we can z-buffer if needed. For small (<= 16) z-buffers,
|
|
// force hardware to be at least as accurate. For larger z-buffers,
|
|
// we can be more lax.
|
|
|
|
if ((modes->depthBits) && zDepth) {
|
|
if (((modes->depthBits <= 16) && (zDepth >= 16)) ||
|
|
((modes->depthBits > 16) && (zDepth > 16)))
|
|
buffersEnabled |= RXENABLE_Z_BUFFER;
|
|
}
|
|
|
|
return buffersEnabled;
|
|
}
|
|
|
|
//
|
|
// This is the main 3D DDI context-creation function. This will be
|
|
// called for the first MakeCurrent of the GL rendering context.
|
|
//
|
|
|
|
GLboolean FASTCALL bInitDrvContext(__GLcontext *gc)
|
|
{
|
|
__GLGENcontext *gengc = (__GLGENcontext *)gc;
|
|
RXGETINFO rxGetInfo;
|
|
RXGLOBALINFO rxGlobalInfo;
|
|
RXWINDOWSURFACE rxWindowSurface;
|
|
GENDRVACCEL *pDrvAccel;
|
|
__GLcontextModes *modes = &gc->modes;
|
|
ULONG buffersEnabled;
|
|
ULONG maxScanSize;
|
|
RXCAPS *pGenCaps;
|
|
HDC hdc = ((__GLGENcontext *)gc)->CurrentDC;
|
|
ULONG cmdBufferSize;
|
|
int cColorBits;
|
|
|
|
gengc->pDrvAccel = (GENDRVACCEL *)NULL;
|
|
return FALSE; //!!!!!!
|
|
|
|
if (!(gengc->pDrvAccel =
|
|
(GENDRVACCEL *)(*gc->imports.calloc)(gc, 1, sizeof(GENDRVACCEL))))
|
|
return FALSE;
|
|
|
|
pDrvAccel = gengc->pDrvAccel;
|
|
|
|
rxWindowSurface.flags = RXCONTEXT_HWND;
|
|
rxWindowSurface.hwnd = NULL;
|
|
rxWindowSurface.hdc = hdc;
|
|
|
|
rxGetInfo.flags = RXGETINFO_CURRENT_MODE;
|
|
if (!modes->rgbMode)
|
|
rxGetInfo.flags |= RXGETINFO_COLOR_INDEX;
|
|
rxGetInfo.height = 0;
|
|
rxGetInfo.width = 0;
|
|
rxGetInfo.bitsPerPixel = 0;
|
|
rxGetInfo.refreshRate = 0;
|
|
|
|
// Get global info
|
|
|
|
rxGetInfo.infoType = RXINFO_GLOBAL_CAPS;
|
|
if (!RxGetInfo(&rxWindowSurface, &rxGetInfo,
|
|
(UCHAR *)&rxGlobalInfo, sizeof(RXGLOBALINFO)))
|
|
goto noDDI;
|
|
|
|
// Get info for this mode
|
|
|
|
rxGetInfo.infoType = RXINFO_SURFACE_CAPS;
|
|
RxGetInfo(&rxWindowSurface, &rxGetInfo,
|
|
(UCHAR *)&pDrvAccel->rxSurfaceInfo, sizeof(RXSURFACEINFO));
|
|
|
|
rxGetInfo.infoType = RXINFO_SPAN_CAPS;
|
|
pDrvAccel->bScan = RxGetInfo(&rxWindowSurface, &rxGetInfo,
|
|
(UCHAR *)&pDrvAccel->rxScanCaps, sizeof(RXCAPS));
|
|
|
|
rxGetInfo.infoType = RXINFO_INTLINE_CAPS;
|
|
pDrvAccel->bIntLine = RxGetInfo(&rxWindowSurface, &rxGetInfo,
|
|
(UCHAR *)&pDrvAccel->rxIntLineCaps, sizeof(RXCAPS));
|
|
|
|
|
|
rxGetInfo.infoType = RXINFO_LINE_CAPS;
|
|
pDrvAccel->bLine = RxGetInfo(&rxWindowSurface, &rxGetInfo,
|
|
(UCHAR *)&pDrvAccel->rxLineCaps, sizeof(RXCAPS));
|
|
|
|
rxGetInfo.infoType = RXINFO_TRIANGLE_CAPS;
|
|
pDrvAccel->bTri = RxGetInfo(&rxWindowSurface, &rxGetInfo,
|
|
(UCHAR *)&pDrvAccel->rxTriCaps, sizeof(RXCAPS));
|
|
|
|
// Make an agragate of the various capabilities to valididate our
|
|
// state-setting
|
|
|
|
pGenCaps = &pDrvAccel->rxGenCaps;
|
|
|
|
RtlCopyMemory(pGenCaps, &pDrvAccel->rxScanCaps, sizeof(RXCAPS));
|
|
|
|
pGenCaps->miscCaps |= (pDrvAccel->rxLineCaps.miscCaps |
|
|
pDrvAccel->rxTriCaps.miscCaps);
|
|
|
|
pGenCaps->rasterCaps |= (pDrvAccel->rxLineCaps.rasterCaps |
|
|
pDrvAccel->rxTriCaps.rasterCaps);
|
|
|
|
pGenCaps->zCmpCaps |= (pDrvAccel->rxLineCaps.zCmpCaps |
|
|
pDrvAccel->rxTriCaps.zCmpCaps);
|
|
|
|
pGenCaps->srcBlendCaps |= (pDrvAccel->rxLineCaps.srcBlendCaps |
|
|
pDrvAccel->rxTriCaps.srcBlendCaps);
|
|
|
|
pGenCaps->dstBlendCaps |= (pDrvAccel->rxLineCaps.dstBlendCaps |
|
|
pDrvAccel->rxTriCaps.dstBlendCaps);
|
|
|
|
pGenCaps->shadeCaps |= (pDrvAccel->rxLineCaps.shadeCaps |
|
|
pDrvAccel->rxTriCaps.shadeCaps);
|
|
|
|
pGenCaps->texCaps |= (pDrvAccel->rxLineCaps.texCaps |
|
|
pDrvAccel->rxTriCaps.texCaps);
|
|
|
|
pGenCaps->texFilterCaps |= (pDrvAccel->rxLineCaps.texFilterCaps |
|
|
pDrvAccel->rxTriCaps.texFilterCaps);
|
|
|
|
pGenCaps->texBlendCaps |= (pDrvAccel->rxLineCaps.texBlendCaps |
|
|
pDrvAccel->rxTriCaps.texBlendCaps);
|
|
|
|
|
|
// Check for backbuffer capability. Conformance will fail if we mix
|
|
// hardware frontbuffer and software backbuffer drawing. We may choose
|
|
// to relax this later...
|
|
|
|
// Check span capability
|
|
|
|
if (pDrvAccel->bScan) {
|
|
if (!(pDrvAccel->rxScanCaps.miscCaps & RXCAPS_HORIZONTAL_SPANS) ||
|
|
!(pDrvAccel->rxScanCaps.miscCaps & RXCAPS_MASK_MSB) ||
|
|
!(pDrvAccel->rxScanCaps.shadeCaps & RXCAPS_SHADE_SMOOTH))
|
|
pDrvAccel->bScan = FALSE;
|
|
}
|
|
|
|
// If we are to enable any of the hardware's buffers, ensure that we
|
|
// have at least some reasonable level of functionality in the 3D-DDI.
|
|
// Otherwise, we will incure a big hit for performing software simulations,
|
|
// and could wind up with worse performance in a majority of cases.
|
|
|
|
buffersEnabled = GenDrvBuffersUsed(gengc);
|
|
|
|
if ((modes->doubleBufferMode) &&
|
|
!(pDrvAccel->rxSurfaceInfo.flags & RXSURFACE_BACK_BUFFER))
|
|
{
|
|
WARNING("No backbuffer available\n");
|
|
goto noDDI;
|
|
}
|
|
|
|
// If we have a z buffer, we should expect to at least be able to do
|
|
// smooth-shaded lines and triangles.
|
|
|
|
// If we are double-buffered, we simple check for at least some form of
|
|
// line support to be able to do animated wireframes. If we are using
|
|
// a software z-buffer, also check for smooth-shaded span capability since
|
|
// we will probably be drawing triangles.
|
|
|
|
if (!rxGlobalInfo.hwBufferOptSize)
|
|
cmdBufferSize = DRV_CMD_BUFFER_SIZE;
|
|
else
|
|
cmdBufferSize = rxGlobalInfo.hwBufferOptSize;
|
|
|
|
pDrvAccel->cmdBufferSize = cmdBufferSize;
|
|
|
|
pDrvAccel->pCmdBuffer1 =
|
|
(*gc->imports.calloc)(gc, 1, cmdBufferSize);
|
|
|
|
pDrvAccel->pCmdBuffer2 =
|
|
(*gc->imports.calloc)(gc, 1, cmdBufferSize);
|
|
|
|
if ((!pDrvAccel->pCmdBuffer1) || (!pDrvAccel->pCmdBuffer2))
|
|
{
|
|
WARNING("Command buffers not created\n");
|
|
goto noDDI;
|
|
}
|
|
|
|
pDrvAccel->vertexStartOffset =
|
|
(((cmdBufferSize * sizeof(RXTRIANGLE)) / (3 * sizeof(RXVERTEX))) & ~0xf);
|
|
|
|
pDrvAccel->vertexEndOffset = cmdBufferSize - sizeof(DWORD);
|
|
|
|
if (buffersEnabled & RXENABLE_Z_BUFFER) {
|
|
if ((!pDrvAccel->bTri) ||
|
|
(!(pDrvAccel->rxTriCaps.shadeCaps & RXCAPS_SHADE_SMOOTH)) ||
|
|
(!pDrvAccel->bLine) ||
|
|
(!(pDrvAccel->rxLineCaps.shadeCaps & RXCAPS_SHADE_SMOOTH)))
|
|
{
|
|
WARNING("Shading not supported by driver\n");
|
|
goto noDDI;
|
|
}
|
|
} else if (buffersEnabled & RXENABLE_BACK_LEFT_BUFFER) {
|
|
if (!pDrvAccel->bIntLine && !pDrvAccel->bLine)
|
|
{
|
|
WARNING("Lines not supported by driver\n");
|
|
goto noDDI;
|
|
}
|
|
if (modes->depthBits && !pDrvAccel->bScan)
|
|
{
|
|
WARNING("Spans not supported by driver\n");
|
|
goto noDDI;
|
|
}
|
|
}
|
|
|
|
// Now set up memory for color and z-buffer scanlines
|
|
|
|
pDrvAccel->pCRWBase = (*gc->imports.calloc)(gc, 1, PIX_BUFFER_SIZE);
|
|
if (!pDrvAccel->pCRWBase)
|
|
{
|
|
WARNING("Pixel buffer not created\n");
|
|
goto noDDI;
|
|
}
|
|
|
|
pDrvAccel->pCDrv = pDrvAccel->pCRWBase +
|
|
sizeof(RXCMD) + sizeof(RXREADRECT);
|
|
|
|
if (buffersEnabled & RXENABLE_Z_BUFFER) {
|
|
|
|
pDrvAccel->pZRWBase = (*gc->imports.calloc)(gc, 1, PIX_BUFFER_SIZE);
|
|
if (!pDrvAccel->pZRWBase)
|
|
{
|
|
WARNING("Z pixel buffer not created\n");
|
|
goto noDDI;
|
|
}
|
|
|
|
pDrvAccel->pZDrv = pDrvAccel->pZRWBase +
|
|
sizeof(RXCMD) + sizeof(RXREADRECT);
|
|
|
|
pDrvAccel->zShift = pDrvAccel->rxSurfaceInfo.zBitShift;
|
|
pDrvAccel->zBitMask = (~1) << (32 - pDrvAccel->rxSurfaceInfo.zDepth);
|
|
|
|
if (pDrvAccel->rxSurfaceInfo.zBytesPerPixel == 4)
|
|
pDrvAccel->pShMemZ = pDrvAccel->pZDrv;
|
|
else if (pDrvAccel->rxSurfaceInfo.zBytesPerPixel == 2) {
|
|
pDrvAccel->pShMemZ = GenMalloc(sizeof(DWORD) * MAX_SPAN_WIDTH);
|
|
|
|
if (!pDrvAccel->pShMemZ)
|
|
{
|
|
WARNING("Z exchange area not created\n");
|
|
goto noDDI;
|
|
}
|
|
} else {
|
|
WARNING("Unsupported Z pixel size\n");
|
|
goto noDDI;
|
|
}
|
|
}
|
|
|
|
WARNING("bInitDrvContext: DDI will be used\n");
|
|
|
|
return TRUE;
|
|
|
|
noDDI:
|
|
// If the device doesn't have the required resources, don't
|
|
// use it. Clean up any dangling resources now!
|
|
// Check for any memory buffers we need to delete:
|
|
|
|
WARNING("bInitDrvContext: DDI will not be used\n");
|
|
|
|
if (pDrvAccel->pCmdBuffer1)
|
|
(*gc->imports.free)(gc, pDrvAccel->pCmdBuffer1);
|
|
if (pDrvAccel->pCmdBuffer2)
|
|
(*gc->imports.free)(gc, pDrvAccel->pCmdBuffer2);
|
|
if (pDrvAccel->pCRWBase)
|
|
(*gc->imports.free)(gc, pDrvAccel->pCRWBase);
|
|
if (pDrvAccel->pZRWBase) {
|
|
if (pDrvAccel->pShMemZ &&
|
|
(pDrvAccel->pZDrv != pDrvAccel->pShMemZ))
|
|
(*gc->imports.free)(gc, pDrvAccel->pShMemZ);
|
|
(*gc->imports.free)(gc, pDrvAccel->pZRWBase);
|
|
}
|
|
|
|
(*gc->imports.free)(gc, pDrvAccel);
|
|
|
|
gengc->pDrvAccel = NULL;
|
|
|
|
#ifdef _CLIENTSIDE_
|
|
cColorBits = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
|
|
#else
|
|
cColorBits = GreGetDeviceCaps(hdc, BITSPIXEL) *
|
|
GreGetDeviceCaps(hdc, PLANES);
|
|
#endif
|
|
|
|
if (cColorBits >= 24) {
|
|
gengc->CurrentFormat.cColorBits = cColorBits;
|
|
if (gengc->CurrentFormat.cRedShift > gengc->CurrentFormat.cBlueShift) {
|
|
gengc->CurrentFormat.cRedShift = 16;
|
|
gengc->CurrentFormat.cGreenShift = 8;
|
|
gengc->CurrentFormat.cBlueShift = 0;
|
|
} else {
|
|
gengc->CurrentFormat.cRedShift = 0;
|
|
gengc->CurrentFormat.cGreenShift = 8;
|
|
gengc->CurrentFormat.cBlueShift = 16;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
GLboolean FASTCALL GenDrvMakeCurrent(__GLGENcontext *genGc, HWND hwnd)
|
|
{
|
|
GENDRVACCEL *pDrvAccel = genGc->pDrvAccel;
|
|
HDC hdc = genGc->CurrentDC;
|
|
RXWINDOWSURFACE rxWindowSurface;
|
|
__GLcontextModes *modes = &genGc->gc.modes;
|
|
__GLcontext *gc = (__GLcontext *)genGc;
|
|
ULONG buffersEnabled;
|
|
RXCREATEMEM rxCreateMem;
|
|
|
|
// If we already have a context, we're done
|
|
// BUGBUG - This isn't actually correct because it doesn't handle
|
|
// the case where a context is switched between different windows
|
|
// We should check and see if the window that the existing context
|
|
// is for is the same as the new one
|
|
|
|
if (genGc->pDrvAccel->hrxRC != NULL)
|
|
{
|
|
return GL_TRUE;
|
|
}
|
|
|
|
rxWindowSurface.flags = RXCONTEXT_HWND;
|
|
rxWindowSurface.hwnd = hwnd;
|
|
rxWindowSurface.hdc = hdc;
|
|
|
|
pDrvAccel->hrxRC = RxCreateContext(&rxWindowSurface, 0);
|
|
|
|
if (!pDrvAccel->hrxRC)
|
|
goto noDDI;
|
|
|
|
rxCreateMem.sourceProcessID = GetCurrentProcessId();
|
|
rxCreateMem.memSize = pDrvAccel->cmdBufferSize;
|
|
rxCreateMem.flags = 0;
|
|
rxCreateMem.pClientBase = (UCHAR *)pDrvAccel->pCmdBuffer1;
|
|
|
|
pDrvAccel->hrxExecBuffer1 = RxCreateExecMem(pDrvAccel->hrxRC, &rxCreateMem);
|
|
|
|
rxCreateMem.sourceProcessID = GetCurrentProcessId();
|
|
rxCreateMem.memSize = pDrvAccel->cmdBufferSize;
|
|
rxCreateMem.flags = 0;
|
|
rxCreateMem.pClientBase = (UCHAR *)pDrvAccel->pCmdBuffer2;
|
|
|
|
pDrvAccel->hrxExecBuffer2 = RxCreateExecMem(pDrvAccel->hrxRC, &rxCreateMem);
|
|
|
|
rxCreateMem.sourceProcessID = GetCurrentProcessId();
|
|
rxCreateMem.memSize = PIX_BUFFER_SIZE;
|
|
rxCreateMem.flags = 0;
|
|
rxCreateMem.pClientBase = (UCHAR *)pDrvAccel->pCRWBase;
|
|
|
|
pDrvAccel->hrxMemC = RxCreateExecMem(pDrvAccel->hrxRC, &rxCreateMem);
|
|
|
|
rxCreateMem.sourceProcessID = GetCurrentProcessId();
|
|
rxCreateMem.memSize = PIX_BUFFER_SIZE;
|
|
rxCreateMem.flags = 0;
|
|
rxCreateMem.pClientBase = (UCHAR *)pDrvAccel->pZRWBase;
|
|
|
|
pDrvAccel->hrxMemZ = RxCreateExecMem(pDrvAccel->hrxRC, &rxCreateMem);
|
|
|
|
// Update header structure for all future commands sent through
|
|
// the shared memory buffer.
|
|
|
|
INIT_NEXT_CMD_BUFFER(pDrvAccel);
|
|
|
|
pDrvAccel->rxExecute.hrxRC = pDrvAccel->hrxRC;
|
|
pDrvAccel->rxExecute.hdc = hdc;
|
|
pDrvAccel->rxExecute.vertexSize = sizeof(RXVERTEX);
|
|
pDrvAccel->rxExecute.type = 0; //XXX What should this be?
|
|
|
|
// Now make sure we can enable our required buffers
|
|
|
|
buffersEnabled = GenDrvBuffersUsed(genGc);
|
|
if (buffersEnabled)
|
|
{
|
|
RXCMD *prxCmd = (RXCMD *)pDrvAccel->pCmd;
|
|
RXENABLEBUFFERS *prxEnableBuffers;
|
|
|
|
prxCmd->command = RXCMD_ENABLE_BUFFERS;
|
|
prxCmd->size = sizeof(RXENABLEBUFFERS);
|
|
prxCmd->count = 1;
|
|
|
|
prxEnableBuffers = (RXENABLEBUFFERS *)(prxCmd + 1);
|
|
prxEnableBuffers->buffers = buffersEnabled;
|
|
|
|
pDrvAccel->rxExecute.cmdSize = (char *)(prxEnableBuffers + 1) -
|
|
pDrvAccel->pCmd;
|
|
pDrvAccel->rxExecute.vertexSize = 0;
|
|
|
|
|
|
if (!RxExecute(&pDrvAccel->rxExecute, TRUE))
|
|
{
|
|
WARNING1("RXCMD_ENABLE_BUFFERS %X failed\n", buffersEnabled);
|
|
goto noDDI;
|
|
}
|
|
}
|
|
|
|
// Force the current state to go to the driver
|
|
GenDrvUpdateState(gc, TRUE);
|
|
|
|
GenDrvFlush(genGc);
|
|
|
|
if (pDrvAccel->bScan)
|
|
{
|
|
BATCHED_DRV_STATE(RXSTATE_SPAN_DIRECTION, RXSPAN_HORIZONTAL);
|
|
}
|
|
|
|
// Flush batched state changes
|
|
|
|
GenDrvFlush(genGc);
|
|
|
|
return GL_TRUE;
|
|
|
|
noDDI:
|
|
|
|
if (pDrvAccel->hrxMemC)
|
|
RxDeleteResource(pDrvAccel->hrxMemC);
|
|
if (pDrvAccel->hrxMemZ)
|
|
RxDeleteResource(pDrvAccel->hrxMemZ);
|
|
if (pDrvAccel->hrxExecBuffer1)
|
|
RxDeleteResource(pDrvAccel->hrxExecBuffer1);
|
|
if (pDrvAccel->hrxExecBuffer2)
|
|
RxDeleteResource(pDrvAccel->hrxExecBuffer2);
|
|
if (pDrvAccel->hrxRC)
|
|
RxDeleteResource(pDrvAccel->hrxRC);
|
|
|
|
return GL_FALSE;
|
|
}
|
|
|
|
#endif //DEAD_3DDDI
|
|
|
|
GENTEXCACHE *GetGenTexCache(__GLcontext *gc, __GLtexture *tex)
|
|
{
|
|
ULONG size;
|
|
GENTEXCACHE *pGenTex;
|
|
ULONG internalFormat;
|
|
GLuint modeFlags = gc->polygon.shader.modeFlags;
|
|
|
|
// Replace maps are only used for a subset of possible modes
|
|
// 8 or 16bpp
|
|
// 16-bit Z
|
|
//
|
|
// No dithering. Since dithering can turn on and off there
|
|
// are two cases:
|
|
// Dither off at TexImage time but on at texturing time -
|
|
// We create a map that's unused
|
|
// Dither on and then off - We won't create a map at
|
|
// TexImage time but it'll be created on the fly when
|
|
// dithering is turned on and everything is repicked
|
|
|
|
if (GENACCEL(gc).bpp < 8 ||
|
|
GENACCEL(gc).bpp > 16 ||
|
|
((modeFlags & (__GL_SHADE_DEPTH_TEST | __GL_SHADE_DEPTH_ITER)) &&
|
|
gc->modes.depthBits > 16) ||
|
|
(modeFlags & __GL_SHADE_DITHER))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
internalFormat = tex->level[0].internalFormat;
|
|
|
|
// We only support 8-bit palettes that are fully populated
|
|
if (internalFormat == GL_COLOR_INDEX16_EXT ||
|
|
(internalFormat == GL_COLOR_INDEX8_EXT &&
|
|
tex->paletteSize != 256))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
pGenTex = tex->pvUser;
|
|
|
|
// Check and see whether the cached information can be reused
|
|
// for the texture passed in
|
|
if (pGenTex != NULL)
|
|
{
|
|
// gc's don't match so this must be a shared texture
|
|
// Don't attempt to create a replace map for this gc
|
|
if (gc != pGenTex->gc)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
// Size and format must match to reuse the existing data area
|
|
// If they don't, release the existing buffer. A new one
|
|
// will then be allocated
|
|
if (internalFormat == GL_COLOR_INDEX8_EXT)
|
|
{
|
|
// All index8 textures have the same amount of replace data
|
|
// so the texture size is irrelevant
|
|
if (pGenTex->internalFormat != internalFormat)
|
|
{
|
|
(*gc->imports.free)(gc, pGenTex);
|
|
tex->pvUser = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pGenTex->internalFormat != internalFormat ||
|
|
pGenTex->width != tex->level[0].width ||
|
|
pGenTex->height != tex->level[0].height)
|
|
{
|
|
(*gc->imports.free)(gc, pGenTex);
|
|
tex->pvUser = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (tex->pvUser == NULL)
|
|
{
|
|
if (internalFormat == GL_COLOR_INDEX8_EXT)
|
|
{
|
|
size = 256 * sizeof(DWORD);
|
|
}
|
|
else
|
|
{
|
|
size = tex->level[0].width * tex->level[0].height *
|
|
GENACCEL(gc).xMultiplier;
|
|
}
|
|
|
|
pGenTex = (GENTEXCACHE *)(*gc->imports.malloc)
|
|
(gc, size + sizeof(GENTEXCACHE));
|
|
|
|
if (pGenTex != NULL)
|
|
{
|
|
tex->pvUser = pGenTex;
|
|
pGenTex->gc = gc;
|
|
pGenTex->paletteTimeStamp =
|
|
((__GLGENcontext *)gc)->PaletteTimestamp;
|
|
pGenTex->height = tex->level[0].height;
|
|
pGenTex->width = tex->level[0].width;
|
|
pGenTex->internalFormat = internalFormat;
|
|
pGenTex->texImageReplace = (UCHAR *)(pGenTex+1);
|
|
}
|
|
}
|
|
|
|
return pGenTex;
|
|
}
|
|
|
|
BOOL FASTCALL __fastGenLoadTexImage(__GLcontext *gc, __GLtexture *tex)
|
|
{
|
|
UCHAR *texBuffer;
|
|
GLint internalFormat = tex->level[0].internalFormat;
|
|
GENTEXCACHE *pGenTex;
|
|
|
|
ASSERTOPENGL(tex->level[0].buffer != NULL,
|
|
"__fastGenLoadTexImage: null texture data\n");
|
|
|
|
if ((internalFormat != GL_BGR_EXT) &&
|
|
(internalFormat != GL_BGRA_EXT) &&
|
|
(internalFormat != GL_COLOR_INDEX8_EXT))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// OK, the texture doesn't have a compressed replace-mode format, so
|
|
// make one...
|
|
|
|
if ((internalFormat == GL_BGR_EXT) ||
|
|
(internalFormat == GL_BGRA_EXT)) {
|
|
|
|
ULONG size;
|
|
UCHAR *replaceBuffer;
|
|
ULONG bytesPerPixel = GENACCEL(gc).xMultiplier;
|
|
|
|
pGenTex = GetGenTexCache(gc, tex);
|
|
if (pGenTex == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
texBuffer = (UCHAR *)tex->level[0].buffer;
|
|
replaceBuffer = pGenTex->texImageReplace;
|
|
|
|
{
|
|
__GLcolorBuffer *cfb = gc->drawBuffer;
|
|
ULONG rShift = cfb->redShift;
|
|
ULONG gShift = cfb->greenShift;
|
|
ULONG bShift = cfb->blueShift;
|
|
ULONG rBits = ((__GLGENcontext *)gc)->CurrentFormat.cRedBits;
|
|
ULONG gBits = ((__GLGENcontext *)gc)->CurrentFormat.cGreenBits;
|
|
ULONG bBits = ((__GLGENcontext *)gc)->CurrentFormat.cBlueBits;
|
|
BYTE *pXlat = ((__GLGENcontext *)gc)->pajTranslateVector;
|
|
ULONG i;
|
|
|
|
size = tex->level[0].width * tex->level[0].height;
|
|
for (i = 0; i < size; i++, texBuffer += 4) {
|
|
ULONG color;
|
|
|
|
color = ((((ULONG)texBuffer[2] << rBits) >> 8) << rShift) |
|
|
((((ULONG)texBuffer[1] << gBits) >> 8) << gShift) |
|
|
((((ULONG)texBuffer[0] << bBits) >> 8) << bShift);
|
|
|
|
if (GENACCEL(gc).bpp == 8)
|
|
*replaceBuffer = pXlat[color & 0xff];
|
|
else
|
|
*((USHORT *)replaceBuffer) = (USHORT)color;
|
|
|
|
replaceBuffer += bytesPerPixel;
|
|
}
|
|
}
|
|
} else {
|
|
|
|
ULONG size = 256;
|
|
ULONG *replaceBuffer;
|
|
|
|
// If we don't have palette data yet we can't create the
|
|
// fast version. It will be created when the ColorTable
|
|
// call happens
|
|
if (tex->paletteData == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pGenTex = GetGenTexCache(gc, tex);
|
|
if (pGenTex == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
texBuffer = (UCHAR *)tex->paletteData;
|
|
replaceBuffer = (ULONG *)pGenTex->texImageReplace;
|
|
|
|
{
|
|
__GLcolorBuffer *cfb = gc->drawBuffer;
|
|
ULONG rShift = cfb->redShift;
|
|
ULONG gShift = cfb->greenShift;
|
|
ULONG bShift = cfb->blueShift;
|
|
ULONG rBits = ((__GLGENcontext *)gc)->CurrentFormat.cRedBits;
|
|
ULONG gBits = ((__GLGENcontext *)gc)->CurrentFormat.cGreenBits;
|
|
ULONG bBits = ((__GLGENcontext *)gc)->CurrentFormat.cBlueBits;
|
|
BYTE *pXlat = ((__GLGENcontext *)gc)->pajTranslateVector;
|
|
ULONG i;
|
|
|
|
for (i = 0; i < size; i++, texBuffer += 4) {
|
|
ULONG color;
|
|
|
|
color = ((((ULONG)texBuffer[2] << rBits) >> 8) << rShift) |
|
|
((((ULONG)texBuffer[1] << gBits) >> 8) << gShift) |
|
|
((((ULONG)texBuffer[0] << bBits) >> 8) << bShift);
|
|
|
|
if (GENACCEL(gc).bpp == 8)
|
|
color = pXlat[color & 0xff];
|
|
|
|
*replaceBuffer++ = (color | ((ULONG)texBuffer[3] << 24));
|
|
}
|
|
}
|
|
}
|
|
|
|
GENACCEL(gc).texImageReplace =
|
|
((GENTEXCACHE *)tex->pvUser)->texImageReplace;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
** Pick the fastest triangle rendering implementation available based on
|
|
** the current mode set. Use any available accelerated resources if
|
|
** available, or use the generic routines for unsupported modes.
|
|
*/
|
|
|
|
void FASTCALL __fastGenCalcDeltas(__GLcontext *gc, __GLvertex *a, __GLvertex *b, __GLvertex *c);
|
|
void FASTCALL __fastGenCalcDeltasTexRGBA(__GLcontext *gc, __GLvertex *a, __GLvertex *b, __GLvertex *c);
|
|
void FASTCALL __fastGenDrvCalcDeltas(__GLcontext *gc, __GLvertex *a, __GLvertex *b, __GLvertex *c);
|
|
|
|
void __fastGenSetInitialParameters(__GLcontext *gc, const __GLvertex *a,
|
|
__GLfloat dx, __GLfloat dy);
|
|
void __fastGenSetInitialParametersTexRGBA(__GLcontext *gc, const __GLvertex *a,
|
|
__GLfloat dx, __GLfloat dy);
|
|
|
|
#if DEAD_3DDDI
|
|
|
|
void GenDrvUpdateClip(__GLcontext *gc)
|
|
{
|
|
__GLGENcontext *genGc = (__GLGENcontext *)gc;
|
|
GENDRVACCEL *pDrvAccel = ((__GLGENcontext *)gc)->pDrvAccel;
|
|
RXEXECUTE rxExecute;
|
|
|
|
if (!pDrvAccel)
|
|
return;
|
|
|
|
// Set scissor rectangle if needed
|
|
|
|
if (!gc->transform.reasonableViewport){
|
|
RXRECT rxRect;
|
|
ULONG state = TRUE;
|
|
|
|
rxExecute.hrxRC = pDrvAccel->rxExecute.hrxRC;
|
|
rxExecute.hdc = pDrvAccel->rxExecute.hdc;
|
|
|
|
rxRect.x = gc->transform.clipX0 - gc->constants.viewportXAdjust;
|
|
rxRect.y = gc->transform.clipY0 - gc->constants.viewportYAdjust;
|
|
rxRect.width = gc->transform.clipX1 - gc->transform.clipX0;
|
|
rxRect.height = gc->transform.clipY1 - gc->transform.clipY0;
|
|
|
|
RxSetContextState(&pDrvAccel->rxExecute, RXSTATE_SCISSORS_RECT,
|
|
(VOID *)&rxRect);
|
|
RxSetContextState(&pDrvAccel->rxExecute, RXSTATE_SCISSORS_ENABLE,
|
|
(VOID *)&state);
|
|
|
|
pDrvAccel->drvModeFlags |= __GL_SCISSOR_TEST_ENABLE;
|
|
} else {
|
|
ULONG state = FALSE;
|
|
|
|
if (pDrvAccel->drvModeFlags & __GL_SCISSOR_TEST_ENABLE) {
|
|
RxSetContextState(&pDrvAccel->rxExecute, RXSTATE_SCISSORS_ENABLE,
|
|
(VOID *)&state);
|
|
pDrvAccel->drvModeFlags &= ~((ULONG)__GL_SCISSOR_TEST_ENABLE);
|
|
}
|
|
}
|
|
}
|
|
|
|
void GenDrvUpdateState(__GLcontext *gc, BOOL bForce)
|
|
{
|
|
__GLGENcontext *genGc = (__GLGENcontext *)gc;
|
|
__GLcolorBuffer *cfb = gc->drawBuffer;
|
|
GENDRVACCEL *pDrvAccel = ((__GLGENcontext *)gc)->pDrvAccel;
|
|
RXCAPS *pCaps;
|
|
BOOL bZenabled;
|
|
GLuint modeFlags = gc->polygon.shader.modeFlags;
|
|
ULONG drvModeFlags;
|
|
ULONG u;
|
|
|
|
if (!pDrvAccel || pDrvAccel->hrxRC == NULL)
|
|
return;
|
|
|
|
drvModeFlags = pDrvAccel->drvModeFlags;
|
|
|
|
// Return if we're not using any 3D DDI high-level functionality.
|
|
// Make sure to at least set the active buffer(s).
|
|
|
|
if (!pDrvAccel->bDrvFill && !pDrvAccel->bDrvLine) {
|
|
SET_DRV_STATE(RXSTATE_ACTIVE_BUFFER,
|
|
((cfb == genGc->gc.front) ? RX_FRONT_LEFT : RX_BACK_LEFT));
|
|
return;
|
|
}
|
|
|
|
// Unless we are forcing an update, return if we are rendering with
|
|
// the same context.
|
|
|
|
if (!bForce) {
|
|
if (pDrvAccel->lastGc == gc)
|
|
return;
|
|
}
|
|
|
|
pCaps = &pDrvAccel->rxGenCaps;
|
|
|
|
// If we get here, we know that we can support the following states
|
|
// which are set in modeFlags:
|
|
//
|
|
// __GL_SHADE_SMOOTH
|
|
// __GL_SHADE_TEXTURE
|
|
// __GL_SHADE_STIPPLE
|
|
// __GL_SHADE_BLEND
|
|
// __GL_SHADE_LOGICOP
|
|
// __GL_SHADE_ALPHA_TEST
|
|
// __GL_SHADE_LINE_STIPPLE
|
|
//
|
|
// We keep a copy of the current gc modeFlags as reflected in the
|
|
// driver state. This is used to minimize the number of states
|
|
// that have to be set/reset in attentions between different
|
|
// OGL rendering contexts. This could be made more fine-grain,
|
|
// as opposed to the current implementation which only checks
|
|
// gross enable states.
|
|
|
|
GenDrvFlush(genGc);
|
|
|
|
BATCHED_DRV_STATE(RXSTATE_ACTIVE_BUFFER,
|
|
((cfb == genGc->gc.front) ? RX_FRONT_LEFT : RX_BACK_LEFT));
|
|
|
|
// Set smooth/flat shading
|
|
|
|
if (modeFlags & __GL_SHADE_SMOOTH) {
|
|
if (!(drvModeFlags & __GL_SHADE_SMOOTH)) {
|
|
BATCHED_DRV_STATE(RXSTATE_SHADE_MODE, RXSHADE_SMOOTH);
|
|
drvModeFlags |= __GL_SHADE_SMOOTH;
|
|
}
|
|
} else {
|
|
if (drvModeFlags & __GL_SHADE_SMOOTH) {
|
|
BATCHED_DRV_STATE(RXSTATE_SHADE_MODE, RXSHADE_FLAT);
|
|
drvModeFlags &= ~((ULONG)__GL_SHADE_SMOOTH);
|
|
}
|
|
}
|
|
|
|
// If we're drawing integer lines, set the solid color:
|
|
|
|
if (gc->procs.renderLine == GenDrvIntLine) {
|
|
DRV_STATE_STRUCT(RXSTATE_SOLID_COLOR, pDrvAccel->rxSolidColor,
|
|
sizeof(RXCOLOR));
|
|
}
|
|
|
|
// Set ROP.
|
|
|
|
if (modeFlags & __GL_SHADE_LOGICOP) {
|
|
if (!(drvModeFlags & __GL_SHADE_LOGICOP)) {
|
|
BATCHED_DRV_STATE(RXSTATE_ROP2,
|
|
__GLtoGDIRop[(gc->state.raster.logicOp & 0xf)]);
|
|
drvModeFlags |= __GL_SHADE_LOGICOP;
|
|
}
|
|
} else {
|
|
if (drvModeFlags & __GL_SHADE_LOGICOP) {
|
|
BATCHED_DRV_STATE(RXSTATE_ROP2,
|
|
__GLtoGDIRop[(gc->state.raster.logicOp & 0xf)]);
|
|
drvModeFlags &= ~((ULONG)__GL_SHADE_LOGICOP);
|
|
}
|
|
}
|
|
|
|
// Set dithering
|
|
|
|
if (pCaps->rasterCaps & RXCAPS_RASTER_DITHER) {
|
|
if (modeFlags & __GL_SHADE_DITHER) {
|
|
if (!(drvModeFlags & __GL_SHADE_DITHER)) {
|
|
BATCHED_DRV_STATE(RXSTATE_DITHER_ENABLE, TRUE);
|
|
drvModeFlags |= __GL_SHADE_DITHER;
|
|
}
|
|
} else {
|
|
if (drvModeFlags & __GL_SHADE_DITHER) {
|
|
BATCHED_DRV_STATE(RXSTATE_DITHER_ENABLE, FALSE);
|
|
drvModeFlags &= ~((ULONG)__GL_SHADE_DITHER);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set z-buffer function. Do this ONLY if we have a hardware z-buffer.
|
|
|
|
if (pCaps->zCmpCaps && pDrvAccel->pShMemZ) {
|
|
|
|
if (modeFlags & __GL_SHADE_DEPTH_TEST) {
|
|
BATCHED_DRV_STATE(RXSTATE_Z_FUNC, (1 << (gc->state.depth.testFunc & 0x7)));
|
|
BATCHED_DRV_STATE(RXSTATE_Z_ENABLE, TRUE);
|
|
BATCHED_DRV_STATE(RXSTATE_Z_WRITE_ENABLE, TRUE);
|
|
drvModeFlags |= __GL_SHADE_DEPTH_TEST;
|
|
} else {
|
|
if (drvModeFlags & __GL_SHADE_DEPTH_TEST) {
|
|
BATCHED_DRV_STATE(RXSTATE_Z_ENABLE, FALSE);
|
|
drvModeFlags &= ~((ULONG)__GL_SHADE_DEPTH_TEST);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set texturing mode
|
|
|
|
if (pCaps->texFilterCaps) {
|
|
if (modeFlags & __GL_SHADE_TEXTURE) {
|
|
ULONG texMode;
|
|
|
|
if (gc->state.texture.env[0].mode == GL_DECAL)
|
|
texMode = RXTEX_DECAL;
|
|
else
|
|
texMode = (ULONG)RXTEX_MODULATE;
|
|
|
|
BATCHED_DRV_STATE(RXSTATE_TEX_MAP_BLEND, texMode);
|
|
|
|
BATCHED_DRV_STATE(RXSTATE_TEX_MAG, RXFILTER_NEAREST);
|
|
|
|
BATCHED_DRV_STATE(RXSTATE_TEX_MIN, RXFILTER_NEAREST);
|
|
|
|
if (genGc->hrxTexture)
|
|
BATCHED_DRV_STATE(RXSTATE_PRIM_FILL,
|
|
(ULONG)(((ULONG)genGc->hrxTexture << 16) | RXFILL_TEXTURE));
|
|
|
|
drvModeFlags |= __GL_SHADE_TEXTURE;
|
|
} else {
|
|
if (drvModeFlags & __GL_SHADE_TEXTURE) {
|
|
BATCHED_DRV_STATE(RXSTATE_PRIM_FILL, (ULONG)RXFILL_TEXTURE);
|
|
drvModeFlags &= ~((ULONG)__GL_SHADE_TEXTURE);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set span type
|
|
|
|
if (pDrvAccel->bScan) {
|
|
pDrvAccel->spanStride = sizeof(RXSPAN);
|
|
if (gc->polygon.shader.modeFlags & __GL_SHADE_TEXTURE) {
|
|
pDrvAccel->spanStride += sizeof(RXZTEX);
|
|
u = (ULONG)RXSPAN_TYPE_COLOR_Z_TEX;
|
|
} else {
|
|
u = (ULONG)RXSPAN_TYPE_COLOR;
|
|
}
|
|
|
|
BATCHED_DRV_STATE(RXSTATE_SPAN_TYPE, u);
|
|
}
|
|
|
|
if (pCaps->srcBlendCaps && pCaps->dstBlendCaps) {
|
|
if (modeFlags & __GL_SHADE_BLEND) {
|
|
|
|
GLenum s = gc->state.raster.blendSrc;
|
|
GLenum d = gc->state.raster.blendDst;
|
|
|
|
if (s > GL_ONE)
|
|
s = (s & 0xf) + 2;
|
|
if (d > GL_ONE)
|
|
d = (d & 0xf) + 2;
|
|
|
|
BATCHED_DRV_STATE(RXSTATE_SRC_BLEND, 1 << s);
|
|
BATCHED_DRV_STATE(RXSTATE_DST_BLEND, 1 << d);
|
|
BATCHED_DRV_STATE(RXSTATE_BLEND_ENABLE, TRUE);
|
|
drvModeFlags |= __GL_SHADE_BLEND;
|
|
} else {
|
|
if (drvModeFlags & __GL_SHADE_BLEND) {
|
|
BATCHED_DRV_STATE(RXSTATE_BLEND_ENABLE, FALSE);
|
|
drvModeFlags &= ~((ULONG)__GL_SHADE_BLEND);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pCaps->alphaCmpCaps) {
|
|
if (modeFlags & __GL_SHADE_ALPHA_TEST) {
|
|
BATCHED_DRV_STATE(RXSTATE_ALPHA_FUNC, (1 << (gc->state.raster.alphaFunction & 0x7)));
|
|
BATCHED_DRV_STATE(RXSTATE_ALPHA_REF, (ULONG)(gc->state.raster.alphaReference * ACCEL_COLOR_SCALE_FIX));
|
|
BATCHED_DRV_STATE(RXSTATE_ALPHA_TEST_ENABLE, TRUE);
|
|
drvModeFlags |= __GL_SHADE_BLEND;
|
|
} else {
|
|
if (drvModeFlags & __GL_SHADE_ALPHA_TEST) {
|
|
BATCHED_DRV_STATE(RXSTATE_ALPHA_TEST_ENABLE, FALSE);
|
|
drvModeFlags &= ~((ULONG)__GL_SHADE_ALPHA_TEST);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set stipple pattern
|
|
|
|
if (pDrvAccel->rxTriCaps.rasterCaps & RXCAPS_RASTER_PAT) {
|
|
RXSTIPPLE rxStipple;
|
|
|
|
if (modeFlags & __GL_SHADE_STIPPLE) {
|
|
DRV_STATE_STRUCT(RXSTATE_STIPPLE_PATTERN, gc->polygon.stipple[0],
|
|
sizeof(RXSTIPPLE));
|
|
drvModeFlags |= __GL_SHADE_STIPPLE;
|
|
} else {
|
|
if (drvModeFlags & __GL_SHADE_STIPPLE) {
|
|
RtlFillMemoryUlong(rxStipple.stipple, 32 * sizeof(ULONG),
|
|
(ULONG)-1);
|
|
DRV_STATE_STRUCT(RXSTATE_STIPPLE_PATTERN, rxStipple.stipple[0],
|
|
sizeof(RXSTIPPLE));
|
|
drvModeFlags &= ~((ULONG)__GL_SHADE_STIPPLE);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set line pattern
|
|
|
|
if ((pDrvAccel->rxLineCaps.rasterCaps & RXCAPS_RASTER_PAT) ||
|
|
(pDrvAccel->rxIntLineCaps.rasterCaps & RXCAPS_RASTER_PAT)) {
|
|
RXLINEPAT rxLinePat;
|
|
|
|
if (modeFlags & __GL_SHADE_LINE_STIPPLE) {
|
|
ULONG maskIn, maskOut, i;
|
|
ULONG stipple = gc->state.line.stipple;
|
|
|
|
rxLinePat.linePattern = 0;
|
|
|
|
maskIn = 0x1;
|
|
maskOut = 0x8000;
|
|
for (i = 0; i < 16; i++) {
|
|
if (stipple & maskIn)
|
|
rxLinePat.linePattern |= maskOut;
|
|
maskIn <<= 1;
|
|
maskOut >>= 1;
|
|
}
|
|
|
|
rxLinePat.repFactor = gc->state.line.stippleRepeat;
|
|
DRV_STATE_STRUCT(RXSTATE_LINE_PATTERN, rxLinePat,
|
|
sizeof(RXLINEPAT));
|
|
drvModeFlags |= __GL_SHADE_LINE_STIPPLE;
|
|
} else {
|
|
if (drvModeFlags & __GL_SHADE_LINE_STIPPLE) {
|
|
rxLinePat.repFactor = 1;
|
|
rxLinePat.linePattern = 0xffff;
|
|
DRV_STATE_STRUCT(RXSTATE_LINE_PATTERN, rxLinePat,
|
|
sizeof(RXLINEPAT));
|
|
drvModeFlags &= ~((ULONG)__GL_SHADE_LINE_STIPPLE);
|
|
}
|
|
}
|
|
GenDrvFlush(genGc);
|
|
}
|
|
|
|
// Set scissor rectangle if needed
|
|
|
|
if (!gc->transform.reasonableViewport){
|
|
RXRECT rect;
|
|
|
|
rect.x = gc->transform.clipX0 - gc->constants.viewportXAdjust;
|
|
rect.y = gc->transform.clipY0 - gc->constants.viewportYAdjust;
|
|
rect.width = gc->transform.clipX1 - gc->transform.clipX0;
|
|
rect.height = gc->transform.clipY1 - gc->transform.clipY0;
|
|
|
|
DRV_STATE_STRUCT(RXSTATE_SCISSORS_RECT, rect, sizeof(RXRECT));
|
|
BATCHED_DRV_STATE(RXSTATE_SCISSORS_ENABLE, TRUE);
|
|
drvModeFlags |= __GL_SCISSOR_TEST_ENABLE;
|
|
} else {
|
|
if (drvModeFlags & __GL_SCISSOR_TEST_ENABLE) {
|
|
BATCHED_DRV_STATE(RXSTATE_SCISSORS_ENABLE, FALSE);
|
|
drvModeFlags &= ~((ULONG)__GL_SCISSOR_TEST_ENABLE);
|
|
}
|
|
}
|
|
|
|
// Flush out any state commands in buffer
|
|
|
|
GenDrvFlush(genGc);
|
|
|
|
pDrvAccel->drvModeFlags = drvModeFlags;
|
|
|
|
pDrvAccel->lastGc = gc;
|
|
}
|
|
|
|
void FASTCALL GenDrvLine(__GLcontext *gc, __GLvertex *a, __GLvertex *b,
|
|
GLuint flags)
|
|
{
|
|
__GLGENcontext *gengc = (__GLGENcontext *)gc;
|
|
GENDRVACCEL *pDrvAccel = ((__GLGENcontext *)gc)->pDrvAccel;
|
|
GLuint modeFlags = gc->polygon.shader.modeFlags;
|
|
RXVERTEX *pv1, *pv2;
|
|
RXCMD *prxCmd;
|
|
RXLINES *prxLines;
|
|
|
|
CHOP_ROUND_ON();
|
|
|
|
if ((pDrvAccel->pCmd + sizeof(RXCMD) + (2 * sizeof(RXLINES)) >
|
|
pDrvAccel->pStartVertex) ||
|
|
(pDrvAccel->pVertex + (2 * sizeof(RXVERTEX)) >
|
|
pDrvAccel->pEndVertex)) {
|
|
GenDrvFlush(gengc);
|
|
}
|
|
|
|
if (pDrvAccel->pCmd == pDrvAccel->pStartCmd)
|
|
gc->line.notResetStipple = FALSE;
|
|
|
|
if (!(a->has & __GL_HAS_FIXEDPT)) {
|
|
gc->line.notResetStipple = FALSE;
|
|
a->has |= __GL_HAS_FIXEDPT;
|
|
}
|
|
|
|
b->has |= __GL_HAS_FIXEDPT;
|
|
|
|
if (gc->line.notResetStipple == FALSE) {
|
|
|
|
gc->line.notResetStipple = TRUE;
|
|
|
|
pDrvAccel->prxCmdBase = prxCmd = (RXCMD *)(pDrvAccel->pCmd);
|
|
prxCmd->command = RXCMD_LINE;
|
|
prxCmd->count = 2;
|
|
prxCmd->size = 2 * sizeof(RXLINES);
|
|
pDrvAccel->pCmd = (char *)(prxCmd + 1);
|
|
|
|
((RXLINES *)pDrvAccel->pCmd)->v[0] = pDrvAccel->vIndex++;
|
|
((RXLINES *)pDrvAccel->pCmd)->v[1] = pDrvAccel->vIndex++;
|
|
pDrvAccel->pCmd += (2 * sizeof(RXLINES));
|
|
|
|
pv1 = (RXVERTEX *)(pDrvAccel->pVertex);
|
|
pv2 = (pv1 + 1);
|
|
pDrvAccel->pVertex = (BYTE *)(pv2 + 1);
|
|
|
|
if (modeFlags & __GL_SHADE_RGB) {
|
|
if (modeFlags & __GL_SHADE_SMOOTH) {
|
|
FLT_TO_RGBA(pv1->color, a->color);
|
|
}
|
|
FLT_TO_RGBA(pv2->color, b->color);
|
|
} else {
|
|
if (modeFlags & __GL_SHADE_SMOOTH) {
|
|
FLT_TO_CINDEX(pv1->color, a->color);
|
|
}
|
|
FLT_TO_CINDEX(pv2->color, b->color);
|
|
}
|
|
|
|
pv1->x = FLT_TO_FIX(a->window.x - gc->constants.viewportXAdjust);
|
|
|
|
pv1->y = FLT_TO_FIX(a->window.y - gc->constants.viewportYAdjust);
|
|
|
|
pv2->x = FLT_TO_FIX(b->window.x - gc->constants.viewportXAdjust);
|
|
|
|
pv2->y = FLT_TO_FIX(b->window.y - gc->constants.viewportYAdjust);
|
|
|
|
if (modeFlags & __GL_SHADE_DEPTH_ITER) {
|
|
pv1->z = (ULONG)a->window.z;
|
|
pv2->z = (ULONG)b->window.z;
|
|
}
|
|
} else {
|
|
|
|
// One more vertex to draw
|
|
|
|
pDrvAccel->prxCmdBase->count++;
|
|
((RXLINES *)pDrvAccel->pCmd)->v[0] = pDrvAccel->vIndex++;
|
|
pDrvAccel->pCmd += sizeof(RXLINES);
|
|
|
|
pv2 = (RXVERTEX *)pDrvAccel->pVertex;
|
|
pDrvAccel->pVertex = (BYTE *)(pv2 + 1);
|
|
|
|
if (modeFlags & __GL_SHADE_RGB) {
|
|
FLT_TO_RGBA(pv2->color, b->color);
|
|
} else {
|
|
FLT_TO_CINDEX(pv2->color, b->color);
|
|
}
|
|
|
|
pv2->x = FLT_TO_FIX(b->window.x - gc->constants.viewportXAdjust);
|
|
|
|
pv2->y = FLT_TO_FIX(b->window.y - gc->constants.viewportYAdjust);
|
|
|
|
if (modeFlags & __GL_SHADE_DEPTH_ITER)
|
|
pv2->z = (ULONG)b->window.z;
|
|
}
|
|
|
|
CHOP_ROUND_OFF();
|
|
}
|
|
|
|
|
|
void FASTCALL GenDrvIntLine(__GLcontext *gc, __GLvertex *a, __GLvertex *b,
|
|
GLuint flags)
|
|
{
|
|
__GLGENcontext *gengc = (__GLGENcontext *)gc;
|
|
GENDRVACCEL *pDrvAccel = ((__GLGENcontext *)gc)->pDrvAccel;
|
|
RXPOINTINT *pv1, *pv2;
|
|
RXCMD *prxCmd;
|
|
|
|
CHOP_ROUND_ON();
|
|
|
|
if ((pDrvAccel->pCmd + (2 * sizeof(RXCMD)) + (2 * sizeof(RXLINES)) +
|
|
sizeof(RXCOLOR) >
|
|
pDrvAccel->pStartVertex) ||
|
|
(pDrvAccel->pVertex + (2 * sizeof(RXPOINTINT)) >
|
|
pDrvAccel->pEndVertex)) {
|
|
GenDrvFlush(gengc);
|
|
}
|
|
|
|
if (pDrvAccel->pCmd == pDrvAccel->pStartCmd)
|
|
gc->line.notResetStipple = FALSE;
|
|
|
|
if (!(a->has & __GL_HAS_FIXEDPT)) {
|
|
gc->line.notResetStipple = FALSE;
|
|
a->has |= __GL_HAS_FIXEDPT;
|
|
}
|
|
|
|
b->has |= __GL_HAS_FIXEDPT;
|
|
|
|
if (gc->line.notResetStipple == FALSE) {
|
|
|
|
gc->line.notResetStipple = TRUE;
|
|
|
|
// Check if we are starting a line with a new color:
|
|
|
|
if (memcmp(&pDrvAccel->solidColor, b->color, sizeof(__GLcolor))) {
|
|
RXSETSTATE *prxSetState;
|
|
|
|
prxCmd = (RXCMD *)(pDrvAccel->pCmd);
|
|
prxCmd->command = RXCMD_SET_STATE;
|
|
prxCmd->size = sizeof(RXSETSTATE);
|
|
prxCmd->count = 1;
|
|
|
|
prxSetState = (RXSETSTATE *)(prxCmd + 1);
|
|
|
|
prxSetState->stateToChange = RXSTATE_SOLID_COLOR;
|
|
|
|
if (gc->polygon.shader.modeFlags & __GL_SHADE_RGB) {
|
|
FLT_TO_RGBA(prxSetState->newState[0], b->color);
|
|
} else {
|
|
FLT_TO_CINDEX(prxSetState->newState[0], b->color);
|
|
}
|
|
|
|
// Save color info:
|
|
|
|
RtlCopyMemory(&pDrvAccel->solidColor, b->color,
|
|
sizeof(__GLcolor));
|
|
pDrvAccel->rxSolidColor = (RXCOLOR)prxSetState->newState[0];
|
|
|
|
pDrvAccel->pCmd += sizeof(RXSETSTATE);
|
|
}
|
|
|
|
pDrvAccel->prxCmdBase = prxCmd = (RXCMD *)(pDrvAccel->pCmd);
|
|
prxCmd->command = RXCMD_INTLINE;
|
|
prxCmd->size = sizeof(RXLINES);
|
|
prxCmd->count = 2;
|
|
pDrvAccel->pCmd = (char *)(prxCmd + 1);
|
|
|
|
((RXLINES *)pDrvAccel->pCmd)->v[0] = pDrvAccel->vIndex++;
|
|
((RXLINES *)pDrvAccel->pCmd)->v[1] = pDrvAccel->vIndex++;
|
|
pDrvAccel->pCmd += (2 * sizeof(RXLINES));
|
|
|
|
pv1 = (RXPOINTINT *)(pDrvAccel->pVertex);
|
|
pv2 = (RXPOINTINT *)((BYTE *)pv1 + sizeof(RXVERTEX));
|
|
pDrvAccel->pVertex = (BYTE *)pv2 + sizeof(RXVERTEX);
|
|
|
|
pv1->x = FTOL(a->window.x - gc->constants.viewportXAdjust);
|
|
pv1->y = FTOL(a->window.y - gc->constants.viewportYAdjust);
|
|
pv2->x = FTOL(b->window.x - gc->constants.viewportXAdjust);
|
|
pv2->y = FTOL(b->window.y - gc->constants.viewportYAdjust);
|
|
|
|
} else {
|
|
|
|
// One more vertex to draw
|
|
|
|
pDrvAccel->prxCmdBase->count++;
|
|
((RXLINES *)pDrvAccel->pCmd)->v[0] = pDrvAccel->vIndex++;
|
|
|
|
pv2 = (RXPOINTINT *)pDrvAccel->pVertex;
|
|
pDrvAccel->pVertex = (BYTE *)pv2 + sizeof(RXVERTEX);
|
|
|
|
pv2->x = FTOL(b->window.x - gc->constants.viewportXAdjust);
|
|
pv2->y = FTOL(b->window.y - gc->constants.viewportYAdjust);
|
|
}
|
|
|
|
CHOP_ROUND_OFF();
|
|
}
|
|
|
|
BOOL FASTCALL bGenDrvRxLines(__GLcontext *gc)
|
|
{
|
|
GLuint modeFlags = gc->polygon.shader.modeFlags;
|
|
GLuint enables = gc->state.enables.general;
|
|
__GLGENcontext *genGc = (__GLGENcontext *)gc;
|
|
__GLcolorBuffer *cfb = gc->drawBuffer;
|
|
GENDRVACCEL *pDrvAccel = ((__GLGENcontext *)gc)->pDrvAccel;
|
|
RXCAPS *pCaps;
|
|
BOOL bZenabled;
|
|
|
|
if (!pDrvAccel)
|
|
return FALSE;
|
|
|
|
pDrvAccel->bDrvLine = FALSE; // assume no 3D DDI acceleration
|
|
|
|
//XXX No wide lines for now.
|
|
|
|
if (gc->state.line.aliasedWidth > 1)
|
|
return FALSE;
|
|
|
|
if (pDrvAccel->bIntLine) {
|
|
GLuint intModeFlags = modeFlags;
|
|
|
|
// Force a reset of the solid color
|
|
|
|
pDrvAccel->solidColor.r = (__GLfloat)-1.0;
|
|
pDrvAccel->solidColor.g = (__GLfloat)-1.0;
|
|
pDrvAccel->solidColor.b = (__GLfloat)-1.0;
|
|
pDrvAccel->solidColor.a = (__GLfloat)-1.0;
|
|
|
|
if (intModeFlags & __GL_SHADE_LINE_STIPPLE) {
|
|
if (pDrvAccel->rxIntLineCaps.rasterCaps & RXCAPS_RASTER_PAT) {
|
|
if (gc->state.line.stippleRepeat > 1) {
|
|
if (pDrvAccel->rxIntLineCaps.miscCaps & RXCAPS_LINE_PATTERN_REP)
|
|
intModeFlags &= (~__GL_SHADE_LINE_STIPPLE);
|
|
} else
|
|
intModeFlags &= (~__GL_SHADE_LINE_STIPPLE);
|
|
}
|
|
}
|
|
|
|
if (!(intModeFlags & (__GL_SHADE_LINE_STIPPLE |
|
|
__GL_SHADE_STENCIL_TEST |
|
|
__GL_SHADE_LOGICOP | __GL_SHADE_BLEND |
|
|
__GL_SHADE_ALPHA_TEST |
|
|
__GL_SHADE_SLOW_FOG | __GL_SHADE_SMOOTH |
|
|
__GL_SHADE_TEXTURE | __GL_SHADE_DEPTH_TEST)) &&
|
|
!(gc->state.raster.drawBuffer == GL_FRONT_AND_BACK) &&
|
|
!((GLuint)gc->drawBuffer->buf.other & COLORMASK_ON) &&
|
|
(genGc->CurrentFormat.cColorBits >= 8)) {
|
|
gc->procs.renderLine = GenDrvIntLine;
|
|
|
|
pDrvAccel->bDrvLine = TRUE;
|
|
|
|
GenDrvUpdateState(gc, TRUE);
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
if (!pDrvAccel->bLine)
|
|
return FALSE;
|
|
|
|
pCaps = &pDrvAccel->rxLineCaps;
|
|
|
|
if (gc->polygon.shader.modeFlags & __GL_SHADE_DEPTH_TEST) {
|
|
if (!((pCaps->zCmpCaps & (1 << (gc->state.depth.testFunc & 0x7))) != 0)) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// Turn off check for modes we can handle
|
|
|
|
if (modeFlags & __GL_SHADE_LOGICOP) {
|
|
if (pCaps->rasterCaps & RXCAPS_RASTER_ROP2)
|
|
modeFlags &= ~(__GL_SHADE_LOGICOP);
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_BLEND) {
|
|
GLenum s = gc->state.raster.blendSrc;
|
|
GLenum d = gc->state.raster.blendDst;
|
|
ULONG src, dst;
|
|
|
|
if (s > GL_ONE)
|
|
s = (s & 0xf) + 2;
|
|
if (d > GL_ONE)
|
|
d = (d & 0xf) + 2;
|
|
|
|
src = (1 << s);
|
|
dst = (1 << d);
|
|
|
|
if ((pCaps->srcBlendCaps & src) &&
|
|
(pCaps->dstBlendCaps & dst))
|
|
modeFlags &= ~(__GL_SHADE_BLEND);
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_ALPHA_TEST) {
|
|
if (pCaps->alphaCmpCaps & (1 << (gc->state.raster.alphaFunction & 0x7)))
|
|
modeFlags &= ~(__GL_SHADE_ALPHA_TEST);
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_LINE_STIPPLE) {
|
|
if (pCaps->rasterCaps & RXCAPS_RASTER_PAT) {
|
|
if (gc->state.line.stippleRepeat > 1) {
|
|
if (pCaps->miscCaps & RXCAPS_LINE_PATTERN_REP)
|
|
modeFlags &= (~__GL_SHADE_LINE_STIPPLE);
|
|
} else
|
|
modeFlags &= (~__GL_SHADE_LINE_STIPPLE);
|
|
}
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_SMOOTH) {
|
|
if (pCaps->shadeCaps & RXCAPS_SHADE_SMOOTH)
|
|
modeFlags &= (~__GL_SHADE_SMOOTH);
|
|
}
|
|
|
|
//XXX fix FRONT_AND_BACK, COLORMASK_ON
|
|
|
|
if (!(modeFlags & (__GL_SHADE_LINE_STIPPLE | __GL_SHADE_STENCIL_TEST |
|
|
__GL_SHADE_LOGICOP | __GL_SHADE_BLEND |
|
|
__GL_SHADE_ALPHA_TEST |
|
|
__GL_SHADE_SLOW_FOG | __GL_SHADE_SMOOTH |
|
|
__GL_SHADE_TEXTURE)) &&
|
|
!(gc->state.raster.drawBuffer == GL_FRONT_AND_BACK) &&
|
|
!((GLuint)gc->drawBuffer->buf.other & COLORMASK_ON) &&
|
|
(genGc->CurrentFormat.cColorBits >= 8)) {
|
|
|
|
gc->procs.renderLine = GenDrvLine;
|
|
|
|
pDrvAccel->bDrvLine = TRUE;
|
|
|
|
GenDrvUpdateState(gc, TRUE);
|
|
|
|
return TRUE;
|
|
} else {
|
|
GenDrvUpdateState(gc, TRUE);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
#if DEAD_3DDDI
|
|
|
|
BOOL FASTCALL bUseRxTriangles(__GLcontext *gc)
|
|
{
|
|
GLuint modeFlags = gc->polygon.shader.modeFlags;
|
|
GLuint enables = gc->state.enables.general;
|
|
__GLGENcontext *genGc = (__GLGENcontext *)gc;
|
|
__GLcolorBuffer *cfb = gc->drawBuffer;
|
|
GENDRVACCEL *pDrvAccel = ((__GLGENcontext *)gc)->pDrvAccel;
|
|
RXCAPS *pCaps;
|
|
BOOL bZenabled;
|
|
BOOL bUseSpan = FALSE;
|
|
|
|
// Set up color scaling for 3D-DDI primitives:
|
|
|
|
GENACCEL(gc).rAccelPrimScale = (GLfloat)255.0 / cfb->redScale;
|
|
GENACCEL(gc).gAccelPrimScale = (GLfloat)255.0 / cfb->greenScale;
|
|
GENACCEL(gc).bAccelPrimScale = (GLfloat)255.0 / cfb->blueScale;
|
|
GENACCEL(gc).aAccelPrimScale = (GLfloat)255.0 / cfb->alphaScale;
|
|
|
|
if (!pDrvAccel)
|
|
return FALSE;
|
|
|
|
pDrvAccel->bDrvFill = FALSE; // assume no 3D DDI acceleration
|
|
|
|
// Select the appropriate capability set to use for our selection.
|
|
// In the case of triangles, revert to using scanlines if z-buffering
|
|
// is unavailable. This could happen in the case where a driver
|
|
// implements 2d triangles/scanlines only, or supports a limited set
|
|
// of depth testing functions.
|
|
|
|
if (pDrvAccel->bTri) {
|
|
pCaps = &pDrvAccel->rxTriCaps;
|
|
if (gc->polygon.shader.modeFlags & __GL_SHADE_DEPTH_TEST) {
|
|
if ((!((pCaps->zCmpCaps & (1 << (gc->state.depth.testFunc & 0x7))) != 0)) ||
|
|
(!pDrvAccel->pShMemZ)) {
|
|
pCaps = &pDrvAccel->rxScanCaps;
|
|
bUseSpan = TRUE;
|
|
}
|
|
}
|
|
} else if (pDrvAccel->bScan) {
|
|
pCaps = &pDrvAccel->rxScanCaps;
|
|
bUseSpan = TRUE;
|
|
} else
|
|
return FALSE;
|
|
|
|
// If we're useing spans, make sure we can do MSB masking since this
|
|
// is what OGL is currently hardwired to use. Also, make sure the
|
|
// hardware actually supports spans
|
|
|
|
if (bUseSpan) {
|
|
if (!(pCaps->miscCaps & RXCAPS_MASK_MSB) ||
|
|
!pDrvAccel->bScan)
|
|
return FALSE;
|
|
}
|
|
|
|
// Turn off check for modes we can handle
|
|
|
|
//XXX Should we special-case dithering for 24bpp boards?
|
|
|
|
if (modeFlags & __GL_SHADE_DITHER) {
|
|
if (pCaps->rasterCaps & RXCAPS_RASTER_DITHER)
|
|
modeFlags &= ~(__GL_SHADE_DITHER);
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_LOGICOP) {
|
|
if (pCaps->rasterCaps & RXCAPS_RASTER_ROP2)
|
|
modeFlags &= ~(__GL_SHADE_LOGICOP);
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_BLEND) {
|
|
GLenum s = gc->state.raster.blendSrc;
|
|
GLenum d = gc->state.raster.blendDst;
|
|
ULONG src, dst;
|
|
|
|
if (s > GL_ONE)
|
|
s = (s & 0xf) + 2;
|
|
if (d > GL_ONE)
|
|
d = (d & 0xf) + 2;
|
|
|
|
src = (1 << s);
|
|
dst = (1 << d);
|
|
|
|
if ((pCaps->srcBlendCaps & src) &&
|
|
(pCaps->dstBlendCaps & dst))
|
|
modeFlags &= ~(__GL_SHADE_BLEND);
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_ALPHA_TEST) {
|
|
if (pCaps->alphaCmpCaps & (1 << (gc->state.raster.alphaFunction & 0x7)))
|
|
modeFlags &= ~(__GL_SHADE_ALPHA_TEST);
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_STIPPLE) {
|
|
if (pCaps->rasterCaps & RXCAPS_RASTER_PAT)
|
|
modeFlags &= (~__GL_SHADE_STIPPLE);
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_SMOOTH) {
|
|
if (pCaps->shadeCaps & RXCAPS_SHADE_SMOOTH)
|
|
modeFlags &= (~__GL_SHADE_SMOOTH);
|
|
}
|
|
|
|
//XXX fix FRONT_AND_BACK, COLORMASK_ON
|
|
|
|
if (!(modeFlags & (__GL_SHADE_STIPPLE | __GL_SHADE_STENCIL_TEST |
|
|
__GL_SHADE_LOGICOP | __GL_SHADE_BLEND |
|
|
__GL_SHADE_ALPHA_TEST |
|
|
__GL_SHADE_SLOW_FOG | __GL_SHADE_SMOOTH)) &&
|
|
!(gc->state.raster.drawBuffer == GL_FRONT_AND_BACK) &&
|
|
!((GLuint)gc->drawBuffer->buf.other & COLORMASK_ON) &&
|
|
(genGc->CurrentFormat.cColorBits >= 8)) {
|
|
|
|
if (modeFlags & __GL_SHADE_TEXTURE) {
|
|
#ifdef DDI_TEXTURES
|
|
if (!(pCaps->texFilterCaps & RX_TEX_NEAREST) ||
|
|
((gc->state.texture.env[0].mode == GL_DECAL) &&
|
|
!(pCaps->texBlendCaps & RX_TEX_DECAL)) ||
|
|
((gc->state.texture.env[0].mode == GL_MODULATE) &&
|
|
!(pCaps->texBlendCaps & RX_TEX_MODULATE)))
|
|
return FALSE;
|
|
|
|
if (!(/**((gc->state.hints.perspectiveCorrection == GL_DONT_CARE) ||
|
|
(gc->state.hints.perspectiveCorrection == GL_FASTEST)) && **/
|
|
((gc->state.texture.env[0].mode == GL_DECAL) ||
|
|
(gc->state.texture.env[0].mode == GL_MODULATE)) &&
|
|
(gc->texture.currentTexture &&
|
|
(gc->texture.currentTexture->params.minFilter == GL_NEAREST) &&
|
|
(gc->texture.currentTexture->params.magFilter == GL_NEAREST) &&
|
|
(gc->texture.currentTexture->params.sWrapMode == GL_REPEAT) &&
|
|
(gc->texture.currentTexture->params.tWrapMode == GL_REPEAT) &&
|
|
(gc->texture.currentTexture->level[0].border == 0) &&
|
|
((gc->texture.currentTexture->level[0].baseFormat == 3) ||
|
|
(gc->texture.currentTexture->level[0].baseFormat == 4)))))
|
|
return FALSE;
|
|
|
|
if (!genGc->hrxTexture) {
|
|
if (!GenDrvLoadTexImage(gc, gc->texture.currentTexture))
|
|
return FALSE;
|
|
}
|
|
#else
|
|
return FALSE;
|
|
#endif
|
|
}
|
|
|
|
|
|
if (pDrvAccel->bTri && !bUseSpan) {
|
|
gc->procs.fillTriangle = GenDrvTriangle;
|
|
} else {
|
|
gc->procs.fillTriangle = __fastGenFillTriangle;
|
|
GENACCEL(gc).__fastCalcDeltaPtr = __fastGenDrvCalcDeltas;
|
|
GENACCEL(gc).__fastFlatSpanFuncPtr = GenDrvSpan;
|
|
GENACCEL(gc).__fastSmoothSpanFuncPtr = GenDrvSpan;
|
|
GENACCEL(gc).__fastSpanFuncPtr = GenDrvSpan;
|
|
GENACCEL(gc).__fastFillSubTrianglePtr = GenDrvFillSubTriangle;
|
|
}
|
|
|
|
// Reset color scaling for spans:
|
|
|
|
GENACCEL(gc).rAccelScale = (GLfloat)(ACCEL_FIX_SCALE) *
|
|
(GLfloat)255.0 / cfb->redScale;
|
|
GENACCEL(gc).gAccelScale = (GLfloat)(ACCEL_FIX_SCALE) *
|
|
(GLfloat)255.0 / cfb->greenScale;
|
|
GENACCEL(gc).bAccelScale = (GLfloat)(ACCEL_FIX_SCALE) *
|
|
(GLfloat)255.0 / cfb->blueScale;
|
|
GENACCEL(gc).aAccelScale = (GLfloat)(ACCEL_FIX_SCALE) *
|
|
(GLfloat)255.0 / cfb->alphaScale;
|
|
|
|
pDrvAccel->bDrvFill = TRUE;
|
|
|
|
GenDrvUpdateState(gc, TRUE);
|
|
|
|
return TRUE;
|
|
} else {
|
|
GenDrvUpdateState(gc, TRUE);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
void __ZippyFT(
|
|
__GLcontext *gc,
|
|
__GLvertex *a,
|
|
__GLvertex *b,
|
|
__GLvertex *c,
|
|
GLboolean ccw);
|
|
|
|
VOID FASTCALL InitAccelTextureValues(__GLcontext *gc, __GLtexture *tex)
|
|
{
|
|
ULONG wLog2;
|
|
ULONG hLog2;
|
|
|
|
GENACCEL(gc).tex = tex;
|
|
GENACCEL(gc).texImage = (ULONG *)tex->level[0].buffer;
|
|
if (tex->level[0].internalFormat == GL_COLOR_INDEX8_EXT ||
|
|
tex->level[0].internalFormat == GL_COLOR_INDEX16_EXT)
|
|
{
|
|
GENACCEL(gc).texPalette = (ULONG *)tex->paletteData;
|
|
}
|
|
else
|
|
{
|
|
GENACCEL(gc).texPalette = NULL;
|
|
}
|
|
|
|
wLog2 = tex->level[0].widthLog2;
|
|
hLog2 = tex->level[0].heightLog2;
|
|
|
|
GENACCEL(gc).sMask = (~(~0 << wLog2)) << TEX_SCALESHIFT;
|
|
GENACCEL(gc).tMask = (~(~0 << hLog2)) << TEX_SCALESHIFT;
|
|
GENACCEL(gc).tShift = TEX_SCALESHIFT - (wLog2 + TEX_SHIFTPER4BPPTEXEL);
|
|
GENACCEL(gc).tMaskSubDiv =
|
|
(~(~0 << hLog2)) << (wLog2 + TEX_T_FRAC_BITS + TEX_SHIFTPER1BPPTEXEL);
|
|
GENACCEL(gc).tShiftSubDiv =
|
|
TEX_SCALESHIFT - (wLog2 + TEX_T_FRAC_BITS + TEX_SHIFTPER1BPPTEXEL);
|
|
GENACCEL(gc).texXScale = (__GLfloat)tex->level[0].width * TEX_SCALEFACT;
|
|
GENACCEL(gc).texYScale = (__GLfloat)tex->level[0].height * TEX_SCALEFACT;
|
|
}
|
|
|
|
BOOL FASTCALL bUseGenTriangles(__GLcontext *gc)
|
|
{
|
|
GLuint modeFlags = gc->polygon.shader.modeFlags;
|
|
GLuint enables = gc->state.enables.general;
|
|
__GLGENcontext *gengc = (__GLGENcontext *)gc;
|
|
ULONG bpp = GENACCEL(gc).bpp;
|
|
int iType;
|
|
BOOL fZippy;
|
|
BOOL bTryFastTexRGBA;
|
|
PFNZIPPYSUB pfnZippySub;
|
|
BOOL fUseFastGenSpan;
|
|
GLboolean bMcdZ;
|
|
ULONG internalFormat;
|
|
ULONG textureMode;
|
|
BOOL bRealTexture;
|
|
|
|
if ((enables & (__GL_ALPHA_TEST_ENABLE |
|
|
__GL_STENCIL_TEST_ENABLE)) ||
|
|
(modeFlags & (__GL_SHADE_STENCIL_TEST | __GL_SHADE_LOGICOP |
|
|
__GL_SHADE_ALPHA_TEST | __GL_SHADE_SLOW_FOG)) ||
|
|
!gc->state.raster.rMask ||
|
|
!gc->state.raster.gMask ||
|
|
!gc->state.raster.bMask ||
|
|
((GLuint)gc->drawBuffer->buf.other & COLORMASK_ON) ||
|
|
(gengc->CurrentFormat.cColorBits < 8) ||
|
|
((modeFlags & __GL_SHADE_DEPTH_TEST) && (!gc->state.depth.writeEnable))
|
|
)
|
|
return FALSE;
|
|
|
|
if (modeFlags & __GL_SHADE_TEXTURE) {
|
|
internalFormat = gc->texture.currentTexture->level[0].internalFormat;
|
|
textureMode = gc->state.texture.env[0].mode;
|
|
|
|
if (!(((textureMode == GL_DECAL) ||
|
|
(textureMode == GL_REPLACE) ||
|
|
(textureMode == GL_MODULATE)) &&
|
|
(gc->texture.currentTexture &&
|
|
(gc->texture.currentTexture->params.minFilter == GL_NEAREST) &&
|
|
(gc->texture.currentTexture->params.magFilter == GL_NEAREST) &&
|
|
(gc->texture.currentTexture->params.sWrapMode == GL_REPEAT) &&
|
|
(gc->texture.currentTexture->params.tWrapMode == GL_REPEAT) &&
|
|
(gc->texture.currentTexture->level[0].border == 0) &&
|
|
(internalFormat == GL_BGR_EXT ||
|
|
internalFormat == GL_BGRA_EXT ||
|
|
internalFormat == GL_COLOR_INDEX8_EXT))))
|
|
return FALSE;
|
|
|
|
InitAccelTextureValues(gc, gc->texture.currentTexture);
|
|
}
|
|
|
|
bMcdZ = ((((__GLGENcontext *)gc)->pMcdState != NULL) &&
|
|
(((__GLGENcontext *)gc)->pMcdState->pDepthSpan != NULL) &&
|
|
(((__GLGENcontext *)gc)->pMcdState->pMcdSurf != NULL) &&
|
|
!(((__GLGENcontext *)gc)->pMcdState->McdBuffers.mcdDepthBuf.bufFlags & MCDBUF_ENABLED));
|
|
|
|
bTryFastTexRGBA = ((gc->state.raster.drawBuffer != GL_FRONT_AND_BACK) &&
|
|
((modeFlags & __GL_SHADE_DEPTH_TEST &&
|
|
modeFlags & __GL_SHADE_DEPTH_ITER)
|
|
|| (!(modeFlags & __GL_SHADE_DEPTH_TEST) &&
|
|
!(modeFlags & __GL_SHADE_DEPTH_ITER))) &&
|
|
(modeFlags & __GL_SHADE_STIPPLE) == 0);
|
|
|
|
fZippy = (bTryFastTexRGBA &&
|
|
(((GLint)gc->drawBuffer->buf.other & DIB_FORMAT) != 0) &&
|
|
(((GLuint)gc->drawBuffer->buf.other & MEMORY_DC) != 0) &&
|
|
gc->transform.reasonableViewport);
|
|
|
|
GENACCEL(gc).flags &= ~(
|
|
GEN_DITHER | GEN_RGBMODE | GEN_TEXTURE | GEN_SHADE |
|
|
GEN_FASTZBUFFER | GEN_LESS | SURFACE_TYPE_DIB | GEN_TEXTURE_ORTHO
|
|
);
|
|
|
|
if ((enables & __GL_BLEND_ENABLE) ||
|
|
(modeFlags & __GL_SHADE_TEXTURE)) {
|
|
GENACCEL(gc).__fastCalcDeltaPtr = __fastGenCalcDeltasTexRGBA;
|
|
GENACCEL(gc).__fastSetInitParamPtr = __fastGenSetInitialParametersTexRGBA;
|
|
} else {
|
|
GENACCEL(gc).__fastCalcDeltaPtr = __fastGenCalcDeltas;
|
|
GENACCEL(gc).__fastSetInitParamPtr = __fastGenSetInitialParameters;
|
|
}
|
|
|
|
#ifdef _MCD_
|
|
// If MCD driver is being used, then we need to call the "floating
|
|
// point state safe" version of fillTriangle. This version will
|
|
// not attempt to span floating point operations over a call that
|
|
// may invoke the MCD driver (which will corrupt the FP state).
|
|
|
|
if (gengc->pMcdState)
|
|
{
|
|
gc->procs.fillTriangle = __fastGenMcdFillTriangle;
|
|
}
|
|
else
|
|
{
|
|
gc->procs.fillTriangle = __fastGenFillTriangle;
|
|
}
|
|
#else
|
|
gc->procs.fillTriangle = __fastGenFillTriangle;
|
|
#endif
|
|
|
|
// If we're doing perspective-corrected texturing, we will support
|
|
// the following combinations:
|
|
// z....... <, <=
|
|
// alpha... src, 1-src
|
|
// dither.. on/off
|
|
// bpp..... 332, 555, 565, 888
|
|
|
|
// NOTE: We will always try this path first for general texturing.
|
|
|
|
if ((modeFlags & __GL_SHADE_TEXTURE) || (enables & __GL_BLEND_ENABLE)) {
|
|
LONG pixType = -1;
|
|
|
|
if (gc->state.hints.perspectiveCorrection != GL_NICEST)
|
|
GENACCEL(gc).flags |= GEN_TEXTURE_ORTHO;
|
|
|
|
if (!bTryFastTexRGBA)
|
|
goto perspTexPathFail;
|
|
|
|
if ((enables & __GL_BLEND_ENABLE) &&
|
|
((gc->state.raster.blendSrc != GL_SRC_ALPHA) ||
|
|
(gc->state.raster.blendDst != GL_ONE_MINUS_SRC_ALPHA)))
|
|
return FALSE;
|
|
|
|
if (!(modeFlags & __GL_SHADE_TEXTURE)) {
|
|
|
|
if (!(modeFlags & __GL_SHADE_RGB))
|
|
goto perspTexPathFail;
|
|
|
|
bRealTexture = FALSE;
|
|
|
|
GENACCEL(gc).flags |= GEN_TEXTURE_ORTHO;
|
|
GENACCEL(gc).texPalette = NULL;
|
|
textureMode = GL_MODULATE;
|
|
internalFormat = GL_BGRA_EXT;
|
|
GENACCEL(gc).texImage = (ULONG *)internalSolidTexture;
|
|
GENACCEL(gc).sMask = 0;
|
|
GENACCEL(gc).tMask = 0;
|
|
GENACCEL(gc).tShift = 0;
|
|
GENACCEL(gc).tMaskSubDiv = 0;
|
|
GENACCEL(gc).tShiftSubDiv = 0;
|
|
}
|
|
else
|
|
{
|
|
bRealTexture = TRUE;
|
|
}
|
|
|
|
if (bpp == 8) {
|
|
if ((gengc->gc.drawBuffer->redShift == 0) &&
|
|
(gengc->gc.drawBuffer->greenShift == 3) &&
|
|
(gengc->gc.drawBuffer->blueShift == 6))
|
|
pixType = 0;
|
|
} else if (bpp == 16) {
|
|
if ((gengc->gc.drawBuffer->greenShift == 5) &&
|
|
(gengc->gc.drawBuffer->blueShift == 0)) {
|
|
|
|
if (gengc->gc.drawBuffer->redShift == 10)
|
|
pixType = 1;
|
|
else if (gengc->gc.drawBuffer->redShift == 11)
|
|
pixType = 2;
|
|
}
|
|
} else if ((bpp == 32) || (bpp == 24)) {
|
|
if ((gengc->gc.drawBuffer->redShift == 16) &&
|
|
(gengc->gc.drawBuffer->greenShift == 8) &&
|
|
(gengc->gc.drawBuffer->blueShift == 0))
|
|
pixType = 3;
|
|
}
|
|
|
|
if (pixType < 0)
|
|
goto perspTexPathFail;
|
|
|
|
pixType *= 6;
|
|
|
|
if (modeFlags & __GL_SHADE_DEPTH_ITER) {
|
|
|
|
if (bMcdZ)
|
|
goto perspTexPathFail;
|
|
|
|
if (!((gc->state.depth.testFunc == GL_LESS) ||
|
|
(gc->state.depth.testFunc == GL_LEQUAL)))
|
|
goto perspTexPathFail;
|
|
|
|
if (gc->modes.depthBits > 16)
|
|
goto perspTexPathFail;
|
|
|
|
if (gc->state.depth.testFunc == GL_LEQUAL)
|
|
pixType += 1;
|
|
else
|
|
pixType += 2;
|
|
|
|
GENACCEL(gc).__fastFillSubTrianglePtr = __ZippyFSTZ;
|
|
}
|
|
|
|
if (enables & __GL_BLEND_ENABLE)
|
|
pixType += 3;
|
|
|
|
// Note: For selecting the sub-triangle filling routine, assume
|
|
// that we will use one of the "zippy" routines. Then, check at the
|
|
// end whether or not we can actually do this, or if we have to fall
|
|
// back to a more generic (and slower) routine.
|
|
|
|
if (internalFormat != GL_COLOR_INDEX8_EXT &&
|
|
internalFormat != GL_COLOR_INDEX16_EXT) {
|
|
|
|
//
|
|
// Handle full RGB(A) textures
|
|
//
|
|
|
|
// Check if we can support the size...
|
|
|
|
if (bRealTexture &&
|
|
GENACCEL(gc).tex &&
|
|
((GENACCEL(gc).tex->level[0].widthLog2 > TEX_MAX_SIZE_LOG2) ||
|
|
(GENACCEL(gc).tex->level[0].heightLog2 > TEX_MAX_SIZE_LOG2)))
|
|
goto perspTexPathFail;
|
|
|
|
if ((textureMode == GL_DECAL) ||
|
|
(textureMode == GL_REPLACE)) {
|
|
|
|
// we don't handle the goofy alpha case for decal...
|
|
|
|
if ((textureMode == GL_DECAL) &&
|
|
(enables & __GL_BLEND_ENABLE))
|
|
return FALSE;
|
|
|
|
// If we're not dithering, we can go with the compressed
|
|
// texture format. Otherwise, we're forced to use flat-shading
|
|
// procs to get the texture colors to dither properly. Ouch...
|
|
|
|
if (modeFlags & __GL_SHADE_DITHER) {
|
|
GENACCEL(gc).__fastTexSpanFuncPtr =
|
|
__fastPerspTexFlatFuncs[pixType];
|
|
} else {
|
|
if ((bpp >= 8 && bpp <= 16) &&
|
|
!(enables & __GL_BLEND_ENABLE)) {
|
|
|
|
// handle the case where we can use compressed textures
|
|
// for optimal performance. We do this for bit depths
|
|
// <= 16 bits, no dithering, and no blending.
|
|
|
|
if (!GENACCEL(gc).tex->pvUser) {
|
|
if (!__fastGenLoadTexImage(gc, GENACCEL(gc).tex))
|
|
return FALSE;
|
|
} else {
|
|
|
|
// If the compressed texture image was created for
|
|
// another gc, revert to using the RGBA image.
|
|
// We do this by using the alpha paths.
|
|
//
|
|
// NOTE: This logic depends on A being forced to
|
|
// 1 for all RGB textures.
|
|
|
|
if (gc != ((GENTEXCACHE *)GENACCEL(gc).tex->pvUser)->gc)
|
|
{
|
|
pixType += 3;
|
|
}
|
|
else
|
|
{
|
|
// Check that the cached data is the right size
|
|
ASSERTOPENGL(((GENTEXCACHE *)GENACCEL(gc).tex->pvUser)->width == GENACCEL(gc).tex->level[0].width &&
|
|
((GENTEXCACHE *)GENACCEL(gc).tex->pvUser)->height == GENACCEL(gc).tex->level[0].height,
|
|
"Cached texture size mismatch\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
GENACCEL(gc).__fastTexSpanFuncPtr =
|
|
__fastPerspTexReplaceFuncs[pixType];
|
|
}
|
|
|
|
if (!(modeFlags & __GL_SHADE_DEPTH_ITER))
|
|
GENACCEL(gc).__fastFillSubTrianglePtr = __ZippyFSTTex;
|
|
|
|
} else if (textureMode == GL_MODULATE) {
|
|
if (modeFlags & __GL_SHADE_SMOOTH) {
|
|
GENACCEL(gc).__fastTexSpanFuncPtr =
|
|
__fastPerspTexSmoothFuncs[pixType];
|
|
if (!(modeFlags & __GL_SHADE_DEPTH_ITER))
|
|
GENACCEL(gc).__fastFillSubTrianglePtr = __ZippyFSTRGBTex;
|
|
} else {
|
|
GENACCEL(gc).__fastTexSpanFuncPtr =
|
|
__fastPerspTexFlatFuncs[pixType];
|
|
if (!(modeFlags & __GL_SHADE_DEPTH_ITER))
|
|
GENACCEL(gc).__fastFillSubTrianglePtr = __ZippyFSTTex;
|
|
}
|
|
}
|
|
} else {
|
|
//
|
|
// Handle palettized textures
|
|
//
|
|
|
|
// Check if we can support the size...
|
|
|
|
if (bRealTexture &&
|
|
GENACCEL(gc).tex &&
|
|
((GENACCEL(gc).tex->level[0].widthLog2 > TEX_MAX_SIZE_LOG2) ||
|
|
(GENACCEL(gc).tex->level[0].heightLog2 > TEX_MAX_SIZE_LOG2)))
|
|
return FALSE;
|
|
|
|
if ((textureMode == GL_DECAL) ||
|
|
(textureMode == GL_REPLACE)) {
|
|
|
|
// we don't handle the goofy alpha case for decal...
|
|
|
|
if ((textureMode == GL_DECAL) &&
|
|
(enables & __GL_BLEND_ENABLE))
|
|
return FALSE;
|
|
|
|
// If we're not dithering, we can go with the compressed
|
|
// texture format. Otherwise, we're forced to use flat-shading
|
|
// procs to get the texture colors to dither properly. Ouch...
|
|
|
|
if (modeFlags & __GL_SHADE_DITHER) {
|
|
GENACCEL(gc).__fastTexSpanFuncPtr =
|
|
__fastPerspTexFlatFuncs[pixType];
|
|
} else {
|
|
|
|
GENACCEL(gc).__fastTexSpanFuncPtr =
|
|
__fastPerspTexPalReplaceFuncs[pixType];
|
|
|
|
if (bpp >= 8 && bpp <= 16) {
|
|
// handle the case where we can use compressed paletted
|
|
// textures for optimal performance. We do this for
|
|
// bit depths <= 16 bits with no dithering.
|
|
|
|
if (!GENACCEL(gc).tex->pvUser) {
|
|
if (!__fastGenLoadTexImage(gc, GENACCEL(gc).tex))
|
|
return FALSE;
|
|
} else {
|
|
|
|
// If the compressed texture image was created for
|
|
// another gc, we have no choice but to fall back to flat shading.
|
|
// BUGBUG -- we should find a better solution for this...
|
|
if (gc != ((GENTEXCACHE *)GENACCEL(gc).tex->pvUser)->gc)
|
|
GENACCEL(gc).__fastTexSpanFuncPtr =
|
|
__fastPerspTexFlatFuncs[pixType];
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!(modeFlags & __GL_SHADE_DEPTH_ITER))
|
|
GENACCEL(gc).__fastFillSubTrianglePtr = __ZippyFSTTex;
|
|
|
|
} else if (textureMode == GL_MODULATE) {
|
|
if (modeFlags & __GL_SHADE_SMOOTH) {
|
|
GENACCEL(gc).__fastTexSpanFuncPtr =
|
|
__fastPerspTexSmoothFuncs[pixType];
|
|
if (!(modeFlags & __GL_SHADE_DEPTH_ITER))
|
|
GENACCEL(gc).__fastFillSubTrianglePtr = __ZippyFSTRGBTex;
|
|
} else {
|
|
GENACCEL(gc).__fastTexSpanFuncPtr =
|
|
__fastPerspTexFlatFuncs[pixType];
|
|
if (!(modeFlags & __GL_SHADE_DEPTH_ITER))
|
|
GENACCEL(gc).__fastFillSubTrianglePtr = __ZippyFSTTex;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!fZippy)
|
|
GENACCEL(gc).__fastFillSubTrianglePtr = __fastGenFillSubTriangleTexRGBA;
|
|
else
|
|
GENACCEL(gc).flags |= SURFACE_TYPE_DIB;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
perspTexPathFail:
|
|
|
|
// We don't support any alpha modes yet...
|
|
|
|
if (enables & __GL_BLEND_ENABLE)
|
|
return FALSE;
|
|
|
|
fUseFastGenSpan = FALSE;
|
|
|
|
if (bpp == 8) {
|
|
iType = 2;
|
|
if (
|
|
(gengc->gc.drawBuffer->redShift != 0)
|
|
|| (gengc->gc.drawBuffer->greenShift != 3)
|
|
|| (gengc->gc.drawBuffer->blueShift != 6)
|
|
) {
|
|
fUseFastGenSpan = TRUE;
|
|
}
|
|
} else if (bpp == 16) {
|
|
if (
|
|
(gengc->gc.drawBuffer->greenShift == 5)
|
|
&& (gengc->gc.drawBuffer->blueShift == 0)
|
|
) {
|
|
if (gengc->gc.drawBuffer->redShift == 10) {
|
|
iType = 3;
|
|
} else if (gengc->gc.drawBuffer->redShift == 11) {
|
|
iType = 4;
|
|
} else {
|
|
iType = 3;
|
|
fUseFastGenSpan = TRUE;
|
|
}
|
|
} else {
|
|
iType = 3;
|
|
fUseFastGenSpan = TRUE;
|
|
}
|
|
} else {
|
|
if (bpp == 24) {
|
|
iType = 0;
|
|
} else {
|
|
iType = 1;
|
|
}
|
|
if (
|
|
(gengc->gc.drawBuffer->redShift != 16)
|
|
|| (gengc->gc.drawBuffer->greenShift != 8)
|
|
|| (gengc->gc.drawBuffer->blueShift != 0)
|
|
) {
|
|
fUseFastGenSpan = TRUE;
|
|
}
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_DITHER) {
|
|
if ( (bpp == 8)
|
|
|| (bpp == 16)
|
|
|| ((modeFlags & __GL_SHADE_DEPTH_ITER) == 0)
|
|
) {
|
|
GENACCEL(gc).flags |= GEN_DITHER;
|
|
}
|
|
iType += 5;
|
|
}
|
|
|
|
// Use the accelerated span functions (with no inline z-buffering) if
|
|
// we support the z-buffer function AND we're not using hardware
|
|
// z-buffering:
|
|
|
|
if (modeFlags & __GL_SHADE_DEPTH_ITER) {
|
|
if (bMcdZ) {
|
|
fUseFastGenSpan = TRUE;
|
|
} else if (!fZippy) {
|
|
fUseFastGenSpan = TRUE;
|
|
} else if (gc->state.depth.testFunc == GL_LESS) {
|
|
GENACCEL(gc).flags |= GEN_LESS;
|
|
} else if (gc->state.depth.testFunc != GL_LEQUAL) {
|
|
fUseFastGenSpan = TRUE;
|
|
}
|
|
iType += 10;
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_RGB) {
|
|
GENACCEL(gc).flags |= GEN_RGBMODE;
|
|
pfnZippySub = __ZippyFSTRGB;
|
|
|
|
if (modeFlags & __GL_SHADE_TEXTURE) {
|
|
GENACCEL(gc).flags |= (GEN_TEXTURE | GEN_TEXTURE_ORTHO);
|
|
|
|
if (gc->state.hints.perspectiveCorrection == GL_NICEST)
|
|
return FALSE;
|
|
|
|
if (internalFormat == GL_COLOR_INDEX8_EXT ||
|
|
internalFormat == GL_COLOR_INDEX16_EXT)
|
|
return FALSE;
|
|
|
|
if (textureMode == GL_DECAL) {
|
|
if (modeFlags & __GL_SHADE_DITHER)
|
|
GENACCEL(gc).__fastTexSpanFuncPtr =
|
|
__fastGenTexFuncs[iType];
|
|
else
|
|
GENACCEL(gc).__fastTexSpanFuncPtr =
|
|
__fastGenTexDecalFuncs[iType];
|
|
|
|
pfnZippySub = __ZippyFSTTex;
|
|
} else {
|
|
GENACCEL(gc).flags |= GEN_SHADE;
|
|
pfnZippySub = __ZippyFSTRGBTex;
|
|
GENACCEL(gc).__fastTexSpanFuncPtr =
|
|
__fastGenTexFuncs[iType];
|
|
}
|
|
|
|
if (GENACCEL(gc).__fastTexSpanFuncPtr == __fastGenSpan) {
|
|
fUseFastGenSpan = TRUE;
|
|
}
|
|
} else {
|
|
GENACCEL(gc).__fastSmoothSpanFuncPtr = __fastGenRGBFuncs[iType];
|
|
GENACCEL(gc).__fastFlatSpanFuncPtr = __fastGenRGBFlatFuncs[iType];
|
|
|
|
if (GENACCEL(gc).__fastSmoothSpanFuncPtr == __fastGenSpan) {
|
|
fUseFastGenSpan = TRUE;
|
|
}
|
|
}
|
|
} else {
|
|
pfnZippySub = __ZippyFSTCI;
|
|
GENACCEL(gc).__fastSmoothSpanFuncPtr = __fastGenCIFuncs[iType];
|
|
GENACCEL(gc).__fastFlatSpanFuncPtr = __fastGenCIFlatFuncs[iType];
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_STIPPLE)
|
|
{
|
|
fUseFastGenSpan = TRUE;
|
|
}
|
|
|
|
if (fUseFastGenSpan) {
|
|
GENACCEL(gc).__fastTexSpanFuncPtr = __fastGenSpan;
|
|
GENACCEL(gc).__fastSmoothSpanFuncPtr = __fastGenSpan;
|
|
GENACCEL(gc).__fastFlatSpanFuncPtr = __fastGenSpan;
|
|
GENACCEL(gc).__fastFillSubTrianglePtr = __fastGenFillSubTriangle;
|
|
} else {
|
|
if (fZippy) {
|
|
GENACCEL(gc).flags |= SURFACE_TYPE_DIB;
|
|
|
|
if ( (iType == 2)
|
|
&& (
|
|
(modeFlags
|
|
& (__GL_SHADE_RGB | __GL_SHADE_SMOOTH)
|
|
) == 0
|
|
)
|
|
) {
|
|
GENACCEL(gc).__fastFillSubTrianglePtr = __ZippyFSTCI8Flat;
|
|
} else if (iType >= 10) {
|
|
GENACCEL(gc).__fastFillSubTrianglePtr = __ZippyFSTZ;
|
|
GENACCEL(gc).flags |= GEN_FASTZBUFFER;
|
|
} else {
|
|
GENACCEL(gc).flags &= ~(HAVE_STIPPLE);
|
|
GENACCEL(gc).__fastFillSubTrianglePtr = pfnZippySub;
|
|
}
|
|
} else {
|
|
GENACCEL(gc).__fastFillSubTrianglePtr = __fastGenFillSubTriangle;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void FASTCALL __fastGenPickTriangleProcs(__GLcontext *gc)
|
|
{
|
|
GLuint modeFlags = gc->polygon.shader.modeFlags;
|
|
__GLGENcontext *genGc = (__GLGENcontext *)gc;
|
|
|
|
CASTINT(gc->polygon.shader.rLittle) = 0;
|
|
CASTINT(gc->polygon.shader.rBig) = 0;
|
|
CASTINT(gc->polygon.shader.gLittle) = 0;
|
|
CASTINT(gc->polygon.shader.gBig) = 0;
|
|
CASTINT(gc->polygon.shader.bLittle) = 0;
|
|
CASTINT(gc->polygon.shader.bBig) = 0;
|
|
CASTINT(gc->polygon.shader.sLittle) = 0;
|
|
CASTINT(gc->polygon.shader.sBig) = 0;
|
|
CASTINT(gc->polygon.shader.tLittle) = 0;
|
|
CASTINT(gc->polygon.shader.tBig) = 0;
|
|
|
|
GENACCEL(gc).spanDelta.r = 0;
|
|
GENACCEL(gc).spanDelta.g = 0;
|
|
GENACCEL(gc).spanDelta.b = 0;
|
|
GENACCEL(gc).spanDelta.a = 0;
|
|
|
|
/*
|
|
** Setup cullFace so that a single test will do the cull check.
|
|
*/
|
|
if (modeFlags & __GL_SHADE_CULL_FACE) {
|
|
switch (gc->state.polygon.cull) {
|
|
case GL_FRONT:
|
|
gc->polygon.cullFace = __GL_CULL_FLAG_FRONT;
|
|
break;
|
|
case GL_BACK:
|
|
gc->polygon.cullFace = __GL_CULL_FLAG_BACK;
|
|
break;
|
|
case GL_FRONT_AND_BACK:
|
|
gc->procs.renderTriangle = __glDontRenderTriangle;
|
|
gc->procs.fillTriangle = 0; /* Done to find bugs */
|
|
return;
|
|
}
|
|
} else {
|
|
gc->polygon.cullFace = __GL_CULL_FLAG_DONT;
|
|
}
|
|
|
|
/* Build lookup table for face direction */
|
|
switch (gc->state.polygon.frontFaceDirection) {
|
|
case GL_CW:
|
|
if (gc->constants.yInverted) {
|
|
gc->polygon.face[__GL_CW] = __GL_BACKFACE;
|
|
gc->polygon.face[__GL_CCW] = __GL_FRONTFACE;
|
|
} else {
|
|
gc->polygon.face[__GL_CW] = __GL_FRONTFACE;
|
|
gc->polygon.face[__GL_CCW] = __GL_BACKFACE;
|
|
}
|
|
break;
|
|
case GL_CCW:
|
|
if (gc->constants.yInverted) {
|
|
gc->polygon.face[__GL_CW] = __GL_FRONTFACE;
|
|
gc->polygon.face[__GL_CCW] = __GL_BACKFACE;
|
|
} else {
|
|
gc->polygon.face[__GL_CW] = __GL_BACKFACE;
|
|
gc->polygon.face[__GL_CCW] = __GL_FRONTFACE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
/* Make polygon mode indexable and zero based */
|
|
gc->polygon.mode[__GL_FRONTFACE] =
|
|
(GLubyte) (gc->state.polygon.frontMode & 0xf);
|
|
gc->polygon.mode[__GL_BACKFACE] =
|
|
(GLubyte) (gc->state.polygon.backMode & 0xf);
|
|
|
|
if (gc->renderMode == GL_FEEDBACK) {
|
|
gc->procs.renderTriangle = __glFeedbackTriangle;
|
|
gc->procs.fillTriangle = 0; /* Done to find bugs */
|
|
return;
|
|
}
|
|
if (gc->renderMode == GL_SELECT) {
|
|
gc->procs.renderTriangle = __glSelectTriangle;
|
|
gc->procs.fillTriangle = 0; /* Done to find bugs */
|
|
return;
|
|
}
|
|
|
|
if ((gc->state.polygon.frontMode == gc->state.polygon.backMode) &&
|
|
(gc->state.polygon.frontMode == GL_FILL)) {
|
|
if (modeFlags & __GL_SHADE_SMOOTH_LIGHT) {
|
|
gc->procs.renderTriangle = __glRenderSmoothTriangle;
|
|
} else {
|
|
gc->procs.renderTriangle = __glRenderFlatTriangle;
|
|
}
|
|
} else {
|
|
gc->procs.renderTriangle = __glRenderTriangle;
|
|
}
|
|
if (gc->state.enables.general & __GL_POLYGON_SMOOTH_ENABLE) {
|
|
gc->procs.fillTriangle = __glFillAntiAliasedTriangle;
|
|
} else {
|
|
if ((gc->state.raster.drawBuffer == GL_NONE) ||
|
|
#if DEAD_3DDDI
|
|
(!bUseRxTriangles(gc) && !bUseGenTriangles(gc)))
|
|
#else
|
|
!bUseGenTriangles(gc))
|
|
#endif
|
|
gc->procs.fillTriangle = __glFillTriangle;
|
|
}
|
|
if ((modeFlags & __GL_SHADE_CHEAP_FOG) &&
|
|
!(modeFlags & __GL_SHADE_SMOOTH_LIGHT)) {
|
|
gc->procs.fillTriangle2 = gc->procs.fillTriangle;
|
|
gc->procs.fillTriangle = __glFillFlatFogTriangle;
|
|
}
|
|
}
|
|
|
|
|
|
void FASTCALL __fastGenPickSpanProcs(__GLcontext *gc)
|
|
{
|
|
__GLGENcontext *genGc = (__GLGENcontext *)gc;
|
|
GLuint enables = gc->state.enables.general;
|
|
GLuint modeFlags = gc->polygon.shader.modeFlags;
|
|
__GLcolorBuffer *cfb = gc->drawBuffer;
|
|
__GLspanFunc *sp;
|
|
__GLstippledSpanFunc *ssp;
|
|
int spanCount;
|
|
GLboolean replicateSpan;
|
|
GLboolean bMcdZ = ((((__GLGENcontext *)gc)->pMcdState != NULL) &&
|
|
(((__GLGENcontext *)gc)->pMcdState->pDepthSpan != NULL) &&
|
|
(((__GLGENcontext *)gc)->pMcdState->pMcdSurf != NULL) &&
|
|
!(((__GLGENcontext *)gc)->pMcdState->McdBuffers.mcdDepthBuf.bufFlags & MCDBUF_ENABLED));
|
|
|
|
// Always reset the color scale values at the beginning of the pick
|
|
// procs. Lines, triangles, and spans may all use these values...
|
|
|
|
GENACCEL(gc).rAccelScale = (GLfloat)ACCEL_FIX_SCALE;
|
|
GENACCEL(gc).gAccelScale = (GLfloat)ACCEL_FIX_SCALE;
|
|
GENACCEL(gc).bAccelScale = (GLfloat)ACCEL_FIX_SCALE;
|
|
|
|
// Note: we need to scale between 0 and 255 to get proper alpha
|
|
// blending. The software-accelerated blending code assumes this
|
|
// scaling for simplicity...
|
|
|
|
GENACCEL(gc).aAccelScale = (GLfloat)(ACCEL_FIX_SCALE) *
|
|
(GLfloat)255.0 / gc->drawBuffer->alphaScale;
|
|
|
|
replicateSpan = GL_FALSE;
|
|
sp = gc->procs.span.spanFuncs;
|
|
ssp = gc->procs.span.stippledSpanFuncs;
|
|
|
|
/* Load phase one procs */
|
|
if (!gc->transform.reasonableViewport) {
|
|
*sp++ = __glClipSpan;
|
|
*ssp++ = NULL;
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_STIPPLE) {
|
|
*sp++ = __glStippleSpan;
|
|
*ssp++ = __glStippleStippledSpan;
|
|
|
|
if (modeFlags & __GL_SHADE_DEPTH_TEST)
|
|
{
|
|
if (gc->state.depth.testFunc == GL_LESS)
|
|
{
|
|
if (gc->modes.depthBits == 32)
|
|
{
|
|
GENACCEL(gc).__fastStippleDepthTestSpan =
|
|
__fastGenStippleLt32Span;
|
|
}
|
|
else
|
|
{
|
|
GENACCEL(gc).__fastStippleDepthTestSpan =
|
|
__fastGenStippleLt16Span;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GENACCEL(gc).__fastStippleDepthTestSpan =
|
|
__fastGenStippleAnyDepthTestSpan;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GENACCEL(gc).__fastStippleDepthTestSpan = __glStippleSpan;
|
|
}
|
|
}
|
|
|
|
/* Load phase three procs */
|
|
if (modeFlags & __GL_SHADE_RGB) {
|
|
if (modeFlags & __GL_SHADE_SMOOTH) {
|
|
*sp = __glShadeRGBASpan;
|
|
*ssp = __glShadeRGBASpan;
|
|
} else {
|
|
*sp = __glFlatRGBASpan;
|
|
*ssp = __glFlatRGBASpan;
|
|
}
|
|
} else {
|
|
if (modeFlags & __GL_SHADE_SMOOTH) {
|
|
*sp = __glShadeCISpan;
|
|
*ssp = __glShadeCISpan;
|
|
} else {
|
|
*sp = __glFlatCISpan;
|
|
*ssp = __glFlatCISpan;
|
|
}
|
|
}
|
|
sp++;
|
|
ssp++;
|
|
|
|
if (modeFlags & __GL_SHADE_TEXTURE) {
|
|
*sp++ = __glTextureSpan;
|
|
*ssp++ = __glTextureStippledSpan;
|
|
}
|
|
if (modeFlags & __GL_SHADE_SLOW_FOG) {
|
|
if (gc->state.hints.fog == GL_NICEST) {
|
|
*sp = __glFogSpanSlow;
|
|
*ssp = __glFogStippledSpanSlow;
|
|
} else {
|
|
*sp = __glFogSpan;
|
|
*ssp = __glFogStippledSpan;
|
|
}
|
|
sp++;
|
|
ssp++;
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_ALPHA_TEST) {
|
|
*sp++ = __glAlphaTestSpan;
|
|
*ssp++ = __glAlphaTestStippledSpan;
|
|
}
|
|
|
|
/* Load phase two procs */
|
|
if (modeFlags & __GL_SHADE_STENCIL_TEST) {
|
|
*sp++ = __glStencilTestSpan;
|
|
*ssp++ = __glStencilTestStippledSpan;
|
|
if (modeFlags & __GL_SHADE_DEPTH_TEST) {
|
|
if (bMcdZ) {
|
|
*sp = GenMcdDepthTestStencilSpan;
|
|
*ssp = GenMcdDepthTestStencilStippledSpan;
|
|
} else {
|
|
*sp = __glDepthTestStencilSpan;
|
|
*ssp = __glDepthTestStencilStippledSpan;
|
|
}
|
|
} else {
|
|
*sp = __glDepthPassSpan;
|
|
*ssp = __glDepthPassStippledSpan;
|
|
}
|
|
sp++;
|
|
ssp++;
|
|
} else {
|
|
if (modeFlags & __GL_SHADE_DEPTH_TEST) {
|
|
if (bMcdZ) {
|
|
*sp++ = GenMcdDepthTestSpan;
|
|
*ssp++ = GenMcdDepthTestStippledSpan;
|
|
if (gc->state.depth.writeEnable)
|
|
((__GLGENcontext *)gc)->pMcdState->softZSpanFuncPtr =
|
|
__fastDepthFuncs[gc->state.depth.testFunc & 0x7];
|
|
else
|
|
((__GLGENcontext *)gc)->pMcdState->softZSpanFuncPtr =
|
|
(__GLspanFunc)NULL;
|
|
|
|
GENACCEL(gc).__fastZSpanFuncPtr = GenMcdDepthTestSpan;
|
|
} else {
|
|
if (gc->state.depth.writeEnable) {
|
|
if( gc->modes.depthBits == 32 ) {
|
|
*sp++ = GENACCEL(gc).__fastZSpanFuncPtr =
|
|
__fastDepthFuncs[gc->state.depth.testFunc & 0x7];
|
|
} else {
|
|
*sp++ = GENACCEL(gc).__fastZSpanFuncPtr =
|
|
__fastDepth16Funcs[gc->state.depth.testFunc & 0x7];
|
|
}
|
|
} else {
|
|
*sp++ = GENACCEL(gc).__fastZSpanFuncPtr =
|
|
__glDepthTestSpan;
|
|
}
|
|
|
|
*ssp++ = __glDepthTestStippledSpan;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (gc->state.raster.drawBuffer == GL_FRONT_AND_BACK) {
|
|
spanCount = sp - gc->procs.span.spanFuncs;
|
|
gc->procs.span.n = spanCount;
|
|
replicateSpan = GL_TRUE;
|
|
}
|
|
|
|
/* Span routines deal with masking, dithering, logicop, blending */
|
|
*sp++ = cfb->storeSpan;
|
|
*ssp++ = cfb->storeStippledSpan;
|
|
|
|
spanCount = sp - gc->procs.span.spanFuncs;
|
|
gc->procs.span.m = spanCount;
|
|
if (replicateSpan) {
|
|
gc->procs.span.processSpan = __glProcessReplicateSpan;
|
|
} else {
|
|
gc->procs.span.processSpan = __glProcessSpan;
|
|
gc->procs.span.n = spanCount;
|
|
}
|
|
}
|
|
|
|
// These are the bits in modeFlags that affect lines
|
|
|
|
#define __FAST_LINE_MODE_FLAGS \
|
|
(__GL_SHADE_DEPTH_TEST | __GL_SHADE_SMOOTH | __GL_SHADE_TEXTURE | \
|
|
__GL_SHADE_LINE_STIPPLE | __GL_SHADE_STENCIL_TEST | __GL_SHADE_LOGICOP | \
|
|
__GL_SHADE_BLEND | __GL_SHADE_ALPHA_TEST | __GL_SHADE_MASK | \
|
|
__GL_SHADE_SLOW_FOG | __GL_SHADE_CHEAP_FOG)
|
|
|
|
/******************************Public*Routine******************************\
|
|
* __fastGenPickLineProcs
|
|
*
|
|
* Picks the line-rendering procedures. Most of this function was copied from
|
|
* the soft code. Some differences include:
|
|
* 1. The beginPrim function pointers are hooked by the accelerated code
|
|
* 2. If the attribute state is such that acceleration can be used,
|
|
* __fastGenLineSetup is called to initialize the state machine.
|
|
*
|
|
* History:
|
|
* 22-Mar-1994 -by- Eddie Robinson [v-eddier]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
|
|
void FASTCALL __fastGenPickLineProcs(__GLcontext *gc)
|
|
{
|
|
__GLGENcontext *genGc = (__GLGENcontext *) gc;
|
|
GENACCEL *genAccel;
|
|
GLuint enables = gc->state.enables.general;
|
|
GLuint modeFlags = gc->polygon.shader.modeFlags;
|
|
__GLspanFunc *sp;
|
|
__GLstippledSpanFunc *ssp;
|
|
int spanCount;
|
|
GLboolean wideLine;
|
|
GLboolean replicateLine;
|
|
GLuint aaline;
|
|
GLboolean bMcdZ = ((genGc->pMcdState != NULL) &&
|
|
(genGc->pMcdState->pDepthSpan != NULL) &&
|
|
(genGc->pMcdState->pMcdSurf != NULL) &&
|
|
!(genGc->pMcdState->McdBuffers.mcdDepthBuf.bufFlags & MCDBUF_ENABLED));
|
|
|
|
/*
|
|
** The fast line code replaces the line function pointers, so reset them
|
|
** to a good state
|
|
*/
|
|
gc->procs.lineBegin = __glNopLineBegin;
|
|
gc->procs.lineEnd = __glNopLineEnd;
|
|
|
|
if (gc->renderMode == GL_FEEDBACK) {
|
|
gc->procs.renderLine = __glFeedbackLine;
|
|
} else if (gc->renderMode == GL_SELECT) {
|
|
gc->procs.renderLine = __glSelectLine;
|
|
} else {
|
|
if (genGc->pDrvAccel) {
|
|
#if DEAD_3DDDI
|
|
if (bGenDrvRxLines(gc))
|
|
return;
|
|
#endif
|
|
} else if (genAccel = (GENACCEL *) genGc->pPrivateArea) {
|
|
if (!(modeFlags & __FAST_LINE_MODE_FLAGS & ~genAccel->flLineAccelModes) &&
|
|
!(gc->state.enables.general & __GL_LINE_SMOOTH_ENABLE) &&
|
|
!(gc->state.raster.drawBuffer == GL_NONE) &&
|
|
!gc->buffers.doubleStore &&
|
|
!genGc->pDrvAccel &&
|
|
!genGc->pMcdState &&
|
|
(genGc->iDCType != DCTYPE_INFO))
|
|
{
|
|
__fastLineComputeOffsets(genGc);
|
|
|
|
#if NT_NO_BUFFER_INVARIANCE
|
|
if (!((GLuint)gc->drawBuffer->buf.other & DIB_FORMAT)) {
|
|
if (genAccel->bFastLineDispAccel) {
|
|
if (__fastGenLineSetupDisplay(gc))
|
|
return;
|
|
}
|
|
} else {
|
|
if (genAccel->bFastLineDIBAccel) {
|
|
if (__fastGenLineSetupDIB(gc))
|
|
return;
|
|
}
|
|
}
|
|
#else
|
|
if (genAccel->bFastLineDispAccel) {
|
|
if (__fastGenLineSetupDisplay(gc))
|
|
return;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (__glGenSetupEitherLines(gc))
|
|
{
|
|
return;
|
|
}
|
|
|
|
replicateLine = wideLine = GL_FALSE;
|
|
|
|
aaline = gc->state.enables.general & __GL_LINE_SMOOTH_ENABLE;
|
|
if (aaline)
|
|
{
|
|
gc->procs.renderLine = __glRenderAntiAliasLine;
|
|
}
|
|
else
|
|
{
|
|
gc->procs.renderLine = __glRenderAliasLine;
|
|
}
|
|
|
|
sp = gc->procs.line.lineFuncs;
|
|
ssp = gc->procs.line.stippledLineFuncs;
|
|
|
|
if (!aaline && (modeFlags & __GL_SHADE_LINE_STIPPLE)) {
|
|
*sp++ = __glStippleLine;
|
|
*ssp++ = NULL;
|
|
}
|
|
|
|
if (!aaline && gc->state.line.aliasedWidth > 1) {
|
|
wideLine = GL_TRUE;
|
|
}
|
|
spanCount = sp - gc->procs.line.lineFuncs;
|
|
gc->procs.line.n = spanCount;
|
|
|
|
*sp++ = __glScissorLine;
|
|
*ssp++ = __glScissorStippledLine;
|
|
|
|
if (!aaline) {
|
|
if (modeFlags & __GL_SHADE_STENCIL_TEST) {
|
|
*sp++ = __glStencilTestLine;
|
|
*ssp++ = __glStencilTestStippledLine;
|
|
if (modeFlags & __GL_SHADE_DEPTH_TEST) {
|
|
if (bMcdZ) {
|
|
*sp = GenMcdDepthTestStencilLine;
|
|
*ssp = GenMcdDepthTestStencilStippledLine;
|
|
} else if( gc->modes.depthBits == 32 ) {
|
|
*sp = __glDepthTestStencilLine;
|
|
*ssp = __glDepthTestStencilStippledLine;
|
|
}
|
|
else {
|
|
*sp = __glDepth16TestStencilLine;
|
|
*ssp = __glDepth16TestStencilStippledLine;
|
|
}
|
|
} else {
|
|
*sp = __glDepthPassLine;
|
|
*ssp = __glDepthPassStippledLine;
|
|
}
|
|
sp++;
|
|
ssp++;
|
|
} else {
|
|
if (modeFlags & __GL_SHADE_DEPTH_TEST) {
|
|
if (gc->state.depth.testFunc == GL_NEVER) {
|
|
/* Unexpected end of line routine picking! */
|
|
spanCount = sp - gc->procs.line.lineFuncs;
|
|
gc->procs.line.m = spanCount;
|
|
gc->procs.line.l = spanCount;
|
|
goto pickLineProcessor;
|
|
#ifdef __GL_USEASMCODE
|
|
} else {
|
|
unsigned long ix;
|
|
|
|
if (gc->state.depth.writeEnable) {
|
|
ix = 0;
|
|
} else {
|
|
ix = 8;
|
|
}
|
|
ix += gc->state.depth.testFunc & 0x7;
|
|
|
|
if (ix == (GL_LEQUAL & 0x7)) {
|
|
*sp++ = __glDepthTestLine_LEQ_asm;
|
|
} else {
|
|
*sp++ = __glDepthTestLine_asm;
|
|
gc->procs.line.depthTestPixel = LDepthTestPixel[ix];
|
|
}
|
|
#else
|
|
} else {
|
|
if (bMcdZ) {
|
|
*sp++ = GenMcdDepthTestLine;
|
|
} else {
|
|
if( gc->modes.depthBits == 32 )
|
|
*sp++ = __glDepthTestLine;
|
|
else
|
|
*sp++ = __glDepth16TestLine;
|
|
}
|
|
#endif
|
|
}
|
|
if (bMcdZ) {
|
|
*ssp++ = GenMcdDepthTestStippledLine;
|
|
} else {
|
|
if( gc->modes.depthBits == 32 )
|
|
*ssp++ = __glDepthTestStippledLine;
|
|
else
|
|
*ssp++ = __glDepth16TestStippledLine;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Load phase three procs */
|
|
if (modeFlags & __GL_SHADE_RGB) {
|
|
if (modeFlags & __GL_SHADE_SMOOTH) {
|
|
*sp = __glShadeRGBASpan;
|
|
*ssp = __glShadeRGBASpan;
|
|
} else {
|
|
*sp = __glFlatRGBASpan;
|
|
*ssp = __glFlatRGBASpan;
|
|
}
|
|
} else {
|
|
if (modeFlags & __GL_SHADE_SMOOTH) {
|
|
*sp = __glShadeCISpan;
|
|
*ssp = __glShadeCISpan;
|
|
} else {
|
|
*sp = __glFlatCISpan;
|
|
*ssp = __glFlatCISpan;
|
|
}
|
|
}
|
|
sp++;
|
|
ssp++;
|
|
if (modeFlags & __GL_SHADE_TEXTURE) {
|
|
*sp++ = __glTextureSpan;
|
|
*ssp++ = __glTextureStippledSpan;
|
|
}
|
|
if (modeFlags & __GL_SHADE_SLOW_FOG) {
|
|
if (gc->state.hints.fog == GL_NICEST) {
|
|
*sp = __glFogSpanSlow;
|
|
*ssp = __glFogStippledSpanSlow;
|
|
} else {
|
|
*sp = __glFogSpan;
|
|
*ssp = __glFogStippledSpan;
|
|
}
|
|
sp++;
|
|
ssp++;
|
|
}
|
|
|
|
if (aaline) {
|
|
*sp++ = __glAntiAliasLine;
|
|
*ssp++ = __glAntiAliasStippledLine;
|
|
}
|
|
|
|
if (aaline) {
|
|
if (modeFlags & __GL_SHADE_STENCIL_TEST) {
|
|
*sp++ = __glStencilTestLine;
|
|
*ssp++ = __glStencilTestStippledLine;
|
|
if (modeFlags & __GL_SHADE_DEPTH_TEST) {
|
|
if (bMcdZ) {
|
|
*sp = GenMcdDepthTestStencilLine;
|
|
*ssp = GenMcdDepthTestStencilStippledLine;
|
|
} else if( gc->modes.depthBits == 32 ) {
|
|
*sp = __glDepthTestStencilLine;
|
|
*ssp = __glDepthTestStencilStippledLine;
|
|
}
|
|
else {
|
|
*sp = __glDepth16TestStencilLine;
|
|
*ssp = __glDepth16TestStencilStippledLine;
|
|
}
|
|
} else {
|
|
*sp = __glDepthPassLine;
|
|
*ssp = __glDepthPassStippledLine;
|
|
}
|
|
sp++;
|
|
ssp++;
|
|
} else {
|
|
if (modeFlags & __GL_SHADE_DEPTH_TEST) {
|
|
if (gc->state.depth.testFunc == GL_NEVER) {
|
|
/* Unexpected end of line routine picking! */
|
|
spanCount = sp - gc->procs.line.lineFuncs;
|
|
gc->procs.line.m = spanCount;
|
|
gc->procs.line.l = spanCount;
|
|
goto pickLineProcessor;
|
|
#ifdef __GL_USEASMCODE
|
|
} else {
|
|
unsigned long ix;
|
|
|
|
if (gc->state.depth.writeEnable) {
|
|
ix = 0;
|
|
} else {
|
|
ix = 8;
|
|
}
|
|
ix += gc->state.depth.testFunc & 0x7;
|
|
*sp++ = __glDepthTestLine_asm;
|
|
gc->procs.line.depthTestPixel = LDepthTestPixel[ix];
|
|
#else
|
|
} else {
|
|
if (bMcdZ)
|
|
*sp++ = GenMcdDepthTestLine;
|
|
else if( gc->modes.depthBits == 32 )
|
|
*sp++ = __glDepthTestLine;
|
|
else
|
|
*sp++ = __glDepth16TestLine;
|
|
#endif
|
|
}
|
|
if (bMcdZ)
|
|
*ssp++ = GenMcdDepthTestStippledLine;
|
|
else if (gc->modes.depthBits == 32)
|
|
*ssp++ = __glDepthTestStippledLine;
|
|
else
|
|
*ssp++ = __glDepth16TestStippledLine;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (modeFlags & __GL_SHADE_ALPHA_TEST) {
|
|
*sp++ = __glAlphaTestSpan;
|
|
*ssp++ = __glAlphaTestStippledSpan;
|
|
}
|
|
|
|
if (gc->buffers.doubleStore) {
|
|
replicateLine = GL_TRUE;
|
|
}
|
|
spanCount = sp - gc->procs.line.lineFuncs;
|
|
gc->procs.line.m = spanCount;
|
|
|
|
*sp++ = __glStoreLine;
|
|
*ssp++ = __glStoreStippledLine;
|
|
|
|
spanCount = sp - gc->procs.line.lineFuncs;
|
|
gc->procs.line.l = spanCount;
|
|
|
|
sp = &gc->procs.line.wideLineRep;
|
|
ssp = &gc->procs.line.wideStippledLineRep;
|
|
if (wideLine) {
|
|
*sp = __glWideLineRep;
|
|
*ssp = __glWideStippleLineRep;
|
|
sp = &gc->procs.line.drawLine;
|
|
ssp = &gc->procs.line.drawStippledLine;
|
|
}
|
|
if (replicateLine) {
|
|
*sp = __glDrawBothLine;
|
|
*ssp = __glDrawBothStippledLine;
|
|
} else {
|
|
*sp = __glNopGCBOOL;
|
|
*ssp = __glNopGCBOOL;
|
|
gc->procs.line.m = gc->procs.line.l;
|
|
}
|
|
if (!wideLine) {
|
|
gc->procs.line.n = gc->procs.line.m;
|
|
}
|
|
|
|
pickLineProcessor:
|
|
if (!wideLine && !replicateLine && spanCount == 3) {
|
|
gc->procs.line.processLine = __glProcessLine3NW;
|
|
} else {
|
|
gc->procs.line.processLine = __glProcessLine;
|
|
}
|
|
if ((modeFlags & __GL_SHADE_CHEAP_FOG) &&
|
|
!(modeFlags & __GL_SHADE_SMOOTH_LIGHT)) {
|
|
gc->procs.renderLine2 = gc->procs.renderLine;
|
|
gc->procs.renderLine = __glRenderFlatFogLine;
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL FASTCALL __glGenCreateAccelContext(__GLcontext *gc)
|
|
{
|
|
__GLGENcontext *genGc = (__GLGENcontext *)gc;
|
|
PIXELFORMATDESCRIPTOR *pfmt;
|
|
ULONG bpp;
|
|
|
|
pfmt = &genGc->CurrentFormat;
|
|
bpp = pfmt->cColorBits;
|
|
|
|
genGc->pPrivateArea = (VOID *)(&genGc->genAccel);
|
|
|
|
__glQueryLineAcceleration(gc);
|
|
|
|
gc->procs.pickTriangleProcs = __fastGenPickTriangleProcs;
|
|
gc->procs.pickSpanProcs = __fastGenPickSpanProcs;
|
|
|
|
// Set up constant-color values:
|
|
|
|
GENACCEL(gc).constantR = ((1 << pfmt->cRedBits) - 1) << 16;
|
|
GENACCEL(gc).constantG = ((1 << pfmt->cGreenBits) - 1) << 16;
|
|
GENACCEL(gc).constantB = ((1 << pfmt->cBlueBits) - 1) << 16;
|
|
GENACCEL(gc).constantA = 0xff << 16;
|
|
|
|
GENACCEL(gc).bpp = bpp;
|
|
GENACCEL(gc).xMultiplier = ((bpp + 7) / 8);
|
|
|
|
if (gc->modes.depthBits == 16 )
|
|
GENACCEL(gc).zScale = (__GLfloat)65536.0;
|
|
else
|
|
GENACCEL(gc).zScale = (__GLfloat)1.0;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
DWORD FASTCALL __glGenLoadTexture(__GLcontext *gc, __GLtexture *tex)
|
|
{
|
|
__GLGENcontext *gengc = (__GLGENcontext *)gc;
|
|
DWORD texHandle;
|
|
DWORD texKey;
|
|
|
|
#ifdef _MCD_
|
|
if (gengc->pMcdState) {
|
|
texHandle = GenMcdCreateTexture(gengc, tex);
|
|
if (texHandle) {
|
|
tex->textureKey = GenMcdTextureKey(gengc, texHandle);
|
|
gc->textureKey = tex->textureKey;
|
|
}
|
|
return texHandle;
|
|
} else
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
|
|
BOOL FASTCALL __glGenMakeTextureCurrent(__GLcontext *gc, __GLtexture *tex, DWORD loadKey)
|
|
{
|
|
GLint internalFormat;
|
|
|
|
if (!tex)
|
|
return FALSE;
|
|
|
|
InitAccelTextureValues(gc, tex);
|
|
|
|
// Update the driver texture key in the context:
|
|
|
|
if (((__GLGENcontext *)gc)->pMcdState && (gc->textureKey = tex->textureKey)) {
|
|
GenMcdUpdateTextureState((__GLGENcontext *)gc, tex, loadKey);
|
|
}
|
|
|
|
// Always call the low-level triangle pick routine(s) to make sure
|
|
// that we can handle the texture and the texturing mode...
|
|
|
|
#if DEAD_3DDDI
|
|
if (!bUseRxTriangles(gc) && !bUseGenTriangles(gc)) {
|
|
#else
|
|
if (!bUseGenTriangles(gc)) {
|
|
#endif
|
|
gc->procs.fillTriangle = __glFillTriangle;
|
|
return TRUE;
|
|
}
|
|
|
|
if (tex->level[0].internalFormat == GL_COLOR_INDEX8_EXT)
|
|
{
|
|
if (tex->pvUser)
|
|
GENACCEL(gc).texImageReplace =
|
|
((GENTEXCACHE *)tex->pvUser)->texImageReplace;
|
|
}
|
|
else if (tex->level[0].internalFormat != GL_COLOR_INDEX16_EXT)
|
|
{
|
|
if (tex->pvUser)
|
|
GENACCEL(gc).texImageReplace =
|
|
((GENTEXCACHE *)tex->pvUser)->texImageReplace;
|
|
|
|
GENACCEL(gc).texPalette = NULL;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL FASTCALL __glGenUpdateTexture(__GLcontext *gc, __GLtexture *tex, DWORD loadKey)
|
|
{
|
|
|
|
//!! NOTE !!
|
|
//!! This should really be broken into separate load and update calls since
|
|
//!! loading and updating are different operations. The texture texture
|
|
//!! data cache will never shrink with the current implementation.
|
|
|
|
// Do not quit if the load fails because we want the repick to occur
|
|
// in MakeTextureCurrent in both the success and failure cases
|
|
__fastGenLoadTexImage(gc, tex);
|
|
|
|
__glGenMakeTextureCurrent(gc, tex, loadKey);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void FASTCALL __glGenFreeTexture(__GLcontext *gc, __GLtexture *tex, DWORD loadKey)
|
|
{
|
|
__GLGENcontext *gengc = (__GLGENcontext *)gc;
|
|
GENDRVACCEL *pDrvAccel;
|
|
|
|
if (GENACCEL(gc).texImage)
|
|
GENACCEL(gc).texImage = NULL;
|
|
|
|
if (tex->pvUser) {
|
|
(*gc->imports.free)(gc, tex->pvUser);
|
|
tex->pvUser = NULL;
|
|
}
|
|
|
|
#ifdef _MCD_
|
|
if (gengc->pMcdState && loadKey) {
|
|
GenMcdDeleteTexture(gengc, loadKey);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void FASTCALL __glGenUpdateTexturePalette(__GLcontext *gc, __GLtexture *tex,
|
|
DWORD loadKey, ULONG start,
|
|
ULONG count)
|
|
{
|
|
UCHAR *texBuffer;
|
|
GENTEXCACHE *pGenTex;
|
|
__GLcolorBuffer *cfb = gc->drawBuffer;
|
|
BYTE *pXlat = ((__GLGENcontext *)gc)->pajTranslateVector;
|
|
ULONG rBits, gBits, bBits;
|
|
ULONG rShift, gShift, bShift;
|
|
ULONG i, end;
|
|
ULONG *replaceBuffer;
|
|
|
|
ASSERTOPENGL(tex->paletteData != NULL,
|
|
"__GenUpdateTexturePalette: null texture data\n");
|
|
|
|
pGenTex = GetGenTexCache(gc, tex);
|
|
if (!pGenTex)
|
|
return;
|
|
|
|
GENACCEL(gc).texImageReplace = pGenTex->texImageReplace;
|
|
|
|
replaceBuffer = (ULONG *)(pGenTex->texImageReplace) + start;
|
|
texBuffer = (UCHAR *)(tex->paletteData + start);
|
|
|
|
rShift = cfb->redShift;
|
|
gShift = cfb->greenShift;
|
|
bShift = cfb->blueShift;
|
|
rBits = ((__GLGENcontext *)gc)->CurrentFormat.cRedBits;
|
|
gBits = ((__GLGENcontext *)gc)->CurrentFormat.cGreenBits;
|
|
bBits = ((__GLGENcontext *)gc)->CurrentFormat.cBlueBits;
|
|
|
|
end = start + count;
|
|
|
|
for (i = start; i < end; i++, texBuffer += 4) {
|
|
ULONG color;
|
|
|
|
color = ((((ULONG)texBuffer[2] << rBits) >> 8) << rShift) |
|
|
((((ULONG)texBuffer[1] << gBits) >> 8) << gShift) |
|
|
((((ULONG)texBuffer[0] << bBits) >> 8) << bShift);
|
|
|
|
if (GENACCEL(gc).bpp == 8)
|
|
color = pXlat[color & 0xff];
|
|
|
|
*replaceBuffer++ = (color | ((ULONG)texBuffer[3] << 24));
|
|
}
|
|
|
|
#ifdef _MCD_
|
|
if (((__GLGENcontext *)gc)->pMcdState && loadKey) {
|
|
GenMcdUpdateTexturePalette((__GLGENcontext *)gc, tex, loadKey, start,
|
|
count);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void FASTCALL __glGenDestroyAccelContext(__GLcontext *gc)
|
|
{
|
|
__GLGENcontext *genGc = (__GLGENcontext *)gc;
|
|
|
|
/* Free any platform-specific private data area */
|
|
|
|
if (genGc->pPrivateArea) {
|
|
|
|
if (GENACCEL(gc).pFastLineBuffer) {
|
|
__wglFree(gc, GENACCEL(gc).pFastLineBuffer);
|
|
#ifndef _CLIENTSIDE_
|
|
wglDeletePath(GENACCEL(gc).pFastLinePathobj);
|
|
#endif
|
|
}
|
|
|
|
genGc->pPrivateArea = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//
|
|
// The funtions below will go into the RX DLL when everything else is ready...
|
|
//
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
// RxGetInfo()
|
|
//
|
|
// Returns requested information on global, surface, or primitive-specific
|
|
// capabilities.
|
|
//****************************************************************************
|
|
|
|
ULONG WINAPI RxGetInfo(void *pSurface, RXGETINFO *prxGetInfo,
|
|
UCHAR *pInfo, ULONG infoSize)
|
|
{
|
|
ULONG retVal = FALSE;
|
|
|
|
return retVal;
|
|
}
|
|
|
|
|
|
//****************************************************************************
|
|
// RxCreateContext()
|
|
//
|
|
// Create a rendering context (RGBA or color-indexed) for the current
|
|
// hardware mode. This call will also initialize window-tracking for
|
|
// the context (which is associated with the specified window).
|
|
//****************************************************************************
|
|
|
|
RXHANDLE WINAPI RxCreateContext(void *pSurface, ULONG flags)
|
|
{
|
|
RXHANDLE retVal = (RXHANDLE)NULL;
|
|
HWND hwnd;
|
|
HDC hdc;
|
|
ULONG surfaceFlags;
|
|
|
|
return (RXHANDLE)retVal;
|
|
}
|
|
|
|
|
|
//****************************************************************************
|
|
// RxCreateTexture()
|
|
//
|
|
// Associates a surface with a 3D DDI handle.
|
|
//****************************************************************************
|
|
|
|
RXHANDLE WINAPI RxCreateTexture(RXHANDLE hrxRc, VOID *pSurface, ULONG flags)
|
|
{
|
|
RXHANDLE hrx = (RXHANDLE)NULL;
|
|
|
|
return (RXHANDLE)hrx;
|
|
}
|
|
|
|
|
|
//****************************************************************************
|
|
// RxCreateExecMem()
|
|
//
|
|
// Creates a handle associated with the specified memory.
|
|
//****************************************************************************
|
|
|
|
RXHANDLE WINAPI RxCreateExecMem(RXHANDLE hrxRC, RXCREATEMEM *prxCreateMem)
|
|
{
|
|
RXHANDLE hrx = (RXHANDLE)NULL;
|
|
|
|
return hrx;
|
|
}
|
|
|
|
|
|
//****************************************************************************
|
|
// RxDeleteResource()
|
|
//
|
|
// Deletes the resource belonging to a rendering context (which currently
|
|
// can be texture resources), or the context itself and all associated
|
|
// resources.
|
|
//****************************************************************************
|
|
|
|
ULONG WINAPI RxDeleteResource(RXHANDLE hrxResource)
|
|
{
|
|
ULONG retVal = FALSE;
|
|
|
|
return retVal;
|
|
}
|
|
|
|
|
|
//****************************************************************************
|
|
// RxExecute()
|
|
//
|
|
//****************************************************************************
|
|
|
|
ULONG WINAPI RxExecute(RXEXECUTE *prxExec, ULONG flags)
|
|
{
|
|
HWND hWnd;
|
|
ULONG retVal = FALSE;
|
|
UCHAR *pMaxMem;
|
|
UCHAR *pMinMem;
|
|
|
|
return retVal;
|
|
}
|
|
|
|
ULONG WINAPI RxLockExecMem(RXHANDLE handle)
|
|
{
|
|
ULONG retVal = FALSE;
|
|
|
|
return retVal;
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI RxUnlockExecMem(RXHANDLE handle)
|
|
{
|
|
BOOL retVal = FALSE;
|
|
|
|
return retVal;
|
|
}
|
|
|
|
ULONG WINAPI RxSetContextState(RXEXECUTE *prxExec, ULONG state, ULONG *pState)
|
|
{
|
|
RXRECT *prxRect;
|
|
HWND hWnd;
|
|
ULONG retVal = FALSE;
|
|
|
|
return retVal;
|
|
}
|