From 1e723abc27bdc2ad675bce79467a7308c2966861 Mon Sep 17 00:00:00 2001 From: marha Date: Tue, 22 Dec 2009 18:34:14 +0000 Subject: Forgotten files in previous commit --- .../drivers/windows/gldirect/dx9/gld_driver_dx9.c | 1206 ++++++++++++++++++++ 1 file changed, 1206 insertions(+) create mode 100644 mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c (limited to 'mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c') diff --git a/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c new file mode 100644 index 000000000..c191564d6 --- /dev/null +++ b/mesalib/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c @@ -0,0 +1,1206 @@ +/**************************************************************************** +* +* Mesa 3-D graphics library +* Direct3D Driver Interface +* +* ======================================================================== +* +* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* ====================================================================== +* +* Language: ANSI C +* Environment: Windows 9x/2000/XP/XBox (Win32) +* +* Description: Driver interface code to Mesa +* +****************************************************************************/ + +//#include +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx9.h" + +#include "glheader.h" +#include "context.h" +#include "colormac.h" +#include "depth.h" +#include "extensions.h" +#include "macros.h" +#include "matrix.h" +// #include "mem.h" +//#include "mmath.h" +#include "mtypes.h" +#include "texformat.h" +#include "teximage.h" +#include "texstore.h" +#include "vbo/vbo.h" +#include "swrast_setup/swrast_setup.h" +#include "swrast_setup/ss_context.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +extern BOOL dglSwapBuffers(HDC hDC); + +// HACK: Hack the _33 member of the OpenGL perspective projection matrix +const float _fPersp_33 = 1.6f; + +//--------------------------------------------------------------------------- +// Internal functions +//--------------------------------------------------------------------------- + +void _gld_mesa_warning( + __GLcontext *gc, + char *str) +{ + // Intercept Mesa's internal warning mechanism + gldLogPrintf(GLDLOG_WARN, "Mesa warning: %s", str); +} + +//--------------------------------------------------------------------------- + +void _gld_mesa_fatal( + __GLcontext *gc, + char *str) +{ + // Intercept Mesa's internal fatal-message mechanism + gldLogPrintf(GLDLOG_CRITICAL, "Mesa FATAL: %s", str); + + // Mesa calls abort(0) here. + ddlogClose(); + exit(0); +} + +//--------------------------------------------------------------------------- + +D3DSTENCILOP _gldConvertStencilOp( + GLenum StencilOp) +{ + // Used by Stencil: pass, fail and zfail + + switch (StencilOp) { + case GL_KEEP: + return D3DSTENCILOP_KEEP; + case GL_ZERO: + return D3DSTENCILOP_ZERO; + case GL_REPLACE: + return D3DSTENCILOP_REPLACE; + case GL_INCR: + return D3DSTENCILOP_INCRSAT; + case GL_DECR: + return D3DSTENCILOP_DECRSAT; + case GL_INVERT: + return D3DSTENCILOP_INVERT; + case GL_INCR_WRAP_EXT: // GL_EXT_stencil_wrap + return D3DSTENCILOP_INCR; + case GL_DECR_WRAP_EXT: // GL_EXT_stencil_wrap + return D3DSTENCILOP_DECR; + } + +#ifdef _DEBUG + gldLogMessage(GLDLOG_ERROR, "_gldConvertStencilOp: Unknown StencilOp\n"); +#endif + + return D3DSTENCILOP_KEEP; +} + +//--------------------------------------------------------------------------- + +D3DCMPFUNC _gldConvertCompareFunc( + GLenum CmpFunc) +{ + // Used for Alpha func, depth func and stencil func. + + switch (CmpFunc) { + case GL_NEVER: + return D3DCMP_NEVER; + case GL_LESS: + return D3DCMP_LESS; + case GL_EQUAL: + return D3DCMP_EQUAL; + case GL_LEQUAL: + return D3DCMP_LESSEQUAL; + case GL_GREATER: + return D3DCMP_GREATER; + case GL_NOTEQUAL: + return D3DCMP_NOTEQUAL; + case GL_GEQUAL: + return D3DCMP_GREATEREQUAL; + case GL_ALWAYS: + return D3DCMP_ALWAYS; + }; + +#ifdef _DEBUG + gldLogMessage(GLDLOG_ERROR, "_gldConvertCompareFunc: Unknown CompareFunc\n"); +#endif + + return D3DCMP_ALWAYS; +} + +//--------------------------------------------------------------------------- + +D3DBLEND _gldConvertBlendFunc( + GLenum blend, + GLenum DefaultBlend) +{ + switch (blend) { + case GL_ZERO: + return D3DBLEND_ZERO; + case GL_ONE: + return D3DBLEND_ONE; + case GL_DST_COLOR: + return D3DBLEND_DESTCOLOR; + case GL_SRC_COLOR: + return D3DBLEND_SRCCOLOR; + case GL_ONE_MINUS_DST_COLOR: + return D3DBLEND_INVDESTCOLOR; + case GL_ONE_MINUS_SRC_COLOR: + return D3DBLEND_INVSRCCOLOR; + case GL_SRC_ALPHA: + return D3DBLEND_SRCALPHA; + case GL_ONE_MINUS_SRC_ALPHA: + return D3DBLEND_INVSRCALPHA; + case GL_DST_ALPHA: + return D3DBLEND_DESTALPHA; + case GL_ONE_MINUS_DST_ALPHA: + return D3DBLEND_INVDESTALPHA; + case GL_SRC_ALPHA_SATURATE: + return D3DBLEND_SRCALPHASAT; + } + +#ifdef _DEBUG + gldLogMessage(GLDLOG_ERROR, "_gldConvertBlendFunc: Unknown BlendFunc\n"); +#endif + + return DefaultBlend; +} + +//--------------------------------------------------------------------------- +// Misc. functions +//--------------------------------------------------------------------------- + +void gld_Noop_DX9( + GLcontext *ctx) +{ +#ifdef _DEBUG + gldLogMessage(GLDLOG_ERROR, "gld_Noop called!\n"); +#endif +} + +//--------------------------------------------------------------------------- + +void gld_Error_DX9( + GLcontext *ctx) +{ +#ifdef _DEBUG + // Quite useless. +// gldLogMessage(GLDLOG_ERROR, "ctx->Driver.Error called!\n"); +#endif +} + +//--------------------------------------------------------------------------- +// Required Mesa functions +//--------------------------------------------------------------------------- + +static GLboolean gld_set_draw_buffer_DX9( + GLcontext *ctx, + GLenum mode) +{ + (void) ctx; + if ((mode==GL_FRONT_LEFT) || (mode == GL_BACK_LEFT)) { + return GL_TRUE; + } + else { + return GL_FALSE; + } +} + +//--------------------------------------------------------------------------- + +static void gld_set_read_buffer_DX9( + GLcontext *ctx, + GLframebuffer *buffer, + GLenum mode) +{ + /* separate read buffer not supported */ +/* + ASSERT(buffer == ctx->DrawBuffer); + ASSERT(mode == GL_FRONT_LEFT); +*/ +} + +//--------------------------------------------------------------------------- + +void gld_Clear_DX9( + GLcontext *ctx, + GLbitfield mask, + GLboolean all, + GLint x, + GLint y, + GLint width, + GLint height) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + DWORD dwFlags = 0; + D3DCOLOR Color = 0; + float Z = 0.0f; + DWORD Stencil = 0; + D3DRECT d3dClearRect; + + // TODO: Colourmask + const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask; + + if (!gld->pDev) + return; + + if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) { + GLubyte col[4]; + CLAMPED_FLOAT_TO_UBYTE(col[0], ctx->Color.ClearColor[0]); + CLAMPED_FLOAT_TO_UBYTE(col[1], ctx->Color.ClearColor[1]); + CLAMPED_FLOAT_TO_UBYTE(col[2], ctx->Color.ClearColor[2]); + CLAMPED_FLOAT_TO_UBYTE(col[3], ctx->Color.ClearColor[3]); + dwFlags |= D3DCLEAR_TARGET; + Color = D3DCOLOR_RGBA(col[0], col[1], col[2], col[3]); + } + + if (mask & DD_DEPTH_BIT) { + // D3D8 will fail the Clear call if we try and clear a + // depth buffer and we haven't created one. + // Also, some apps try and clear a depth buffer, + // when a depth buffer hasn't been requested by the app. + if (ctx->Visual.depthBits == 0) { + mask &= ~DD_DEPTH_BIT; // Remove depth bit from mask + } else { + dwFlags |= D3DCLEAR_ZBUFFER; + Z = ctx->Depth.Clear; + } + } + + if (mask & DD_STENCIL_BIT) { + if (ctx->Visual.stencilBits == 0) { + // No stencil bits in depth buffer + mask &= ~DD_STENCIL_BIT; // Remove stencil bit from mask + } else { + dwFlags |= D3DCLEAR_STENCIL; + Stencil = ctx->Stencil.Clear; + } + } + + // Some apps do really weird things with the rect, such as Quake3. + if ((x < 0) || (y < 0) || (width <= 0) || (height <= 0)) { + all = GL_TRUE; + } + + if (!all) { + // Calculate clear subrect + d3dClearRect.x1 = x; + d3dClearRect.y1 = gldCtx->dwHeight - (y + height); + d3dClearRect.x2 = x + width; + d3dClearRect.y2 = d3dClearRect.y1 + height; +// gldLogPrintf(GLDLOG_INFO, "Rect %d,%d %d,%d", x,y,width,height); + } + + // dwFlags will be zero if there's nothing to clear + if (dwFlags) { + _GLD_DX9_DEV(Clear( + gld->pDev, + all ? 0 : 1, + all ? NULL : &d3dClearRect, + dwFlags, + Color, Z, Stencil)); + } + + if (mask & DD_ACCUM_BIT) { + // Clear accumulation buffer + } +} + +//--------------------------------------------------------------------------- + +// Mesa 5: Parameter change +static void gld_buffer_size_DX9( +// GLcontext *ctx, + GLframebuffer *fb, + GLuint *width, + GLuint *height) +{ +// GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + + *width = fb->Width; // gldCtx->dwWidth; + *height = fb->Height; // gldCtx->dwHeight; +} + +//--------------------------------------------------------------------------- + +static void gld_Finish_DX9( + GLcontext *ctx) +{ +} + +//--------------------------------------------------------------------------- + +static void gld_Flush_DX9( + GLcontext *ctx) +{ + GLD_context *gld = GLD_GET_CONTEXT(ctx); + + // TODO: Detect apps that glFlush() then SwapBuffers() ? + + if (gld->EmulateSingle) { + // Emulating a single-buffered context. + // [Direct3D doesn't allow rendering to front buffer] + dglSwapBuffers(gld->hDC); + } +} + +//--------------------------------------------------------------------------- + +void gld_NEW_STENCIL( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + // Two-sided stencil. New for Mesa 5 + const GLuint uiFace = 0UL; + + struct gl_stencil_attrib *pStencil = &ctx->Stencil; + + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILENABLE, pStencil->Enabled ? TRUE : FALSE)); + if (pStencil->Enabled) { + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILFUNC, _gldConvertCompareFunc(pStencil->Function[uiFace]))); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILREF, pStencil->Ref[uiFace])); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILMASK, pStencil->ValueMask[uiFace])); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILWRITEMASK, pStencil->WriteMask[uiFace])); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILFAIL, _gldConvertStencilOp(pStencil->FailFunc[uiFace]))); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILZFAIL, _gldConvertStencilOp(pStencil->ZFailFunc[uiFace]))); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILPASS, _gldConvertStencilOp(pStencil->ZPassFunc[uiFace]))); + } +} + +//--------------------------------------------------------------------------- + +void gld_NEW_COLOR( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + DWORD dwFlags = 0; + D3DBLEND src; + D3DBLEND dest; + + // Alpha func + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ALPHAFUNC, _gldConvertCompareFunc(ctx->Color.AlphaFunc))); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ALPHAREF, (DWORD)ctx->Color.AlphaRef)); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ALPHATESTENABLE, ctx->Color.AlphaEnabled)); + + // Blend func + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ALPHABLENDENABLE, ctx->Color.BlendEnabled)); + src = _gldConvertBlendFunc(ctx->Color.BlendSrcRGB, GL_ONE); + dest = _gldConvertBlendFunc(ctx->Color.BlendDstRGB, GL_ZERO); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SRCBLEND, src)); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_DESTBLEND, dest)); + + // Color mask + if (ctx->Color.ColorMask[0]) dwFlags |= D3DCOLORWRITEENABLE_RED; + if (ctx->Color.ColorMask[1]) dwFlags |= D3DCOLORWRITEENABLE_GREEN; + if (ctx->Color.ColorMask[2]) dwFlags |= D3DCOLORWRITEENABLE_BLUE; + if (ctx->Color.ColorMask[3]) dwFlags |= D3DCOLORWRITEENABLE_ALPHA; + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_COLORWRITEENABLE, dwFlags)); +} + +//--------------------------------------------------------------------------- + +void gld_NEW_DEPTH( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ZENABLE, ctx->Depth.Test ? D3DZB_TRUE : D3DZB_FALSE)); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ZFUNC, _gldConvertCompareFunc(ctx->Depth.Func))); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ZWRITEENABLE, ctx->Depth.Mask ? TRUE : FALSE)); +} + +//--------------------------------------------------------------------------- + +void gld_NEW_POLYGON( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + D3DFILLMODE d3dFillMode = D3DFILL_SOLID; + D3DCULL d3dCullMode = D3DCULL_NONE; + float fOffset = 0; // Changed from int to float for DX9 + + // Fillmode + switch (ctx->Polygon.FrontMode) { + case GL_POINT: + d3dFillMode = D3DFILL_POINT; + break; + case GL_LINE: + d3dFillMode = D3DFILL_WIREFRAME; + break; + case GL_FILL: + d3dFillMode = D3DFILL_SOLID; + break; + } + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FILLMODE, d3dFillMode)); + + if (ctx->Polygon.CullFlag) { + switch (ctx->Polygon.CullFaceMode) { + case GL_BACK: + if (ctx->Polygon.FrontFace == GL_CCW) + d3dCullMode = D3DCULL_CW; + else + d3dCullMode = D3DCULL_CCW; + break; + case GL_FRONT: + if (ctx->Polygon.FrontFace == GL_CCW) + d3dCullMode = D3DCULL_CCW; + else + d3dCullMode = D3DCULL_CW; + break; + case GL_FRONT_AND_BACK: + d3dCullMode = D3DCULL_NONE; + break; + default: + break; + } + } else { + d3dCullMode = D3DCULL_NONE; + } +// d3dCullMode = D3DCULL_NONE; // FOR DEBUGGING + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_CULLMODE, d3dCullMode)); + + // Polygon offset + // ZBIAS ranges from 0 to 16 and can only move towards the viewer + // Mesa5: ctx->Polygon._OffsetAny removed + if (ctx->Polygon.OffsetFill) { + fOffset = ctx->Polygon.OffsetUnits; +// if (iOffset < 0.0f) +// iOffset = -iOffset; +// else +// iOffset = 0.0f; // D3D can't push away + } + // NOTE: SetRenderState() required a DWORD, so need to cast + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_DEPTHBIAS, *((DWORD*)&fOffset))); +} + +//--------------------------------------------------------------------------- + +void gld_NEW_FOG( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + D3DCOLOR d3dFogColour; + D3DFOGMODE d3dFogMode = D3DFOG_LINEAR; + + // TODO: Fog is calculated seperately in the Mesa pipeline + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGENABLE, FALSE)); + return; + + // Fog enable + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGENABLE, ctx->Fog.Enabled)); + if (!ctx->Fog.Enabled) { + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGTABLEMODE, D3DFOG_NONE)); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGVERTEXMODE, D3DFOG_NONE)); + return; // If disabled, don't bother setting any fog state + } + + // Fog colour + d3dFogColour = D3DCOLOR_COLORVALUE( ctx->Fog.Color[0], + ctx->Fog.Color[1], + ctx->Fog.Color[2], + ctx->Fog.Color[3]); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGCOLOR, d3dFogColour)); + + // Fog density + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGDENSITY, *((DWORD*) (&ctx->Fog.Density)))); + + // Fog start + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGSTART, *((DWORD*) (&ctx->Fog.Start)))); + + // Fog end + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGEND, *((DWORD*) (&ctx->Fog.End)))); + + // Fog mode + switch (ctx->Fog.Mode) { + case GL_LINEAR: + d3dFogMode = D3DFOG_LINEAR; + break; + case GL_EXP: + d3dFogMode = D3DFOG_EXP; + break; + case GL_EXP2: + d3dFogMode = D3DFOG_EXP2; + break; + } + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGTABLEMODE, d3dFogMode)); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGVERTEXMODE, D3DFOG_NONE)); +} + +//--------------------------------------------------------------------------- + +void gld_NEW_LIGHT( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + DWORD dwSpecularEnable; + + // Shademode + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SHADEMODE, (ctx->Light.ShadeModel == GL_SMOOTH) ? D3DSHADE_GOURAUD : D3DSHADE_FLAT)); + + // Separate specular colour + if (ctx->Light.Enabled) + dwSpecularEnable = (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) ? TRUE: FALSE; + else + dwSpecularEnable = FALSE; + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SPECULARENABLE, dwSpecularEnable)); +} + +//--------------------------------------------------------------------------- + +void gld_NEW_MODELVIEW( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + D3DMATRIX m; + //GLfloat *pM = ctx->ModelView.m; + // Mesa5: Model-view is now a stack + GLfloat *pM = ctx->ModelviewMatrixStack.Top->m; + m._11 = pM[0]; + m._12 = pM[1]; + m._13 = pM[2]; + m._14 = pM[3]; + m._21 = pM[4]; + m._22 = pM[5]; + m._23 = pM[6]; + m._24 = pM[7]; + m._31 = pM[8]; + m._32 = pM[9]; + m._33 = pM[10]; + m._34 = pM[11]; + m._41 = pM[12]; + m._42 = pM[13]; + m._43 = pM[14]; + m._44 = pM[15]; + + gld->matModelView = m; +} + +//--------------------------------------------------------------------------- + +void gld_NEW_PROJECTION( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + D3DMATRIX m; + //GLfloat *pM = ctx->ProjectionMatrix.m; + // Mesa 5: Now a stack + GLfloat *pM = ctx->ProjectionMatrixStack.Top->m; + m._11 = pM[0]; + m._12 = pM[1]; + m._13 = pM[2]; + m._14 = pM[3]; + + m._21 = pM[4]; + m._22 = pM[5]; + m._23 = pM[6]; + m._24 = pM[7]; + + m._31 = pM[8]; + m._32 = pM[9]; + m._33 = pM[10] / _fPersp_33; // / 1.6f; + m._34 = pM[11]; + + m._41 = pM[12]; + m._42 = pM[13]; + m._43 = pM[14] / 2.0f; + m._44 = pM[15]; + + gld->matProjection = m; +} + +//--------------------------------------------------------------------------- +/* +void gldFrustumHook_DX9( + GLdouble left, + GLdouble right, + GLdouble bottom, + GLdouble top, + GLdouble nearval, + GLdouble farval) +{ + GET_CURRENT_CONTEXT(ctx); + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + // Pass values on to Mesa first (in case we mess with them) + _mesa_Frustum(left, right, bottom, top, nearval, farval); + + _fPersp_33 = farval / (nearval - farval); + +// ddlogPrintf(GLDLOG_SYSTEM, "Frustum: %f", farval/nearval); +} + +//--------------------------------------------------------------------------- + +void gldOrthoHook_DX9( + GLdouble left, + GLdouble right, + GLdouble bottom, + GLdouble top, + GLdouble nearval, + GLdouble farval) +{ + GET_CURRENT_CONTEXT(ctx); + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + // Pass values on to Mesa first (in case we mess with them) + _mesa_Ortho(left, right, bottom, top, nearval, farval); + + _fPersp_33 = 1.6f; + +// ddlogPrintf(GLDLOG_SYSTEM, "Ortho: %f", farval/nearval); +} +*/ +//--------------------------------------------------------------------------- + +void gld_NEW_VIEWPORT( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + D3DVIEWPORT9 d3dvp; +// GLint x, y; +// GLsizei w, h; + + // Set depth range + _GLD_DX9_DEV(GetViewport(gld->pDev, &d3dvp)); + // D3D can't do Quake1/Quake2 z-trick + if (ctx->Viewport.Near <= ctx->Viewport.Far) { + d3dvp.MinZ = ctx->Viewport.Near; + d3dvp.MaxZ = ctx->Viewport.Far; + } else { + d3dvp.MinZ = ctx->Viewport.Far; + d3dvp.MaxZ = ctx->Viewport.Near; + } +/* x = ctx->Viewport.X; + y = ctx->Viewport.Y; + w = ctx->Viewport.Width; + h = ctx->Viewport.Height; + if (x < 0) x = 0; + if (y < 0) y = 0; + if (w > gldCtx->dwWidth) w = gldCtx->dwWidth; + if (h > gldCtx->dwHeight) h = gldCtx->dwHeight; + // Ditto for D3D viewport dimensions + if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x; + if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y; + d3dvp.X = x; + d3dvp.Y = gldCtx->dwHeight - (y + h); + d3dvp.Width = w; + d3dvp.Height = h;*/ + _GLD_DX9_DEV(SetViewport(gld->pDev, &d3dvp)); + +// gld->fFlipWindowY = (float)gldCtx->dwHeight; +} + +//--------------------------------------------------------------------------- + +void gld_NEW_SCISSOR( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + // Bail if IHV driver cannot scissor + if (!gld->bCanScissor) + return; + + // Set scissor rect + if (ctx->Scissor.Enabled) { + RECT rcRect; + // Keep in mind that RECT's need an extra row and column + rcRect.left = ctx->Scissor.X; + rcRect.right = ctx->Scissor.X + ctx->Scissor.Width; // + 1; + rcRect.top = gldCtx->dwHeight - (ctx->Scissor.Y + ctx->Scissor.Height); + rcRect.bottom = rcRect.top + ctx->Scissor.Height; + IDirect3DDevice9_SetScissorRect(gld->pDev, &rcRect); + } + + // Enable/disable scissor as required + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SCISSORTESTENABLE, ctx->Scissor.Enabled)); +} + +//--------------------------------------------------------------------------- + +__inline BOOL _gldAnyEvalEnabled( + GLcontext *ctx) +{ + struct gl_eval_attrib *eval = &ctx->Eval; + + if ((eval->AutoNormal) || + (eval->Map1Color4) || + (eval->Map1Index) || + (eval->Map1Normal) || + (eval->Map1TextureCoord1) || + (eval->Map1TextureCoord2) || + (eval->Map1TextureCoord3) || + (eval->Map1TextureCoord4) || + (eval->Map1Vertex3) || + (eval->Map1Vertex4) || + (eval->Map2Color4) || + (eval->Map2Index) || + (eval->Map2Normal) || + (eval->Map2TextureCoord1) || + (eval->Map2TextureCoord2) || + (eval->Map2TextureCoord3) || + (eval->Map2TextureCoord4) || + (eval->Map2Vertex3) || + (eval->Map2Vertex4) + ) + return TRUE; + + return FALSE; +} + +//--------------------------------------------------------------------------- + +BOOL _gldChooseInternalPipeline( + GLcontext *ctx, + GLD_driver_dx9 *gld) +{ +// return TRUE; // DEBUGGING: ALWAYS USE MESA +// return FALSE; // DEBUGGING: ALWAYS USE D3D + + if ((glb.dwTnL == GLDS_TNL_MESA) || (gld->bHasHWTnL == FALSE)) + { + gld->PipelineUsage.qwMesa.QuadPart++; + return TRUE; // Force Mesa TnL + } + + if ((ctx->Light.Enabled) || + (1) || + (ctx->Texture._TexGenEnabled) || + (ctx->Texture._TexMatEnabled) || +// (ctx->Transform._AnyClip) || + (ctx->Scissor.Enabled) || + _gldAnyEvalEnabled(ctx) // Put this last so we can early-out + ) + { + gld->PipelineUsage.qwMesa.QuadPart++; + return TRUE; + } + + gld->PipelineUsage.qwD3DFVF.QuadPart++; + return FALSE; + +/* // Force Mesa pipeline? + if (glb.dwTnL == GLDS_TNL_MESA) { + gld->PipelineUsage.dwMesa.QuadPart++; + return GLD_PIPELINE_MESA; + } + + // Test for functionality not exposed in the D3D pathways + if ((ctx->Texture._GenFlags)) { + gld->PipelineUsage.dwMesa.QuadPart++; + return GLD_PIPELINE_MESA; + } + + // Now decide if vertex shader can be used. + // If two sided lighting is enabled then we must either + // use Mesa TnL or the vertex shader + if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) { + if (gld->VStwosidelight.hShader && !ctx->Fog.Enabled) { + // Use Vertex Shader + gld->PipelineUsage.dwD3D2SVS.QuadPart++; + return GLD_PIPELINE_D3D_VS_TWOSIDE; + } else { + // Use Mesa TnL + gld->PipelineUsage.dwMesa.QuadPart++; + return GLD_PIPELINE_MESA; + } + } + + // Must be D3D fixed-function pipeline + gld->PipelineUsage.dwD3DFVF.QuadPart++; + return GLD_PIPELINE_D3D_FVF; +*/ +} + +//--------------------------------------------------------------------------- + +void gld_update_state_DX9( + GLcontext *ctx, + GLuint new_state) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLD_pb_dx9 *gldPB; + + if (!gld || !gld->pDev) + return; + + _swsetup_InvalidateState( ctx, new_state ); + _vbo_InvalidateState( ctx, new_state ); + _tnl_InvalidateState( ctx, new_state ); + + // SetupIndex will be used in the pipelines for choosing setup function + if ((ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE | DD_SEPARATE_SPECULAR)) || + (ctx->Fog.Enabled)) + { + if (ctx->_TriangleCaps & DD_FLATSHADE) + gld->iSetupFunc = GLD_SI_FLAT_EXTRAS; + else + gld->iSetupFunc = GLD_SI_SMOOTH_EXTRAS; + } else { + if (ctx->_TriangleCaps & DD_FLATSHADE) + gld->iSetupFunc = GLD_SI_FLAT; // Setup flat shade + texture + else + gld->iSetupFunc = GLD_SI_SMOOTH; // Setup smooth shade + texture + } + + gld->bUseMesaTnL = _gldChooseInternalPipeline(ctx, gld); + if (gld->bUseMesaTnL) { + gldPB = &gld->PB2d; + _GLD_DX9_DEV(SetSoftwareVertexProcessing(gld->pDev, TRUE)); + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_CLIPPING, FALSE)); + _GLD_DX9_DEV(SetVertexShader(gld->pDev, NULL)); + _GLD_DX9_DEV(SetFVF(gld->pDev, gldPB->dwFVF)); + } else { + gldPB = &gld->PB3d; + _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_CLIPPING, TRUE)); +// if (gld->TnLPipeline == GLD_PIPELINE_D3D_VS_TWOSIDE) { +// _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->VStwosidelight.bHardware)); +// _GLD_DX9_DEV(SetVertexShader(gld->pDev, gld->VStwosidelight.hShader)); +// } else { +// _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->bHasHWTnL)); + _GLD_DX9_DEV(SetSoftwareVertexProcessing(gld->pDev, !gld->bHasHWTnL)); + _GLD_DX9_DEV(SetVertexShader(gld->pDev, NULL)); + _GLD_DX9_DEV(SetFVF(gld->pDev, gldPB->dwFVF)); +// } + } + +#define _GLD_TEST_STATE(a) \ + if (new_state & (a)) { \ + gld##a(ctx); \ + new_state &= ~(a); \ + } + +#define _GLD_TEST_STATE_DX9(a) \ + if (new_state & (a)) { \ + gld##a##_DX9(ctx); \ + new_state &= ~(a); \ + } + +#define _GLD_IGNORE_STATE(a) new_state &= ~(a); + +// if (!gld->bUseMesaTnL) { + // Not required if Mesa is doing the TnL. + // Problem: If gld->bUseMesaTnL is TRUE when these are signaled, + // then we'll miss updating the D3D TnL pipeline. + // Therefore, don't test for gld->bUseMesaTnL + _GLD_TEST_STATE(_NEW_MODELVIEW); + _GLD_TEST_STATE(_NEW_PROJECTION); +// } + + _GLD_TEST_STATE_DX9(_NEW_TEXTURE); // extern, so guard with _DX9 + _GLD_TEST_STATE(_NEW_COLOR); + _GLD_TEST_STATE(_NEW_DEPTH); + _GLD_TEST_STATE(_NEW_POLYGON); + _GLD_TEST_STATE(_NEW_STENCIL); + _GLD_TEST_STATE(_NEW_FOG); + _GLD_TEST_STATE(_NEW_LIGHT); + _GLD_TEST_STATE(_NEW_VIEWPORT); + + _GLD_IGNORE_STATE(_NEW_TRANSFORM); + + // Scissor Test: New for DX9 + _GLD_TEST_STATE(_NEW_SCISSOR); + +// Stubs for future use. +/* _GLD_TEST_STATE(_NEW_TEXTURE_MATRIX); + _GLD_TEST_STATE(_NEW_COLOR_MATRIX); + _GLD_TEST_STATE(_NEW_ACCUM); + _GLD_TEST_STATE(_NEW_EVAL); + _GLD_TEST_STATE(_NEW_HINT); + _GLD_TEST_STATE(_NEW_LINE); + _GLD_TEST_STATE(_NEW_PIXEL); + _GLD_TEST_STATE(_NEW_POINT); + _GLD_TEST_STATE(_NEW_POLYGONSTIPPLE); + _GLD_TEST_STATE(_NEW_PACKUNPACK); + _GLD_TEST_STATE(_NEW_ARRAY); + _GLD_TEST_STATE(_NEW_RENDERMODE); + _GLD_TEST_STATE(_NEW_BUFFERS); + _GLD_TEST_STATE(_NEW_MULTISAMPLE); +*/ + +// For debugging. +#if 0 +#define _GLD_TEST_UNHANDLED_STATE(a) \ + if (new_state & (a)) { \ + gldLogMessage(GLDLOG_ERROR, "Unhandled " #a "\n"); \ + } + _GLD_TEST_UNHANDLED_STATE(_NEW_TEXTURE_MATRIX); + _GLD_TEST_UNHANDLED_STATE(_NEW_COLOR_MATRIX); + _GLD_TEST_UNHANDLED_STATE(_NEW_ACCUM); + _GLD_TEST_UNHANDLED_STATE(_NEW_EVAL); + _GLD_TEST_UNHANDLED_STATE(_NEW_HINT); + _GLD_TEST_UNHANDLED_STATE(_NEW_LINE); + _GLD_TEST_UNHANDLED_STATE(_NEW_PIXEL); + _GLD_TEST_UNHANDLED_STATE(_NEW_POINT); + _GLD_TEST_UNHANDLED_STATE(_NEW_POLYGONSTIPPLE); +// _GLD_TEST_UNHANDLED_STATE(_NEW_SCISSOR); + _GLD_TEST_UNHANDLED_STATE(_NEW_PACKUNPACK); + _GLD_TEST_UNHANDLED_STATE(_NEW_ARRAY); + _GLD_TEST_UNHANDLED_STATE(_NEW_RENDERMODE); + _GLD_TEST_UNHANDLED_STATE(_NEW_BUFFERS); + _GLD_TEST_UNHANDLED_STATE(_NEW_MULTISAMPLE); +#undef _GLD_UNHANDLED_STATE +#endif + +#undef _GLD_TEST_STATE +} + +//--------------------------------------------------------------------------- +// Viewport +//--------------------------------------------------------------------------- + +void gld_Viewport_DX9( + GLcontext *ctx, + GLint x, + GLint y, + GLsizei w, + GLsizei h) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + D3DVIEWPORT9 d3dvp; + + if (!gld || !gld->pDev) + return; + + // This is a hack. When the app is minimized, Mesa passes + // w=1 and h=1 for viewport dimensions. Without this test + // we get a GPF in gld_wgl_resize_buffers(). + if ((w==1) && (h==1)) + return; + + // Call ResizeBuffersMESA. This function will early-out + // if no resize is needed. + //ctx->Driver.ResizeBuffersMESA(ctx); + // Mesa 5: Changed parameters + ctx->Driver.ResizeBuffers(gldCtx->glBuffer); + +#if 0 + ddlogPrintf(GLDLOG_SYSTEM, ">> Viewport x=%d y=%d w=%d h=%d", x,y,w,h); +#endif + + // ** D3D viewport must not be outside the render target surface ** + // Sanity check the GL viewport dimensions + if (x < 0) x = 0; + if (y < 0) y = 0; + if (w > gldCtx->dwWidth) w = gldCtx->dwWidth; + if (h > gldCtx->dwHeight) h = gldCtx->dwHeight; + // Ditto for D3D viewport dimensions + if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x; + if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y; + + d3dvp.X = x; + d3dvp.Y = gldCtx->dwHeight - (y + h); + d3dvp.Width = w; + d3dvp.Height = h; + if (ctx->Viewport.Near <= ctx->Viewport.Far) { + d3dvp.MinZ = ctx->Viewport.Near; + d3dvp.MaxZ = ctx->Viewport.Far; + } else { + d3dvp.MinZ = ctx->Viewport.Far; + d3dvp.MaxZ = ctx->Viewport.Near; + } + + // TODO: DEBUGGING +// d3dvp.MinZ = 0.0f; +// d3dvp.MaxZ = 1.0f; + + _GLD_DX9_DEV(SetViewport(gld->pDev, &d3dvp)); + +} + +//--------------------------------------------------------------------------- + +extern BOOL dglWglResizeBuffers(GLcontext *ctx, BOOL bDefaultDriver); + +// Mesa 5: Parameter change +void gldResizeBuffers_DX9( +// GLcontext *ctx) + GLframebuffer *fb) +{ + GET_CURRENT_CONTEXT(ctx); + dglWglResizeBuffers(ctx, TRUE); +} + +//--------------------------------------------------------------------------- +#ifdef _DEBUG +// This is only for debugging. +// To use, plug into ctx->Driver.Enable pointer below. +void gld_Enable( + GLcontext *ctx, + GLenum e, + GLboolean b) +{ + char buf[1024]; + sprintf(buf, "Enable: %s (%s)\n", _mesa_lookup_enum_by_nr(e), b?"TRUE":"FALSE"); + ddlogMessage(DDLOG_SYSTEM, buf); +} +#endif +//--------------------------------------------------------------------------- +// Driver pointer setup +//--------------------------------------------------------------------------- + +extern const GLubyte* _gldGetStringGeneric(GLcontext*, GLenum); + +void gldSetupDriverPointers_DX9( + GLcontext *ctx) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + TNLcontext *tnl = TNL_CONTEXT(ctx); + + // Mandatory functions + ctx->Driver.GetString = _gldGetStringGeneric; + ctx->Driver.UpdateState = gld_update_state_DX9; + ctx->Driver.Clear = gld_Clear_DX9; + ctx->Driver.DrawBuffer = gld_set_draw_buffer_DX9; + ctx->Driver.GetBufferSize = gld_buffer_size_DX9; + ctx->Driver.Finish = gld_Finish_DX9; + ctx->Driver.Flush = gld_Flush_DX9; + ctx->Driver.Error = gld_Error_DX9; + + // Hardware accumulation buffer + ctx->Driver.Accum = NULL; // TODO: gld_Accum; + + // Bitmap functions + ctx->Driver.CopyPixels = gld_CopyPixels_DX9; + ctx->Driver.DrawPixels = gld_DrawPixels_DX9; + ctx->Driver.ReadPixels = gld_ReadPixels_DX9; + ctx->Driver.Bitmap = gld_Bitmap_DX9; + + // Buffer resize + ctx->Driver.ResizeBuffers = gldResizeBuffers_DX9; + + // Texture image functions + ctx->Driver.ChooseTextureFormat = gld_ChooseTextureFormat_DX9; + ctx->Driver.TexImage1D = gld_TexImage1D_DX9; + ctx->Driver.TexImage2D = gld_TexImage2D_DX9; + ctx->Driver.TexImage3D = _mesa_store_teximage3d; + ctx->Driver.TexSubImage1D = gld_TexSubImage1D_DX9; + ctx->Driver.TexSubImage2D = gld_TexSubImage2D_DX9; + ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d; + + ctx->Driver.CopyTexImage1D = gldCopyTexImage1D_DX9; //NULL; + ctx->Driver.CopyTexImage2D = gldCopyTexImage2D_DX9; //NULL; + ctx->Driver.CopyTexSubImage1D = gldCopyTexSubImage1D_DX9; //NULL; + ctx->Driver.CopyTexSubImage2D = gldCopyTexSubImage2D_DX9; //NULL; + ctx->Driver.CopyTexSubImage3D = gldCopyTexSubImage3D_DX9; + ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage; + + // Texture object functions + ctx->Driver.BindTexture = NULL; + ctx->Driver.NewTextureObject = NULL; // Not yet implemented by Mesa!; + ctx->Driver.DeleteTexture = gld_DeleteTexture_DX9; + ctx->Driver.PrioritizeTexture = NULL; + + // Imaging functionality + ctx->Driver.CopyColorTable = NULL; + ctx->Driver.CopyColorSubTable = NULL; + ctx->Driver.CopyConvolutionFilter1D = NULL; + ctx->Driver.CopyConvolutionFilter2D = NULL; + + // State changing functions + ctx->Driver.AlphaFunc = NULL; //gld_AlphaFunc; + ctx->Driver.BlendFuncSeparate = NULL; //gld_BlendFunc; + ctx->Driver.ClearColor = NULL; //gld_ClearColor; + ctx->Driver.ClearDepth = NULL; //gld_ClearDepth; + ctx->Driver.ClearStencil = NULL; //gld_ClearStencil; + ctx->Driver.ColorMask = NULL; //gld_ColorMask; + ctx->Driver.CullFace = NULL; //gld_CullFace; + ctx->Driver.ClipPlane = NULL; //gld_ClipPlane; + ctx->Driver.FrontFace = NULL; //gld_FrontFace; + ctx->Driver.DepthFunc = NULL; //gld_DepthFunc; + ctx->Driver.DepthMask = NULL; //gld_DepthMask; + ctx->Driver.DepthRange = NULL; + ctx->Driver.Enable = NULL; //gld_Enable; + ctx->Driver.Fogfv = NULL; //gld_Fogfv; + ctx->Driver.Hint = NULL; //gld_Hint; + ctx->Driver.Lightfv = NULL; //gld_Lightfv; + ctx->Driver.LightModelfv = NULL; //gld_LightModelfv; + ctx->Driver.LineStipple = NULL; //gld_LineStipple; + ctx->Driver.LineWidth = NULL; //gld_LineWidth; + ctx->Driver.LogicOpcode = NULL; //gld_LogicOpcode; + ctx->Driver.PointParameterfv = NULL; //gld_PointParameterfv; + ctx->Driver.PointSize = NULL; //gld_PointSize; + ctx->Driver.PolygonMode = NULL; //gld_PolygonMode; + ctx->Driver.PolygonOffset = NULL; //gld_PolygonOffset; + ctx->Driver.PolygonStipple = NULL; //gld_PolygonStipple; + ctx->Driver.RenderMode = NULL; //gld_RenderMode; + ctx->Driver.Scissor = NULL; //gld_Scissor; + ctx->Driver.ShadeModel = NULL; //gld_ShadeModel; + ctx->Driver.StencilFunc = NULL; //gld_StencilFunc; + ctx->Driver.StencilMask = NULL; //gld_StencilMask; + ctx->Driver.StencilOp = NULL; //gld_StencilOp; + ctx->Driver.TexGen = NULL; //gld_TexGen; + ctx->Driver.TexEnv = NULL; + ctx->Driver.TexParameter = NULL; + ctx->Driver.TextureMatrix = NULL; //gld_TextureMatrix; + ctx->Driver.Viewport = gld_Viewport_DX9; + + _swsetup_Wakeup(ctx); + + tnl->Driver.RunPipeline = _tnl_run_pipeline; + tnl->Driver.Render.ResetLineStipple = gld_ResetLineStipple_DX9; + tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon; + tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine; + + // Hook into glFrustum() and glOrtho() +// ctx->Exec->Frustum = gldFrustumHook_DX9; +// ctx->Exec->Ortho = gldOrthoHook_DX9; + +} + +//--------------------------------------------------------------------------- -- cgit v1.2.3