From 485438e2be08c6d57110101f76dd41a5f484a4ee Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Tue, 20 Apr 2004 11:13:11 +0000 Subject: add SciTech's GLDirect driver for Windows. This code is donated to Mesa which allows the usage of a Direct3D layer (DX7, DX8, DX9 or complete software fallback). No build system exists for this code yet, that will come..... --- .../drivers/windows/gldirect/dx9/gld_driver_dx9.c | 1205 ++++++++++++ src/mesa/drivers/windows/gldirect/dx9/gld_dx9.h | 327 ++++ src/mesa/drivers/windows/gldirect/dx9/gld_dxerr9.h | 77 + .../drivers/windows/gldirect/dx9/gld_ext_dx9.c | 344 ++++ .../windows/gldirect/dx9/gld_pipeline_dx9.c | 77 + .../windows/gldirect/dx9/gld_primitive_dx9.c | 1446 ++++++++++++++ .../drivers/windows/gldirect/dx9/gld_texture_dx9.c | 1965 ++++++++++++++++++++ .../windows/gldirect/dx9/gld_vb_d3d_render_dx9.c | 281 +++ .../windows/gldirect/dx9/gld_vb_mesa_render_dx9.c | 510 +++++ .../drivers/windows/gldirect/dx9/gld_wgl_dx9.c | 1345 ++++++++++++++ 10 files changed, 7577 insertions(+) create mode 100644 src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c create mode 100644 src/mesa/drivers/windows/gldirect/dx9/gld_dx9.h create mode 100644 src/mesa/drivers/windows/gldirect/dx9/gld_dxerr9.h create mode 100644 src/mesa/drivers/windows/gldirect/dx9/gld_ext_dx9.c create mode 100644 src/mesa/drivers/windows/gldirect/dx9/gld_pipeline_dx9.c create mode 100644 src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c create mode 100644 src/mesa/drivers/windows/gldirect/dx9/gld_texture_dx9.c create mode 100644 src/mesa/drivers/windows/gldirect/dx9/gld_vb_d3d_render_dx9.c create mode 100644 src/mesa/drivers/windows/gldirect/dx9/gld_vb_mesa_render_dx9.c create mode 100644 src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c (limited to 'src/mesa/drivers/windows/gldirect/dx9') diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c new file mode 100644 index 0000000000..96ad213f17 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c @@ -0,0 +1,1205 @@ +/**************************************************************************** +* +* 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 "texstore.h" +#include "array_cache/acache.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 ); + _ac_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.CreateTexture = 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.BlendFunc = 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; + +} + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_dx9.h b/src/mesa/drivers/windows/gldirect/dx9/gld_dx9.h new file mode 100644 index 0000000000..aec40ac9dd --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_dx9.h @@ -0,0 +1,327 @@ +/**************************************************************************** +* +* 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: GLDirect Direct3D 9.0 header file +* +****************************************************************************/ + +#ifndef _GLD_DX9_H +#define _GLD_DX9_H + +//--------------------------------------------------------------------------- +// Windows includes +//--------------------------------------------------------------------------- + +//#ifndef STRICT +//#define STRICT +//#endif + +//#define WIN32_LEAN_AND_MEAN +//#include +#include +#include + +// MS screwed up with the DX8.1 SDK - there's no compile-time +// method of compiling for 8.0 via the 8.1 SDK unless you +// "make sure you don't use any 8.1 interfaces". +// We CAN use 8.1 D3DX static functions, though - just not new 8.1 interfaces. +// +// D3D_SDK_VERSION is 120 for 8.0 (supported by Windows 95). +// D3D_SDK_VERSION is 220 for 8.1 (NOT supported by Windows 95). +// +//#define D3D_SDK_VERSION_DX9_SUPPORT_WIN95 120 +//#define D3D_SDK_VERSION_DX91 220 + +// Typedef for obtaining function from d3d8.dll +typedef IDirect3D9* (WINAPI *FNDIRECT3DCREATE9) (UINT); + + +//--------------------------------------------------------------------------- +// Defines +//--------------------------------------------------------------------------- + +#ifdef _DEBUG +#define _GLD_TEST_HRESULT(h) \ +{ \ + HRESULT _hr = (h); \ + if (FAILED(_hr)) { \ + gldLogError(GLDLOG_ERROR, #h, _hr); \ + } \ +} +#define _GLD_DX9(func) _GLD_TEST_HRESULT(IDirect3D9_##func##) +#define _GLD_DX9_DEV(func) _GLD_TEST_HRESULT(IDirect3DDevice9_##func##) +#define _GLD_DX9_VB(func) _GLD_TEST_HRESULT(IDirect3DVertexBuffer9_##func##) +#define _GLD_DX9_TEX(func) _GLD_TEST_HRESULT(IDirect3DTexture9_##func##) +#else +#define _GLD_DX9(func) IDirect3D9_##func +#define _GLD_DX9_DEV(func) IDirect3DDevice9_##func +#define _GLD_DX9_VB(func) IDirect3DVertexBuffer9_##func +#define _GLD_DX9_TEX(func) IDirect3DTexture9_##func +#endif + +#define SAFE_RELEASE(p) \ +{ \ + if (p) { \ + (p)->lpVtbl->Release(p); \ + (p) = NULL; \ + } \ +} + +#define SAFE_RELEASE_VB9(p) \ +{ \ + if (p) { \ + IDirect3DVertexBuffer9_Release((p)); \ + (p) = NULL; \ + } \ +} + +#define SAFE_RELEASE_SURFACE9(p) \ +{ \ + if (p) { \ + IDirect3DSurface9_Release((p)); \ + (p) = NULL; \ + } \ +} + +// Setup index. +enum { + GLD_SI_FLAT = 0, + GLD_SI_SMOOTH = 1, + GLD_SI_FLAT_EXTRAS = 2, + GLD_SI_SMOOTH_EXTRAS = 3, +}; +/* +// Internal pipeline +typedef enum { + GLD_PIPELINE_MESA = 0, // Mesa pipeline + GLD_PIPELINE_D3D_FVF = 1, // Direct3D Fixed-function pipeline + GLD_PIPELINE_D3D_VS_TWOSIDE = 2 // Direct3D two-sided-lighting vertex shader +} GLD_tnl_pipeline; +*/ +//--------------------------------------------------------------------------- +// Vertex definitions for Fixed-Function pipeline +//--------------------------------------------------------------------------- + +// +// NOTE: If the number of texture units is altered then most of +// the texture code will need to be revised. +// + +#define GLD_MAX_TEXTURE_UNITS_DX9 2 + +// +// 2D vertex transformed by Mesa +// +#define GLD_FVF_2D_VERTEX ( D3DFVF_XYZRHW | \ + D3DFVF_DIFFUSE | \ + D3DFVF_SPECULAR | \ + D3DFVF_TEX2) +typedef struct { + FLOAT x, y; // 2D raster coords + FLOAT sz; // Screen Z (depth) + FLOAT rhw; // Reciprocal homogenous W + DWORD diffuse; // Diffuse colour + DWORD specular; // For separate-specular support + FLOAT t0_u, t0_v; // 1st set of texture coords + FLOAT t1_u, t1_v; // 2nd set of texture coords +} GLD_2D_VERTEX; + + +// +// 3D vertex transformed by Direct3D +// +#define GLD_FVF_3D_VERTEX ( D3DFVF_XYZ | \ + D3DFVF_DIFFUSE | \ + D3DFVF_TEX2) + +typedef struct { + D3DXVECTOR3 Position; // XYZ Vector in object space + D3DCOLOR Diffuse; // Diffuse colour + D3DXVECTOR2 TexUnit0; // Texture unit 0 + D3DXVECTOR2 TexUnit1; // Texture unit 1 +} GLD_3D_VERTEX; + +//--------------------------------------------------------------------------- +// Vertex Shaders +//--------------------------------------------------------------------------- +/* +// DX8 Vertex Shader +typedef struct { + DWORD hShader; // If NULL, shader is invalid and cannot be used + BOOL bHardware; // If TRUE then shader was created for hardware, + // otherwise shader was created for software. +} GLD_vertexShader; +*/ +//--------------------------------------------------------------------------- +// Structs +//--------------------------------------------------------------------------- + +// This keeps a count of how many times we choose each individual internal +// pathway. Useful for seeing if a certain pathway was ever used by an app, and +// how much each pathway is biased. +// Zero the members at context creation and dump stats at context deletion. +typedef struct { + // Note: DWORD is probably too small + ULARGE_INTEGER qwMesa; // Mesa TnL pipeline + ULARGE_INTEGER qwD3DFVF; // Direct3D Fixed-Function pipeline +// ULARGE_INTEGER dwD3D2SVS; // Direct3D Two-Sided Vertex Shader pipeline +} GLD_pipeline_usage; + +// GLDirect Primitive Buffer (points, lines, triangles and quads) +typedef struct { + // Data for IDirect3DDevice9::CreateVertexBuffer() + DWORD dwStride; // Stride of vertex + DWORD dwUsage; // Usage flags + DWORD dwFVF; // Direct3D Flexible Vertex Format + DWORD dwPool; // Pool flags + + IDirect3DVertexBuffer9 *pVB; // Holds points, lines, tris and quads. + + // Point list is assumed to be at start of buffer + DWORD iFirstLine; // Index of start of line list + DWORD iFirstTriangle; // Index of start of triangle list + + BYTE *pPoints; // Pointer to next free point + BYTE *pLines; // Pointer to next free line + BYTE *pTriangles; // Pointer to next free triangle + + DWORD nPoints; // Number of points ready to render + DWORD nLines; // Number of lines ready to render + DWORD nTriangles; // Number of triangles ready to render +} GLD_pb_dx9; + +// GLDirect DX9 driver data +typedef struct { + // GLDirect vars + BOOL bDoublebuffer; // Doublebuffer (otherwise single-buffered) + BOOL bDepthStencil; // Depth buffer needed (stencil optional) + D3DFORMAT RenderFormat; // Format of back/front buffer + D3DFORMAT DepthFormat; // Format of depth/stencil +// float fFlipWindowY; // Value for flipping viewport Y coord + + // Direct3D vars + D3DCAPS9 d3dCaps9; + BOOL bHasHWTnL; // Device has Hardware Transform/Light? + IDirect3D9 *pD3D; // Base Direct3D9 interface + IDirect3DDevice9 *pDev; // Direct3D9 Device interface + GLD_pb_dx9 PB2d; // Vertices transformed by Mesa + GLD_pb_dx9 PB3d; // Vertices transformed by Direct3D + D3DPRIMITIVETYPE d3dpt; // Current Direct3D primitive type + D3DXMATRIX matProjection; // Projection matrix for D3D TnL + D3DXMATRIX matModelView; // Model/View matrix for D3D TnL + int iSetupFunc; // Which setup functions to use + BOOL bUseMesaTnL; // Whether to use Mesa or D3D for TnL + + // Direct3D vars for two-sided lighting +// GLD_vertexShader VStwosidelight; // Vertex Shader for two-sided lighting +// D3DXMATRIX matWorldViewProj;// World/View/Projection matrix for shaders + + +// GLD_tnl_pipeline TnLPipeline; // Index of current internal pipeline + GLD_pipeline_usage PipelineUsage; + + BOOL bCanScissor; // Scissor test - new for DX9 +} GLD_driver_dx9; + +#define GLD_GET_DX9_DRIVER(c) (GLD_driver_dx9*)(c)->glPriv + +//--------------------------------------------------------------------------- +// Function prototypes +//--------------------------------------------------------------------------- + +PROC gldGetProcAddress_DX9(LPCSTR a); +void gldEnableExtensions_DX9(GLcontext *ctx); +void gldInstallPipeline_DX9(GLcontext *ctx); +void gldSetupDriverPointers_DX9(GLcontext *ctx); +//void gldResizeBuffers_DX9(GLcontext *ctx); +void gldResizeBuffers_DX9(GLframebuffer *fb); + + +// Texture functions + +void gldCopyTexImage1D_DX9(GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); +void gldCopyTexImage2D_DX9(GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +void gldCopyTexSubImage1D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width ); +void gldCopyTexSubImage2D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height ); +void gldCopyTexSubImage3D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height ); + +void gld_NEW_TEXTURE_DX9(GLcontext *ctx); +void gld_DrawPixels_DX9(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels); +void gld_ReadPixels_DX9(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, GLvoid *dest); +void gld_CopyPixels_DX9(GLcontext *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLint dstx, GLint dsty, GLenum type); +void gld_Bitmap_DX9(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap); +const struct gl_texture_format* gld_ChooseTextureFormat_DX9(GLcontext *ctx, GLint internalFormat, GLenum srcFormat, GLenum srcType); +void gld_TexImage2D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint height, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *tObj, struct gl_texture_image *texImage); +void gld_TexImage1D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage ); +void gld_TexSubImage2D_DX9( GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage ); +void gld_TexSubImage1D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage); +void gld_DeleteTexture_DX9(GLcontext *ctx, struct gl_texture_object *tObj); +void gld_ResetLineStipple_DX9(GLcontext *ctx); + +// 2D primitive functions + +void gld_Points2D_DX9(GLcontext *ctx, GLuint first, GLuint last); + +void gld_Line2DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1); +void gld_Line2DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1); + +void gld_Triangle2DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Triangle2DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Triangle2DFlatExtras_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Triangle2DSmoothExtras_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); + +void gld_Quad2DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +void gld_Quad2DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +void gld_Quad2DFlatExtras_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +void gld_Quad2DSmoothExtras_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); + +// 3D primitive functions + +void gld_Points3D_DX9(GLcontext *ctx, GLuint first, GLuint last); +void gld_Line3DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1); +void gld_Triangle3DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Quad3DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +void gld_Line3DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1); +void gld_Triangle3DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Quad3DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); + +// Primitive functions for Two-sided-lighting Vertex Shader + +void gld_Points2DTwoside_DX9(GLcontext *ctx, GLuint first, GLuint last); +void gld_Line2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1); +void gld_Line2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1); +void gld_Triangle2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Triangle2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2); +void gld_Quad2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +void gld_Quad2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3); + +#endif diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_dxerr9.h b/src/mesa/drivers/windows/gldirect/dx9/gld_dxerr9.h new file mode 100644 index 0000000000..1d6b7b1c76 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_dxerr9.h @@ -0,0 +1,77 @@ +/*==========================================================================; + * + * + * File: dxerr9.h + * Content: DirectX Error Library Include File + * + ****************************************************************************/ + +#ifndef _GLD_DXERR9_H_ +#define _GLD_DXERR9_H_ + + +#include + +// +// DXGetErrorString9 +// +// Desc: Converts an DirectX HRESULT to a string +// +// Args: HRESULT hr Can be any error code from +// DPLAY D3D8 D3DX8 DMUSIC DSOUND +// +// Return: Converted string +// +const char* __stdcall DXGetErrorString9A(HRESULT hr); +const WCHAR* __stdcall DXGetErrorString9W(HRESULT hr); + +#ifdef UNICODE + #define DXGetErrorString9 DXGetErrorString9W +#else + #define DXGetErrorString9 DXGetErrorString9A +#endif + + +// +// DXTrace +// +// Desc: Outputs a formatted error message to the debug stream +// +// Args: CHAR* strFile The current file, typically passed in using the +// __FILE__ macro. +// DWORD dwLine The current line number, typically passed in using the +// __LINE__ macro. +// HRESULT hr An HRESULT that will be traced to the debug stream. +// CHAR* strMsg A string that will be traced to the debug stream (may be NULL) +// BOOL bPopMsgBox If TRUE, then a message box will popup also containing the passed info. +// +// Return: The hr that was passed in. +// +//HRESULT __stdcall DXTraceA( char* strFile, DWORD dwLine, HRESULT hr, char* strMsg, BOOL bPopMsgBox = FALSE ); +//HRESULT __stdcall DXTraceW( char* strFile, DWORD dwLine, HRESULT hr, WCHAR* strMsg, BOOL bPopMsgBox = FALSE ); +HRESULT __stdcall DXTraceA( char* strFile, DWORD dwLine, HRESULT hr, char* strMsg, BOOL bPopMsgBox); +HRESULT __stdcall DXTraceW( char* strFile, DWORD dwLine, HRESULT hr, WCHAR* strMsg, BOOL bPopMsgBox); + +#ifdef UNICODE + #define DXTrace DXTraceW +#else + #define DXTrace DXTraceA +#endif + + +// +// Helper macros +// +#if defined(DEBUG) | defined(_DEBUG) + #define DXTRACE_MSG(str) DXTrace( __FILE__, (DWORD)__LINE__, 0, str, FALSE ) + #define DXTRACE_ERR(str,hr) DXTrace( __FILE__, (DWORD)__LINE__, hr, str, TRUE ) + #define DXTRACE_ERR_NOMSGBOX(str,hr) DXTrace( __FILE__, (DWORD)__LINE__, hr, str, FALSE ) +#else + #define DXTRACE_MSG(str) (0L) + #define DXTRACE_ERR(str,hr) (hr) + #define DXTRACE_ERR_NOMSGBOX(str,hr) (hr) +#endif + + +#endif + diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_ext_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_ext_dx9.c new file mode 100644 index 0000000000..a542806d2f --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_ext_dx9.c @@ -0,0 +1,344 @@ +/**************************************************************************** +* +* 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: GL extensions +* +****************************************************************************/ + +//#include "../GLDirect.h" +//#include "../gld_log.h" +//#include "../gld_settings.h" + +#include +#define GL_GLEXT_PROTOTYPES +#include +#include + +//#include "ddlog.h" +//#include "gld_dx8.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 "texstore.h" +#include "array_cache/acache.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" + +#include "dglcontext.h" +#include "extensions.h" + +// For some reason this is not defined in an above header... +extern void _mesa_enable_imaging_extensions(GLcontext *ctx); + +//--------------------------------------------------------------------------- +// Hack for the SGIS_multitexture extension that was removed from Mesa +// NOTE: SGIS_multitexture enums also clash with GL_SGIX_async_pixel + + // NOTE: Quake2 ran *slower* with this enabled, so I've + // disabled it for now. + // To enable, uncomment: + // _mesa_add_extension(ctx, GL_TRUE, szGL_SGIS_multitexture, 0); + +//--------------------------------------------------------------------------- + +enum { + /* Quake2 GL_SGIS_multitexture */ + GL_SELECTED_TEXTURE_SGIS = 0x835B, + GL_SELECTED_TEXTURE_COORD_SET_SGIS = 0x835C, + GL_MAX_TEXTURES_SGIS = 0x835D, + GL_TEXTURE0_SGIS = 0x835E, + GL_TEXTURE1_SGIS = 0x835F, + GL_TEXTURE2_SGIS = 0x8360, + GL_TEXTURE3_SGIS = 0x8361, + GL_TEXTURE_COORD_SET_SOURCE_SGIS = 0x8363, +}; + +//--------------------------------------------------------------------------- + +void APIENTRY gldSelectTextureSGIS( + GLenum target) +{ + GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS); + glActiveTextureARB(ARB_target); +} + +//--------------------------------------------------------------------------- + +void APIENTRY gldMTexCoord2fSGIS( + GLenum target, + GLfloat s, + GLfloat t) +{ + GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS); + glMultiTexCoord2fARB(ARB_target, s, t); +} + +//--------------------------------------------------------------------------- + +void APIENTRY gldMTexCoord2fvSGIS( + GLenum target, + const GLfloat *v) +{ + GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS); + glMultiTexCoord2fvARB(ARB_target, v); +} + +//--------------------------------------------------------------------------- +// Extensions +//--------------------------------------------------------------------------- + +typedef struct { + PROC proc; + char *name; +} GLD_extension; + +GLD_extension GLD_extList[] = { +#ifdef GL_EXT_polygon_offset + { (PROC)glPolygonOffsetEXT, "glPolygonOffsetEXT" }, +#endif + { (PROC)glBlendEquationEXT, "glBlendEquationEXT" }, + { (PROC)glBlendColorEXT, "glBlendColorExt" }, + { (PROC)glVertexPointerEXT, "glVertexPointerEXT" }, + { (PROC)glNormalPointerEXT, "glNormalPointerEXT" }, + { (PROC)glColorPointerEXT, "glColorPointerEXT" }, + { (PROC)glIndexPointerEXT, "glIndexPointerEXT" }, + { (PROC)glTexCoordPointerEXT, "glTexCoordPointer" }, + { (PROC)glEdgeFlagPointerEXT, "glEdgeFlagPointerEXT" }, + { (PROC)glGetPointervEXT, "glGetPointervEXT" }, + { (PROC)glArrayElementEXT, "glArrayElementEXT" }, + { (PROC)glDrawArraysEXT, "glDrawArrayEXT" }, + { (PROC)glAreTexturesResidentEXT, "glAreTexturesResidentEXT" }, + { (PROC)glBindTextureEXT, "glBindTextureEXT" }, + { (PROC)glDeleteTexturesEXT, "glDeleteTexturesEXT" }, + { (PROC)glGenTexturesEXT, "glGenTexturesEXT" }, + { (PROC)glIsTextureEXT, "glIsTextureEXT" }, + { (PROC)glPrioritizeTexturesEXT, "glPrioritizeTexturesEXT" }, + { (PROC)glCopyTexSubImage3DEXT, "glCopyTexSubImage3DEXT" }, + { (PROC)glTexImage3DEXT, "glTexImage3DEXT" }, + { (PROC)glTexSubImage3DEXT, "glTexSubImage3DEXT" }, + { (PROC)glPointParameterfEXT, "glPointParameterfEXT" }, + { (PROC)glPointParameterfvEXT, "glPointParameterfvEXT" }, + + { (PROC)glLockArraysEXT, "glLockArraysEXT" }, + { (PROC)glUnlockArraysEXT, "glUnlockArraysEXT" }, + { NULL, "\0" } +}; + +GLD_extension GLD_multitexList[] = { +/* + { (PROC)glMultiTexCoord1dSGIS, "glMTexCoord1dSGIS" }, + { (PROC)glMultiTexCoord1dvSGIS, "glMTexCoord1dvSGIS" }, + { (PROC)glMultiTexCoord1fSGIS, "glMTexCoord1fSGIS" }, + { (PROC)glMultiTexCoord1fvSGIS, "glMTexCoord1fvSGIS" }, + { (PROC)glMultiTexCoord1iSGIS, "glMTexCoord1iSGIS" }, + { (PROC)glMultiTexCoord1ivSGIS, "glMTexCoord1ivSGIS" }, + { (PROC)glMultiTexCoord1sSGIS, "glMTexCoord1sSGIS" }, + { (PROC)glMultiTexCoord1svSGIS, "glMTexCoord1svSGIS" }, + { (PROC)glMultiTexCoord2dSGIS, "glMTexCoord2dSGIS" }, + { (PROC)glMultiTexCoord2dvSGIS, "glMTexCoord2dvSGIS" }, + { (PROC)glMultiTexCoord2fSGIS, "glMTexCoord2fSGIS" }, + { (PROC)glMultiTexCoord2fvSGIS, "glMTexCoord2fvSGIS" }, + { (PROC)glMultiTexCoord2iSGIS, "glMTexCoord2iSGIS" }, + { (PROC)glMultiTexCoord2ivSGIS, "glMTexCoord2ivSGIS" }, + { (PROC)glMultiTexCoord2sSGIS, "glMTexCoord2sSGIS" }, + { (PROC)glMultiTexCoord2svSGIS, "glMTexCoord2svSGIS" }, + { (PROC)glMultiTexCoord3dSGIS, "glMTexCoord3dSGIS" }, + { (PROC)glMultiTexCoord3dvSGIS, "glMTexCoord3dvSGIS" }, + { (PROC)glMultiTexCoord3fSGIS, "glMTexCoord3fSGIS" }, + { (PROC)glMultiTexCoord3fvSGIS, "glMTexCoord3fvSGIS" }, + { (PROC)glMultiTexCoord3iSGIS, "glMTexCoord3iSGIS" }, + { (PROC)glMultiTexCoord3ivSGIS, "glMTexCoord3ivSGIS" }, + { (PROC)glMultiTexCoord3sSGIS, "glMTexCoord3sSGIS" }, + { (PROC)glMultiTexCoord3svSGIS, "glMTexCoord3svSGIS" }, + { (PROC)glMultiTexCoord4dSGIS, "glMTexCoord4dSGIS" }, + { (PROC)glMultiTexCoord4dvSGIS, "glMTexCoord4dvSGIS" }, + { (PROC)glMultiTexCoord4fSGIS, "glMTexCoord4fSGIS" }, + { (PROC)glMultiTexCoord4fvSGIS, "glMTexCoord4fvSGIS" }, + { (PROC)glMultiTexCoord4iSGIS, "glMTexCoord4iSGIS" }, + { (PROC)glMultiTexCoord4ivSGIS, "glMTexCoord4ivSGIS" }, + { (PROC)glMultiTexCoord4sSGIS, "glMTexCoord4sSGIS" }, + { (PROC)glMultiTexCoord4svSGIS, "glMTexCoord4svSGIS" }, + { (PROC)glMultiTexCoordPointerSGIS, "glMTexCoordPointerSGIS" }, + { (PROC)glSelectTextureSGIS, "glSelectTextureSGIS" }, + { (PROC)glSelectTextureCoordSetSGIS, "glSelectTextureCoordSetSGIS" }, +*/ + { (PROC)glActiveTextureARB, "glActiveTextureARB" }, + { (PROC)glClientActiveTextureARB, "glClientActiveTextureARB" }, + { (PROC)glMultiTexCoord1dARB, "glMultiTexCoord1dARB" }, + { (PROC)glMultiTexCoord1dvARB, "glMultiTexCoord1dvARB" }, + { (PROC)glMultiTexCoord1fARB, "glMultiTexCoord1fARB" }, + { (PROC)glMultiTexCoord1fvARB, "glMultiTexCoord1fvARB" }, + { (PROC)glMultiTexCoord1iARB, "glMultiTexCoord1iARB" }, + { (PROC)glMultiTexCoord1ivARB, "glMultiTexCoord1ivARB" }, + { (PROC)glMultiTexCoord1sARB, "glMultiTexCoord1sARB" }, + { (PROC)glMultiTexCoord1svARB, "glMultiTexCoord1svARB" }, + { (PROC)glMultiTexCoord2dARB, "glMultiTexCoord2dARB" }, + { (PROC)glMultiTexCoord2dvARB, "glMultiTexCoord2dvARB" }, + { (PROC)glMultiTexCoord2fARB, "glMultiTexCoord2fARB" }, + { (PROC)glMultiTexCoord2fvARB, "glMultiTexCoord2fvARB" }, + { (PROC)glMultiTexCoord2iARB, "glMultiTexCoord2iARB" }, + { (PROC)glMultiTexCoord2ivARB, "glMultiTexCoord2ivARB" }, + { (PROC)glMultiTexCoord2sARB, "glMultiTexCoord2sARB" }, + { (PROC)glMultiTexCoord2svARB, "glMultiTexCoord2svARB" }, + { (PROC)glMultiTexCoord3dARB, "glMultiTexCoord3dARB" }, + { (PROC)glMultiTexCoord3dvARB, "glMultiTexCoord3dvARB" }, + { (PROC)glMultiTexCoord3fARB, "glMultiTexCoord3fARB" }, + { (PROC)glMultiTexCoord3fvARB, "glMultiTexCoord3fvARB" }, + { (PROC)glMultiTexCoord3iARB, "glMultiTexCoord3iARB" }, + { (PROC)glMultiTexCoord3ivARB, "glMultiTexCoord3ivARB" }, + { (PROC)glMultiTexCoord3sARB, "glMultiTexCoord3sARB" }, + { (PROC)glMultiTexCoord3svARB, "glMultiTexCoord3svARB" }, + { (PROC)glMultiTexCoord4dARB, "glMultiTexCoord4dARB" }, + { (PROC)glMultiTexCoord4dvARB, "glMultiTexCoord4dvARB" }, + { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4fARB" }, + { (PROC)glMultiTexCoord4fvARB, "glMultiTexCoord4fvARB" }, + { (PROC)glMultiTexCoord4iARB, "glMultiTexCoord4iARB" }, + { (PROC)glMultiTexCoord4ivARB, "glMultiTexCoord4ivARB" }, + { (PROC)glMultiTexCoord4sARB, "glMultiTexCoord4sARB" }, + { (PROC)glMultiTexCoord4svARB, "glMultiTexCoord4svARB" }, + + // Descent3 doesn't use correct string, hence this hack + { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4f" }, + + // Quake2 SGIS multitexture + { (PROC)gldSelectTextureSGIS, "glSelectTextureSGIS" }, + { (PROC)gldMTexCoord2fSGIS, "glMTexCoord2fSGIS" }, + { (PROC)gldMTexCoord2fvSGIS, "glMTexCoord2fvSGIS" }, + + { NULL, "\0" } +}; + +//--------------------------------------------------------------------------- + +PROC gldGetProcAddress_DX( + LPCSTR a) +{ + int i; + PROC proc = NULL; + + for (i=0; GLD_extList[i].proc; i++) { + if (!strcmp(a, GLD_extList[i].name)) { + proc = GLD_extList[i].proc; + break; + } + } + + if (glb.bMultitexture) { + for (i=0; GLD_multitexList[i].proc; i++) { + if (!strcmp(a, GLD_multitexList[i].name)) { + proc = GLD_multitexList[i].proc; + break; + } + } + } + + gldLogPrintf(GLDLOG_INFO, "GetProcAddress: %s (%s)", a, proc ? "OK" : "Failed"); + + return proc; +} + +//--------------------------------------------------------------------------- + +void gldEnableExtensions_DX9( + GLcontext *ctx) +{ + GLuint i; + + // Mesa enables some extensions by default. + // This table decides which ones we want to switch off again. + + // NOTE: GL_EXT_compiled_vertex_array appears broken. + + const char *gld_disable_extensions[] = { +// "GL_ARB_transpose_matrix", +// "GL_EXT_compiled_vertex_array", +// "GL_EXT_polygon_offset", +// "GL_EXT_rescale_normal", + "GL_EXT_texture3D", +// "GL_NV_texgen_reflection", + NULL + }; + + const char *gld_multitex_extensions[] = { + "GL_ARB_multitexture", // Quake 3 + NULL + }; + + // Quake 2 engines + const char *szGL_SGIS_multitexture = "GL_SGIS_multitexture"; + + const char *gld_enable_extensions[] = { + "GL_EXT_texture_env_add", // Quake 3 + "GL_ARB_texture_env_add", // Quake 3 + NULL + }; + + for (i=0; gld_disable_extensions[i]; i++) { + _mesa_disable_extension(ctx, gld_disable_extensions[i]); + } + + for (i=0; gld_enable_extensions[i]; i++) { + _mesa_enable_extension(ctx, gld_enable_extensions[i]); + } + + if (glb.bMultitexture) { + for (i=0; gld_multitex_extensions[i]; i++) { + _mesa_enable_extension(ctx, gld_multitex_extensions[i]); + } + + // GL_SGIS_multitexture + // NOTE: Quake2 ran *slower* with this enabled, so I've + // disabled it for now. + // Fair bit slower on GeForce256, + // Much slower on 3dfx Voodoo5 5500. +// _mesa_add_extension(ctx, GL_TRUE, szGL_SGIS_multitexture, 0); + + } + + _mesa_enable_imaging_extensions(ctx); + _mesa_enable_1_3_extensions(ctx); + _mesa_enable_1_4_extensions(ctx); +} + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_pipeline_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_pipeline_dx9.c new file mode 100644 index 0000000000..c69ad26dfe --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_pipeline_dx9.c @@ -0,0 +1,77 @@ +/**************************************************************************** +* +* 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: Mesa transformation pipeline with GLDirect fastpath +* +****************************************************************************/ + +//#include "../GLDirect.h" + +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx9.h" + +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +//--------------------------------------------------------------------------- + +extern struct gl_pipeline_stage _gld_d3d_render_stage; +extern struct gl_pipeline_stage _gld_mesa_render_stage; + +static const struct gl_pipeline_stage *gld_pipeline[] = { + &_gld_d3d_render_stage, // Direct3D TnL + &_tnl_vertex_transform_stage, + &_tnl_normal_transform_stage, + &_tnl_lighting_stage, + &_tnl_fog_coordinate_stage, /* TODO: Omit fog stage. ??? */ + &_tnl_texgen_stage, + &_tnl_texture_transform_stage, + &_tnl_point_attenuation_stage, + &_gld_mesa_render_stage, // Mesa TnL, D3D rendering + 0, +}; + +//--------------------------------------------------------------------------- + +void gldInstallPipeline_DX9( + GLcontext *ctx) +{ + // Remove any existing pipeline stages, + // then install GLDirect pipeline stages. + + _tnl_destroy_pipeline(ctx); + _tnl_install_pipeline(ctx, gld_pipeline); +} + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c new file mode 100644 index 0000000000..6edbe702a7 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c @@ -0,0 +1,1446 @@ +/**************************************************************************** +* +* 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: Primitive (points/lines/tris/quads) rendering +* +****************************************************************************/ + +//#include "../GLDirect.h" + +//#include "gld_dx8.h" + +#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 "texstore.h" +#include "array_cache/acache.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "swrast_setup/ss_context.h" +#include "swrast/s_context.h" +#include "swrast/s_depth.h" +#include "swrast/s_lines.h" +#include "swrast/s_triangle.h" +#include "swrast/s_trispan.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" + +// Disable compiler complaints about unreferenced local variables +#pragma warning (disable:4101) + +//--------------------------------------------------------------------------- +// Helper defines for primitives +//--------------------------------------------------------------------------- + +//static const float ooZ = 1.0f / 65536.0f; // One over Z + +#define GLD_COLOUR (D3DCOLOR_RGBA(swv->color[0], swv->color[1], swv->color[2], swv->color[3])) +#define GLD_SPECULAR (D3DCOLOR_RGBA(swv->specular[0], swv->specular[1], swv->specular[2], swv->specular[3])) +#define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y)) + +//--------------------------------------------------------------------------- +// 2D vertex setup +//--------------------------------------------------------------------------- + +#define GLD_SETUP_2D_VARS_POINTS \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \ + GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pPoints; \ + SScontext *ss = SWSETUP_CONTEXT(ctx); \ + SWvertex *swv; \ + DWORD dwSpecularColour; \ + DWORD dwFlatColour + +#define GLD_SETUP_2D_VARS_LINES \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \ + GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pLines; \ + SScontext *ss = SWSETUP_CONTEXT(ctx); \ + SWvertex *swv; \ + DWORD dwSpecularColour; \ + DWORD dwFlatColour + +#define GLD_SETUP_2D_VARS_TRIANGLES \ + BOOL bFog = ctx->Fog.Enabled; \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \ + GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pTriangles; \ + SScontext *ss = SWSETUP_CONTEXT(ctx); \ + SWvertex *swv; \ + DWORD dwSpecularColour; \ + DWORD dwFlatColour; \ + GLuint facing = 0; \ + struct vertex_buffer *VB; \ + GLchan (*vbcolor)[4]; \ + GLchan (*vbspec)[4] + +#define GLD_SETUP_GET_SWVERT(s) \ + swv = &ss->verts[##s] + +#define GLD_SETUP_2D_VERTEX \ + pV->x = swv->win[0]; \ + pV->y = GLD_FLIP_Y(swv->win[1]); \ + pV->rhw = swv->win[3] + +#define GLD_SETUP_SMOOTH_COLOUR \ + pV->diffuse = GLD_COLOUR + +#define GLD_SETUP_GET_FLAT_COLOUR \ + dwFlatColour = GLD_COLOUR +#define GLD_SETUP_GET_FLAT_FOG_COLOUR \ + dwFlatColour = _gldComputeFog(ctx, swv) + +#define GLD_SETUP_USE_FLAT_COLOUR \ + pV->diffuse = dwFlatColour + +#define GLD_SETUP_GET_FLAT_SPECULAR \ + dwSpecularColour= GLD_SPECULAR + +#define GLD_SETUP_USE_FLAT_SPECULAR \ + pV->specular = dwSpecularColour + +#define GLD_SETUP_DEPTH \ + pV->sz = swv->win[2] / ctx->DepthMaxF +// pV->z = swv->win[2] * ooZ; + +#define GLD_SETUP_SPECULAR \ + pV->specular = GLD_SPECULAR + +#define GLD_SETUP_FOG \ + pV->diffuse = _gldComputeFog(ctx, swv) + +#define GLD_SETUP_TEX0 \ + pV->t0_u = swv->texcoord[0][0]; \ + pV->t0_v = swv->texcoord[0][1] + +#define GLD_SETUP_TEX1 \ + pV->t1_u = swv->texcoord[1][0]; \ + pV->t1_v = swv->texcoord[1][1] + +#define GLD_SETUP_LIGHTING(v) \ + if (facing == 1) { \ + pV->diffuse = D3DCOLOR_RGBA(vbcolor[##v][0], vbcolor[##v][1], vbcolor[##v][2], vbcolor[##v][3]); \ + if (vbspec) { \ + pV->specular = D3DCOLOR_RGBA(vbspec[##v][0], vbspec[##v][1], vbspec[##v][2], vbspec[##v][3]); \ + } \ + } else { \ + if (bFog) \ + GLD_SETUP_FOG; \ + else \ + GLD_SETUP_SMOOTH_COLOUR; \ + GLD_SETUP_SPECULAR; \ + } + +#define GLD_SETUP_GET_FLAT_LIGHTING(v) \ + if (facing == 1) { \ + dwFlatColour = D3DCOLOR_RGBA(vbcolor[##v][0], vbcolor[##v][1], vbcolor[##v][2], vbcolor[##v][3]); \ + if (vbspec) { \ + dwSpecularColour = D3DCOLOR_RGBA(vbspec[##v][0], vbspec[##v][1], vbspec[##v][2], vbspec[##v][3]); \ + } \ + } + +#define GLD_SETUP_TWOSIDED_LIGHTING \ + /* Two-sided lighting */ \ + if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) { \ + SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts; \ + SWvertex *v[3]; \ + GLfloat ex,ey,fx,fy,cc; \ + /* Get vars for later */ \ + VB = &TNL_CONTEXT(ctx)->vb; \ + vbcolor = (GLchan (*)[4])VB->ColorPtr[1]->Ptr; \ + if (VB->SecondaryColorPtr[1]) { \ + vbspec = (GLchan (*)[4])VB->SecondaryColorPtr[1]->Ptr; \ + } else { \ + vbspec = NULL; \ + } \ + v[0] = &verts[v0]; \ + v[1] = &verts[v1]; \ + v[2] = &verts[v2]; \ + ex = v[0]->win[0] - v[2]->win[0]; \ + ey = v[0]->win[1] - v[2]->win[1]; \ + fx = v[1]->win[0] - v[2]->win[0]; \ + fy = v[1]->win[1] - v[2]->win[1]; \ + cc = ex*fy - ey*fx; \ + facing = (cc < 0.0) ^ ctx->Polygon._FrontBit; \ + } + +//--------------------------------------------------------------------------- +// 3D vertex setup +//--------------------------------------------------------------------------- + +#define GLD_SETUP_3D_VARS_POINTS \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \ + GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pPoints; \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + struct vertex_buffer *VB = &tnl->vb; \ + GLfloat (*p4f)[4]; \ + GLfloat (*tc)[4]; \ + DWORD dwColor; + +#define GLD_SETUP_3D_VARS_LINES \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \ + GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pLines; \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + struct vertex_buffer *VB = &tnl->vb; \ + GLfloat (*p4f)[4]; \ + GLfloat (*tc)[4]; \ + DWORD dwColor; + +#define GLD_SETUP_3D_VARS_TRIANGLES \ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \ + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \ + GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pTriangles; \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + struct vertex_buffer *VB = &tnl->vb; \ + GLfloat (*p4f)[4]; \ + GLfloat (*tc)[4]; \ + DWORD dwColor; + +#define GLD_SETUP_3D_VERTEX(v) \ + p4f = VB->ObjPtr->data; \ + pV->Position.x = p4f[##v][0]; \ + pV->Position.y = p4f[##v][1]; \ + pV->Position.z = p4f[##v][2]; + +#define GLD_SETUP_SMOOTH_COLOUR_3D(v) \ + p4f = (GLfloat (*)[4])VB->ColorPtr[0]->Ptr; \ + pV->Diffuse = D3DCOLOR_COLORVALUE(p4f[##v][0], p4f[##v][1], p4f[##v][2], p4f[##v][3]); + + +#define GLD_SETUP_GET_FLAT_COLOUR_3D(v) \ + p4f = (GLfloat (*)[4])VB->ColorPtr[0]->Ptr; \ + dwColor = D3DCOLOR_COLORVALUE(p4f[##v][0], p4f[##v][1], p4f[##v][2], p4f[##v][3]); + +#define GLD_SETUP_USE_FLAT_COLOUR_3D \ + pV->Diffuse = dwColor; + +#define GLD_SETUP_TEX0_3D(v) \ + if (VB->TexCoordPtr[0]) { \ + tc = VB->TexCoordPtr[0]->data; \ + pV->TexUnit0.x = tc[##v][0]; \ + pV->TexUnit0.y = tc[##v][1]; \ + } + +#define GLD_SETUP_TEX1_3D(v) \ + if (VB->TexCoordPtr[1]) { \ + tc = VB->TexCoordPtr[1]->data; \ + pV->TexUnit1.x = tc[##v][0]; \ + pV->TexUnit1.y = tc[##v][1]; \ + } + +//--------------------------------------------------------------------------- +// Helper functions +//--------------------------------------------------------------------------- + +__inline DWORD _gldComputeFog( + GLcontext *ctx, + SWvertex *swv) +{ + // Full fog calculation. + // Based on Mesa code. + + GLchan rFog, gFog, bFog; + GLchan fR, fG, fB; + const GLfloat f = swv->fog; + const GLfloat g = 1.0 - f; + + UNCLAMPED_FLOAT_TO_CHAN(rFog, ctx->Fog.Color[RCOMP]); + UNCLAMPED_FLOAT_TO_CHAN(gFog, ctx->Fog.Color[GCOMP]); + UNCLAMPED_FLOAT_TO_CHAN(bFog, ctx->Fog.Color[BCOMP]); + fR = f * swv->color[0] + g * rFog; + fG = f * swv->color[1] + g * gFog; + fB = f * swv->color[2] + g * bFog; + return D3DCOLOR_RGBA(fR, fG, fB, swv->color[3]); +} + +//--------------------------------------------------------------------------- + +void gld_ResetLineStipple_DX9( + GLcontext *ctx) +{ + // TODO: Fake stipple with a 32x32 texture. +} + +//--------------------------------------------------------------------------- +// 2D (post-transformed) primitives +//--------------------------------------------------------------------------- + +void gld_Points2D_DX9( + GLcontext *ctx, + GLuint first, + GLuint last) +{ + GLD_SETUP_2D_VARS_POINTS; + + unsigned i; + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + + // _Size is already clamped to MaxPointSize and MinPointSize + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_POINTSIZE, *((DWORD*)&ctx->Point._Size)); + + if (VB->Elts) { + for (i=first; iClipMask[VB->Elts[i]] == 0) { +// _swrast_Point( ctx, &verts[VB->Elts[i]] ); + GLD_SETUP_GET_SWVERT(VB->Elts[i]); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_SPECULAR; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + } + } + } else { + GLD_SETUP_GET_SWVERT(first); + for (i=first; iClipMask[i] == 0) { +// _swrast_Point( ctx, &verts[i] ); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_SPECULAR; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + } + } + } + + gld->PB2d.pPoints = (BYTE*)pV; + gld->PB2d.nPoints += (last-first); +} + +//--------------------------------------------------------------------------- + +void gld_Line2DFlat_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1) +{ + GLD_SETUP_2D_VARS_LINES; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_GET_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_GET_FLAT_SPECULAR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + gld->PB2d.pLines = (BYTE*)pV; + gld->PB2d.nLines++; +} + +//--------------------------------------------------------------------------- + +void gld_Line2DSmooth_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1) +{ + GLD_SETUP_2D_VARS_LINES; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_SPECULAR; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_SPECULAR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + gld->PB2d.pLines = (BYTE*)pV; + gld->PB2d.nLines++; +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DFlat_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_GET_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_COLOUR; + pV++;; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DSmooth_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DFlatExtras_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_TWOSIDED_LIGHTING(v2); + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + if (bFog) + GLD_SETUP_GET_FLAT_FOG_COLOUR; + else + GLD_SETUP_GET_FLAT_COLOUR; + GLD_SETUP_GET_FLAT_SPECULAR; + GLD_SETUP_GET_FLAT_LIGHTING(v2); + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DSmoothExtras_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_TWOSIDED_LIGHTING(v0); + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v0); + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v1); + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v2); + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DFlat_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_GET_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DSmooth_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_SMOOTH_COLOUR; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DFlatExtras_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_TWOSIDED_LIGHTING(v3); + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + if (bFog) + GLD_SETUP_GET_FLAT_FOG_COLOUR; + else + GLD_SETUP_GET_FLAT_COLOUR; + GLD_SETUP_GET_FLAT_SPECULAR; + GLD_SETUP_GET_FLAT_LIGHTING(v3); + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_USE_FLAT_COLOUR; + GLD_SETUP_USE_FLAT_SPECULAR; + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DSmoothExtras_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_2D_VARS_TRIANGLES; + + GLD_SETUP_TWOSIDED_LIGHTING(v0); + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v0); + pV++; + + GLD_SETUP_GET_SWVERT(v1); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v1); + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v2); + pV++; + + GLD_SETUP_GET_SWVERT(v2); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v2); + pV++; + + GLD_SETUP_GET_SWVERT(v3); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v3); + pV++; + + GLD_SETUP_GET_SWVERT(v0); + GLD_SETUP_2D_VERTEX; + GLD_SETUP_DEPTH; + GLD_SETUP_TEX0; + GLD_SETUP_TEX1; + GLD_SETUP_LIGHTING(v0); + pV++; + + gld->PB2d.pTriangles = (BYTE*)pV; + gld->PB2d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- +// 3D (pre-transformed) primitives +//--------------------------------------------------------------------------- + +void gld_Points3D_DX9( + GLcontext *ctx, + GLuint first, + GLuint last) +{ + GLD_SETUP_3D_VARS_POINTS + + unsigned i; +// struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + + // _Size is already clamped to MaxPointSize and MinPointSize + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_POINTSIZE, *((DWORD*)&ctx->Point._Size)); + + if (VB->Elts) { + for (i=first; iClipMask[VB->Elts[i]] == 0) { +// _swrast_Point( ctx, &verts[VB->Elts[i]] ); +// GLD_SETUP_GET_SWVERT(VB->Elts[i]); + GLD_SETUP_3D_VERTEX(VB->Elts[i]) + GLD_SETUP_SMOOTH_COLOUR_3D(i) + GLD_SETUP_TEX0_3D(i) + GLD_SETUP_TEX1_3D(i) + } + } + } else { +// GLD_SETUP_GET_SWVERT(first); + for (i=first; iClipMask[i] == 0) { +// _swrast_Point( ctx, &verts[i] ); + GLD_SETUP_3D_VERTEX(i) + GLD_SETUP_SMOOTH_COLOUR_3D(i) + GLD_SETUP_TEX0_3D(i) + GLD_SETUP_TEX1_3D(i) + } + } + } +/* + for (i=first; iPB3d.pPoints = (BYTE*)pV; + gld->PB3d.nPoints += (last-first); +} + +//--------------------------------------------------------------------------- +// Line functions +//--------------------------------------------------------------------------- + +void gld_Line3DFlat_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1) +{ + GLD_SETUP_3D_VARS_LINES + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_GET_FLAT_COLOUR_3D(v1) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + gld->PB3d.pLines = (BYTE*)pV; + gld->PB3d.nLines++; +} + +//--------------------------------------------------------------------------- + +void gld_Line3DSmooth_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1) +{ + GLD_SETUP_3D_VARS_LINES + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_SMOOTH_COLOUR_3D(v1) + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_SMOOTH_COLOUR_3D(v0) + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + gld->PB3d.pLines = (BYTE*)pV; + gld->PB3d.nLines++; +} + +//--------------------------------------------------------------------------- +// Triangle functions +//--------------------------------------------------------------------------- + +void gld_Triangle3DFlat_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + GLD_SETUP_3D_VARS_TRIANGLES + + GLD_SETUP_3D_VERTEX(v2) + GLD_SETUP_TEX0_3D(v2) + GLD_SETUP_TEX1_3D(v2) + GLD_SETUP_GET_FLAT_COLOUR_3D(v2) + GLD_SETUP_USE_FLAT_COLOUR_3D + pV++; + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + GLD_SETUP_USE_FLAT_COLOUR_3D + pV++; + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + GLD_SETUP_USE_FLAT_COLOUR_3D + pV++; + + gld->PB3d.pTriangles = (BYTE*)pV; + gld->PB3d.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Triangle3DSmooth_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2) +{ + GLD_SETUP_3D_VARS_TRIANGLES + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_SMOOTH_COLOUR_3D(v0) + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_SMOOTH_COLOUR_3D(v1) + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v2) + GLD_SETUP_SMOOTH_COLOUR_3D(v2) + GLD_SETUP_TEX0_3D(v2) + GLD_SETUP_TEX1_3D(v2) + pV++; + + gld->PB3d.pTriangles = (BYTE*)pV; + gld->PB3d.nTriangles++; +} + +//--------------------------------------------------------------------------- +// Quad functions +//--------------------------------------------------------------------------- + +void gld_Quad3DFlat_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_3D_VARS_TRIANGLES + + GLD_SETUP_3D_VERTEX(v3) + GLD_SETUP_GET_FLAT_COLOUR_3D(v3) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v3) + GLD_SETUP_TEX1_3D(v3) + pV++; + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v2) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v2) + GLD_SETUP_TEX1_3D(v2) + pV++; + + GLD_SETUP_3D_VERTEX(v3) + GLD_SETUP_USE_FLAT_COLOUR_3D + GLD_SETUP_TEX0_3D(v3) + GLD_SETUP_TEX1_3D(v3) + pV++; + + gld->PB3d.pTriangles = (BYTE*)pV; + gld->PB3d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +void gld_Quad3DSmooth_DX9( + GLcontext *ctx, + GLuint v0, + GLuint v1, + GLuint v2, + GLuint v3) +{ + GLD_SETUP_3D_VARS_TRIANGLES + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_SMOOTH_COLOUR_3D(v0) + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + GLD_SETUP_3D_VERTEX(v1) + GLD_SETUP_SMOOTH_COLOUR_3D(v1) + GLD_SETUP_TEX0_3D(v1) + GLD_SETUP_TEX1_3D(v1) + pV++; + + GLD_SETUP_3D_VERTEX(v2) + GLD_SETUP_SMOOTH_COLOUR_3D(v2) + GLD_SETUP_TEX0_3D(v2) + GLD_SETUP_TEX1_3D(v2) + pV++; + + GLD_SETUP_3D_VERTEX(v2) + GLD_SETUP_SMOOTH_COLOUR_3D(v2) + GLD_SETUP_TEX0_3D(v2) + GLD_SETUP_TEX1_3D(v2) + pV++; + + GLD_SETUP_3D_VERTEX(v3) + GLD_SETUP_SMOOTH_COLOUR_3D(v3) + GLD_SETUP_TEX0_3D(v3) + GLD_SETUP_TEX1_3D(v3) + pV++; + + GLD_SETUP_3D_VERTEX(v0) + GLD_SETUP_SMOOTH_COLOUR_3D(v0) + GLD_SETUP_TEX0_3D(v0) + GLD_SETUP_TEX1_3D(v0) + pV++; + + gld->PB3d.pTriangles = (BYTE*)pV; + gld->PB3d.nTriangles += 2; +} + +//--------------------------------------------------------------------------- +// Vertex setup for two-sided-lighting vertex shader +//--------------------------------------------------------------------------- + +/* + +void gld_Points2DTwoside_DX9(GLcontext *ctx, GLuint first, GLuint last) +{ + // NOTE: Two-sided lighting does not apply to Points +} + +//--------------------------------------------------------------------------- + +void gld_Line2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1) +{ + // NOTE: Two-sided lighting does not apply to Lines +} + +//--------------------------------------------------------------------------- + +void gld_Line2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1) +{ + // NOTE: Two-sided lighting does not apply to Lines +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2) +{ +} + +//--------------------------------------------------------------------------- + +void gld_Triangle2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles; + SScontext *ss = SWSETUP_CONTEXT(ctx); + SWvertex *swv; + DWORD dwSpecularColour; + DWORD dwFlatColour; + GLuint facing = 0; + struct vertex_buffer *VB; + GLchan (*vbcolor)[4]; + GLchan (*vbspec)[4]; + + // Reciprocal of DepthMax + const float ooDepthMax = 1.0f / ctx->DepthMaxF; + + // 1st vert + swv = &ss->verts[v0]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 2nd vert + swv = &ss->verts[v1]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 3rd vert + swv = &ss->verts[v2]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + gld->PBtwosidelight.pTriangles = (BYTE*)pV; + gld->PBtwosidelight.nTriangles++; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles; + SScontext *ss = SWSETUP_CONTEXT(ctx); + SWvertex *swv; + DWORD dwSpecularColour; + DWORD dwFlatColour; + GLuint facing = 0; + struct vertex_buffer *VB; + GLchan (*vbcolor)[4]; + GLchan (*vbspec)[4]; + + // Reciprocal of DepthMax + const float ooDepthMax = 1.0f / ctx->DepthMaxF; + + // 1st vert + swv = &ss->verts[v0]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 2nd vert + swv = &ss->verts[v1]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 3rd vert + swv = &ss->verts[v2]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 4th vert + swv = &ss->verts[v2]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 5th vert + swv = &ss->verts[v3]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 6th vert + swv = &ss->verts[v0]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + gld->PBtwosidelight.pTriangles = (BYTE*)pV; + gld->PBtwosidelight.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +void gld_Quad2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles; + SScontext *ss = SWSETUP_CONTEXT(ctx); + SWvertex *swv; + DWORD dwSpecularColour; + DWORD dwFlatColour; + GLuint facing = 0; + struct vertex_buffer *VB; + GLchan (*vbcolor)[4]; + GLchan (*vbspec)[4]; + + // Reciprocal of DepthMax + const float ooDepthMax = 1.0f / ctx->DepthMaxF; + + // 1st vert + swv = &ss->verts[v0]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 2nd vert + swv = &ss->verts[v1]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 3rd vert + swv = &ss->verts[v2]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 4th vert + swv = &ss->verts[v2]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 5th vert + swv = &ss->verts[v3]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + // 6th vert + swv = &ss->verts[v0]; + pV->Position.x = swv->win[0]; + pV->Position.y = GLD_FLIP_Y(swv->win[1]); + pV->Position.z = swv->win[2] * ooDepthMax; + pV->Position.w = swv->win[3]; + pV->TexUnit0.x = swv->texcoord[0][0]; + pV->TexUnit0.y = swv->texcoord[0][1]; + pV->TexUnit1.x = swv->texcoord[1][0]; + pV->TexUnit1.y = swv->texcoord[1][1]; + pV->FrontDiffuse = GLD_COLOUR; + pV->FrontSpecular = GLD_SPECULAR; + pV++; + + gld->PBtwosidelight.pTriangles = (BYTE*)pV; + gld->PBtwosidelight.nTriangles += 2; +} + +//--------------------------------------------------------------------------- + +*/ diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_texture_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_texture_dx9.c new file mode 100644 index 0000000000..ad2f4aab6f --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_texture_dx9.c @@ -0,0 +1,1965 @@ +/**************************************************************************** +* +* 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: Texture / Bitmap functions +* +****************************************************************************/ + +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx9.h" + +#include + +#include "texformat.h" +#include "colormac.h" +#include "texstore.h" +#include "image.h" +// #include "mem.h" + +//--------------------------------------------------------------------------- + +#define GLD_FLIP_HEIGHT(y,h) (gldCtx->dwHeight - (y) - (h)) + +//--------------------------------------------------------------------------- +// 1D texture fetch +//--------------------------------------------------------------------------- + +#define CHAN_SRC( t, i, j, k, sz ) \ + ((GLchan *)(t)->Data + (i) * (sz)) +#define UBYTE_SRC( t, i, j, k, sz ) \ + ((GLubyte *)(t)->Data + (i) * (sz)) +#define USHORT_SRC( t, i, j, k ) \ + ((GLushort *)(t)->Data + (i)) +#define FLOAT_SRC( t, i, j, k ) \ + ((GLfloat *)(t)->Data + (i)) + +//--------------------------------------------------------------------------- + +static void gld_fetch_1d_texel_X8R8G8B8( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLvoid *texel ) +{ + const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); + GLchan *rgba = (GLchan *) texel; + rgba[RCOMP] = src[2]; + rgba[GCOMP] = src[1]; + rgba[BCOMP] = src[0]; + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_1d_texel_X1R5G5B5( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLvoid *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_1d_texel_X4R4G4B4( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLvoid *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +#undef CHAN_SRC +#undef UBYTE_SRC +#undef USHORT_SRC +#undef FLOAT_SRC + +//--------------------------------------------------------------------------- +// 2D texture fetch +//--------------------------------------------------------------------------- + +#define CHAN_SRC( t, i, j, k, sz ) \ + ((GLchan *)(t)->Data + ((t)->Width * (j) + (i)) * (sz)) +#define UBYTE_SRC( t, i, j, k, sz ) \ + ((GLubyte *)(t)->Data + ((t)->Width * (j) + (i)) * (sz)) +#define USHORT_SRC( t, i, j, k ) \ + ((GLushort *)(t)->Data + ((t)->Width * (j) + (i))) +#define FLOAT_SRC( t, i, j, k ) \ + ((GLfloat *)(t)->Data + ((t)->Width * (j) + (i))) + +//--------------------------------------------------------------------------- + +static void gld_fetch_2d_texel_X8R8G8B8( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLvoid *texel ) +{ + const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); + GLchan *rgba = (GLchan *) texel; + rgba[RCOMP] = src[2]; + rgba[GCOMP] = src[1]; + rgba[BCOMP] = src[0]; + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_2d_texel_X1R5G5B5( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLvoid *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_2d_texel_X4R4G4B4( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLvoid *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +#undef CHAN_SRC +#undef UBYTE_SRC +#undef USHORT_SRC +#undef FLOAT_SRC + +//--------------------------------------------------------------------------- +// 3D texture fetch +//--------------------------------------------------------------------------- + +#define CHAN_SRC( t, i, j, k, sz ) \ + (GLchan *)(t)->Data + (((t)->Height * (k) + (j)) * \ + (t)->Width + (i)) * (sz) +#define UBYTE_SRC( t, i, j, k, sz ) \ + ((GLubyte *)(t)->Data + (((t)->Height * (k) + (j)) * \ + (t)->Width + (i)) * (sz)) +#define USHORT_SRC( t, i, j, k ) \ + ((GLushort *)(t)->Data + (((t)->Height * (k) + (j)) * \ + (t)->Width + (i))) +#define FLOAT_SRC( t, i, j, k ) \ + ((GLfloat *)(t)->Data + (((t)->Height * (k) + (j)) * \ + (t)->Width + (i))) + +//--------------------------------------------------------------------------- + +static void gld_fetch_3d_texel_X8R8G8B8( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLvoid *texel ) +{ + const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 ); + GLchan *rgba = (GLchan *) texel; + rgba[RCOMP] = src[2]; + rgba[GCOMP] = src[1]; + rgba[BCOMP] = src[0]; + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_3d_texel_X1R5G5B5( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLvoid *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +static void gld_fetch_3d_texel_X4R4G4B4( + const struct gl_texture_image *texImage, + GLint i, GLint j, GLint k, GLvoid *texel ) +{ + const GLushort *src = USHORT_SRC( texImage, i, j, k ); + GLchan *rgba = (GLchan *) texel; GLushort s = *src; + rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf ); + rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf ); + rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf ); + rgba[ACOMP] = CHAN_MAX; +} + +//--------------------------------------------------------------------------- + +#undef CHAN_SRC +#undef UBYTE_SRC +#undef USHORT_SRC +#undef FLOAT_SRC + +//--------------------------------------------------------------------------- +// Direct3D texture formats that have no Mesa equivalent +//--------------------------------------------------------------------------- + +const struct gl_texture_format _gld_texformat_X8R8G8B8 = { + MESA_FORMAT_ARGB8888, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ +// GL_UNSIGNED_BYTE, /* Type */ + 8, /* RedBits */ + 8, /* GreenBits */ + 8, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 4, /* TexelBytes */ + gld_fetch_1d_texel_X8R8G8B8, /* FetchTexel1D */ + gld_fetch_2d_texel_X8R8G8B8, /* FetchTexel2D */ + gld_fetch_3d_texel_X8R8G8B8, /* FetchTexel3D */ +}; + +const struct gl_texture_format _gld_texformat_X1R5G5B5 = { + MESA_FORMAT_ARGB1555, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ +// GL_UNSIGNED_SHORT_1_5_5_5_REV, /* Type */ + 5, /* RedBits */ + 5, /* GreenBits */ + 5, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 2, /* TexelBytes */ + gld_fetch_1d_texel_X1R5G5B5, /* FetchTexel1D */ + gld_fetch_2d_texel_X1R5G5B5, /* FetchTexel2D */ + gld_fetch_3d_texel_X1R5G5B5, /* FetchTexel3D */ +}; + +const struct gl_texture_format _gld_texformat_X4R4G4B4 = { + MESA_FORMAT_ARGB4444, /* MesaFormat */ + GL_RGBA, /* BaseFormat */ +// GL_UNSIGNED_SHORT_4_4_4_4_REV, /* Type */ + 4, /* RedBits */ + 4, /* GreenBits */ + 4, /* BlueBits */ + 0, /* AlphaBits */ + 0, /* LuminanceBits */ + 0, /* IntensityBits */ + 0, /* IndexBits */ + 0, /* DepthBits */ + 2, /* TexelBytes */ + gld_fetch_1d_texel_X4R4G4B4, /* FetchTexel1D */ + gld_fetch_2d_texel_X4R4G4B4, /* FetchTexel2D */ + gld_fetch_3d_texel_X4R4G4B4, /* FetchTexel3D */ +}; + +//--------------------------------------------------------------------------- +// Texture unit constants +//--------------------------------------------------------------------------- + +// List of possible combinations of texture environments. +// Example: GLD_TEXENV_MODULATE_RGBA means +// GL_MODULATE, GL_RGBA base internal format. +#define GLD_TEXENV_DECAL_RGB 0 +#define GLD_TEXENV_DECAL_RGBA 1 +#define GLD_TEXENV_DECAL_ALPHA 2 +#define GLD_TEXENV_REPLACE_RGB 3 +#define GLD_TEXENV_REPLACE_RGBA 4 +#define GLD_TEXENV_REPLACE_ALPHA 5 +#define GLD_TEXENV_MODULATE_RGB 6 +#define GLD_TEXENV_MODULATE_RGBA 7 +#define GLD_TEXENV_MODULATE_ALPHA 8 +#define GLD_TEXENV_BLEND_RGB 9 +#define GLD_TEXENV_BLEND_RGBA 10 +#define GLD_TEXENV_BLEND_ALPHA 11 +#define GLD_TEXENV_ADD_RGB 12 +#define GLD_TEXENV_ADD_RGBA 13 +#define GLD_TEXENV_ADD_ALPHA 14 + +// Per-stage (i.e. per-unit) texture environment +typedef struct { + DWORD ColorArg1; // Colour argument 1 + D3DTEXTUREOP ColorOp; // Colour operation + DWORD ColorArg2; // Colour argument 2 + DWORD AlphaArg1; // Alpha argument 1 + D3DTEXTUREOP AlphaOp; // Alpha operation + DWORD AlphaArg2; // Alpha argument 2 +} GLD_texenv; + +// TODO: Do we really need to set ARG1 and ARG2 every time? +// They seem to always be TEXTURE and CURRENT respectively. + +// C = Colour out +// A = Alpha out +// Ct = Colour from Texture +// Cf = Colour from fragment (diffuse) +// At = Alpha from Texture +// Af = Alpha from fragment (diffuse) +// Cc = GL_TEXTURE_ENV_COLOUR (GL_BLEND) +const GLD_texenv gldTexEnv[] = { + // DECAL_RGB: C=Ct, A=Af + {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // DECAL_RGBA: C=Cf(1-At)+CtAt, A=Af + {D3DTA_TEXTURE, D3DTOP_BLENDTEXTUREALPHA, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // DECAL_ALPHA: use DECAL_RGB + {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + + // REPLACE_RGB: C=Ct, A=Af + {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // REPLACE_RGBA: C=Ct, A=At + {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT}, + // REPLACE_ALPHA: C=Cf, A=At + {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT}, + + // MODULATE_RGB: C=CfCt, A=Af + {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // MODULATE_RGBA: C=CfCt, A=AfAt + {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, + // MODULATE_ALPHA: C=Cf, A=AfAt + {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, + + // BLEND_RGB: C=Cf(1-Ct)+CcCt, A=Af + {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // BLEND_RGBA: C=Cf(1-Ct)+CcCt, A=AfAt + {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, + // BLEND_ALPHA: C=Cf, A=AfAt + {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, + + // ADD_RGB: C=Cf+Ct, A=Af + {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT}, + // ADD_RGBA: C=Cf+Ct, A=AfAt + {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, + // ADD_ALPHA: C=Cf, A=AfAt + {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT, + D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT}, +}; + +//--------------------------------------------------------------------------- + +D3DTEXTUREADDRESS _gldConvertWrap( + GLenum wrap) +{ + return (wrap == GL_CLAMP) ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP; +} + +//--------------------------------------------------------------------------- + +D3DTEXTUREFILTERTYPE _gldConvertMagFilter( + GLenum magfilter) +{ + return (magfilter == GL_LINEAR) ? D3DTEXF_LINEAR : D3DTEXF_POINT; +} + +//--------------------------------------------------------------------------- + +void _gldConvertMinFilter( + GLenum minfilter, + D3DTEXTUREFILTERTYPE *min_filter, + D3DTEXTUREFILTERTYPE *mip_filter) +{ + switch (minfilter) { + case GL_NEAREST: + *min_filter = D3DTEXF_POINT; + *mip_filter = D3DTEXF_NONE; + break; + case GL_LINEAR: + *min_filter = D3DTEXF_LINEAR; + *mip_filter = D3DTEXF_NONE; + break; + case GL_NEAREST_MIPMAP_NEAREST: + *min_filter = D3DTEXF_POINT; + *mip_filter = D3DTEXF_POINT; + break; + case GL_LINEAR_MIPMAP_NEAREST: + *min_filter = D3DTEXF_LINEAR; + *mip_filter = D3DTEXF_POINT; + break; + case GL_NEAREST_MIPMAP_LINEAR: + *min_filter = D3DTEXF_POINT; + *mip_filter = D3DTEXF_LINEAR; + break; + case GL_LINEAR_MIPMAP_LINEAR: + *min_filter = D3DTEXF_LINEAR; + *mip_filter = D3DTEXF_LINEAR; + break; + } +} + +//--------------------------------------------------------------------------- + +D3DFORMAT _gldGLFormatToD3DFormat( + GLenum internalFormat) +{ + switch (internalFormat) { + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + // LUNIMANCE != INTENSITY, but D3D doesn't have I8 textures + return D3DFMT_L8; + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + return D3DFMT_L8; + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + return D3DFMT_A8; + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + return D3DFMT_X8R8G8B8; + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + return D3DFMT_A8L8; + case GL_R3_G3_B2: + // TODO: Mesa does not support RGB332 internally + return D3DFMT_X4R4G4B4; //D3DFMT_R3G3B2; + case GL_RGB4: + return D3DFMT_X4R4G4B4; + case GL_RGB5: + return D3DFMT_X1R5G5B5; + case 3: + case GL_RGB: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + return D3DFMT_R8G8B8; + case GL_RGBA4: + return D3DFMT_A4R4G4B4; + case 4: + case GL_RGBA: + case GL_RGBA2: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return D3DFMT_A8R8G8B8; + case GL_RGB5_A1: + return D3DFMT_A1R5G5B5; + } + + // Return an acceptable default + return D3DFMT_A8R8G8B8; +} + +//--------------------------------------------------------------------------- + +GLenum _gldDecodeBaseFormat( + IDirect3DTexture9 *pTex) +{ + // Examine Direct3D texture and return base OpenGL internal texture format + // NOTE: We can't use any base format info from Mesa because D3D might have + // used a different texture format when we used D3DXCreateTexture(). + + // Base internal format is one of (Red Book p355): + // GL_ALPHA, + // GL_LUMINANCE, + // GL_LUMINANCE_ALPHA, + // GL_INTENSITY, + // GL_RGB, + // GL_RGBA + + // NOTE: INTENSITY not used (not supported by Direct3D) + // LUMINANCE has same texture functions as RGB + // LUMINANCE_ALPHA has same texture functions as RGBA + + // TODO: cache format instead of using GetLevelDesc() + D3DSURFACE_DESC desc; + _GLD_DX9_TEX(GetLevelDesc(pTex, 0, &desc)); + + switch (desc.Format) { + case D3DFMT_R8G8B8: + case D3DFMT_X8R8G8B8: + case D3DFMT_R5G6B5: + case D3DFMT_X1R5G5B5: + case D3DFMT_R3G3B2: + case D3DFMT_X4R4G4B4: + case D3DFMT_P8: + case D3DFMT_L8: + return GL_RGB; + case D3DFMT_A8R8G8B8: + case D3DFMT_A1R5G5B5: + case D3DFMT_A4R4G4B4: + case D3DFMT_A8R3G3B2: + case D3DFMT_A8P8: + case D3DFMT_A8L8: + case D3DFMT_A4L4: + return GL_RGBA; + case D3DFMT_A8: + return GL_ALPHA; + // Compressed texture formats. Need to check these... + case D3DFMT_DXT1: + return GL_RGBA; + case D3DFMT_DXT2: + return GL_RGB; + case D3DFMT_DXT3: + return GL_RGBA; + case D3DFMT_DXT4: + return GL_RGB; + case D3DFMT_DXT5: + return GL_RGBA; + } + + // Fell through. Return arbitary default. + return GL_RGBA; +} + +//--------------------------------------------------------------------------- + +const struct gl_texture_format* _gldMesaFormatForD3DFormat( + D3DFORMAT d3dfmt) +{ + switch (d3dfmt) { + case D3DFMT_A8R8G8B8: + return &_mesa_texformat_argb8888; + case D3DFMT_R8G8B8: + return &_mesa_texformat_rgb888; + case D3DFMT_R5G6B5: + return &_mesa_texformat_rgb565; + case D3DFMT_A4R4G4B4: + return &_mesa_texformat_argb4444; + case D3DFMT_A1R5G5B5: + return &_mesa_texformat_argb1555; + case D3DFMT_A8L8: + return &_mesa_texformat_al88; + case D3DFMT_R3G3B2: + return &_mesa_texformat_rgb332; + case D3DFMT_A8: + return &_mesa_texformat_a8; + case D3DFMT_L8: + return &_mesa_texformat_l8; + case D3DFMT_X8R8G8B8: + return &_gld_texformat_X8R8G8B8; + case D3DFMT_X1R5G5B5: + return &_gld_texformat_X1R5G5B5; + case D3DFMT_X4R4G4B4: + return &_gld_texformat_X4R4G4B4; + } + + // If we reach here then we've made an error somewhere else + // by allowing a format that is not supported. + assert(0); + + return NULL; // Shut up compiler warning +} + +//--------------------------------------------------------------------------- +// Copy* functions +//--------------------------------------------------------------------------- + +void gldCopyTexImage1D_DX9( + GLcontext *ctx, + GLenum target, GLint level, + GLenum internalFormat, + GLint x, GLint y, + GLsizei width, GLint border ) +{ + // TODO +} + +//--------------------------------------------------------------------------- + +void gldCopyTexImage2D_DX9( + GLcontext *ctx, + GLenum target, + GLint level, + GLenum internalFormat, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLint border) +{ + // TODO +} + +//--------------------------------------------------------------------------- + +void gldCopyTexSubImage1D_DX9( + GLcontext *ctx, + GLenum target, GLint level, + GLint xoffset, GLint x, GLint y, GLsizei width ) +{ + // TODO +} + +//--------------------------------------------------------------------------- + +void gldCopyTexSubImage2D_DX9( + GLcontext *ctx, + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height) +{ + // TODO +} + +//--------------------------------------------------------------------------- + +void gldCopyTexSubImage3D_DX9( + GLcontext *ctx, + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height ) +{ + // TODO ? +} + +//--------------------------------------------------------------------------- +// Bitmap/Pixel functions +//--------------------------------------------------------------------------- + +#define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y)) + +#define _GLD_FVF_IMAGE (D3DFVF_XYZRHW | D3DFVF_TEX1) + +typedef struct { + FLOAT x, y; // 2D raster coords + FLOAT z; // depth value + FLOAT rhw; // reciprocal homogenous W (always 1.0f) + FLOAT tu, tv; // texture coords +} _GLD_IMAGE_VERTEX; + +//--------------------------------------------------------------------------- + +HRESULT _gldDrawPixels( + GLcontext *ctx, + BOOL bChromakey, // Alpha test for glBitmap() images + GLint x, // GL x position + GLint y, // GL y position (needs flipping) + GLsizei width, // Width of input image + GLsizei height, // Height of input image + IDirect3DSurface9 *pImage) +{ + // + // Draw input image as texture implementing PixelZoom and clipping. + // Any fragment operations currently enabled will be used. + // + + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + IDirect3DTexture9 *pTexture; + D3DSURFACE_DESC d3dsd; + IDirect3DSurface9 *pSurface; + _GLD_IMAGE_VERTEX v[4]; + HRESULT hr; + + float ZoomWidth, ZoomHeight; + float ScaleWidth, ScaleHeight; + + // Create a texture to hold image + hr = D3DXCreateTexture( + gld->pDev, + width, height, + 1, // miplevels + 0, // usage + D3DFMT_A8R8G8B8, // format + D3DPOOL_MANAGED, // pool + &pTexture); + if (FAILED(hr)) + return hr; + + hr = IDirect3DTexture9_GetSurfaceLevel(pTexture, 0, &pSurface); + if (FAILED(hr)) { + IDirect3DTexture9_Release(pTexture); + return hr; + } + + // Copy image into texture + hr = D3DXLoadSurfaceFromSurface( + pSurface, NULL, NULL, // Dest surface + pImage, NULL, NULL, // Src surface + D3DX_FILTER_NONE, + 0); + IDirect3DSurface9_Release(pSurface); + if (FAILED(hr)) { + IDirect3DTexture9_Release(pTexture); + return hr; + } + + // + // Set up the quad like this (ascii-art ahead!) + // + // 3--2 + // | | + // 0--1 + // + // + + // Set depth + v[0].z = v[1].z = v[2].z = v[3].z = ctx->Current.RasterPos[2]; + // Set Reciprocal Homogenous W + v[0].rhw = v[1].rhw = v[2].rhw = v[3].rhw = 1.0f; + + // Set texcoords + // Examine texture size - if different to input width and height + // then we'll need to munge the texcoords to fit. + IDirect3DTexture9_GetLevelDesc(pTexture, 0, &d3dsd); + ScaleWidth = (float)width / (float)d3dsd.Width; + ScaleHeight = (float)height / (float)d3dsd.Height; + v[0].tu = 0.0f; v[0].tv = 0.0f; + v[1].tu = ScaleWidth; v[1].tv = 0.0f; + v[2].tu = ScaleWidth; v[2].tv = ScaleHeight; + v[3].tu = 0.0f; v[3].tv = ScaleHeight; + + // Set raster positions + ZoomWidth = (float)width * ctx->Pixel.ZoomX; + ZoomHeight = (float)height * ctx->Pixel.ZoomY; + + v[0].x = x; v[0].y = GLD_FLIP_Y(y); + v[1].x = x+ZoomWidth; v[1].y = GLD_FLIP_Y(y); + v[2].x = x+ZoomWidth; v[2].y = GLD_FLIP_Y(y+ZoomHeight); + v[3].x = x; v[3].y = GLD_FLIP_Y(y+ZoomHeight); + + // Draw image with full HW acceleration + // NOTE: Be nice to use a State Block for all this state... + IDirect3DDevice9_SetTexture(gld->pDev, 0, pTexture); + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_CULLMODE, D3DCULL_NONE); + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_CLIPPING, TRUE); + +// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_MINFILTER, D3DTEXF_POINT); +// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_MIPFILTER, D3DTEXF_POINT); +// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_MAGFILTER, D3DTEXF_POINT); +// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP); +// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP); + IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT); + IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT); + IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); + IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); + + IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + IDirect3DDevice9_SetTextureStageState(gld->pDev, 1, D3DTSS_COLOROP, D3DTOP_DISABLE); + IDirect3DDevice9_SetTextureStageState(gld->pDev, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); + + IDirect3DDevice9_SetVertexShader(gld->pDev, NULL); + IDirect3DDevice9_SetFVF(gld->pDev, _GLD_FVF_IMAGE); + + // + // Emulate Chromakey with an Alpha Test. + // [Alpha Test is more widely supported anyway] + // + if (bChromakey) { + // Switch on alpha testing + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ALPHATESTENABLE, TRUE); + // Fragment passes is alpha is greater than reference value + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ALPHAFUNC, D3DCMP_GREATER); + // Set alpha reference value between Bitmap alpha values of + // zero (transparent) and one (opaque). + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ALPHAREF, 0x7f); + } + + IDirect3DDevice9_DrawPrimitiveUP(gld->pDev, D3DPT_TRIANGLEFAN, 2, &v, sizeof(_GLD_IMAGE_VERTEX)); + + // Release texture + IDirect3DDevice9_SetTexture(gld->pDev, 0, NULL); + IDirect3DTexture9_Release(pTexture); + + // Reset state to before we messed it up + FLUSH_VERTICES(ctx, _NEW_ALL); + + return S_OK; +} + +//--------------------------------------------------------------------------- + +void gld_DrawPixels_DX9( + GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *unpack, + const GLvoid *pixels ) +{ + GLD_context *gldCtx; + GLD_driver_dx9 *gld; + + IDirect3DSurface9 *pImage; + HRESULT hr; + D3DLOCKED_RECT d3dLockedRect; + + // Mesa does not currently handle this format. + if (format == GL_BGR) + return; + + gldCtx = GLD_GET_CONTEXT(ctx); + gld = GLD_GET_DX9_DRIVER(gldCtx); + + hr = IDirect3DDevice9_CreateOffscreenPlainSurface( + gld->pDev, + width, + height, + D3DFMT_A8R8G8B8, + D3DPOOL_SCRATCH, + &pImage, + NULL); + if (FAILED(hr)) { + return; + } + + // + // Use Mesa to fill in image + // + + // Lock all of surface + hr = IDirect3DSurface9_LockRect(pImage, &d3dLockedRect, NULL, 0); + if (FAILED(hr)) { + IDirect3DSurface9_Release(pImage); + return; + } + + // unpack image, apply transfer ops and store directly in texture + _mesa_transfer_teximage( + ctx, + 2, + GL_RGBA, + &_mesa_texformat_argb8888, + d3dLockedRect.pBits, + width, height, 1, 0, 0, 0, + d3dLockedRect.Pitch, + 0, /* dstImageStride */ + format, type, pixels, unpack); + + IDirect3DSurface9_UnlockRect(pImage); + + _gldDrawPixels(ctx, FALSE, x, y, width, height, pImage); + + IDirect3DSurface9_Release(pImage); +} + +//--------------------------------------------------------------------------- + +void gld_ReadPixels_DX9( + GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *pack, + GLvoid *dest) +{ + + GLD_context *gldCtx; + GLD_driver_dx9 *gld; + + IDirect3DSurface9 *pBackbuffer = NULL; + IDirect3DSurface9 *pNativeImage = NULL; + IDirect3DSurface9 *pCanonicalImage = NULL; + + D3DSURFACE_DESC d3dsd; + RECT rcSrc; // Source rect + POINT ptDst; // Dest point + HRESULT hr; + D3DLOCKED_RECT d3dLockedRect; + struct gl_pixelstore_attrib srcPacking; + int i; + GLint DstRowStride; + const struct gl_texture_format *MesaFormat; + + switch (format) { + case GL_STENCIL_INDEX: + case GL_DEPTH_COMPONENT: + return; + } + + MesaFormat = _mesa_choose_tex_format(ctx, format, format, type); + DstRowStride = _mesa_image_row_stride(pack, width, format, type); + + gldCtx = GLD_GET_CONTEXT(ctx); + gld = GLD_GET_DX9_DRIVER(gldCtx); + + // Get backbuffer + hr = IDirect3DDevice9_GetBackBuffer( + gld->pDev, + 0, // First swapchain + 0, // First backbuffer + D3DBACKBUFFER_TYPE_MONO, + &pBackbuffer); + if (FAILED(hr)) + return; + + // Get backbuffer description + hr = IDirect3DSurface9_GetDesc(pBackbuffer, &d3dsd); + if (FAILED(hr)) { + goto gld_ReadPixels_DX9_return; + } + + // Create a surface compatible with backbuffer + hr = IDirect3DDevice9_CreateOffscreenPlainSurface( + gld->pDev, + width, + height, + d3dsd.Format, + D3DPOOL_SCRATCH, + &pNativeImage, + NULL); + if (FAILED(hr)) { + goto gld_ReadPixels_DX9_return; + } + + // Compute source rect and dest point + SetRect(&rcSrc, 0, 0, width, height); + OffsetRect(&rcSrc, x, GLD_FLIP_HEIGHT(y, height)); + ptDst.x = ptDst.y = 0; + + // Get source pixels. + // + // This intermediate surface ensure that we can use CopyRects() + // instead of relying on D3DXLoadSurfaceFromSurface(), which may + // try and lock the backbuffer. This way seems safer. + // + // CopyRects has been removed for DX9. + // +/* hr = IDirect3DDevice9_CopyRects( + gld->pDev, + pBackbuffer, + &rcSrc, + 1, + pNativeImage, + &ptDst);*/ + hr = D3DXLoadSurfaceFromSurface( + pNativeImage, // Dest surface + NULL, // Dest palette + &rcSrc, // Dest rect + pBackbuffer, // Src surface + NULL, // Src palette + &rcSrc, // Src rect + D3DX_FILTER_NONE, // Filter + 0 // Colorkey (0=no colorkey) + ); + if (FAILED(hr)) { + goto gld_ReadPixels_DX9_return; + } + + // Create an RGBA8888 surface + hr = IDirect3DDevice9_CreateOffscreenPlainSurface( + gld->pDev, + width, + height, + D3DFMT_A8R8G8B8, + D3DPOOL_SCRATCH, + &pCanonicalImage, + NULL); + if (FAILED(hr)) { + goto gld_ReadPixels_DX9_return; + } + + // Convert to RGBA8888 + hr = D3DXLoadSurfaceFromSurface( + pCanonicalImage, // Dest surface + NULL, NULL, // Dest palette, RECT + pNativeImage, // Src surface + NULL, NULL, // Src palette, RECT + D3DX_FILTER_NONE, // Filter + 0); // Colourkey + if (FAILED(hr)) { + goto gld_ReadPixels_DX9_return; + } + + srcPacking.Alignment = 1; + srcPacking.ImageHeight = height; + srcPacking.LsbFirst = GL_FALSE; + srcPacking.RowLength = 0; + srcPacking.SkipImages = 0; + srcPacking.SkipPixels = 0; + srcPacking.SkipRows = 0; + srcPacking.SwapBytes = GL_FALSE; + + // Lock all of image + hr = IDirect3DSurface9_LockRect(pCanonicalImage, &d3dLockedRect, NULL, 0); + if (FAILED(hr)) { + goto gld_ReadPixels_DX9_return; + } + + // We need to flip the data. Yuck. + // Perhaps Mesa has a span packer we can use in future... + for (i=0; ipDev, + 0, // First swapchain + 0, // First backbuffer + D3DBACKBUFFER_TYPE_MONO, + &pBackbuffer); + if (FAILED(hr)) + return; + + // Get backbuffer description + hr = IDirect3DSurface9_GetDesc(pBackbuffer, &d3dsd); + if (FAILED(hr)) { + IDirect3DSurface9_Release(pBackbuffer); + return; + } + + // Create a surface compatible with backbuffer + hr = IDirect3DDevice9_CreateOffscreenPlainSurface( + gld->pDev, + width, + height, + d3dsd.Format, + D3DPOOL_SCRATCH, + &pImage, + NULL); + if (FAILED(hr)) { + IDirect3DSurface9_Release(pBackbuffer); + return; + } + + // Compute source rect and dest point + SetRect(&rcSrc, 0, 0, width, height); + OffsetRect(&rcSrc, srcx, GLD_FLIP_HEIGHT(srcy, height)); + ptDst.x = ptDst.y = 0; + + // Get source pixels +/* hr = IDirect3DDevice8_CopyRects( + gld->pDev, + pBackbuffer, + &rcSrc, + 1, + pImage, + &ptDst);*/ + hr = D3DXLoadSurfaceFromSurface( + pImage, // Dest surface + NULL, // Dest palette + &rcSrc, // Dest rect + pBackbuffer, // Src surface + NULL, // Src palette + &rcSrc, // Src rect + D3DX_FILTER_NONE, // Filter + 0 // Colorkey (0=no colorkey) + ); + IDirect3DSurface9_Release(pBackbuffer); + if (FAILED(hr)) { + IDirect3DSurface9_Release(pImage); + return; + } + + _gldDrawPixels(ctx, FALSE, dstx, dsty, width, height, pImage); + + IDirect3DSurface9_Release(pImage); +} + +//--------------------------------------------------------------------------- + +void gld_Bitmap_DX9( + GLcontext *ctx, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + const struct gl_pixelstore_attrib *unpack, + const GLubyte *bitmap) +{ + GLD_context *gldCtx; + GLD_driver_dx9 *gld; + + IDirect3DSurface9 *pImage; + HRESULT hr; + D3DLOCKED_RECT d3dLockedRect; + BYTE *pTempBitmap; + D3DCOLOR clBitmapOne, clBitmapZero; + D3DCOLOR *pBits; + const GLubyte *src; + int i, j, k; + + gldCtx = GLD_GET_CONTEXT(ctx); + gld = GLD_GET_DX9_DRIVER(gldCtx); + + // A NULL bitmap is valid, but merely advances the raster position + if ((bitmap == NULL) || (width == 0) || (height == 0)) + return; + + clBitmapZero = D3DCOLOR_RGBA(0,0,0,0); // NOTE: Alpha is Zero + clBitmapOne = D3DCOLOR_COLORVALUE( + ctx->Current.RasterColor[0], + ctx->Current.RasterColor[1], + ctx->Current.RasterColor[2], + 1.0f); // NOTE: Alpha is One + + hr = IDirect3DDevice9_CreateOffscreenPlainSurface( + gld->pDev, + width, + height, + D3DFMT_A8R8G8B8, + D3DPOOL_SCRATCH, + &pImage, + NULL); + if (FAILED(hr)) { + return; + } + + // Lock all of surface + hr = IDirect3DSurface9_LockRect(pImage, &d3dLockedRect, NULL, 0); + if (FAILED(hr)) { + IDirect3DSurface9_Release(pImage); + return; + } + + pTempBitmap = _mesa_unpack_bitmap(width, height, bitmap, unpack); + if (pTempBitmap == NULL) { + IDirect3DSurface9_Release(pImage); + return; + } + + pBits = (D3DCOLOR*)d3dLockedRect.pBits; + + for (i=0; i>3); j++) { + byte = *src++; + for (k=0; k<8; k++) { + *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero; + byte <<= 1; + } + } + // Fill remaining bits from bitmap + if (width & 7) { + byte = *src; + for (k=0; k<(width & 7); k++) { + *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero; + byte <<= 1; + } + } + } + + FREE(pTempBitmap); + +/* + // unpack image, apply transfer ops and store directly in texture + _mesa_transfer_teximage( + ctx, + 2, + GL_BITMAP, + &_mesa_texformat_argb8888, + d3dLockedRect.pBits, + width, height, 1, 0, 0, 0, + d3dLockedRect.Pitch, + 0, // dstImageStride + GL_BITMAP, GL_COLOR_INDEX, bitmap, unpack); +*/ + IDirect3DSurface9_UnlockRect(pImage); + + _gldDrawPixels(ctx, TRUE, x, y, width, height, pImage); + + IDirect3DSurface9_Release(pImage); +} + +//--------------------------------------------------------------------------- +// Texture functions +//--------------------------------------------------------------------------- + +void _gldAllocateTexture( + GLcontext *ctx, + struct gl_texture_object *tObj, + struct gl_texture_image *texImage) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + IDirect3DTexture9 *pTex; + D3DFORMAT d3dFormat; + + if (!tObj || !texImage) + return; + + pTex = (IDirect3DTexture9*)tObj->DriverData; + if (pTex) { + // Decide whether we can keep existing D3D texture + // by examining top-level surface. + D3DSURFACE_DESC d3dsd; + _GLD_DX9_TEX(GetLevelDesc(pTex, 0, &d3dsd)); + // Release existing texture if not compatible + if ((d3dsd.Width == texImage->Width) || + (d3dsd.Height == texImage->Height)) + { + return; // Keep the existing texture + } + tObj->DriverData = NULL; + _GLD_DX9_TEX(Release(pTex)); + } + + d3dFormat = _gldGLFormatToD3DFormat(texImage->IntFormat); + D3DXCreateTexture( + gld->pDev, + texImage->Width, + texImage->Height, + // TODO: Re-evaluate mipmapping + (glb.bUseMipmaps) ? D3DX_DEFAULT : 1, + 0, // Usage + d3dFormat, + D3DPOOL_MANAGED, + &pTex); + tObj->DriverData = pTex; +} + +//--------------------------------------------------------------------------- + +const struct gl_texture_format* gld_ChooseTextureFormat_DX9( + GLcontext *ctx, + GLint internalFormat, + GLenum srcFormat, + GLenum srcType) +{ + // [Based on mesa_choose_tex_format()] + // + // We will choose only texture formats that are supported + // by Direct3D. If the hardware doesn't support a particular + // texture format, then the D3DX texture calls that we use + // will automatically use a HW supported format. + // + // The most critical aim is to reduce copying; if we can use + // texture-image data directly then it will be a big performance assist. + // + + switch (internalFormat) { + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + return &_mesa_texformat_l8; // D3DFMT_L8 + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + return &_mesa_texformat_l8; // D3DFMT_L8 + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + return &_mesa_texformat_a8; // D3DFMT_A8 + case GL_COLOR_INDEX: + case GL_COLOR_INDEX1_EXT: + case GL_COLOR_INDEX2_EXT: + case GL_COLOR_INDEX4_EXT: + case GL_COLOR_INDEX8_EXT: + case GL_COLOR_INDEX12_EXT: + case GL_COLOR_INDEX16_EXT: + return &_mesa_texformat_rgb565; // D3DFMT_R5G6B5 + // Mesa will convert this for us later... + // return &_mesa_texformat_ci8; // D3DFMT_R5G6B5 + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + return &_mesa_texformat_al88; // D3DFMT_A8L8 + case GL_R3_G3_B2: + return &_mesa_texformat_rgb332; // D3DFMT_R3G3B2 + case GL_RGB4: + case GL_RGBA4: + case GL_RGBA2: + return &_mesa_texformat_argb4444; // D3DFMT_A4R4G4B4 + case 3: + case GL_RGB: + case GL_RGB5: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + return &_mesa_texformat_rgb565; + case 4: + case GL_RGBA: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return &_mesa_texformat_argb8888; + case GL_RGB5_A1: + return &_mesa_texformat_argb1555; + default: + _mesa_problem(NULL, "unexpected format in fxDDChooseTextureFormat"); + return NULL; + } +} + +//--------------------------------------------------------------------------- + +/* +// Safer(?), slower version. +void gld_TexImage2D_DX9( + GLcontext *ctx, + GLenum target, + GLint level, + GLint internalFormat, + GLint width, + GLint height, + GLint border, + GLenum format, + GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *tObj, + struct gl_texture_image *texImage) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + IDirect3DTexture9 *pTex; + IDirect3DSurface9 *pSurface; + RECT rcSrcRect; + HRESULT hr; + GLint texelBytes = 4; + GLvoid *tempImage; + + if (!tObj || !texImage) + return; + + if (level == 0) { + _gldAllocateTexture(ctx, tObj, texImage); + } + + pTex = (IDirect3DTexture9*)tObj->DriverData; + if (!pTex) + return; // Texture has not been created + if (level >= IDirect3DTexture9_GetLevelCount(pTex)) + return; // Level does not exist + hr = IDirect3DTexture9_GetSurfaceLevel(pTex, level, &pSurface); + if (FAILED(hr)) + return; // Surface level doesn't exist (or just a plain error) + + tempImage = MALLOC(width * height * texelBytes); + if (!tempImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); + IDirect3DSurface9_Release(pSurface); + return; + } + // unpack image, apply transfer ops and store in tempImage + _mesa_transfer_teximage(ctx, 2, texImage->Format, + &_mesa_texformat_argb8888, // dest format + tempImage, + width, height, 1, 0, 0, 0, + width * texelBytes, + 0, // dstImageStride + format, type, pixels, packing); + + SetRect(&rcSrcRect, 0, 0, width, height); + D3DXLoadSurfaceFromMemory( + pSurface, + NULL, + NULL, + tempImage, + D3DFMT_A8R8G8B8, + width * texelBytes, + NULL, + &rcSrcRect, + D3DX_FILTER_NONE, + 0); + + FREE(tempImage); + IDirect3DSurface9_Release(pSurface); +} +*/ + +//--------------------------------------------------------------------------- + +// Faster, more efficient version. +// Copies subimage straight to dest texture +void gld_TexImage2D_DX9( + GLcontext *ctx, + GLenum target, + GLint level, + GLint internalFormat, + GLint width, + GLint height, + GLint border, + GLenum format, + GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *tObj, + struct gl_texture_image *texImage) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + IDirect3DTexture9 *pTex; + IDirect3DSurface9 *pSurface; + HRESULT hr; + D3DLOCKED_RECT d3dLockedRect; + D3DSURFACE_DESC d3dsd; + + if (!tObj || !texImage) + return; + + // GLQUAKE FIX + // Test for input alpha data with non-alpha internalformat + if (((internalFormat==3) || (internalFormat==GL_RGB)) && (format==GL_RGBA)) { + // Input format has alpha, but a non-alpha format has been requested. + texImage->IntFormat = GL_RGBA; + internalFormat = GL_RGBA; + } + + if (level == 0) { + _gldAllocateTexture(ctx, tObj, texImage); + } + + pTex = (IDirect3DTexture9*)tObj->DriverData; + if (!pTex) + return; // Texture has not been created + if (level >= IDirect3DTexture9_GetLevelCount(pTex)) + return; // Level does not exist + hr = IDirect3DTexture9_GetSurfaceLevel(pTex, level, &pSurface); + if (FAILED(hr)) + return; // Surface level doesn't exist (or just a plain error) + + IDirect3DSurface9_GetDesc(pSurface, &d3dsd); + + // Lock all of surface + hr = IDirect3DSurface9_LockRect(pSurface, &d3dLockedRect, NULL, 0); + if (FAILED(hr)) { + IDirect3DSurface9_Release(pSurface); + return; + } + + // unpack image, apply transfer ops and store directly in texture + _mesa_transfer_teximage( + ctx, + 2, + texImage->Format, + _gldMesaFormatForD3DFormat(d3dsd.Format), + d3dLockedRect.pBits, + width, height, 1, 0, 0, 0, + d3dLockedRect.Pitch, + 0, // dstImageStride + format, type, pixels, packing); + + IDirect3DSurface9_UnlockRect(pSurface); + IDirect3DSurface9_Release(pSurface); +} + +//--------------------------------------------------------------------------- + +void gld_TexImage1D_DX9(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint border, + GLenum format, GLenum type, const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ) +{ + // A 1D texture is a 2D texture with a height of zero + gld_TexImage2D_DX9(ctx, target, level, internalFormat, width, 1, border, format, type, pixels, packing, texObj, texImage); +} + +//--------------------------------------------------------------------------- + +/* +void gld_TexSubImage2D( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *tObj, + struct gl_texture_image *texImage ) +{ + GLD_GET_CONTEXT + IDirect3DTexture9 *pTex; + IDirect3DSurface9 *pSurface; + D3DFORMAT d3dFormat; + HRESULT hr; + GLint texelBytes = 4; + GLvoid *tempImage; + RECT rcSrcRect; + RECT rcDstRect; + + if (!tObj || !texImage) + return; + + pTex = (IDirect3DTexture9*)tObj->DriverData; + if (!pTex) + return; // Texture has not been created + if (level >= _GLD_DX9_TEX(GetLevelCount(pTex)) + return; // Level does not exist + hr = _GLD_DX9_TEX(GetSurfaceLevel(pTex, level, &pSurface); + if (FAILED(hr)) + return; // Surface level doesn't exist (or just a plain error) + + d3dFormat = _gldGLFormatToD3DFormat(texImage->Format); + tempImage = MALLOC(width * height * texelBytes); + if (!tempImage) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); + IDirect3DSurface9_Release(pSurface); + return; + } + + // unpack image, apply transfer ops and store in tempImage + _mesa_transfer_teximage(ctx, 2, texImage->Format, + &_mesa_texformat_argb8888, // dest format + tempImage, + width, height, 1, 0, 0, 0, + width * texelBytes, + 0, // dstImageStride + format, type, pixels, packing); + + // Source rectangle is whole of input image + SetRect(&rcSrcRect, 0, 0, width, height); + + // Dest rectangle must be offset to dest image + SetRect(&rcDstRect, 0, 0, width, height); + OffsetRect(&rcDstRect, xoffset, yoffset); + + D3DXLoadSurfaceFromMemory( + pSurface, + NULL, + &rcDstRect, + tempImage, + D3DFMT_A8R8G8B8, + width * texelBytes, + NULL, + &rcSrcRect, + D3DX_FILTER_NONE, + 0); + + FREE(tempImage); + IDirect3DSurface9_Release(pSurface); +} +*/ + +//--------------------------------------------------------------------------- + +// Faster, more efficient version. +// Copies subimage straight to dest texture +void gld_TexSubImage2D_DX9( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *tObj, + struct gl_texture_image *texImage ) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + IDirect3DTexture9 *pTex; + IDirect3DSurface9 *pSurface; + HRESULT hr; + RECT rcDstRect; + D3DLOCKED_RECT d3dLockedRect; + D3DSURFACE_DESC d3dsd; + + if (!tObj || !texImage) + return; + + pTex = (IDirect3DTexture9*)tObj->DriverData; + if (!pTex) + return; // Texture has not been created + if (level >= IDirect3DTexture9_GetLevelCount(pTex)) + return; // Level does not exist + hr = IDirect3DTexture9_GetSurfaceLevel(pTex, level, &pSurface); + if (FAILED(hr)) + return; // Surface level doesn't exist (or just a plain error) + + IDirect3DSurface9_GetDesc(pSurface, &d3dsd); + + // Dest rectangle must be offset to dest image + SetRect(&rcDstRect, 0, 0, width, height); + OffsetRect(&rcDstRect, xoffset, yoffset); + + // Lock sub-rect of surface + hr = IDirect3DSurface9_LockRect(pSurface, &d3dLockedRect, &rcDstRect, 0); + if (FAILED(hr)) { + IDirect3DSurface9_Release(pSurface); + return; + } + + // unpack image, apply transfer ops and store directly in texture + _mesa_transfer_teximage(ctx, 2, texImage->Format, + _gldMesaFormatForD3DFormat(d3dsd.Format), + d3dLockedRect.pBits, + width, height, 1, + 0, 0, 0, // NOTE: d3dLockedRect.pBits is already offset!!! + d3dLockedRect.Pitch, + 0, // dstImageStride + format, type, pixels, packing); + + + IDirect3DSurface9_UnlockRect(pSurface); + IDirect3DSurface9_Release(pSurface); +} + +//--------------------------------------------------------------------------- + +void gld_TexSubImage1D_DX9( GLcontext *ctx, GLenum target, GLint level, + GLint xoffset, GLsizei width, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ) +{ + gld_TexSubImage2D_DX9(ctx, target, level, xoffset, 0, width, 1, format, type, pixels, packing, texObj, texImage); +} + +//--------------------------------------------------------------------------- + +void gld_DeleteTexture_DX9( + GLcontext *ctx, + struct gl_texture_object *tObj) +{ + GLD_context *gld = (GLD_context*)(ctx->DriverCtx); + + if (tObj) { + IDirect3DTexture9 *pTex = (IDirect3DTexture9*)tObj->DriverData; + if (pTex) { +/* // Make sure texture is not bound to a stage before releasing it + for (int i=0; iCurrentTexture[i] == pTex) { + gld->pDev->SetTexture(i, NULL); + gld->CurrentTexture[i] = NULL; + } + }*/ + _GLD_DX9_TEX(Release(pTex)); + tObj->DriverData = NULL; + } + } +} + +//--------------------------------------------------------------------------- + +__inline void _gldSetColorOps( + const GLD_driver_dx9 *gld, + GLuint unit, + DWORD ColorArg1, + D3DTEXTUREOP ColorOp, + DWORD ColorArg2) +{ + _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG1, ColorArg1)); + _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLOROP, ColorOp)); + _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG2, ColorArg2)); +} + +//--------------------------------------------------------------------------- + +__inline void _gldSetAlphaOps( + const GLD_driver_dx9 *gld, + GLuint unit, + DWORD AlphaArg1, + D3DTEXTUREOP AlphaOp, + DWORD AlphaArg2) +{ + _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG1, AlphaArg1)); + _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAOP, AlphaOp)); + _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG2, AlphaArg2)); +} + +//--------------------------------------------------------------------------- + +void gldUpdateTextureUnit( + GLcontext *ctx, + GLuint unit, + BOOL bPassThrough) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + D3DTEXTUREFILTERTYPE minfilter; + D3DTEXTUREFILTERTYPE mipfilter; + GLenum BaseFormat; + DWORD dwColorArg0; + int iTexEnv = 0; + GLD_texenv *pTexenv; + + // NOTE: If bPassThrough is FALSE then texture stage can be + // disabled otherwise it must pass-through it's current fragment. + + const struct gl_texture_unit *pUnit = &ctx->Texture.Unit[unit]; + const struct gl_texture_object *tObj = pUnit->_Current; + + IDirect3DTexture9 *pTex = NULL; + if (tObj) { + pTex = (IDirect3DTexture9*)tObj->DriverData; + } + + // Enable texturing if unit is enabled and a valid D3D texture exists + // Mesa 5: TEXTUREn_x altered to TEXTURE_nD_BIT + //if (pTex && (pUnit->Enabled & (TEXTURE0_1D | TEXTURE0_2D))) { + if (pTex && (pUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT))) { + // Enable texturing + _GLD_DX9_DEV(SetTexture(gld->pDev, unit, pTex)); + } else { + // Disable texturing, then return + _GLD_DX9_DEV(SetTexture(gld->pDev, unit, NULL)); + if (bPassThrough) { + _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE); + _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE); + } else { + _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE); + _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE); + } + return; + } + + // Texture parameters + _gldConvertMinFilter(tObj->MinFilter, &minfilter, &mipfilter); +// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MINFILTER, minfilter)); +// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MIPFILTER, mipfilter)); +// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MAGFILTER, _gldConvertMagFilter(tObj->MagFilter))); +// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSU, _gldConvertWrap(tObj->WrapS))); +// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSV, _gldConvertWrap(tObj->WrapT))); + _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_MINFILTER, minfilter)); + _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_MIPFILTER, mipfilter)); + _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_MAGFILTER, _gldConvertMagFilter(tObj->MagFilter))); + _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_ADDRESSU, _gldConvertWrap(tObj->WrapS))); + _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_ADDRESSV, _gldConvertWrap(tObj->WrapT))); + + // Texture priority + _GLD_DX9_TEX(SetPriority(pTex, (DWORD)(tObj->Priority*65535.0f))); + + // Texture environment + // TODO: Examine input texture for alpha and use specific alpha/non-alpha ops. + // See Page 355 of the Red Book. + BaseFormat = _gldDecodeBaseFormat(pTex); + + switch (BaseFormat) { + case GL_RGB: + iTexEnv = 0; + break; + case GL_RGBA: + iTexEnv = 1; + break; + case GL_ALPHA: + iTexEnv = 2; + break; + } + + switch (pUnit->EnvMode) { + case GL_DECAL: + iTexEnv += 0; + break; + case GL_REPLACE: + iTexEnv += 3; + break; + case GL_MODULATE: + iTexEnv += 6; + break; + case GL_BLEND: + // Set blend colour + dwColorArg0 = D3DCOLOR_COLORVALUE(pUnit->EnvColor[0], pUnit->EnvColor[1], pUnit->EnvColor[2], pUnit->EnvColor[3]); + _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG0, dwColorArg0)); + iTexEnv += 9; + break; + case GL_ADD: + iTexEnv += 12; + break; + } + pTexenv = (GLD_texenv*)&gldTexEnv[iTexEnv]; + _gldSetColorOps(gld, unit, pTexenv->ColorArg1, pTexenv->ColorOp, pTexenv->ColorArg2); + _gldSetAlphaOps(gld, unit, pTexenv->AlphaArg1, pTexenv->AlphaOp, pTexenv->AlphaArg2); +} + +//--------------------------------------------------------------------------- + +void gld_NEW_TEXTURE_DX9( + GLcontext *ctx) +{ + // TODO: Support for three (ATI Radeon) or more (nVidia GeForce3) texture units + + BOOL bUnit0Enabled; + BOOL bUnit1Enabled; + + if (!ctx) + return; // Sanity check + + if (ctx->Const.MaxTextureUnits == 1) { + gldUpdateTextureUnit(ctx, 0, TRUE); + return; + } + + // + // NOTE: THE FOLLOWING RELATES TO TWO TEXTURE UNITS, AND TWO ONLY!! + // + + // Mesa 5: Texture Units altered + //bUnit0Enabled = (ctx->Texture._ReallyEnabled & (TEXTURE0_1D | TEXTURE0_2D)) ? TRUE : FALSE; + //bUnit1Enabled = (ctx->Texture._ReallyEnabled & (TEXTURE1_1D | TEXTURE1_2D)) ? TRUE : FALSE; + bUnit0Enabled = (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE; + bUnit1Enabled = (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE; + + // If Unit0 is disabled and Unit1 is enabled then we must pass-though + gldUpdateTextureUnit(ctx, 0, (!bUnit0Enabled && bUnit1Enabled) ? TRUE : FALSE); + // We can always disable the last texture unit + gldUpdateTextureUnit(ctx, 1, FALSE); + +#ifdef _DEBUG +#if 0 + { + // Find out whether device supports current renderstates + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); +// GLD_context *gld = GLD_GET_CONTEXT(ctx); + + DWORD dwPasses; + _GLD_DX9_DEV(ValidateDevice(gld->pDev, &dwPasses)); +// if (FAILED(hr)) { +// gldLogError(GLDLOG_ERROR, "ValidateDevice failed", hr); +// } + if (dwPasses != 1) { + gldLogMessage(GLDLOG_ERROR, "ValidateDevice: Can't do in one pass\n"); + } + } +#endif +#endif +}; + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_vb_d3d_render_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_vb_d3d_render_dx9.c new file mode 100644 index 0000000000..30650d6f9a --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_vb_d3d_render_dx9.c @@ -0,0 +1,281 @@ +/**************************************************************************** +* +* 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: GLDirect fastpath pipeline stage +* +****************************************************************************/ + +//--------------------------------------------------------------------------- + +//#include "../GLDirect.h" +//#include "../gld_log.h" +//#include "gld_dx8.h" + +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx9.h" + +//--------------------------------------------------------------------------- + +#include "glheader.h" +#include "context.h" +#include "macros.h" +// #include "mem.h" +#include "mtypes.h" +#include "mmath.h" + +#include "math/m_matrix.h" +#include "math/m_xform.h" + +#include "tnl/t_pipeline.h" + +//--------------------------------------------------------------------------- + +__inline void _gldSetVertexShaderConstants( + GLcontext *ctx, + GLD_driver_dx9 *gld) +{ + D3DXMATRIX mat, matView, matProj; + GLfloat *pM; + + // Mesa 5: Altered to a Stack + //pM = ctx->ModelView.m; + pM = ctx->ModelviewMatrixStack.Top->m; + matView._11 = pM[0]; + matView._12 = pM[1]; + matView._13 = pM[2]; + matView._14 = pM[3]; + matView._21 = pM[4]; + matView._22 = pM[5]; + matView._23 = pM[6]; + matView._24 = pM[7]; + matView._31 = pM[8]; + matView._32 = pM[9]; + matView._33 = pM[10]; + matView._34 = pM[11]; + matView._41 = pM[12]; + matView._42 = pM[13]; + matView._43 = pM[14]; + matView._44 = pM[15]; + + // Mesa 5: Altered to a Stack + //pM = ctx->ProjectionMatrix.m; + pM = ctx->ProjectionMatrixStack.Top->m; + matProj._11 = pM[0]; + matProj._12 = pM[1]; + matProj._13 = pM[2]; + matProj._14 = pM[3]; + matProj._21 = pM[4]; + matProj._22 = pM[5]; + matProj._23 = pM[6]; + matProj._24 = pM[7]; + matProj._31 = pM[8]; + matProj._32 = pM[9]; + matProj._33 = pM[10]; + matProj._34 = pM[11]; + matProj._41 = pM[12]; + matProj._42 = pM[13]; + matProj._43 = pM[14]; + matProj._44 = pM[15]; + + D3DXMatrixMultiply( &mat, &matView, &matProj ); + D3DXMatrixTranspose( &mat, &mat ); + + _GLD_DX9_DEV(SetVertexShaderConstantF(gld->pDev, 0, (float*)&mat, 4)); +} + +//--------------------------------------------------------------------------- + +static GLboolean gld_d3d_render_stage_run( + GLcontext *ctx, + struct gl_pipeline_stage *stage) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + TNLcontext *tnl; + struct vertex_buffer *VB; + GLuint new_inputs; + render_func *tab; + GLint pass; + GLD_pb_dx9 *gldPB = &gld->PB3d; +/* + static int count = 0; + count++; + if (count != 2) + return GL_FALSE; +*/ + // The "check" function should disable this stage, + // but we'll test gld->bUseMesaTnL anyway. + if (gld->bUseMesaTnL) { + // Do nothing in this stage, but continue pipeline + return GL_FALSE; + } + + tnl = TNL_CONTEXT(ctx); + VB = &tnl->vb; + new_inputs = stage->changed_inputs; + pass = 0; + + tnl->Driver.Render.Start( ctx ); + +#if 0 + // For debugging: Useful to see if an app passes colour data in + // an unusual format. + switch (VB->ColorPtr[0]->Type) { + case GL_FLOAT: + ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_FLOAT\n"); + break; + case GL_UNSIGNED_BYTE: + ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_UNSIGNED_BYTE\n"); + break; + default: + ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: *?*\n"); + break; + } +#endif + + tnl->Driver.Render.Points = gld_Points3D_DX9; + if (ctx->_TriangleCaps & DD_FLATSHADE) { + tnl->Driver.Render.Line = gld_Line3DFlat_DX9; + tnl->Driver.Render.Triangle = gld_Triangle3DFlat_DX9; + tnl->Driver.Render.Quad = gld_Quad3DFlat_DX9; + } else { + tnl->Driver.Render.Line = gld_Line3DSmooth_DX9; + tnl->Driver.Render.Triangle = gld_Triangle3DSmooth_DX9; + tnl->Driver.Render.Quad = gld_Quad3DSmooth_DX9; + } + + _GLD_DX9_VB(Lock(gldPB->pVB, 0, 0, &gldPB->pPoints, D3DLOCK_DISCARD)); + gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0; + // Allocate primitive pointers + // gldPB->pPoints is always first + gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine); + gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle); + + ASSERT(tnl->Driver.Render.BuildVertices); + ASSERT(tnl->Driver.Render.PrimitiveNotify); + ASSERT(tnl->Driver.Render.Points); + ASSERT(tnl->Driver.Render.Line); + ASSERT(tnl->Driver.Render.Triangle); + ASSERT(tnl->Driver.Render.Quad); + ASSERT(tnl->Driver.Render.ResetLineStipple); + ASSERT(tnl->Driver.Render.Interp); + ASSERT(tnl->Driver.Render.CopyPV); + ASSERT(tnl->Driver.Render.ClippedLine); + ASSERT(tnl->Driver.Render.ClippedPolygon); + ASSERT(tnl->Driver.Render.Finish); + + tab = (VB->Elts ? tnl->Driver.Render.PrimTabElts : tnl->Driver.Render.PrimTabVerts); + + do { + GLuint i, length, flags = 0; + for (i = 0 ; !(flags & PRIM_LAST) ; i += length) + { + flags = VB->Primitive[i]; + length= VB->PrimitiveLength[i]; + ASSERT(length || (flags & PRIM_LAST)); + ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1); + if (length) + tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags ); + } + } while (tnl->Driver.Render.Multipass && + tnl->Driver.Render.Multipass( ctx, ++pass )); + + _GLD_DX9_VB(Unlock(gldPB->pVB)); + + _GLD_DX9_DEV(SetStreamSource(gld->pDev, 0, gldPB->pVB, 0, gldPB->dwStride)); + + _GLD_DX9_DEV(SetTransform(gld->pDev, D3DTS_PROJECTION, &gld->matProjection)); + _GLD_DX9_DEV(SetTransform(gld->pDev, D3DTS_WORLD, &gld->matModelView)); + + if (gldPB->nPoints) { + _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_POINTLIST, 0, gldPB->nPoints)); + gldPB->nPoints = 0; + } + + if (gldPB->nLines) { + _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_LINELIST, gldPB->iFirstLine, gldPB->nLines)); + gldPB->nLines = 0; + } + + if (gldPB->nTriangles) { + _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_TRIANGLELIST, gldPB->iFirstTriangle, gldPB->nTriangles)); + gldPB->nTriangles = 0; + } + + return GL_FALSE; /* finished the pipe */ +} + +//--------------------------------------------------------------------------- + +static void gld_d3d_render_stage_check( + GLcontext *ctx, + struct gl_pipeline_stage *stage) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + // Is this thread safe? + stage->active = (gld->bUseMesaTnL) ? GL_FALSE : GL_TRUE; + return; +} + +//--------------------------------------------------------------------------- + +static void gld_d3d_render_stage_dtr( struct gl_pipeline_stage *stage ) +{ +} + +//--------------------------------------------------------------------------- + +const struct gl_pipeline_stage _gld_d3d_render_stage = +{ + "gld_d3d_render_stage", + (_NEW_BUFFERS | + _DD_NEW_SEPARATE_SPECULAR | + _DD_NEW_FLATSHADE | + _NEW_TEXTURE| + _NEW_LIGHT| + _NEW_POINT| + _NEW_FOG| + _DD_NEW_TRI_UNFILLED | + _NEW_RENDERMODE), /* re-check (new inputs, interp function) */ + 0, /* re-run (always runs) */ + GL_TRUE, /* active */ + 0, 0, /* inputs (set in check_render), outputs */ + 0, 0, /* changed_inputs, private */ + gld_d3d_render_stage_dtr, /* destructor */ + gld_d3d_render_stage_check, /* check */ + gld_d3d_render_stage_run /* run */ +}; + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_vb_mesa_render_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_vb_mesa_render_dx9.c new file mode 100644 index 0000000000..10e994c3c8 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_vb_mesa_render_dx9.c @@ -0,0 +1,510 @@ +/* $Id: gld_vb_mesa_render_dx9.c,v 1.1 2004/04/20 11:13:11 alanh Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 Brian Paul 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 + * BRIAN PAUL 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. + * + * Authors: + * Keith Whitwell + */ + + +/* + * Render whole vertex buffers, including projection of vertices from + * clip space and clipping of primitives. + * + * This file makes calls to project vertices and to the point, line + * and triangle rasterizers via the function pointers: + * + * context->Driver.Render.* + * + */ + + +//--------------------------------------------------------------------------- + +#include "dglcontext.h" +#include "ddlog.h" +#include "gld_dx9.h" + +//--------------------------------------------------------------------------- + +#include "glheader.h" +#include "context.h" +#include "macros.h" +#include "mtypes.h" +#include "mmath.h" + +#include "math/m_matrix.h" +#include "math/m_xform.h" + +#include "tnl/t_pipeline.h" + +/**********************************************************************/ +/* Clip single primitives */ +/**********************************************************************/ + + +#if defined(USE_IEEE) +#define NEGATIVE(x) (GET_FLOAT_BITS(x) & (1<<31)) +#define DIFFERENT_SIGNS(x,y) ((GET_FLOAT_BITS(x) ^ GET_FLOAT_BITS(y)) & (1<<31)) +#else +#define NEGATIVE(x) (x < 0) +#define DIFFERENT_SIGNS(x,y) (x * y <= 0 && x - y != 0) +/* Could just use (x*y<0) except for the flatshading requirements. + * Maybe there's a better way? + */ +#endif + + +#define W(i) coord[i][3] +#define Z(i) coord[i][2] +#define Y(i) coord[i][1] +#define X(i) coord[i][0] +#define SIZE 4 +#define TAG(x) x##_4 +#include "tnl/t_vb_cliptmp.h" + + + +/**********************************************************************/ +/* Clip and render whole begin/end objects */ +/**********************************************************************/ + +#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED) +#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx] +#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val + + +/* Vertices, with the possibility of clipping. + */ +#define RENDER_POINTS( start, count ) \ + tnl->Driver.Render.Points( ctx, start, count ) + +#define RENDER_LINE( v1, v2 ) \ +do { \ + GLubyte c1 = mask[v1], c2 = mask[v2]; \ + GLubyte ormask = c1|c2; \ + if (!ormask) \ + LineFunc( ctx, v1, v2 ); \ + else if (!(c1 & c2 & 0x3f)) \ + clip_line_4( ctx, v1, v2, ormask ); \ +} while (0) + +#define RENDER_TRI( v1, v2, v3 ) \ +do { \ + GLubyte c1 = mask[v1], c2 = mask[v2], c3 = mask[v3]; \ + GLubyte ormask = c1|c2|c3; \ + if (!ormask) \ + TriangleFunc( ctx, v1, v2, v3 ); \ + else if (!(c1 & c2 & c3 & 0x3f)) \ + clip_tri_4( ctx, v1, v2, v3, ormask ); \ +} while (0) + +#define RENDER_QUAD( v1, v2, v3, v4 ) \ +do { \ + GLubyte c1 = mask[v1], c2 = mask[v2]; \ + GLubyte c3 = mask[v3], c4 = mask[v4]; \ + GLubyte ormask = c1|c2|c3|c4; \ + if (!ormask) \ + QuadFunc( ctx, v1, v2, v3, v4 ); \ + else if (!(c1 & c2 & c3 & c4 & 0x3f)) \ + clip_quad_4( ctx, v1, v2, v3, v4, ormask ); \ +} while (0) + + +#define LOCAL_VARS \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + struct vertex_buffer *VB = &tnl->vb; \ + const GLuint * const elt = VB->Elts; \ + const GLubyte *mask = VB->ClipMask; \ + const GLuint sz = VB->ClipPtr->size; \ + const line_func LineFunc = tnl->Driver.Render.Line; \ + const triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \ + const quad_func QuadFunc = tnl->Driver.Render.Quad; \ + const GLboolean stipple = ctx->Line.StippleFlag; \ + (void) (LineFunc && TriangleFunc && QuadFunc); \ + (void) elt; (void) mask; (void) sz; (void) stipple; + +#define TAG(x) clip_##x##_verts +#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x ) +#define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx ) +#define RESET_OCCLUSION ctx->OcclusionResult = GL_TRUE +#define PRESERVE_VB_DEFS +#include "tnl/t_vb_rendertmp.h" + + + +/* Elts, with the possibility of clipping. + */ +#undef ELT +#undef TAG +#define ELT(x) elt[x] +#define TAG(x) clip_##x##_elts +#include "tnl/t_vb_rendertmp.h" + +/* TODO: do this for all primitives, verts and elts: + */ +static void clip_elt_triangles( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + render_func render_tris = tnl->Driver.Render.PrimTabElts[GL_TRIANGLES]; + struct vertex_buffer *VB = &tnl->vb; + const GLuint * const elt = VB->Elts; + GLubyte *mask = VB->ClipMask; + GLuint last = count-2; + GLuint j; + (void) flags; + + tnl->Driver.Render.PrimitiveNotify( ctx, GL_TRIANGLES ); + + for (j=start; j < last; j+=3 ) { + GLubyte c1 = mask[elt[j]]; + GLubyte c2 = mask[elt[j+1]]; + GLubyte c3 = mask[elt[j+2]]; + GLubyte ormask = c1|c2|c3; + if (ormask) { + if (start < j) + render_tris( ctx, start, j, 0 ); + if (!(c1&c2&c3&0x3f)) + clip_tri_4( ctx, elt[j], elt[j+1], elt[j+2], ormask ); + start = j+3; + } + } + + if (start < j) + render_tris( ctx, start, j, 0 ); +} + +/**********************************************************************/ +/* Render whole begin/end objects */ +/**********************************************************************/ + +#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED) +#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx] +#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val + + +/* Vertices, no clipping. + */ +#define RENDER_POINTS( start, count ) \ + tnl->Driver.Render.Points( ctx, start, count ) + +#define RENDER_LINE( v1, v2 ) \ + LineFunc( ctx, v1, v2 ) + +#define RENDER_TRI( v1, v2, v3 ) \ + TriangleFunc( ctx, v1, v2, v3 ) + +#define RENDER_QUAD( v1, v2, v3, v4 ) \ + QuadFunc( ctx, v1, v2, v3, v4 ) + +#define TAG(x) _gld_tnl_##x##_verts + +#define LOCAL_VARS \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + struct vertex_buffer *VB = &tnl->vb; \ + const GLuint * const elt = VB->Elts; \ + const line_func LineFunc = tnl->Driver.Render.Line; \ + const triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \ + const quad_func QuadFunc = tnl->Driver.Render.Quad; \ + (void) (LineFunc && TriangleFunc && QuadFunc); \ + (void) elt; + +#define RESET_STIPPLE tnl->Driver.Render.ResetLineStipple( ctx ) +#define RESET_OCCLUSION ctx->OcclusionResult = GL_TRUE +#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x ) +#define RENDER_TAB_QUALIFIER +#define PRESERVE_VB_DEFS +#include "tnl/t_vb_rendertmp.h" + + +/* Elts, no clipping. + */ +#undef ELT +#define TAG(x) _gld_tnl_##x##_elts +#define ELT(x) elt[x] +#include "tnl/t_vb_rendertmp.h" + + +/**********************************************************************/ +/* Helper functions for drivers */ +/**********************************************************************/ +/* +void _tnl_RenderClippedPolygon( GLcontext *ctx, const GLuint *elts, GLuint n ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint *tmp = VB->Elts; + + VB->Elts = (GLuint *)elts; + tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END ); + VB->Elts = tmp; +} + +void _tnl_RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + tnl->Driver.Render.Line( ctx, ii, jj ); +} +*/ + + +/**********************************************************************/ +/* Clip and render whole vertex buffers */ +/**********************************************************************/ + +points_func _gldSetupPoints[4] = { + gld_Points2D_DX9, + gld_Points2D_DX9, + gld_Points2D_DX9, + gld_Points2D_DX9 +}; +line_func _gldSetupLine[4] = { + gld_Line2DFlat_DX9, + gld_Line2DSmooth_DX9, + gld_Line2DFlat_DX9, + gld_Line2DSmooth_DX9, +}; +triangle_func _gldSetupTriangle[4] = { + gld_Triangle2DFlat_DX9, + gld_Triangle2DSmooth_DX9, + gld_Triangle2DFlatExtras_DX9, + gld_Triangle2DSmoothExtras_DX9 +}; +quad_func _gldSetupQuad[4] = { + gld_Quad2DFlat_DX9, + gld_Quad2DSmooth_DX9, + gld_Quad2DFlatExtras_DX9, + gld_Quad2DSmoothExtras_DX9 +}; + +//--------------------------------------------------------------------------- + +static GLboolean _gld_mesa_render_stage_run( + GLcontext *ctx, + struct gl_pipeline_stage *stage) +{ + GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); + GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); + + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint new_inputs = stage->changed_inputs; + render_func *tab; + GLint pass = 0; + GLD_pb_dx9 *gldPB; + + /* Allow the drivers to lock before projected verts are built so + * that window coordinates are guarenteed not to change before + * rendering. + */ + ASSERT(tnl->Driver.Render.Start); + + tnl->Driver.Render.Start( ctx ); + + // NOTE: Setting D3DRS_SOFTWAREVERTEXPROCESSING for a mixed-mode device resets + // stream, indices and shader to default values of NULL or 0. +/* if ((ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) && + gld->VStwosidelight.hShader && + !ctx->Fog.Enabled) + { + IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->VStwosidelight.bHardware); + _GLD_DX9_DEV(SetVertexShader(gld->pDev, gld->VStwosidelight.hShader)); + gldPB = &gld->PBtwosidelight; + tnl->Driver.Render.Points = gld_Points2DTwoside_DX9; + if (ctx->_TriangleCaps & DD_FLATSHADE) { + tnl->Driver.Render.Line = gld_Line2DFlatTwoside_DX9; + tnl->Driver.Render.Triangle = gld_Triangle2DFlatTwoside_DX9; + tnl->Driver.Render.Quad = gld_Quad2DFlatTwoside_DX9; + } else { + tnl->Driver.Render.Line = gld_Line2DSmoothTwoside_DX9; + tnl->Driver.Render.Triangle = gld_Triangle2DSmoothTwoside_DX9; + tnl->Driver.Render.Quad = gld_Quad2DSmoothTwoside_DX9; + } + } else {*/ +// IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, TRUE); + IDirect3DDevice9_SetSoftwareVertexProcessing(gld->pDev, TRUE); + gldPB = &gld->PB2d; + _GLD_DX9_DEV(SetVertexShader(gld->pDev, NULL)); + _GLD_DX9_DEV(SetFVF(gld->pDev, gldPB->dwFVF)); + tnl->Driver.Render.Points = _gldSetupPoints[gld->iSetupFunc]; + tnl->Driver.Render.Line = _gldSetupLine[gld->iSetupFunc]; + tnl->Driver.Render.Triangle = _gldSetupTriangle[gld->iSetupFunc]; + tnl->Driver.Render.Quad = _gldSetupQuad[gld->iSetupFunc]; +// } + + _GLD_DX9_VB(Lock(gldPB->pVB, 0, 0, &gldPB->pPoints, D3DLOCK_DISCARD)); + gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0; + // Allocate primitive pointers + // gldPB->pPoints is always first + gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine); + gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle); + + ASSERT(tnl->Driver.Render.BuildVertices); + ASSERT(tnl->Driver.Render.PrimitiveNotify); + ASSERT(tnl->Driver.Render.Points); + ASSERT(tnl->Driver.Render.Line); + ASSERT(tnl->Driver.Render.Triangle); + ASSERT(tnl->Driver.Render.Quad); + ASSERT(tnl->Driver.Render.ResetLineStipple); + ASSERT(tnl->Driver.Render.Interp); + ASSERT(tnl->Driver.Render.CopyPV); + ASSERT(tnl->Driver.Render.ClippedLine); + ASSERT(tnl->Driver.Render.ClippedPolygon); + ASSERT(tnl->Driver.Render.Finish); + + tnl->Driver.Render.BuildVertices( ctx, 0, VB->Count, new_inputs ); + + if (VB->ClipOrMask) { + tab = VB->Elts ? clip_render_tab_elts : clip_render_tab_verts; + clip_render_tab_elts[GL_TRIANGLES] = clip_elt_triangles; + } + else { + tab = (VB->Elts ? + tnl->Driver.Render.PrimTabElts : + tnl->Driver.Render.PrimTabVerts); + } + + do { + GLuint i, length, flags = 0; + for (i = 0 ; !(flags & PRIM_LAST) ; i += length) { + flags = VB->Primitive[i]; + length= VB->PrimitiveLength[i]; + ASSERT(length || (flags & PRIM_LAST)); + ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1); + if (length) + tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags ); + } + } while (tnl->Driver.Render.Multipass && + tnl->Driver.Render.Multipass( ctx, ++pass )); + + +// tnl->Driver.Render.Finish( ctx ); + + _GLD_DX9_VB(Unlock(gldPB->pVB)); + + _GLD_DX9_DEV(SetStreamSource(gld->pDev, 0, gldPB->pVB, 0, gldPB->dwStride)); + + if (gldPB->nPoints) { + _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_POINTLIST, 0, gldPB->nPoints)); + gldPB->nPoints = 0; + } + + if (gldPB->nLines) { + _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_LINELIST, gldPB->iFirstLine, gldPB->nLines)); + gldPB->nLines = 0; + } + + if (gldPB->nTriangles) { + _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_TRIANGLELIST, gldPB->iFirstTriangle, gldPB->nTriangles)); + gldPB->nTriangles = 0; + } + + return GL_FALSE; /* finished the pipe */ +} + + +/**********************************************************************/ +/* Render pipeline stage */ +/**********************************************************************/ + + + +/* Quite a bit of work involved in finding out the inputs for the + * render stage. + */ +static void _gld_mesa_render_stage_check( + GLcontext *ctx, + struct gl_pipeline_stage *stage) +{ + GLuint inputs = VERT_BIT_CLIP; + GLuint i; + + if (ctx->Visual.rgbMode) { + inputs |= VERT_BIT_COLOR0; + + if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) + inputs |= VERT_BIT_COLOR1; //VERT_BIT_SPEC_RGB; + + //if (ctx->Texture._ReallyEnabled) { + for (i=0; iConst.MaxTextureUnits; i++) { + if (ctx->Texture.Unit[i]._ReallyEnabled) + inputs |= VERT_BIT_TEX(i); + } + //} + } else { + inputs |= VERT_BIT_INDEX; + } + + if (ctx->Point._Attenuated) + inputs |= VERT_BIT_POINT_SIZE; + + /* How do drivers turn this off? + */ + if (ctx->Fog.Enabled) + inputs |= VERT_BIT_FOG; // VERT_FOG_COORD; + + if (ctx->_TriangleCaps & DD_TRI_UNFILLED) + inputs |= VERT_BIT_EDGEFLAG; + + if (ctx->RenderMode==GL_FEEDBACK) + inputs |= VERT_BITS_TEX_ANY; + + stage->inputs = inputs; +} + +//--------------------------------------------------------------------------- + +// Destructor +static void _gld_mesa_render_stage_dtr( + struct gl_pipeline_stage *stage) +{ +} + +//--------------------------------------------------------------------------- + +const struct gl_pipeline_stage _gld_mesa_render_stage = +{ + "gld_mesa_render_stage", + (_NEW_BUFFERS | + _DD_NEW_SEPARATE_SPECULAR | + _DD_NEW_FLATSHADE | + _NEW_TEXTURE| + _NEW_LIGHT| + _NEW_POINT| + _NEW_FOG| + _DD_NEW_TRI_UNFILLED | + _NEW_RENDERMODE), // re-check (new inputs, interp function) + 0, /* re-run (always runs) */ + GL_TRUE, /* active */ + 0, 0, /* inputs (set in check_render), outputs */ + 0, 0, /* changed_inputs, private */ + _gld_mesa_render_stage_dtr, /* destructor */ + _gld_mesa_render_stage_check, /* check */ + _gld_mesa_render_stage_run /* run */ +}; + +//--------------------------------------------------------------------------- diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c new file mode 100644 index 0000000000..86c4e30555 --- /dev/null +++ b/src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c @@ -0,0 +1,1345 @@ +/**************************************************************************** +* +* 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: GLDirect Direct3D 8.x WGL (WindowsGL) +* +****************************************************************************/ + +#include "dglcontext.h" +#include "gld_driver.h" +#include "gld_dxerr9.h" +#include "gld_dx9.h" + +#include "tnl/tnl.h" +#include "tnl/t_context.h" + +// Copied from dglcontect.c +#define GLDERR_NONE 0 +#define GLDERR_MEM 1 +#define GLDERR_DDRAW 2 +#define GLDERR_D3D 3 +#define GLDERR_BPP 4 +#define GLDERR_DDS 5 +// This external var keeps track of any error +extern int nContextError; + +#define DDLOG_CRITICAL_OR_WARN DDLOG_CRITICAL + +extern void _gld_mesa_warning(GLcontext *, char *); +extern void _gld_mesa_fatal(GLcontext *, char *); + +//--------------------------------------------------------------------------- + +static char szColorDepthWarning[] = +"GLDirect does not support the current desktop\n\ +color depth.\n\n\ +You may need to change the display resolution to\n\ +16 bits per pixel or higher color depth using\n\ +the Windows Display Settings control panel\n\ +before running this OpenGL application.\n"; + +// The only depth-stencil formats currently supported by Direct3D +// Surface Format Depth Stencil Total Bits +// D3DFMT_D32 32 - 32 +// D3DFMT_D15S1 15 1 16 +// D3DFMT_D24S8 24 8 32 +// D3DFMT_D16 16 - 16 +// D3DFMT_D24X8 24 - 32 +// D3DFMT_D24X4S4 24 4 32 + +// This pixel format will be used as a template when compiling the list +// of pixel formats supported by the hardware. Many fields will be +// filled in at runtime. +// PFD flag defaults are upgraded to match ChoosePixelFormat() -- DaveM +static DGL_pixelFormat pfTemplateHW = +{ + { + sizeof(PIXELFORMATDESCRIPTOR), // Size of the data structure + 1, // Structure version - should be 1 + // Flags: + PFD_DRAW_TO_WINDOW | // The buffer can draw to a window or device surface. + PFD_DRAW_TO_BITMAP | // The buffer can draw to a bitmap. (DaveM) + PFD_SUPPORT_GDI | // The buffer supports GDI drawing. (DaveM) + PFD_SUPPORT_OPENGL | // The buffer supports OpenGL drawing. + PFD_DOUBLEBUFFER | // The buffer is double-buffered. + 0, // Placeholder for easy commenting of above flags + PFD_TYPE_RGBA, // Pixel type RGBA. + 16, // Total colour bitplanes (excluding alpha bitplanes) + 5, 0, // Red bits, shift + 5, 0, // Green bits, shift + 5, 0, // Blue bits, shift + 0, 0, // Alpha bits, shift (destination alpha) + 0, // Accumulator bits (total) + 0, 0, 0, 0, // Accumulator bits: Red, Green, Blue, Alpha + 0, // Depth bits + 0, // Stencil bits + 0, // Number of auxiliary buffers + 0, // Layer type + 0, // Specifies the number of overlay and underlay planes. + 0, // Layer mask + 0, // Specifies the transparent color or index of an underlay plane. + 0 // Damage mask + }, + D3DFMT_UNKNOWN, // No depth/stencil buffer +}; + +//--------------------------------------------------------------------------- +// Vertex Shaders +//--------------------------------------------------------------------------- +/* +// Vertex Shader Declaration +static DWORD dwTwoSidedLightingDecl[] = +{ + D3DVSD_STREAM(0), + D3DVSD_REG(0, D3DVSDT_FLOAT3), // XYZ position + D3DVSD_REG(1, D3DVSDT_FLOAT3), // XYZ normal + D3DVSD_REG(2, D3DVSDT_D3DCOLOR), // Diffuse color + D3DVSD_REG(3, D3DVSDT_D3DCOLOR), // Specular color + D3DVSD_REG(4, D3DVSDT_FLOAT2), // 2D texture unit 0 + D3DVSD_REG(5, D3DVSDT_FLOAT2), // 2D texture unit 1 + D3DVSD_END() +}; + +// Vertex Shader for two-sided lighting +static char *szTwoSidedLightingVS = +// This is a test shader! +"vs.1.0\n" +"m4x4 oPos,v0,c0\n" +"mov oD0,v2\n" +"mov oD1,v3\n" +"mov oT0,v4\n" +"mov oT1,v5\n" +; +*/ +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- + +typedef struct { + HINSTANCE hD3D9DLL; // Handle to d3d9.dll + FNDIRECT3DCREATE9 fnDirect3DCreate9; // Direct3DCreate9 function prototype + BOOL bDirect3D; // Persistant Direct3D9 exists + BOOL bDirect3DDevice; // Persistant Direct3DDevice9 exists + IDirect3D9 *pD3D; // Persistant Direct3D9 + IDirect3DDevice9 *pDev; // Persistant Direct3DDevice9 +} GLD_dx9_globals; + +// These are "global" to all DX9 contexts. KeithH +static GLD_dx9_globals dx9Globals; + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- + +BOOL gldGetDXErrorString_DX( + HRESULT hr, + char *buf, + int nBufSize) +{ + // + // Return a string describing the input HRESULT error code + // + + const char *pStr = DXGetErrorString9(hr); + + if (pStr == NULL) + return FALSE; + + if (strlen(pStr) > nBufSize) + strncpy(buf, pStr, nBufSize); + else + strcpy(buf, pStr); + +// D3DXGetErrorString(hr, buf, nBufSize); + + return TRUE; +} + +//--------------------------------------------------------------------------- + +static D3DMULTISAMPLE_TYPE _gldGetDeviceMultiSampleType( + IDirect3D9 *pD3D9, + D3DFORMAT SurfaceFormat, + D3DDEVTYPE d3dDevType, + BOOL Windowed) +{ + int i; + HRESULT hr; + + if (glb.dwMultisample == GLDS_MULTISAMPLE_NONE) + return D3DMULTISAMPLE_NONE; + + if (glb.dwMultisample == GLDS_MULTISAMPLE_FASTEST) { + // Find fastest multisample + for (i=2; i<17; i++) { + hr = IDirect3D9_CheckDeviceMultiSampleType( + pD3D9, + glb.dwAdapter, + d3dDevType, + SurfaceFormat, + Windowed, + (D3DMULTISAMPLE_TYPE)i, + NULL); + if (SUCCEEDED(hr)) { + return (D3DMULTISAMPLE_TYPE)i; + } + } + } else { + // Find nicest multisample + for (i=16; i>1; i--) { + hr = IDirect3D9_CheckDeviceMultiSampleType( + pD3D9, + glb.dwAdapter, + d3dDevType, + SurfaceFormat, + Windowed, + (D3DMULTISAMPLE_TYPE)i, + NULL); + if (SUCCEEDED(hr)) { + return (D3DMULTISAMPLE_TYPE)i; + } + } + } + + // Nothing found - return default + return D3DMULTISAMPLE_NONE; +} + +//--------------------------------------------------------------------------- + +void _gldDestroyPrimitiveBuffer( + GLD_pb_dx9 *gldVB) +{ + SAFE_RELEASE(gldVB->pVB); + + // Sanity check... + gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0; +} + +//--------------------------------------------------------------------------- + +HRESULT _gldCreatePrimitiveBuffer( + GLcontext *ctx, + GLD_driver_dx9 *lpCtx, + GLD_pb_dx9 *gldVB) +{ + HRESULT hResult; + char *szCreateVertexBufferFailed = "CreateVertexBuffer failed"; + DWORD dwMaxVertices; // Max number of vertices in vertex buffer + DWORD dwVBSize; // Total size of vertex buffer + + // If CVA (Compiled Vertex Array) is used by an OpenGL app, then we + // will need enough vertices to cater for Mesa::Const.MaxArrayLockSize. + // We'll use IMM_SIZE if it's larger (which it should not be). + dwMaxVertices = (IMM_SIZE < MAX_ARRAY_LOCK_SIZE) ? MAX_ARRAY_LOCK_SIZE : IMM_SIZE; + + // Now calculate how many vertices to allow for in total + // 1 per point, 2 per line, 6 per quad = 9 + dwVBSize = dwMaxVertices * 9 * gldVB->dwStride; + + hResult = IDirect3DDevice9_CreateVertexBuffer( + lpCtx->pDev, + dwVBSize, + gldVB->dwUsage, + gldVB->dwFVF, + gldVB->dwPool, + &gldVB->pVB, + NULL); + if (FAILED(hResult)) { + ddlogMessage(DDLOG_CRITICAL_OR_WARN, szCreateVertexBufferFailed); + return hResult; + } + + gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0; + gldVB->pPoints = gldVB->pLines = gldVB->pTriangles = NULL; + gldVB->iFirstLine = dwMaxVertices; // Index of first line in VB + gldVB->iFirstTriangle = dwMaxVertices*3; // Index of first triangle in VB + + return S_OK; +} + +//--------------------------------------------------------------------------- +// Function: _gldCreateVertexShaders +// Create DX9 Vertex Shaders. +//--------------------------------------------------------------------------- +/* +void _gldCreateVertexShaders( + GLD_driver_dx9 *gld) +{ + DWORD dwFlags; + LPD3DXBUFFER pVSOpcodeBuffer; // Vertex Shader opcode buffer + HRESULT hr; + +#ifdef _DEBUG + dwFlags = D3DXASM_DEBUG; +#else + dwFlags = 0; // D3DXASM_SKIPVALIDATION; +#endif + + ddlogMessage(DDLOG_INFO, "Creating shaders...\n"); + + // Init the shader handle + gld->VStwosidelight.hShader = 0; + + if (gld->d3dCaps8.MaxStreams == 0) { + // Lame DX8 driver doesn't support streams + // Not fatal, as defaults will be used + ddlogMessage(DDLOG_WARN, "Driver doesn't support Vertex Shaders (MaxStreams==0)\n"); + return; + } + + // ** THIS DISABLES VERTEX SHADER SUPPORT ** +// return; + // ** THIS DISABLES VERTEX SHADER SUPPORT ** + + // + // Two-sided lighting + // + +#if 0 + // + // DEBUGGING: Load shader from a text file + // + { + LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer + hr = D3DXAssembleShaderFromFile( + "twoside.vsh", + dwFlags, + NULL, // No constants + &pVSOpcodeBuffer, + &pVSErrorBuffer); + if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer)) + ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer)); + SAFE_RELEASE(pVSErrorBuffer); + } +#else + { + LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer + // Assemble ascii shader text into shader opcodes + hr = D3DXAssembleShader( + szTwoSidedLightingVS, + strlen(szTwoSidedLightingVS), + dwFlags, + NULL, // No constants + &pVSOpcodeBuffer, + &pVSErrorBuffer); + if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer)) + ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer)); + SAFE_RELEASE(pVSErrorBuffer); + } +#endif + if (FAILED(hr)) { + ddlogError(DDLOG_WARN, "AssembleShader failed", hr); + SAFE_RELEASE(pVSOpcodeBuffer); + return; + } + +// This is for debugging. Remove to enable vertex shaders in HW +#define _GLD_FORCE_SW_VS 0 + + if (_GLD_FORCE_SW_VS) { + // _GLD_FORCE_SW_VS should be disabled for Final Release + ddlogMessage(DDLOG_SYSTEM, "[Forcing shaders in SW]\n"); + } + + // Try and create shader in hardware. + // NOTE: The D3D Ref device appears to succeed when trying to + // create the device in hardware, but later complains + // when trying to set it with SetVertexShader(). Go figure. + if (_GLD_FORCE_SW_VS || glb.dwDriver == GLDS_DRIVER_REF) { + // Don't try and create a hardware shader with the Ref device + hr = E_FAIL; // COM error/fail result + } else { + gld->VStwosidelight.bHardware = TRUE; + hr = IDirect3DDevice8_CreateVertexShader( + gld->pDev, + dwTwoSidedLightingDecl, + pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer), + &gld->VStwosidelight.hShader, + 0); + } + if (FAILED(hr)) { + ddlogMessage(DDLOG_INFO, "... HW failed, trying SW...\n"); + // Failed. Try and create shader for software processing + hr = IDirect3DDevice8_CreateVertexShader( + gld->pDev, + dwTwoSidedLightingDecl, + pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer), + &gld->VStwosidelight.hShader, + D3DUSAGE_SOFTWAREPROCESSING); + if (FAILED(hr)) { + gld->VStwosidelight.hShader = 0; // Sanity check + ddlogError(DDLOG_WARN, "CreateVertexShader failed", hr); + return; + } + // Succeeded, but for software processing + gld->VStwosidelight.bHardware = FALSE; + } + + SAFE_RELEASE(pVSOpcodeBuffer); + + ddlogMessage(DDLOG_INFO, "... OK\n"); +} + +//--------------------------------------------------------------------------- + +void _gldDestroyVertexShaders( + GLD_driver_dx9 *gld) +{ + if (gld->VStwosidelight.hShader) { + IDirect3DDevice8_DeleteVertexShader(gld->pDev, gld->VStwosidelight.hShader); + gld->VStwosidelight.hShader = 0; + } +} +*/ +//--------------------------------------------------------------------------- + +BOOL gldCreateDrawable_DX( + DGL_ctx *ctx, +// BOOL bDefaultDriver, + BOOL bDirectDrawPersistant, + BOOL bPersistantBuffers) +{ + // + // bDirectDrawPersistant: applies to IDirect3D9 + // bPersistantBuffers: applies to IDirect3DDevice9 + // + + HRESULT hResult; + GLD_driver_dx9 *lpCtx = NULL; + D3DDEVTYPE d3dDevType; + D3DPRESENT_PARAMETERS d3dpp; + D3DDISPLAYMODE d3ddm; + DWORD dwBehaviourFlags; + D3DADAPTER_IDENTIFIER9 d3dIdent; + + // Error if context is NULL. + if (ctx == NULL) + return FALSE; + + if (ctx->glPriv) { + lpCtx = ctx->glPriv; + // Release any existing interfaces + SAFE_RELEASE(lpCtx->pDev); + SAFE_RELEASE(lpCtx->pD3D); + } else { + lpCtx = (GLD_driver_dx9*)malloc(sizeof(GLD_driver_dx9)); + ZeroMemory(lpCtx, sizeof(lpCtx)); + } + + d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF; + // TODO: Check this +// if (bDefaultDriver) +// d3dDevType = D3DDEVTYPE_REF; + + // Use persistant interface if needed + if (bDirectDrawPersistant && dx9Globals.bDirect3D) { + lpCtx->pD3D = dx9Globals.pD3D; + IDirect3D9_AddRef(lpCtx->pD3D); + goto SkipDirectDrawCreate; + } + + // Create Direct3D9 object + lpCtx->pD3D = dx9Globals.fnDirect3DCreate9(D3D_SDK_VERSION); + if (lpCtx->pD3D == NULL) { + MessageBox(NULL, "Unable to initialize Direct3D9", "GLDirect", MB_OK); + ddlogMessage(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D9 interface"); + nContextError = GLDERR_D3D; + goto return_with_error; + } + + // Cache Direct3D interface for subsequent GLRCs + if (bDirectDrawPersistant && !dx9Globals.bDirect3D) { + dx9Globals.pD3D = lpCtx->pD3D; + IDirect3D9_AddRef(dx9Globals.pD3D); + dx9Globals.bDirect3D = TRUE; + } +SkipDirectDrawCreate: + + // Get the display mode so we can make a compatible backbuffer + hResult = IDirect3D9_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm); + if (FAILED(hResult)) { + nContextError = GLDERR_D3D; + goto return_with_error; + } + + // Get device caps + hResult = IDirect3D9_GetDeviceCaps(lpCtx->pD3D, glb.dwAdapter, d3dDevType, &lpCtx->d3dCaps9); + if (FAILED(hResult)) { + ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D9_GetDeviceCaps failed", hResult); + nContextError = GLDERR_D3D; + goto return_with_error; + } + + // Check for hardware transform & lighting + lpCtx->bHasHWTnL = lpCtx->d3dCaps9.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE; + +/* + // + // GONE FOR DX9? + // + // If this flag is present then we can't default to Mesa + // SW rendering between BeginScene() and EndScene(). + if (lpCtx->d3dCaps9.Caps2 & D3DCAPS2_NO2DDURING3DSCENE) { + ddlogMessage(DDLOG_WARN, + "Warning : No 2D allowed during 3D scene.\n"); + } +*/ + + // + // Create the Direct3D context + // + + // Re-use original IDirect3DDevice if persistant buffers exist. + // Note that we test for persistant IDirect3D9 as well + // bDirectDrawPersistant == persistant IDirect3D9 (DirectDraw9 does not exist) + if (bDirectDrawPersistant && bPersistantBuffers && dx9Globals.pD3D && dx9Globals.pDev) { + lpCtx->pDev = dx9Globals.pDev; + IDirect3DDevice9_AddRef(dx9Globals.pDev); + goto skip_direct3ddevice_create; + } + + // Clear the presentation parameters (sets all members to zero) + ZeroMemory(&d3dpp, sizeof(d3dpp)); + + // Recommended by MS; needed for MultiSample. + // Be careful if altering this for FullScreenBlit + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + + d3dpp.BackBufferFormat = d3ddm.Format; + d3dpp.BackBufferCount = 2; //1; + d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(lpCtx->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen); + d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData; + d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE; + + if (ctx->bFullscreen) { + ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen + d3dpp.Windowed = FALSE; + d3dpp.BackBufferWidth = d3ddm.Width; + d3dpp.BackBufferHeight = d3ddm.Height; + d3dpp.hDeviceWindow = ctx->hWnd; + d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; + + // Support for vertical retrace synchronisation. + // Set default presentation interval in case caps bits are missing + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + if (glb.bWaitForRetrace) { + if (lpCtx->d3dCaps9.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; + } else { + if (lpCtx->d3dCaps9.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + } + } else { + ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages + d3dpp.Windowed = TRUE; + d3dpp.BackBufferWidth = ctx->dwWidth; + d3dpp.BackBufferHeight = ctx->dwHeight; + d3dpp.hDeviceWindow = ctx->hWnd; + d3dpp.FullScreen_RefreshRateInHz = 0; + // PresentationInterval Windowed mode is optional now in DX9 (DaveM) + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + if (glb.bWaitForRetrace) { + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; + } else { + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + } + } + + // Decide if we can use hardware TnL + dwBehaviourFlags = (lpCtx->bHasHWTnL) ? + D3DCREATE_MIXED_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING; + // Add flag to tell D3D to be thread-safe + if (glb.bMultiThreaded) + dwBehaviourFlags |= D3DCREATE_MULTITHREADED; + // Add flag to tell D3D to be FPU-safe + if (!glb.bFastFPU) + dwBehaviourFlags |= D3DCREATE_FPU_PRESERVE; + hResult = IDirect3D9_CreateDevice(lpCtx->pD3D, + glb.dwAdapter, + d3dDevType, + ctx->hWnd, + dwBehaviourFlags, + &d3dpp, + &lpCtx->pDev); + if (FAILED(hResult)) { + ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D9_CreateDevice failed", hResult); + nContextError = GLDERR_D3D; + goto return_with_error; + } + + if (bDirectDrawPersistant && bPersistantBuffers && dx9Globals.pD3D) { + dx9Globals.pDev = lpCtx->pDev; + dx9Globals.bDirect3DDevice = TRUE; + } + + // Dump some useful stats + hResult = IDirect3D9_GetAdapterIdentifier( + lpCtx->pD3D, + glb.dwAdapter, + 0, // No WHQL detection (avoid few seconds delay) + &d3dIdent); + if (SUCCEEDED(hResult)) { + ddlogPrintf(DDLOG_INFO, "[Driver Description: %s]", &d3dIdent.Description); + ddlogPrintf(DDLOG_INFO, "[Driver file: %s %d.%d.%02d.%d]", + d3dIdent.Driver, + HIWORD(d3dIdent.DriverVersion.HighPart), + LOWORD(d3dIdent.DriverVersion.HighPart), + HIWORD(d3dIdent.DriverVersion.LowPart), + LOWORD(d3dIdent.DriverVersion.LowPart)); + ddlogPrintf(DDLOG_INFO, "[VendorId: 0x%X, DeviceId: 0x%X, SubSysId: 0x%X, Revision: 0x%X]", + d3dIdent.VendorId, d3dIdent.DeviceId, d3dIdent.SubSysId, d3dIdent.Revision); + } + + // Test to see if IHV driver exposes Scissor Test (new for DX9) + lpCtx->bCanScissor = lpCtx->d3dCaps9.RasterCaps & D3DPRASTERCAPS_SCISSORTEST; + ddlogPrintf(DDLOG_INFO, "Can Scissor: %s", lpCtx->bCanScissor ? "Yes" : "No"); + + // Init projection matrix for D3D TnL + D3DXMatrixIdentity(&lpCtx->matProjection); + lpCtx->matModelView = lpCtx->matProjection; +// gld->bUseMesaProjection = TRUE; + +skip_direct3ddevice_create: + + // Create buffers to hold primitives + lpCtx->PB2d.dwFVF = GLD_FVF_2D_VERTEX; + lpCtx->PB2d.dwPool = D3DPOOL_SYSTEMMEM; + lpCtx->PB2d.dwStride = sizeof(GLD_2D_VERTEX); + lpCtx->PB2d.dwUsage = D3DUSAGE_DONOTCLIP | + D3DUSAGE_DYNAMIC | + D3DUSAGE_SOFTWAREPROCESSING | + D3DUSAGE_WRITEONLY; + hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB2d); + if (FAILED(hResult)) + goto return_with_error; + + lpCtx->PB3d.dwFVF = GLD_FVF_3D_VERTEX; + lpCtx->PB3d.dwPool = D3DPOOL_DEFAULT; + lpCtx->PB3d.dwStride = sizeof(GLD_3D_VERTEX); + lpCtx->PB3d.dwUsage = D3DUSAGE_DYNAMIC | +//DaveM D3DUSAGE_SOFTWAREPROCESSING | + D3DUSAGE_WRITEONLY; + hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB3d); + if (FAILED(hResult)) + goto return_with_error; + +/* // NOTE: A FVF code of zero indicates a non-FVF vertex buffer (for vertex shaders) + lpCtx->PBtwosidelight.dwFVF = 0; //GLD_FVF_TWOSIDED_VERTEX; + lpCtx->PBtwosidelight.dwPool = D3DPOOL_DEFAULT; + lpCtx->PBtwosidelight.dwStride = sizeof(GLD_TWOSIDED_VERTEX); + lpCtx->PBtwosidelight.dwUsage = D3DUSAGE_DONOTCLIP | + D3DUSAGE_DYNAMIC | + D3DUSAGE_SOFTWAREPROCESSING | + D3DUSAGE_WRITEONLY; + hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PBtwosidelight); + if (FAILED(hResult)) + goto return_with_error;*/ + + // Now try and create the DX9 Vertex Shaders +// _gldCreateVertexShaders(lpCtx); + + // Zero the pipeline usage counters + lpCtx->PipelineUsage.qwMesa.QuadPart = +// lpCtx->PipelineUsage.dwD3D2SVS.QuadPart = + lpCtx->PipelineUsage.qwD3DFVF.QuadPart = 0; + + // Assign drawable to GL private + ctx->glPriv = lpCtx; + return TRUE; + +return_with_error: + // Clean up and bail + +// _gldDestroyVertexShaders(lpCtx); + +// _gldDestroyPrimitiveBuffer(&lpCtx->PBtwosidelight); + _gldDestroyPrimitiveBuffer(&lpCtx->PB3d); + _gldDestroyPrimitiveBuffer(&lpCtx->PB2d); + + SAFE_RELEASE(lpCtx->pDev); + SAFE_RELEASE(lpCtx->pD3D); + return FALSE; +} + +//--------------------------------------------------------------------------- + +BOOL gldResizeDrawable_DX( + DGL_ctx *ctx, + BOOL bDefaultDriver, + BOOL bPersistantInterface, + BOOL bPersistantBuffers) +{ + GLD_driver_dx9 *gld = NULL; + D3DDEVTYPE d3dDevType; + D3DPRESENT_PARAMETERS d3dpp; + D3DDISPLAYMODE d3ddm; + HRESULT hResult; + + // Error if context is NULL. + if (ctx == NULL) + return FALSE; + + gld = ctx->glPriv; + if (gld == NULL) + return FALSE; + + if (ctx->bSceneStarted) { + IDirect3DDevice9_EndScene(gld->pDev); + ctx->bSceneStarted = FALSE; + } + + d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF; + if (!bDefaultDriver) + d3dDevType = D3DDEVTYPE_REF; // Force Direct3D Reference Rasterise (software) + + // Get the display mode so we can make a compatible backbuffer + hResult = IDirect3D9_GetAdapterDisplayMode(gld->pD3D, glb.dwAdapter, &d3ddm); + if (FAILED(hResult)) { + nContextError = GLDERR_D3D; +// goto return_with_error; + return FALSE; + } + + // Destroy DX9 Vertex Shaders before Reset() +// _gldDestroyVertexShaders(gld); + + // Release POOL_DEFAULT objects before Reset() + if (gld->PB2d.dwPool == D3DPOOL_DEFAULT) + _gldDestroyPrimitiveBuffer(&gld->PB2d); + if (gld->PB3d.dwPool == D3DPOOL_DEFAULT) + _gldDestroyPrimitiveBuffer(&gld->PB3d); +// if (gld->PBtwosidelight.dwPool == D3DPOOL_DEFAULT) +// _gldDestroyPrimitiveBuffer(&gld->PBtwosidelight); + + // Clear the presentation parameters (sets all members to zero) + ZeroMemory(&d3dpp, sizeof(d3dpp)); + + // Recommended by MS; needed for MultiSample. + // Be careful if altering this for FullScreenBlit + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + + d3dpp.BackBufferFormat = d3ddm.Format; + d3dpp.BackBufferCount = 1; + d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(gld->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen); + d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData; + d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE; + + // TODO: Sync to refresh + + if (ctx->bFullscreen) { + ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen + d3dpp.Windowed = FALSE; + d3dpp.BackBufferWidth = d3ddm.Width; + d3dpp.BackBufferHeight = d3ddm.Height; + d3dpp.hDeviceWindow = ctx->hWnd; + d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + // Get better benchmark results? KeithH +// d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_UNLIMITED; + } else { + ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages + d3dpp.Windowed = TRUE; + d3dpp.BackBufferWidth = ctx->dwWidth; + d3dpp.BackBufferHeight = ctx->dwHeight; + d3dpp.hDeviceWindow = ctx->hWnd; + d3dpp.FullScreen_RefreshRateInHz = 0; + d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + } + hResult = IDirect3DDevice9_Reset(gld->pDev, &d3dpp); + if (FAILED(hResult)) { + ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Reset failed", hResult); + return FALSE; + //goto cleanup_and_return_with_error; + } + + // + // Recreate POOL_DEFAULT objects + // + if (gld->PB2d.dwPool == D3DPOOL_DEFAULT) { + _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB2d); + } + if (gld->PB3d.dwPool == D3DPOOL_DEFAULT) { + _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB3d); + } +// if (gld->PBtwosidelight.dwPool == D3DPOOL_DEFAULT) { +// _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB2d); +// } + + // Recreate DX9 Vertex Shaders +// _gldCreateVertexShaders(gld); + + // Signal a complete state update + ctx->glCtx->Driver.UpdateState(ctx->glCtx, _NEW_ALL); + + // Begin a new scene + IDirect3DDevice9_BeginScene(gld->pDev); + ctx->bSceneStarted = TRUE; + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldDestroyDrawable_DX( + DGL_ctx *ctx) +{ + GLD_driver_dx9 *lpCtx = NULL; + + // Error if context is NULL. + if (!ctx) + return FALSE; + + // Error if the drawable does not exist. + if (!ctx->glPriv) + return FALSE; + + lpCtx = ctx->glPriv; + +#ifdef _DEBUG + // Dump out stats + ddlogPrintf(DDLOG_SYSTEM, "Usage: M:0x%X%X, D:0x%X%X", + lpCtx->PipelineUsage.qwMesa.HighPart, + lpCtx->PipelineUsage.qwMesa.LowPart, + lpCtx->PipelineUsage.qwD3DFVF.HighPart, + lpCtx->PipelineUsage.qwD3DFVF.LowPart); +#endif + +// _gldDestroyVertexShaders(lpCtx); + +// _gldDestroyPrimitiveBuffer(&lpCtx->PBtwosidelight); + _gldDestroyPrimitiveBuffer(&lpCtx->PB3d); + _gldDestroyPrimitiveBuffer(&lpCtx->PB2d); + + SAFE_RELEASE(lpCtx->pDev); + SAFE_RELEASE(lpCtx->pD3D); + + // Free the private drawable data + free(ctx->glPriv); + ctx->glPriv = NULL; + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldCreatePrivateGlobals_DX(void) +{ + ZeroMemory(&dx9Globals, sizeof(dx9Globals)); + + // Load d3d9.dll + dx9Globals.hD3D9DLL = LoadLibrary("D3D9.DLL"); + if (dx9Globals.hD3D9DLL == NULL) + return FALSE; + + // Now try and obtain Direct3DCreate9 + dx9Globals.fnDirect3DCreate9 = (FNDIRECT3DCREATE9)GetProcAddress(dx9Globals.hD3D9DLL, "Direct3DCreate9"); + if (dx9Globals.fnDirect3DCreate9 == NULL) { + FreeLibrary(dx9Globals.hD3D9DLL); + return FALSE; + } + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldDestroyPrivateGlobals_DX(void) +{ + if (dx9Globals.bDirect3DDevice) { + SAFE_RELEASE(dx9Globals.pDev); + dx9Globals.bDirect3DDevice = FALSE; + } + if (dx9Globals.bDirect3D) { + SAFE_RELEASE(dx9Globals.pD3D); + dx9Globals.bDirect3D = FALSE; + } + + FreeLibrary(dx9Globals.hD3D9DLL); + dx9Globals.hD3D9DLL = NULL; + dx9Globals.fnDirect3DCreate9 = NULL; + + return TRUE; +} + +//--------------------------------------------------------------------------- + +static void _BitsFromDisplayFormat( + D3DFORMAT fmt, + BYTE *cColorBits, + BYTE *cRedBits, + BYTE *cGreenBits, + BYTE *cBlueBits, + BYTE *cAlphaBits) +{ + switch (fmt) { + case D3DFMT_X1R5G5B5: + *cColorBits = 16; + *cRedBits = 5; + *cGreenBits = 5; + *cBlueBits = 5; + *cAlphaBits = 0; + return; + case D3DFMT_R5G6B5: + *cColorBits = 16; + *cRedBits = 5; + *cGreenBits = 6; + *cBlueBits = 5; + *cAlphaBits = 0; + return; + case D3DFMT_X8R8G8B8: + *cColorBits = 32; + *cRedBits = 8; + *cGreenBits = 8; + *cBlueBits = 8; + *cAlphaBits = 0; + return; + case D3DFMT_A8R8G8B8: + *cColorBits = 32; + *cRedBits = 8; + *cGreenBits = 8; + *cBlueBits = 8; + *cAlphaBits = 8; + return; + } + + // Should not get here! + *cColorBits = 32; + *cRedBits = 8; + *cGreenBits = 8; + *cBlueBits = 8; + *cAlphaBits = 0; +} + +//--------------------------------------------------------------------------- + +static void _BitsFromDepthStencilFormat( + D3DFORMAT fmt, + BYTE *cDepthBits, + BYTE *cStencilBits) +{ + // NOTE: GL expects either 32 or 16 as depth bits. + switch (fmt) { + case D3DFMT_D32: + *cDepthBits = 32; + *cStencilBits = 0; + return; + case D3DFMT_D15S1: + *cDepthBits = 16; + *cStencilBits = 1; + return; + case D3DFMT_D24S8: + *cDepthBits = 32; + *cStencilBits = 8; + return; + case D3DFMT_D16: + *cDepthBits = 16; + *cStencilBits = 0; + return; + case D3DFMT_D24X8: + *cDepthBits = 32; + *cStencilBits = 0; + return; + case D3DFMT_D24X4S4: + *cDepthBits = 32; + *cStencilBits = 4; + return; + } +} + +//--------------------------------------------------------------------------- + +BOOL gldBuildPixelformatList_DX(void) +{ + D3DDISPLAYMODE d3ddm; + D3DFORMAT fmt[6]; + IDirect3D9 *pD3D = NULL; + HRESULT hr; + int nSupportedFormats = 0; + int i; + DGL_pixelFormat *pPF; + BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits; +// char buf[128]; +// char cat[8]; + + // Direct3D (SW or HW) + // These are arranged so that 'best' pixelformat + // is higher in the list (for ChoosePixelFormat). + const D3DFORMAT DepthStencil[6] = { +// New order: increaing Z, then increasing stencil + D3DFMT_D15S1, + D3DFMT_D16, + D3DFMT_D24X4S4, + D3DFMT_D24X8, + D3DFMT_D24S8, + D3DFMT_D32, + }; + + // Dump DX version + ddlogMessage(GLDLOG_SYSTEM, "DirectX Version : 9.0\n"); + + // Release any existing pixelformat list + if (glb.lpPF) { + free(glb.lpPF); + } + + glb.nPixelFormatCount = 0; + glb.lpPF = NULL; + + // + // Pixelformats for Direct3D (SW or HW) rendering + // + + // Get a Direct3D 9.0 interface + pD3D = dx9Globals.fnDirect3DCreate9(D3D_SDK_VERSION); + if (!pD3D) { + return FALSE; + } + + // We will use the display mode format when finding compliant + // rendertarget/depth-stencil surfaces. + hr = IDirect3D9_GetAdapterDisplayMode(pD3D, glb.dwAdapter, &d3ddm); + if (FAILED(hr)) { + IDirect3D9_Release(pD3D); + return FALSE; + } + + // Run through the possible formats and detect supported formats + for (i=0; i<6; i++) { + hr = IDirect3D9_CheckDeviceFormat( + pD3D, + glb.dwAdapter, + glb.dwDriver==GLDS_DRIVER_HAL ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF, + d3ddm.Format, + D3DUSAGE_DEPTHSTENCIL, + D3DRTYPE_SURFACE, + DepthStencil[i]); + if (FAILED(hr)) + // A failure here is not fatal. + continue; + + // Verify that the depth format is compatible. + hr = IDirect3D9_CheckDepthStencilMatch( + pD3D, + glb.dwAdapter, + glb.dwDriver==GLDS_DRIVER_HAL ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF, + d3ddm.Format, + d3ddm.Format, + DepthStencil[i]); + if (FAILED(hr)) + // A failure here is not fatal, just means depth-stencil + // format is not compatible with this display mode. + continue; + + fmt[nSupportedFormats++] = DepthStencil[i]; + } + + IDirect3D9_Release(pD3D); + + if (nSupportedFormats == 0) + return FALSE; // Bail: no compliant pixelformats + + // Total count of pixelformats is: + // (nSupportedFormats+1)*2 + // UPDATED: nSupportedFormats*2 + glb.lpPF = (DGL_pixelFormat *)calloc(nSupportedFormats*2, sizeof(DGL_pixelFormat)); + glb.nPixelFormatCount = nSupportedFormats*2; + if (glb.lpPF == NULL) { + glb.nPixelFormatCount = 0; + return FALSE; + } + + // Get a copy of pointer that we can alter + pPF = glb.lpPF; + + // Cache colour bits from display format + _BitsFromDisplayFormat(d3ddm.Format, &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits); + + // + // Add single-buffer formats + // +/* + // NOTE: No longer returning pixelformats that don't contain depth + // Single-buffer, no depth-stencil buffer + memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat)); + pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag + pPF->pfd.cColorBits = cColorBits; + pPF->pfd.cRedBits = cRedBits; + pPF->pfd.cGreenBits = cGreenBits; + pPF->pfd.cBlueBits = cBlueBits; + pPF->pfd.cAlphaBits = cAlphaBits; + pPF->pfd.cDepthBits = 0; + pPF->pfd.cStencilBits = 0; + pPF->dwDriverData = D3DFMT_UNKNOWN; + pPF++; +*/ + for (i=0; ipfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag + pPF->pfd.cColorBits = cColorBits; + pPF->pfd.cRedBits = cRedBits; + pPF->pfd.cGreenBits = cGreenBits; + pPF->pfd.cBlueBits = cBlueBits; + pPF->pfd.cAlphaBits = cAlphaBits; + _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits); + pPF->dwDriverData = fmt[i]; + } + + // + // Add double-buffer formats + // + + // NOTE: No longer returning pixelformats that don't contain depth +/* + memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat)); + pPF->pfd.cColorBits = cColorBits; + pPF->pfd.cRedBits = cRedBits; + pPF->pfd.cGreenBits = cGreenBits; + pPF->pfd.cBlueBits = cBlueBits; + pPF->pfd.cAlphaBits = cAlphaBits; + pPF->pfd.cDepthBits = 0; + pPF->pfd.cStencilBits = 0; + pPF->dwDriverData = D3DFMT_UNKNOWN; + pPF++; +*/ + for (i=0; ipfd.cColorBits = cColorBits; + pPF->pfd.cRedBits = cRedBits; + pPF->pfd.cGreenBits = cGreenBits; + pPF->pfd.cBlueBits = cBlueBits; + pPF->pfd.cAlphaBits = cAlphaBits; + _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits); + pPF->dwDriverData = fmt[i]; + } + + // Popup warning message if non RGB color mode + { + // This is a hack. KeithH + HDC hdcDesktop = GetDC(NULL); + DWORD dwDisplayBitDepth = GetDeviceCaps(hdcDesktop, BITSPIXEL); + ReleaseDC(0, hdcDesktop); + if (dwDisplayBitDepth <= 8) { + ddlogPrintf(DDLOG_WARN, "Current Color Depth %d bpp is not supported", dwDisplayBitDepth); + MessageBox(NULL, szColorDepthWarning, "GLDirect", MB_OK | MB_ICONWARNING); + } + } + + // Mark list as 'current' + glb.bPixelformatsDirty = FALSE; + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldInitialiseMesa_DX( + DGL_ctx *lpCtx) +{ + GLD_driver_dx9 *gld = NULL; + int MaxTextureSize, TextureLevels; + BOOL bSoftwareTnL; + + if (lpCtx == NULL) + return FALSE; + + gld = lpCtx->glPriv; + if (gld == NULL) + return FALSE; + + if (glb.bMultitexture) { + lpCtx->glCtx->Const.MaxTextureUnits = gld->d3dCaps9.MaxSimultaneousTextures; + // Only support MAX_TEXTURE_UNITS texture units. + // ** If this is altered then the FVF formats must be reviewed **. + if (lpCtx->glCtx->Const.MaxTextureUnits > GLD_MAX_TEXTURE_UNITS_DX9) + lpCtx->glCtx->Const.MaxTextureUnits = GLD_MAX_TEXTURE_UNITS_DX9; + } else { + // Multitexture override + lpCtx->glCtx->Const.MaxTextureUnits = 1; + } + + // max texture size + MaxTextureSize = min(gld->d3dCaps9.MaxTextureHeight, gld->d3dCaps9.MaxTextureWidth); + if (MaxTextureSize == 0) + MaxTextureSize = 256; // Sanity check + + // + // HACK!! + if (MaxTextureSize > 1024) + MaxTextureSize = 1024; // HACK - CLAMP TO 1024 + // HACK!! + // + + // Got to set MAX_TEXTURE_SIZE as max levels. + // Who thought this stupid idea up? ;) + TextureLevels = 0; + // Calculate power-of-two. + while (MaxTextureSize) { + TextureLevels++; + MaxTextureSize >>= 1; + } + lpCtx->glCtx->Const.MaxTextureLevels = (TextureLevels) ? TextureLevels : 8; + + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_LIGHTING, FALSE); + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_CULLMODE, D3DCULL_NONE); + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_DITHERENABLE, TRUE); + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_SHADEMODE, D3DSHADE_GOURAUD); + + IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ZENABLE, + (lpCtx->lpPF->dwDriverData!=D3DFMT_UNKNOWN) ? D3DZB_TRUE : D3DZB_FALSE); + + // Set the view matrix + { + D3DXMATRIX vm; +#if 1 + D3DXMatrixIdentity(&vm); +#else + D3DXVECTOR3 Eye(0.0f, 0.0f, 0.0f); + D3DXVECTOR3 At(0.0f, 0.0f, -1.0f); + D3DXVECTOR3 Up(0.0f, 1.0f, 0.0f); + D3DXMatrixLookAtRH(&vm, &Eye, &At, &Up); + vm._31 = -vm._31; + vm._32 = -vm._32; + vm._33 = -vm._33; + vm._34 = -vm._34; +#endif + IDirect3DDevice9_SetTransform(gld->pDev, D3DTS_VIEW, &vm); + } + + if (gld->bHasHWTnL) { + if (glb.dwTnL == GLDS_TNL_DEFAULT) + bSoftwareTnL = FALSE; // HW TnL + else { + bSoftwareTnL = ((glb.dwTnL == GLDS_TNL_MESA) || (glb.dwTnL == GLDS_TNL_D3DSW)) ? TRUE : FALSE; + } + } else { + // No HW TnL, so no choice possible + bSoftwareTnL = TRUE; + } +// IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, bSoftwareTnL); + IDirect3DDevice9_SetSoftwareVertexProcessing(gld->pDev, bSoftwareTnL); + +// Dump this in a Release build as well, now. +//#ifdef _DEBUG + ddlogPrintf(DDLOG_INFO, "HW TnL: %s", + gld->bHasHWTnL ? (bSoftwareTnL ? "Disabled" : "Enabled") : "Unavailable"); +//#endif + + gldEnableExtensions_DX9(lpCtx->glCtx); + gldInstallPipeline_DX9(lpCtx->glCtx); + gldSetupDriverPointers_DX9(lpCtx->glCtx); + + // Signal a complete state update + lpCtx->glCtx->Driver.UpdateState(lpCtx->glCtx, _NEW_ALL); + + // Start a scene + IDirect3DDevice9_BeginScene(gld->pDev); + lpCtx->bSceneStarted = TRUE; + + return TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldSwapBuffers_DX( + DGL_ctx *ctx, + HDC hDC, + HWND hWnd) +{ + HRESULT hr; + GLD_driver_dx9 *gld = NULL; + + if (ctx == NULL) + return FALSE; + + gld = ctx->glPriv; + if (gld == NULL) + return FALSE; + + if (ctx->bSceneStarted) { + IDirect3DDevice9_EndScene(gld->pDev); + ctx->bSceneStarted = FALSE; + } + + // Swap the buffers. hWnd may override the hWnd used for CreateDevice() + hr = IDirect3DDevice9_Present(gld->pDev, NULL, NULL, hWnd, NULL); + +exit_swap: + + IDirect3DDevice9_BeginScene(gld->pDev); + ctx->bSceneStarted = TRUE; + +// Debugging code +#ifdef _DEBUG +// ddlogMessage(GLDLOG_WARN, "SwapBuffers\n"); +#endif + + return (FAILED(hr)) ? FALSE : TRUE; +} + +//--------------------------------------------------------------------------- + +BOOL gldGetDisplayMode_DX( + DGL_ctx *ctx, + GLD_displayMode *glddm) +{ + D3DDISPLAYMODE d3ddm; + HRESULT hr; + GLD_driver_dx9 *lpCtx = NULL; + BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits; + + if ((glddm == NULL) || (ctx == NULL)) + return FALSE; + + lpCtx = ctx->glPriv; + if (lpCtx == NULL) + return FALSE; + + if (lpCtx->pD3D == NULL) + return FALSE; + + hr = IDirect3D9_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm); + if (FAILED(hr)) + return FALSE; + + // Get info from the display format + _BitsFromDisplayFormat(d3ddm.Format, + &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits); + + glddm->Width = d3ddm.Width; + glddm->Height = d3ddm.Height; + glddm->BPP = cColorBits; + glddm->Refresh = d3ddm.RefreshRate; + + return TRUE; +} + +//--------------------------------------------------------------------------- + -- cgit v1.2.3