Advertisement
Guest User

Untitled

a guest
Jun 17th, 2019
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 125.87 KB | None | 0 0
  1. /*
  2. ====================================================================================================================================
  3.  
  4.     NEW FAKE GL WRAPPER - MH 2009
  5.  
  6.     Uses Direct3D 8 for an (almost) seamless replacement of OpenGL.
  7.  
  8.     It is assumed that your OpenGL code is reasonably correct so far as OpenGL is concerned, and therefore a certain layer
  9.     of error checking and validation that *could* be included is actually omitted.  It is recommended that you test any
  10.     OpenGL code you write using native OpenGL calls before sending it through this wrapper in order to ensure this
  11.     correctness.
  12.  
  13.     Wherever possible the OpenGL specifications at http://www.opengl.org were used for guidance and interpretation of
  14.     OpenGL calls.  The Direct3D 8 SDK help files and several sample aplications and other sources were used for the D3D
  15.     portion of the code.  Every effort has been made to ensure that my interpretation of things is conformant with
  16.     the published specs of each API.  It has been known for published specs to have bugs, and it has also been known
  17.     for my interpretation to be incorrect, however; so let me know if there is anything that needs fixing.
  18.  
  19.     Compilation should be relatively seamless, although there are some changes you will need to make to your application
  20.     in order to get the best experience from it.  These include the following items (listed with a GLQuake-derived engine
  21.     in mind):
  22.  
  23.     - Replace the SwapBuffers call in gl_vidnt.c with FakeSwapBuffers
  24.  
  25.     YOU WILL NEED THE DIRECTX 8 SDK TO COMPILE THIS.
  26.  
  27.     It's still available on the internet (but not on microsoft.com) so just search on Google.
  28.  
  29.     It should compile OK on Visual C++ 2008 (including express) but there are a few steps to complete first.
  30.  
  31.     - Add the DirectX 8 SDK headers and libs to your Visual C++ directories.  I suggest you place them at the very end of the
  32.       list, as if you add them towards the top some defines or other files may conflict with the version of the platform SDK
  33.       used for this IDE.
  34.  
  35.     - create a fake libci.lib static library project (it can just contain one empty function called what you want, compile it,
  36.       and place the resulting .lib in your source directory so that d3dx8 can link OK.
  37.  
  38. ====================================================================================================================================
  39. */
  40.  
  41. // This is FakeGLx, a WIP XBOX port of FakeGL.
  42.  
  43. #ifdef _USEFAKEGLX_09
  44.  
  45. // TODO Fix this warning instead of disabling it
  46. #pragma warning (disable: 4273)
  47.  
  48. // we get a few signed/unsigned mismatches here
  49. #pragma warning (disable: 4018)
  50. #pragma warning (disable: 4244)
  51.  
  52. #include <xtl.h>
  53. #include <xgraphics.h>
  54.  
  55. #include "fakeglx09.h"
  56.  
  57. extern void SysMessage(const char *fmt, ...);
  58. extern void SetGUID3DDevice(LPDIRECT3DDEVICE8 pD3DDevice, D3DPRESENT_PARAMETERS PresentParams);
  59.  
  60. // d3d basic stuff
  61. LPDIRECT3D8 d3d_Object = NULL;
  62. LPDIRECT3DDEVICE8 d3d_Device = NULL;
  63.  
  64. int g_iWidth = 640;
  65. int g_iHeight = 480;
  66. BOOL g_bHDEnabled = FALSE;
  67.  
  68. // mode definition
  69. int d3d_BPP = -1;
  70. //HWND d3d_Window;
  71.  
  72. BOOL d3d_RequestStencil = FALSE;
  73.  
  74. // the desktop and current display modes
  75. D3DDISPLAYMODE d3d_DesktopMode;
  76. D3DDISPLAYMODE d3d_CurrentMode;
  77.  
  78. // presentation parameters that the device was created with
  79. D3DPRESENT_PARAMETERS d3d_PresentParams;
  80.  
  81. // capabilities
  82. // these can exist for both the object and the device
  83. D3DCAPS8 d3d_Caps;
  84.  
  85. // we're going to need this a lot so store it globally to save me having to redeclare it every time
  86. HRESULT hr = S_OK;
  87.  
  88. // global state defines
  89. DWORD d3d_ClearColor = 0x00000000;
  90. BOOL d3d_DeviceLost = FALSE;
  91. D3DVIEWPORT8 d3d_Viewport;
  92.  
  93. BOOL g_bScissorTest = FALSE;
  94. D3DRECT g_ScissorRect;
  95.  
  96. int g_iCurrentTextureID = -1;
  97.  
  98. // cache float size
  99. float g_fSize16 = sizeof (float) * 16;
  100.  
  101. //#define BYTE_CLAMP(i) (int) ((((i) > 255) ? 255 : (((i) < 0) ? 0 : (i))))
  102. __forceinline byte BYTE_CLAMP(int n)
  103. {
  104.     if (n&(~0xFF))
  105.         return (-n)>>31;
  106.  
  107.     return n;
  108. }
  109.  
  110. // Go through the vtable rather than use the macros to make this generic
  111. #define D3D_SAFE_RELEASE(p) {if (p) (p)->lpVtbl->Release (p);  (p) = NULL;}
  112. //#define D3D_SAFE_RELEASE(p) {if (p) (p)->Release();            (p)=NULL;}
  113.  
  114. DWORD GL_ColorToD3D (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
  115. {
  116.     return D3DCOLOR_ARGB
  117.     (
  118.         BYTE_CLAMP (alpha * 255.0f),
  119.         BYTE_CLAMP (red * 255.0f),
  120.         BYTE_CLAMP (green * 255.0f),
  121.         BYTE_CLAMP (blue * 255.0f)
  122.     );
  123. }
  124.  
  125. typedef struct d3d_texture_s
  126. {
  127.     // OpenGL number for glBindTexture/glGenTextures/glDeleteTextures/etc
  128.     int glnum;
  129.  
  130.     // format the texture was uploaded as; 1 or 4 bytes.
  131.     // glTexSubImage2D needs this.
  132.     GLenum internalformat;
  133.  
  134.     // parameters
  135.     DWORD addressu;
  136.     DWORD addressv;
  137.     DWORD anisotropy;
  138.     DWORD magfilter;
  139.     DWORD minfilter;
  140.     DWORD mipfilter;
  141.  
  142.     // the texture image itself
  143.     LPDIRECT3DTEXTURE8 teximg;
  144.  
  145.     struct d3d_texture_s *next;
  146. } d3d_texture_t;
  147.  
  148. typedef struct SubImage_s
  149. {
  150.     int iTextureNum;
  151.     struct SubImage_s *next;
  152.     LPDIRECT3DSURFACE8 texture;
  153. } SubImage_t;
  154.  
  155. SubImage_t *SubImageCache = NULL;
  156.  
  157. int d3d_TextureExtensionNumber = 1;
  158.  
  159. // opengl specified up to 32 TMUs, D3D only allows up to 8 stages
  160. // XBOX: Only 4 stages available, max value is therefore 3 -> see docs IDirect3DDevice8::SetTextureStageState
  161.  
  162. #define D3D_MAX_TMUS    1//8
  163. /*
  164. typedef struct gl_combine_s
  165. {
  166.     DWORD colorop;
  167.     DWORD colorarg1;
  168.     DWORD colorarg2;
  169.     DWORD alphaop;
  170.     DWORD alphaarg1;
  171.     DWORD alphaarg2;
  172.     DWORD colorarg0;
  173.     DWORD alphaarg0;
  174.     DWORD resultarg;
  175.     DWORD colorscale;
  176.     DWORD alphascale;
  177. } gl_combine_t;
  178. */
  179. typedef struct gl_tmustate_s
  180. {
  181.     d3d_texture_t *boundtexture;
  182.     BOOL enabled;
  183.     // BOOL combine;
  184.  
  185.     // gl_combine_t combstate;
  186.  
  187.     // these come from glTexEnv and are properties of the TMU; other D3DTEXTURESTAGESTATETYPEs
  188.     // come from glTexParameter and are properties of the individual texture.
  189.     DWORD colorop;
  190.     DWORD colorarg1;
  191.     DWORD colorarg2;
  192.     DWORD alphaop;
  193.     DWORD alphaarg1;
  194.     DWORD alphaarg2;
  195.     DWORD texcoordindex;
  196.  
  197.     BOOL texenvdirty;
  198.     BOOL texparamdirty;
  199. } gl_tmustate_t;
  200.  
  201. gl_tmustate_t d3d_TMUs[D3D_MAX_TMUS];
  202.  
  203. int d3d_CurrentTMU = 0;
  204.  
  205. // used in various places
  206. int D3D_TMUForTexture (GLenum texture)
  207. {
  208.     switch (texture)
  209.     {
  210.     case GLD3D_TEXTURE0: return 0;
  211.     case GLD3D_TEXTURE1: return 1;
  212.     //case GLD3D_TEXTURE2: return 2;
  213.     //case GLD3D_TEXTURE3: return 3;
  214.     //case GLD3D_TEXTURE4: return 4;
  215.     //case GLD3D_TEXTURE5: return 5;
  216.     //case GLD3D_TEXTURE6: return 6;
  217.     //case GLD3D_TEXTURE7: return 7;
  218.  
  219.     default:
  220.         // ? how best to fail gracefully (if we should fail gracefully at all?)
  221.         return 0;
  222.     }
  223. }
  224.  
  225. // backface culling
  226. // (fix me - put all of these into a state struct)
  227. GLboolean gl_CullEnable = GL_TRUE;
  228. GLenum gl_CullMode = GL_BACK;
  229. GLenum gl_FrontFace = GL_CCW;
  230.  
  231. /*
  232. ===================================================================================================================
  233.  
  234.             HINT MECHANISM
  235.  
  236.     D3D generally doesn't provide a hint mechanism, instead relying on the programmer to explicitly set
  237.     parameters for stuff.  In cases where certain items are in doubt we add hint capability.
  238.  
  239. ===================================================================================================================
  240. */
  241.  
  242. // default to per-pixel fog
  243. GLenum d3d_Fog_Hint = GL_NICEST;
  244.  
  245. void glHint (GLenum target, GLenum mode)
  246. {
  247.     switch (target)
  248.     {
  249.     case GL_FOG_HINT:
  250.         d3d_Fog_Hint = mode;
  251.         break;
  252.  
  253.     default:
  254.         // ignore other driver hints
  255.         break;
  256.     }
  257. }
  258.  
  259.  
  260. /*
  261. ===================================================================================================================
  262.  
  263.             MATRIXES
  264.  
  265.     Most matrix ops occur in software in D3D; the only part that may (or may not) occur in hardware (depending
  266.     on whether or not we have a hardware vp device) is the final transformation of submitted verts.  Note that
  267.     OpenGL is probably the same.
  268.  
  269.     This interface just models the most common OpenGL matrix ops with their D3D equivalents.  I don't use the
  270.     IDirect3DXMatrixStack interface because of overhead and baggage associated with it.
  271.  
  272.     The critical differences are in glGetFloatv and glLoadMatrix; OpenGL uses column major ordering whereas
  273.     D3D uses row major ordering, so we need to translate from one order to the next.
  274.  
  275.     Also be aware that D3D defines separate world and view matrixes whereas OpenGL concatenates them into a
  276.     single modelview matrix.  To keep things clean and consistent we will always use an identity view matrix
  277.     on a beginscene and will just work off the world matrix.
  278.  
  279.     Finally, D3D does weird and horrible things in the texture matrix which are better left unsaid for now.
  280.  
  281. ===================================================================================================================
  282. */
  283.  
  284. // OpenGL only has a stack depth of 2 for projection, but no reason to not use the full depth
  285. #define MAX_MATRIX_STACK    32
  286.  
  287. typedef struct d3d_matrix_s
  288. {
  289.     BOOL dirty;
  290.     int stackdepth;
  291.     D3DTRANSFORMSTATETYPE usage;
  292.     D3DXMATRIX stack[MAX_MATRIX_STACK];
  293. } d3d_matrix_t;
  294.  
  295. // init all matrixes to be dirty and at depth 0 (these will be re-inited each frame)
  296. d3d_matrix_t d3d_ModelViewMatrix = {TRUE, 0, D3DTS_WORLD};
  297. d3d_matrix_t d3d_ProjectionMatrix = {TRUE, 0, D3DTS_PROJECTION};
  298.  
  299. d3d_matrix_t *d3d_CurrentMatrix = &d3d_ModelViewMatrix;
  300.  
  301.  
  302. void D3D_InitializeMatrix (d3d_matrix_t *m)
  303. {
  304.     // initializes a matrix to a known state prior to rendering
  305.     m->dirty = TRUE;
  306.     m->stackdepth = 0;
  307.     D3DXMatrixIdentity (&m->stack[0]);
  308. }
  309.  
  310.  
  311. void D3D_CheckDirtyMatrix (d3d_matrix_t *m)
  312. {
  313.     if (m->dirty)
  314.     {
  315.         IDirect3DDevice8_SetTransform (d3d_Device, m->usage, &m->stack[m->stackdepth]);
  316.         m->dirty = FALSE;
  317.     }
  318. }
  319.  
  320.  
  321. void glMatrixMode (GLenum mode)
  322. {
  323.     switch (mode)
  324.     {
  325.     case GL_MODELVIEW:
  326.         d3d_CurrentMatrix = &d3d_ModelViewMatrix;
  327.         break;
  328.  
  329.     case GL_PROJECTION:
  330.         d3d_CurrentMatrix = &d3d_ProjectionMatrix;
  331.         break;
  332.  
  333.     default:
  334.         SysMessage ("glMatrixMode: unimplemented mode");
  335.         break;
  336.     }
  337. }
  338.  
  339.  
  340. void glLoadIdentity (void)
  341. {
  342.     D3DXMatrixIdentity (&d3d_CurrentMatrix->stack[d3d_CurrentMatrix->stackdepth]);
  343.     d3d_CurrentMatrix->dirty = TRUE;
  344. }
  345.  
  346.  
  347. void glLoadMatrixf (const GLfloat *m)
  348. {
  349.     memcpy (d3d_CurrentMatrix->stack[d3d_CurrentMatrix->stackdepth].m, m, g_fSize16);
  350.     d3d_CurrentMatrix->dirty = TRUE;
  351. }
  352.  
  353.  
  354. void glFrustum (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar)
  355. {
  356.     D3DXMATRIX tmp;
  357.  
  358.     // per spec, glFrustum multiplies the current matrix by the specified orthographic projection rather than replacing it
  359.     D3DXMatrixPerspectiveOffCenterRH (&tmp, left, right, bottom, top, zNear, zFar);
  360.  
  361.     D3DXMatrixMultiply (&d3d_CurrentMatrix->stack[d3d_CurrentMatrix->stackdepth], &tmp, &d3d_CurrentMatrix->stack[d3d_CurrentMatrix->stackdepth]);
  362.     d3d_CurrentMatrix->dirty = TRUE;
  363. }
  364.  
  365.  
  366. void glOrtho (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar)
  367. {
  368.     D3DXMATRIX tmp;
  369.  
  370.     // per spec, glOrtho multiplies the current matrix by the specified orthographic projection rather than replacing it
  371.     D3DXMatrixOrthoOffCenterRH (&tmp, left, right, bottom, top, zNear, zFar);
  372.  
  373.     D3DXMatrixMultiply (&d3d_CurrentMatrix->stack[d3d_CurrentMatrix->stackdepth], &tmp, &d3d_CurrentMatrix->stack[d3d_CurrentMatrix->stackdepth]);
  374.     d3d_CurrentMatrix->dirty = TRUE;
  375. }
  376.  
  377.  
  378. void glPopMatrix (void)
  379. {
  380.     if (!d3d_CurrentMatrix->stackdepth)
  381.     {
  382.         // opengl silently allows this and so should we (witness TQ's R_DrawAliasModel, which pushes the
  383.         // matrix once but pops it twice - on line 423 and line 468
  384.         d3d_CurrentMatrix->dirty = TRUE;
  385.         return;
  386.     }
  387.  
  388.     // go to a new matrix
  389.     d3d_CurrentMatrix->stackdepth--;
  390.  
  391.     // flag as dirty
  392.     d3d_CurrentMatrix->dirty = TRUE;
  393. }
  394.  
  395.  
  396. void glPushMatrix (void)
  397. {
  398.     if (d3d_CurrentMatrix->stackdepth <= (MAX_MATRIX_STACK - 1))
  399.     {
  400.         // go to a new matrix (only push if there's room to push)
  401.         d3d_CurrentMatrix->stackdepth++;
  402.  
  403.         // copy up the previous matrix (per spec)
  404.         memcpy
  405.         (
  406.             &d3d_CurrentMatrix->stack[d3d_CurrentMatrix->stackdepth],
  407.             &d3d_CurrentMatrix->stack[d3d_CurrentMatrix->stackdepth - 1],
  408.             sizeof (D3DXMATRIX)
  409.         );
  410.     }
  411.  
  412.     // flag as dirty
  413.     d3d_CurrentMatrix->dirty = TRUE;
  414. }
  415.  
  416.  
  417. void glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
  418. {
  419.     // replicates the OpenGL glRotatef with 3 components and angle in degrees
  420.     D3DXVECTOR3 vec;
  421.     D3DXMATRIX tmp;
  422.  
  423.     vec.x = x;
  424.     vec.y = y;
  425.     vec.z = z;
  426.  
  427.     D3DXMatrixRotationAxis (&tmp, &vec, D3DXToRadian (angle));
  428.     D3DXMatrixMultiply (&d3d_CurrentMatrix->stack[d3d_CurrentMatrix->stackdepth], &tmp, &d3d_CurrentMatrix->stack[d3d_CurrentMatrix->stackdepth]);
  429.  
  430.     // dirty the matrix
  431.     d3d_CurrentMatrix->dirty = TRUE;
  432. }
  433.  
  434.  
  435. void glScalef (GLfloat x, GLfloat y, GLfloat z)
  436. {
  437.     D3DXMATRIX tmp;
  438.     D3DXMatrixScaling (&tmp, x, y, z);
  439.     D3DXMatrixMultiply (&d3d_CurrentMatrix->stack[d3d_CurrentMatrix->stackdepth], &tmp, &d3d_CurrentMatrix->stack[d3d_CurrentMatrix->stackdepth]);
  440.  
  441.     // dirty the matrix
  442.     d3d_CurrentMatrix->dirty = TRUE;
  443. }
  444.  
  445.  
  446. void glTranslatef (GLfloat x, GLfloat y, GLfloat z)
  447. {
  448.     D3DXMATRIX tmp;
  449.     D3DXMatrixTranslation (&tmp, x, y, z);
  450.     D3DXMatrixMultiply (&d3d_CurrentMatrix->stack[d3d_CurrentMatrix->stackdepth], &tmp, &d3d_CurrentMatrix->stack[d3d_CurrentMatrix->stackdepth]);
  451.  
  452.     // dirty the matrix
  453.     d3d_CurrentMatrix->dirty = TRUE;
  454. }
  455.  
  456.  
  457. void glMultMatrixf (const GLfloat *m)
  458. {
  459.     D3DXMATRIX mat;
  460.  
  461.     // copy out
  462.     mat._11 = m[0];
  463.     mat._12 = m[1];
  464.     mat._13 = m[2];
  465.     mat._14 = m[3];
  466.  
  467.     mat._21 = m[4];
  468.     mat._22 = m[5];
  469.     mat._23 = m[6];
  470.     mat._24 = m[7];
  471.  
  472.     mat._31 = m[8];
  473.     mat._32 = m[9];
  474.     mat._33 = m[10];
  475.     mat._34 = m[11];
  476.  
  477.     mat._41 = m[12];
  478.     mat._42 = m[13];
  479.     mat._43 = m[14];
  480.     mat._44 = m[15];
  481.  
  482.     D3DXMatrixMultiply (&d3d_CurrentMatrix->stack[d3d_CurrentMatrix->stackdepth], &mat, &d3d_CurrentMatrix->stack[d3d_CurrentMatrix->stackdepth]);
  483.  
  484.     // dirty the matrix
  485.     d3d_CurrentMatrix->dirty = TRUE;
  486. }
  487.  
  488.  
  489. /*
  490. ===================================================================================================================
  491.  
  492.             STATE MANAGEMENT
  493.  
  494.     The D3D runtime will filter states for us anyway as we have selected a non-pure device (intentional even if
  495.     a pure device is available as we need to support certain glGet functions); this just keeps the filtering local
  496.  
  497. ===================================================================================================================
  498. */
  499.  
  500. LPDIRECT3DTEXTURE8 d3d_BoundTextures[D3D_MAX_TMUS];
  501.  
  502. void D3D_SetTexture (int stage, LPDIRECT3DTEXTURE8 texture)
  503. {
  504.     if (d3d_BoundTextures[stage] != texture)
  505.     {
  506.         d3d_BoundTextures[stage] = texture;
  507.    
  508.         IDirect3DDevice8_SetTexture (d3d_Device, stage, (IDirect3DBaseTexture8 *) texture);
  509.     }
  510. }
  511.  
  512.  
  513. void D3D_DirtyAllStates (void)
  514. {
  515.     int i;
  516.  
  517.     // dirty TMUs
  518.     for (i = 0; i < D3D_MAX_TMUS; i++)
  519.     {
  520.         d3d_TMUs[i].texenvdirty = TRUE;
  521.         d3d_TMUs[i].texparamdirty = TRUE;
  522.         d3d_BoundTextures[i] = NULL;
  523.     }
  524.  
  525.     // and these as well
  526.     d3d_ModelViewMatrix.dirty = TRUE;
  527.     d3d_ProjectionMatrix.dirty = TRUE;
  528. }
  529.  
  530.  
  531. // d3d8 specifies 174 render states; here we just provide headroom
  532. DWORD d3d_RenderStates[256];
  533.  
  534. // 28 stage states per stage
  535. DWORD d3d_TextureStates[D3D_MAX_TMUS][32];
  536.  
  537. DWORD D3D_FloatToDWORD (float f)
  538. {
  539.     return ((DWORD *) &f)[0];
  540. }
  541.  
  542.  
  543. void D3D_SetRenderState (D3DRENDERSTATETYPE state, DWORD value)
  544. {
  545.     // filter state
  546.     if (d3d_RenderStates[(int) state] == value) return;
  547.  
  548.     // set the state and cache it back
  549.     IDirect3DDevice8_SetRenderState (d3d_Device, state, value);
  550.     d3d_RenderStates[(int) state] = value;
  551. }
  552.  
  553.  
  554. void D3D_SetTextureState (DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value)
  555. {
  556.     // filter state
  557.     if (d3d_TextureStates[Stage][(int) Type] == Value) return;
  558.  
  559.     // set the state and cache it back
  560.     IDirect3DDevice8_SetTextureStageState (d3d_Device, Stage, Type, Value);
  561.     d3d_TextureStates[Stage][(int) Type] = Value;
  562. }
  563.  
  564.  
  565. void D3D_SetVertexShader (DWORD shader)
  566. {
  567.     // init this to something invalid so that we know it'll never match
  568.     static DWORD oldshader = D3DFVF_XYZ | D3DFVF_XYZRHW;
  569.  
  570.     // check for change
  571.     if (shader == oldshader) return;
  572.  
  573.     // set and cache back
  574.     IDirect3DDevice8_SetVertexShader (d3d_Device, shader);
  575.     oldshader = shader;
  576. }
  577.  
  578.  
  579. void D3D_InitTexture (d3d_texture_t *tex)
  580. {
  581.     tex->glnum = 0;
  582.  
  583.     // note - we can't set the ->next pointer to NULL here as this texture may be a
  584.     // member of the linked list that has just become free...
  585.     tex->addressu = D3DTADDRESS_WRAP;
  586.     tex->addressv = D3DTADDRESS_WRAP;
  587.     tex->magfilter = D3DTEXF_LINEAR;
  588.     tex->minfilter = D3DTEXF_LINEAR;
  589.     tex->mipfilter = D3DTEXF_LINEAR;
  590.     tex->anisotropy = 1;
  591.  
  592.     //D3D_SAFE_RELEASE (tex->teximg); //FIXME
  593.     if(tex->teximg)
  594.     {
  595.         IDirect3DTexture8_Release(tex->teximg);
  596.         tex->teximg = NULL;
  597.     }  
  598. }
  599.  
  600.  
  601. void D3D_GetRenderStates (void)
  602. {
  603.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_ZENABLE, &d3d_RenderStates[D3DRS_ZENABLE]);
  604.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_FILLMODE, &d3d_RenderStates[D3DRS_FILLMODE]);
  605.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_SHADEMODE, &d3d_RenderStates[D3DRS_SHADEMODE]);
  606. //  IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_LINEPATTERN, &d3d_RenderStates[D3DRS_LINEPATTERN]);
  607.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_ZWRITEENABLE, &d3d_RenderStates[D3DRS_ZWRITEENABLE]);
  608.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_ALPHATESTENABLE, &d3d_RenderStates[D3DRS_ALPHATESTENABLE]);
  609. //  IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_LASTPIXEL, &d3d_RenderStates[D3DRS_LASTPIXEL]);
  610.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_SRCBLEND, &d3d_RenderStates[D3DRS_SRCBLEND]);
  611.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_DESTBLEND, &d3d_RenderStates[D3DRS_DESTBLEND]);
  612.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_CULLMODE, &d3d_RenderStates[D3DRS_CULLMODE]);
  613.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_ZFUNC, &d3d_RenderStates[D3DRS_ZFUNC]);
  614.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_ALPHAREF, &d3d_RenderStates[D3DRS_ALPHAREF]);
  615.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_ALPHAFUNC, &d3d_RenderStates[D3DRS_ALPHAFUNC]);
  616.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_DITHERENABLE, &d3d_RenderStates[D3DRS_DITHERENABLE]);
  617.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_ALPHABLENDENABLE, &d3d_RenderStates[D3DRS_ALPHABLENDENABLE]);
  618.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_FOGENABLE, &d3d_RenderStates[D3DRS_FOGENABLE]);
  619.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_SPECULARENABLE, &d3d_RenderStates[D3DRS_SPECULARENABLE]);
  620. //  IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_ZVISIBLE, &d3d_RenderStates[D3DRS_ZVISIBLE]);
  621.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_FOGCOLOR, &d3d_RenderStates[D3DRS_FOGCOLOR]);
  622.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_FOGTABLEMODE, &d3d_RenderStates[D3DRS_FOGTABLEMODE]);
  623.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_FOGSTART, &d3d_RenderStates[D3DRS_FOGSTART]);
  624.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_FOGEND, &d3d_RenderStates[D3DRS_FOGEND]);
  625.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_FOGDENSITY, &d3d_RenderStates[D3DRS_FOGDENSITY]);
  626.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_EDGEANTIALIAS, &d3d_RenderStates[D3DRS_EDGEANTIALIAS]);
  627.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_ZBIAS, &d3d_RenderStates[D3DRS_ZBIAS]);
  628.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_RANGEFOGENABLE, &d3d_RenderStates[D3DRS_RANGEFOGENABLE]);
  629.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_STENCILENABLE, &d3d_RenderStates[D3DRS_STENCILENABLE]);
  630.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_STENCILFAIL, &d3d_RenderStates[D3DRS_STENCILFAIL]);
  631.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_STENCILZFAIL, &d3d_RenderStates[D3DRS_STENCILZFAIL]);
  632.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_STENCILPASS, &d3d_RenderStates[D3DRS_STENCILPASS]);
  633.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_STENCILFUNC, &d3d_RenderStates[D3DRS_STENCILFUNC]);
  634.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_STENCILREF, &d3d_RenderStates[D3DRS_STENCILREF]);
  635.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_STENCILMASK, &d3d_RenderStates[D3DRS_STENCILMASK]);
  636.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_STENCILWRITEMASK, &d3d_RenderStates[D3DRS_STENCILWRITEMASK]);
  637.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_TEXTUREFACTOR, &d3d_RenderStates[D3DRS_TEXTUREFACTOR]);
  638.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_WRAP0, &d3d_RenderStates[D3DRS_WRAP0]);
  639.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_WRAP1, &d3d_RenderStates[D3DRS_WRAP1]);
  640.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_WRAP2, &d3d_RenderStates[D3DRS_WRAP2]);
  641.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_WRAP3, &d3d_RenderStates[D3DRS_WRAP3]);
  642. //  IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_WRAP4, &d3d_RenderStates[D3DRS_WRAP4]);
  643. //  IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_WRAP5, &d3d_RenderStates[D3DRS_WRAP5]);
  644. //  IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_WRAP6, &d3d_RenderStates[D3DRS_WRAP6]);
  645. //  IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_WRAP7, &d3d_RenderStates[D3DRS_WRAP7]);
  646. //  IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_CLIPPING, &d3d_RenderStates[D3DRS_CLIPPING]);
  647.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_LIGHTING, &d3d_RenderStates[D3DRS_LIGHTING]);
  648.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_AMBIENT, &d3d_RenderStates[D3DRS_AMBIENT]);
  649. //  IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_FOGVERTEXMODE, &d3d_RenderStates[D3DRS_FOGVERTEXMODE]);
  650.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_COLORVERTEX, &d3d_RenderStates[D3DRS_COLORVERTEX]);
  651.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_LOCALVIEWER, &d3d_RenderStates[D3DRS_LOCALVIEWER]);
  652.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_NORMALIZENORMALS, &d3d_RenderStates[D3DRS_NORMALIZENORMALS]);
  653.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_DIFFUSEMATERIALSOURCE, &d3d_RenderStates[D3DRS_DIFFUSEMATERIALSOURCE]);
  654.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_SPECULARMATERIALSOURCE, &d3d_RenderStates[D3DRS_SPECULARMATERIALSOURCE]);
  655.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_AMBIENTMATERIALSOURCE, &d3d_RenderStates[D3DRS_AMBIENTMATERIALSOURCE]);
  656.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_EMISSIVEMATERIALSOURCE, &d3d_RenderStates[D3DRS_EMISSIVEMATERIALSOURCE]);
  657.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_VERTEXBLEND, &d3d_RenderStates[D3DRS_VERTEXBLEND]);
  658. //  IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_CLIPPLANEENABLE, &d3d_RenderStates[D3DRS_CLIPPLANEENABLE]);
  659. //  IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_SOFTWAREVERTEXPROCESSING, &d3d_RenderStates[D3DRS_SOFTWAREVERTEXPROCESSING]);
  660.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_POINTSIZE, &d3d_RenderStates[D3DRS_POINTSIZE]);
  661.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_POINTSIZE_MIN, &d3d_RenderStates[D3DRS_POINTSIZE_MIN]);
  662.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_POINTSPRITEENABLE, &d3d_RenderStates[D3DRS_POINTSPRITEENABLE]);
  663.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_POINTSCALEENABLE, &d3d_RenderStates[D3DRS_POINTSCALEENABLE]);
  664.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_POINTSCALE_A, &d3d_RenderStates[D3DRS_POINTSCALE_A]);
  665.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_POINTSCALE_B, &d3d_RenderStates[D3DRS_POINTSCALE_B]);
  666.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_POINTSCALE_C, &d3d_RenderStates[D3DRS_POINTSCALE_C]);
  667.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_MULTISAMPLEANTIALIAS, &d3d_RenderStates[D3DRS_MULTISAMPLEANTIALIAS]);
  668.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_MULTISAMPLEMASK, &d3d_RenderStates[D3DRS_MULTISAMPLEMASK]);
  669.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_PATCHEDGESTYLE, &d3d_RenderStates[D3DRS_PATCHEDGESTYLE]);
  670.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_PATCHSEGMENTS, &d3d_RenderStates[D3DRS_PATCHSEGMENTS]);
  671. //  IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_DEBUGMONITORTOKEN, &d3d_RenderStates[D3DRS_DEBUGMONITORTOKEN]);
  672.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_POINTSIZE_MAX, &d3d_RenderStates[D3DRS_POINTSIZE_MAX]);
  673. //  IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_INDEXEDVERTEXBLENDENABLE, &d3d_RenderStates[D3DRS_INDEXEDVERTEXBLENDENABLE]);
  674.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_COLORWRITEENABLE, &d3d_RenderStates[D3DRS_COLORWRITEENABLE]);
  675. //  IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_TWEENFACTOR, &d3d_RenderStates[D3DRS_TWEENFACTOR]);
  676.     IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_BLENDOP, &d3d_RenderStates[D3DRS_BLENDOP]);
  677. //  IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_POSITIONORDER, &d3d_RenderStates[D3DRS_POSITIONORDER]);
  678. //  IDirect3DDevice8_GetRenderState (d3d_Device, D3DRS_NORMALORDER, &d3d_RenderStates[D3DRS_NORMALORDER]);
  679. }
  680.  
  681.  
  682. void D3D_SetRenderStates (void)
  683. {
  684.     // this forces a set of all render states will the current cached values rather than filtering, to
  685.     // ensure that they are properly updated
  686.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_ZENABLE, d3d_RenderStates[D3DRS_ZENABLE]);
  687.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_FILLMODE, d3d_RenderStates[D3DRS_FILLMODE]);
  688.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_SHADEMODE, d3d_RenderStates[D3DRS_SHADEMODE]);
  689. //  IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_LINEPATTERN, d3d_RenderStates[D3DRS_LINEPATTERN]);
  690.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_ZWRITEENABLE, d3d_RenderStates[D3DRS_ZWRITEENABLE]);
  691.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_ALPHATESTENABLE, d3d_RenderStates[D3DRS_ALPHATESTENABLE]);
  692. //  IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_LASTPIXEL, d3d_RenderStates[D3DRS_LASTPIXEL]);
  693.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_SRCBLEND, d3d_RenderStates[D3DRS_SRCBLEND]);
  694.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_DESTBLEND, d3d_RenderStates[D3DRS_DESTBLEND]);
  695.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_CULLMODE, d3d_RenderStates[D3DRS_CULLMODE]);
  696.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_ZFUNC, d3d_RenderStates[D3DRS_ZFUNC]);
  697.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_ALPHAREF, d3d_RenderStates[D3DRS_ALPHAREF]);
  698.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_ALPHAFUNC, d3d_RenderStates[D3DRS_ALPHAFUNC]);
  699.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_DITHERENABLE, d3d_RenderStates[D3DRS_DITHERENABLE]);
  700.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_ALPHABLENDENABLE, d3d_RenderStates[D3DRS_ALPHABLENDENABLE]);
  701.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_FOGENABLE, d3d_RenderStates[D3DRS_FOGENABLE]);
  702.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_SPECULARENABLE, d3d_RenderStates[D3DRS_SPECULARENABLE]);
  703. //  IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_ZVISIBLE, d3d_RenderStates[D3DRS_ZVISIBLE]);
  704.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_FOGCOLOR, d3d_RenderStates[D3DRS_FOGCOLOR]);
  705.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_FOGTABLEMODE, d3d_RenderStates[D3DRS_FOGTABLEMODE]);
  706.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_FOGSTART, d3d_RenderStates[D3DRS_FOGSTART]);
  707.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_FOGEND, d3d_RenderStates[D3DRS_FOGEND]);
  708.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_FOGDENSITY, d3d_RenderStates[D3DRS_FOGDENSITY]);
  709.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_EDGEANTIALIAS, d3d_RenderStates[D3DRS_EDGEANTIALIAS]);
  710.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_ZBIAS, d3d_RenderStates[D3DRS_ZBIAS]);
  711.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_RANGEFOGENABLE, d3d_RenderStates[D3DRS_RANGEFOGENABLE]);
  712.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_STENCILENABLE, d3d_RenderStates[D3DRS_STENCILENABLE]);
  713.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_STENCILFAIL, d3d_RenderStates[D3DRS_STENCILFAIL]);
  714.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_STENCILZFAIL, d3d_RenderStates[D3DRS_STENCILZFAIL]);
  715.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_STENCILPASS, d3d_RenderStates[D3DRS_STENCILPASS]);
  716.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_STENCILFUNC, d3d_RenderStates[D3DRS_STENCILFUNC]);
  717.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_STENCILREF, d3d_RenderStates[D3DRS_STENCILREF]);
  718.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_STENCILMASK, d3d_RenderStates[D3DRS_STENCILMASK]);
  719.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_STENCILWRITEMASK, d3d_RenderStates[D3DRS_STENCILWRITEMASK]);
  720.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_TEXTUREFACTOR, d3d_RenderStates[D3DRS_TEXTUREFACTOR]);
  721.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_WRAP0, d3d_RenderStates[D3DRS_WRAP0]);
  722.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_WRAP1, d3d_RenderStates[D3DRS_WRAP1]);
  723.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_WRAP2, d3d_RenderStates[D3DRS_WRAP2]);
  724.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_WRAP3, d3d_RenderStates[D3DRS_WRAP3]);
  725. //  IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_WRAP4, d3d_RenderStates[D3DRS_WRAP4]);
  726. //  IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_WRAP5, d3d_RenderStates[D3DRS_WRAP5]);
  727. //  IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_WRAP6, d3d_RenderStates[D3DRS_WRAP6]);
  728. //  IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_WRAP7, d3d_RenderStates[D3DRS_WRAP7]);
  729. //  IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_CLIPPING, d3d_RenderStates[D3DRS_CLIPPING]);
  730.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_LIGHTING, d3d_RenderStates[D3DRS_LIGHTING]);
  731.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_AMBIENT, d3d_RenderStates[D3DRS_AMBIENT]);
  732. //  IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_FOGVERTEXMODE, d3d_RenderStates[D3DRS_FOGVERTEXMODE]);
  733.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_COLORVERTEX, d3d_RenderStates[D3DRS_COLORVERTEX]);
  734.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_LOCALVIEWER, d3d_RenderStates[D3DRS_LOCALVIEWER]);
  735.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_NORMALIZENORMALS, d3d_RenderStates[D3DRS_NORMALIZENORMALS]);
  736.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_DIFFUSEMATERIALSOURCE, d3d_RenderStates[D3DRS_DIFFUSEMATERIALSOURCE]);
  737.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_SPECULARMATERIALSOURCE, d3d_RenderStates[D3DRS_SPECULARMATERIALSOURCE]);
  738.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_AMBIENTMATERIALSOURCE, d3d_RenderStates[D3DRS_AMBIENTMATERIALSOURCE]);
  739.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_EMISSIVEMATERIALSOURCE, d3d_RenderStates[D3DRS_EMISSIVEMATERIALSOURCE]);
  740.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_VERTEXBLEND, d3d_RenderStates[D3DRS_VERTEXBLEND]);
  741. //  IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_CLIPPLANEENABLE, d3d_RenderStates[D3DRS_CLIPPLANEENABLE]);
  742. //  IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_SOFTWAREVERTEXPROCESSING, d3d_RenderStates[D3DRS_SOFTWAREVERTEXPROCESSING]);
  743.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_POINTSIZE, d3d_RenderStates[D3DRS_POINTSIZE]);
  744.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_POINTSIZE_MIN, d3d_RenderStates[D3DRS_POINTSIZE_MIN]);
  745.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_POINTSPRITEENABLE, d3d_RenderStates[D3DRS_POINTSPRITEENABLE]);
  746.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_POINTSCALEENABLE, d3d_RenderStates[D3DRS_POINTSCALEENABLE]);
  747.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_POINTSCALE_A, d3d_RenderStates[D3DRS_POINTSCALE_A]);
  748.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_POINTSCALE_B, d3d_RenderStates[D3DRS_POINTSCALE_B]);
  749.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_POINTSCALE_C, d3d_RenderStates[D3DRS_POINTSCALE_C]);
  750.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_MULTISAMPLEANTIALIAS, d3d_RenderStates[D3DRS_MULTISAMPLEANTIALIAS]);
  751.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_MULTISAMPLEMASK, d3d_RenderStates[D3DRS_MULTISAMPLEMASK]);
  752.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_PATCHEDGESTYLE, d3d_RenderStates[D3DRS_PATCHEDGESTYLE]);
  753.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_PATCHSEGMENTS, d3d_RenderStates[D3DRS_PATCHSEGMENTS]);
  754. //  IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_DEBUGMONITORTOKEN, d3d_RenderStates[D3DRS_DEBUGMONITORTOKEN]);
  755.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_POINTSIZE_MAX, d3d_RenderStates[D3DRS_POINTSIZE_MAX]);
  756. //  IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_INDEXEDVERTEXBLENDENABLE, d3d_RenderStates[D3DRS_INDEXEDVERTEXBLENDENABLE]);
  757.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_COLORWRITEENABLE, d3d_RenderStates[D3DRS_COLORWRITEENABLE]);
  758. //  IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_TWEENFACTOR, d3d_RenderStates[D3DRS_TWEENFACTOR]);
  759.     IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_BLENDOP, d3d_RenderStates[D3DRS_BLENDOP]);
  760. //  IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_POSITIONORDER, d3d_RenderStates[D3DRS_POSITIONORDER]);
  761. //  IDirect3DDevice8_SetRenderState (d3d_Device, D3DRS_NORMALORDER, d3d_RenderStates[D3DRS_NORMALORDER]);
  762. }
  763.  
  764.  
  765. void D3D_GetTextureStates (void)
  766. {
  767.     int i;
  768.  
  769.     for (i = 0; i < D3D_MAX_TMUS; i++)
  770.     {
  771.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_COLOROP, &d3d_TextureStates[i][D3DTSS_COLOROP]);
  772.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_COLORARG1, &d3d_TextureStates[i][D3DTSS_COLORARG1]);
  773.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_COLORARG2, &d3d_TextureStates[i][D3DTSS_COLORARG2]);
  774.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_ALPHAOP, &d3d_TextureStates[i][D3DTSS_ALPHAOP]);
  775.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_ALPHAARG1, &d3d_TextureStates[i][D3DTSS_ALPHAARG1]);
  776.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_ALPHAARG2, &d3d_TextureStates[i][D3DTSS_ALPHAARG2]);
  777.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_BUMPENVMAT00, &d3d_TextureStates[i][D3DTSS_BUMPENVMAT00]);
  778.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_BUMPENVMAT01, &d3d_TextureStates[i][D3DTSS_BUMPENVMAT01]);
  779.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_BUMPENVMAT10, &d3d_TextureStates[i][D3DTSS_BUMPENVMAT10]);
  780.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_BUMPENVMAT11, &d3d_TextureStates[i][D3DTSS_BUMPENVMAT11]);
  781.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_TEXCOORDINDEX, &d3d_TextureStates[i][D3DTSS_TEXCOORDINDEX]);
  782.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_ADDRESSU, &d3d_TextureStates[i][D3DTSS_ADDRESSU]);
  783.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_ADDRESSV, &d3d_TextureStates[i][D3DTSS_ADDRESSV]);
  784.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_BORDERCOLOR, &d3d_TextureStates[i][D3DTSS_BORDERCOLOR]);
  785.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_MAGFILTER, &d3d_TextureStates[i][D3DTSS_MAGFILTER]);
  786.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_MINFILTER, &d3d_TextureStates[i][D3DTSS_MINFILTER]);
  787.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_MIPFILTER, &d3d_TextureStates[i][D3DTSS_MIPFILTER]);
  788.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_MIPMAPLODBIAS, &d3d_TextureStates[i][D3DTSS_MIPMAPLODBIAS]);
  789.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_MAXMIPLEVEL, &d3d_TextureStates[i][D3DTSS_MAXMIPLEVEL]);
  790.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_MAXANISOTROPY, &d3d_TextureStates[i][D3DTSS_MAXANISOTROPY]);
  791.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_BUMPENVLSCALE, &d3d_TextureStates[i][D3DTSS_BUMPENVLSCALE]);
  792.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_BUMPENVLOFFSET, &d3d_TextureStates[i][D3DTSS_BUMPENVLOFFSET]);
  793.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_TEXTURETRANSFORMFLAGS, &d3d_TextureStates[i][D3DTSS_TEXTURETRANSFORMFLAGS]);
  794.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_ADDRESSW, &d3d_TextureStates[i][D3DTSS_ADDRESSW]);
  795.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_COLORARG0, &d3d_TextureStates[i][D3DTSS_COLORARG0]);
  796.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_ALPHAARG0, &d3d_TextureStates[i][D3DTSS_ALPHAARG0]);
  797.         IDirect3DDevice8_GetTextureStageState (d3d_Device, i, D3DTSS_RESULTARG, &d3d_TextureStates[i][D3DTSS_RESULTARG]);
  798.     }
  799. }
  800.  
  801.  
  802. void D3D_SetTextureStates (void)
  803. {
  804.     int i;
  805.  
  806.     for (i = 0; i < D3D_MAX_TMUS; i++)
  807.     {
  808.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_COLOROP, d3d_TextureStates[i][D3DTSS_COLOROP]);
  809.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_COLORARG1, d3d_TextureStates[i][D3DTSS_COLORARG1]);
  810.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_COLORARG2, d3d_TextureStates[i][D3DTSS_COLORARG2]);
  811.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_ALPHAOP, d3d_TextureStates[i][D3DTSS_ALPHAOP]);
  812.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_ALPHAARG1, d3d_TextureStates[i][D3DTSS_ALPHAARG1]);
  813.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_ALPHAARG2, d3d_TextureStates[i][D3DTSS_ALPHAARG2]);
  814.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_BUMPENVMAT00, d3d_TextureStates[i][D3DTSS_BUMPENVMAT00]);
  815.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_BUMPENVMAT01, d3d_TextureStates[i][D3DTSS_BUMPENVMAT01]);
  816.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_BUMPENVMAT10, d3d_TextureStates[i][D3DTSS_BUMPENVMAT10]);
  817.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_BUMPENVMAT11, d3d_TextureStates[i][D3DTSS_BUMPENVMAT11]);
  818.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_TEXCOORDINDEX, d3d_TextureStates[i][D3DTSS_TEXCOORDINDEX]);
  819.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_ADDRESSU, d3d_TextureStates[i][D3DTSS_ADDRESSU]);
  820.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_ADDRESSV, d3d_TextureStates[i][D3DTSS_ADDRESSV]);
  821.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_BORDERCOLOR, d3d_TextureStates[i][D3DTSS_BORDERCOLOR]);
  822.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_MAGFILTER, d3d_TextureStates[i][D3DTSS_MAGFILTER]);
  823.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_MINFILTER, d3d_TextureStates[i][D3DTSS_MINFILTER]);
  824.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_MIPFILTER, d3d_TextureStates[i][D3DTSS_MIPFILTER]);
  825.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_MIPMAPLODBIAS, d3d_TextureStates[i][D3DTSS_MIPMAPLODBIAS]);
  826.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_MAXMIPLEVEL, d3d_TextureStates[i][D3DTSS_MAXMIPLEVEL]);
  827.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_MAXANISOTROPY, d3d_TextureStates[i][D3DTSS_MAXANISOTROPY]);
  828.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_BUMPENVLSCALE, d3d_TextureStates[i][D3DTSS_BUMPENVLSCALE]);
  829.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_BUMPENVLOFFSET, d3d_TextureStates[i][D3DTSS_BUMPENVLOFFSET]);
  830.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_TEXTURETRANSFORMFLAGS, d3d_TextureStates[i][D3DTSS_TEXTURETRANSFORMFLAGS]);
  831.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_ADDRESSW, d3d_TextureStates[i][D3DTSS_ADDRESSW]);
  832.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_COLORARG0, d3d_TextureStates[i][D3DTSS_COLORARG0]);
  833.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_ALPHAARG0, d3d_TextureStates[i][D3DTSS_ALPHAARG0]);
  834.         IDirect3DDevice8_SetTextureStageState (d3d_Device, i, D3DTSS_RESULTARG, d3d_TextureStates[i][D3DTSS_RESULTARG]);
  835.     }
  836. }
  837.  
  838.  
  839. void D3D_InitStates (void)
  840. {
  841.     int i;
  842.  
  843.     // init tmus
  844.     for (i = 0; i < D3D_MAX_TMUS; i++)
  845.     {
  846.         d3d_TMUs[i].boundtexture = NULL;
  847.         d3d_TMUs[i].enabled = FALSE;
  848.         d3d_TMUs[i].texcoordindex = i;
  849.     }
  850.  
  851.     // store out all states
  852.     D3D_GetRenderStates ();
  853.     D3D_GetTextureStates ();
  854.  
  855.     // force all states to dirty on entry
  856.     D3D_DirtyAllStates ();
  857. }
  858.  
  859.  
  860. D3DTEXTUREOP D3D_DecodeOp (D3DTEXTUREOP opin, DWORD scale)
  861. {
  862.     if (scale == 1)
  863.         return opin;
  864.     else if (scale == 2)
  865.     {
  866.         if (opin == D3DTOP_MODULATE)
  867.             return D3DTOP_MODULATE2X;
  868.         else if (opin == D3DTOP_ADDSIGNED)
  869.             return D3DTOP_ADDSIGNED2X;
  870.         else return opin;
  871.     }
  872.     else
  873.     {
  874.         if (opin == D3DTOP_MODULATE)
  875.             return D3DTOP_MODULATE4X;
  876.         else return opin;
  877.     }
  878. }
  879.  
  880.  
  881. void D3D_CheckDirtyTextureStates (int tmu)
  882. {
  883.     if (d3d_TMUs[tmu].boundtexture)
  884.     {
  885.         if (d3d_TMUs[d3d_CurrentTMU].texparamdirty)
  886.         {
  887.             // setup texture states - these ones are specific to the texture and come from glTexParameter
  888.             D3D_SetTextureState (tmu, D3DTSS_ADDRESSU, d3d_TMUs[tmu].boundtexture->addressu);
  889.             D3D_SetTextureState (tmu, D3DTSS_ADDRESSV, d3d_TMUs[tmu].boundtexture->addressv);
  890.             D3D_SetTextureState (tmu, D3DTSS_MAXANISOTROPY, d3d_TMUs[tmu].boundtexture->anisotropy);
  891.  
  892.             // minfilter and magfilter need to switch to anisotropic
  893.             if (d3d_TMUs[tmu].boundtexture->anisotropy > 1)
  894.             {
  895.                 D3D_SetTextureState (tmu, D3DTSS_MAGFILTER, D3DTEXF_ANISOTROPIC);
  896.                 D3D_SetTextureState (tmu, D3DTSS_MINFILTER, D3DTEXF_ANISOTROPIC);
  897.                 D3D_SetTextureState (tmu, D3DTSS_MIPFILTER, d3d_TMUs[tmu].boundtexture->mipfilter);
  898.             }
  899.             else
  900.             {
  901.                 D3D_SetTextureState (tmu, D3DTSS_MAGFILTER, d3d_TMUs[tmu].boundtexture->magfilter);
  902.                 D3D_SetTextureState (tmu, D3DTSS_MINFILTER, d3d_TMUs[tmu].boundtexture->minfilter);
  903.                 D3D_SetTextureState (tmu, D3DTSS_MIPFILTER, d3d_TMUs[tmu].boundtexture->mipfilter);
  904.             }
  905.  
  906.             d3d_TMUs[tmu].texparamdirty = FALSE;
  907.         }
  908.     }
  909.  
  910.     if (d3d_TMUs[tmu].texenvdirty)
  911.     {
  912.         /*
  913.         if (d3d_TMUs[tmu].combine)
  914.         {
  915.             d3d_TMUs[tmu].colorop = D3D_DecodeOp (d3d_TMUs[tmu].combstate.colorop, d3d_TMUs[tmu].combstate.colorscale);
  916.             d3d_TMUs[tmu].colorarg1 = d3d_TMUs[tmu].combstate.colorarg1;
  917.             d3d_TMUs[tmu].colorarg2 = d3d_TMUs[tmu].combstate.colorarg2;
  918.  
  919.             d3d_TMUs[tmu].alphaop = D3D_DecodeOp (d3d_TMUs[tmu].combstate.alphaop, d3d_TMUs[tmu].combstate.alphascale);
  920.             d3d_TMUs[tmu].alphaarg1 = d3d_TMUs[tmu].combstate.alphaarg1;
  921.             d3d_TMUs[tmu].alphaarg2 = d3d_TMUs[tmu].combstate.alphaarg2;
  922.  
  923.             D3D_SetTextureState (tmu, D3DTSS_COLORARG0, d3d_TMUs[tmu].combstate.colorarg0);
  924.             D3D_SetTextureState (tmu, D3DTSS_ALPHAARG0, d3d_TMUs[tmu].combstate.alphaarg0);
  925.             D3D_SetTextureState (tmu, D3DTSS_RESULTARG, d3d_TMUs[tmu].combstate.resultarg);
  926.         }
  927.         */
  928.  
  929.         // these ones are specific to the TMU and come from glTexEnv
  930.         D3D_SetTextureState (tmu, D3DTSS_COLOROP, d3d_TMUs[tmu].colorop);
  931.         D3D_SetTextureState (tmu, D3DTSS_COLORARG1, d3d_TMUs[tmu].colorarg1);
  932.         D3D_SetTextureState (tmu, D3DTSS_COLORARG2, d3d_TMUs[tmu].colorarg2);
  933.         D3D_SetTextureState (tmu, D3DTSS_ALPHAOP, d3d_TMUs[tmu].alphaop);
  934.         D3D_SetTextureState (tmu, D3DTSS_ALPHAARG1, d3d_TMUs[tmu].alphaarg1);
  935.         D3D_SetTextureState (tmu, D3DTSS_ALPHAARG2, d3d_TMUs[tmu].alphaarg2);
  936.         D3D_SetTextureState (tmu, D3DTSS_TEXCOORDINDEX, d3d_TMUs[tmu].texcoordindex);
  937.  
  938.         d3d_TMUs[tmu].texenvdirty = FALSE;
  939.     }
  940. }
  941.  
  942.  
  943. /*
  944. ===================================================================================================================
  945.  
  946.             POLYGON OFFSET
  947.  
  948.     Who said D3D didn't have polygon offset?
  949.  
  950.     It's implementation is quite a bit simpler than OpenGL's however; just a pretty basic static bias
  951.     (it's better in D3D9)
  952.  
  953. ===================================================================================================================
  954. */
  955.  
  956. BOOL d3d_PolyOffsetEnabled = FALSE;
  957. BOOL d3d_PolyOffsetSwitched = FALSE;
  958. float d3d_PolyOffsetFactor = 8;
  959.  
  960. void glPolygonOffset (GLfloat factor, GLfloat units)
  961. {
  962.     // need to switch polygon offset
  963.     d3d_PolyOffsetSwitched = FALSE;
  964.  
  965.     // just use the units here as we're going to fudge it using D3DRS_ZBIAS
  966.     // 0 is furthest; 16 is nearest; d3d default is 0 so our default is an intermediate value (8)
  967.     // so that we can do both push back and pull forward
  968.     // negative values come nearer; positive values go further, so invert the sense
  969. //  d3d_PolyOffsetFactor = 8 - units;
  970.     d3d_PolyOffsetFactor = 4 + units; //HACK This is a nasty hack for Xash3D only - MARTY
  971.                                       //     Polygons look very glitchy if we dont do this!    
  972.     // clamp to d3d scale
  973.     if (d3d_PolyOffsetFactor < 0) d3d_PolyOffsetFactor = 0;
  974.     if (d3d_PolyOffsetFactor > 16) d3d_PolyOffsetFactor = 16;
  975. }
  976.  
  977.  
  978. /*
  979. ===================================================================================================================
  980.  
  981.             VERTEX SUBMISSION
  982.  
  983.     Per the spec for glVertex (http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml) glColor, glNormal and
  984.     glTexCoord just specify a *current* color, normal and texcoord, whereas glVertex actually creates a vertex
  985.     that inherits the current color, normal and texcoord.
  986.  
  987.     Real D3D code looks *nothing* like this.
  988.  
  989. ===================================================================================================================
  990. */
  991.  
  992. int d3d_PrimitiveMode = 0;
  993. int d3d_NumVerts = 0;
  994.  
  995. // this should be a multiple of 12 to support both GL_QUADS and GL_TRIANGLES
  996. // it should also be large enough to hold the biggest tristrip or fan in use in the engine
  997. // individual quads or tris can be submitted in batches
  998. #define D3D_MAX_VERTEXES    12//600
  999.  
  1000. typedef struct gl_texcoord_s
  1001. {
  1002.     float s;
  1003.     float t;
  1004. } gl_texcoord_t;
  1005.  
  1006. typedef struct gl_xyz_s
  1007. {
  1008.     float x;
  1009.     float y;
  1010.     float z;
  1011. } gl_xyz_t;
  1012.  
  1013. // defaults that are picked up by each glVertex call
  1014. D3DCOLOR d3d_CurrentColor = 0xffffffff;
  1015. gl_texcoord_t d3d_CurrentTexCoord[D3D_MAX_TMUS] = {{0, 0}/*, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}*/};
  1016. //gl_xyz_t d3d_CurrentNormal = {0, 1, 0};
  1017.  
  1018. // this may be a little wasteful as it's a full sized vertex for 8 TMUs
  1019. // we'll fix it if it becomes a problem (it's not like Quake stresses the GPU too much anyway)
  1020. typedef struct gl_vertex_s
  1021. {
  1022.     gl_xyz_t position;
  1023.     //gl_xyz_t normal;
  1024.     D3DCOLOR c;
  1025.     gl_texcoord_t st[D3D_MAX_TMUS];
  1026. } gl_vertex_t;
  1027.  
  1028. gl_vertex_t d3d_Vertexes[D3D_MAX_VERTEXES];
  1029.  
  1030. BOOL d3d_SceneBegun = FALSE;
  1031.  
  1032. void GL_SubmitVertexes (void)
  1033. {
  1034.     int i;
  1035.  
  1036.     DWORD d3d_VertexShader;
  1037.     DWORD d3d_TexCoordSizes;
  1038.     DWORD d3d_TMUShader[] =
  1039.     {
  1040.         D3DFVF_TEX0,
  1041.         D3DFVF_TEX1,
  1042. //      D3DFVF_TEX2,
  1043. //      D3DFVF_TEX3,
  1044. //      D3DFVF_TEX4
  1045. //      D3DFVF_TEX5,
  1046. //      D3DFVF_TEX6,
  1047. //      D3DFVF_TEX7,
  1048. //      D3DFVF_TEX8
  1049.     };
  1050.  
  1051.     if (!d3d_Device) return;
  1052.  
  1053.     // check for a beginscene
  1054.     if (!d3d_SceneBegun)
  1055.     {
  1056.         // D3D has a separate view matrix which is concatenated with the world in OpenGL.  We maintain
  1057.         // a compatible interface by just setting the D3D view matrix to identity and doing all modelview
  1058.         // transforms via the world matrix.
  1059.         D3DXMATRIX d3d_ViewMatrix;
  1060.  
  1061. #ifndef _XBOX // Not used on Xbox
  1062.         // issue a beginscene (geometry needs this
  1063.         IDirect3DDevice8_BeginScene (d3d_Device);
  1064. #endif
  1065.         // force an invalid vertex shader so that the first time will change it
  1066.         D3D_SetVertexShader (D3DFVF_XYZ | D3DFVF_XYZRHW);
  1067.  
  1068.         // clear down bound textures
  1069.         for (i = 0; i < D3D_MAX_TMUS; i++) d3d_BoundTextures[i] = NULL;
  1070.  
  1071.         // we're in a scene now
  1072.         d3d_SceneBegun = TRUE;
  1073.  
  1074.         // now set our identity view matrix
  1075.         D3DXMatrixIdentity (&d3d_ViewMatrix);
  1076.         IDirect3DDevice8_SetTransform (d3d_Device, D3DTS_VIEW, &d3d_ViewMatrix);
  1077.     }
  1078.  
  1079.     // Checked for scissor test
  1080.     if(g_bScissorTest)
  1081.         IDirect3DDevice8_SetScissors(d3d_Device, 1, FALSE, &g_ScissorRect);
  1082.  
  1083. #ifndef _XBOX // Not used in PCSX-R
  1084.     // check polygon offset
  1085.     if (!d3d_PolyOffsetSwitched)
  1086.     {
  1087.         if (d3d_PolyOffsetEnabled)
  1088.         {
  1089.             // setup polygon offset
  1090.             D3D_SetRenderState (D3DRS_ZBIAS, d3d_PolyOffsetFactor);
  1091.         }
  1092.         else
  1093.         {
  1094.             // no polygon offset - back to normal z bias
  1095. //          D3D_SetRenderState (D3DRS_ZBIAS, 8);
  1096.             D3D_SetRenderState (D3DRS_ZBIAS, 0);
  1097.         }                                        
  1098.  
  1099.         // we've switched polygon offset now
  1100.         d3d_PolyOffsetSwitched = TRUE;
  1101.     }
  1102. #endif
  1103.  
  1104.     // check for dirty matrixes
  1105.     D3D_CheckDirtyMatrix (&d3d_ModelViewMatrix);
  1106.     D3D_CheckDirtyMatrix (&d3d_ProjectionMatrix);
  1107.  
  1108.     // initial vertex shader (will be added to as TMUs accumulate)
  1109.     d3d_VertexShader = D3DFVF_XYZ /*| D3DFVF_NORMAL */| D3DFVF_DIFFUSE;
  1110.     d3d_TexCoordSizes = 0;
  1111.  
  1112.     // set up textures
  1113.     for (i = 0; i < D3D_MAX_TMUS; i++)
  1114.     {
  1115.         // end of TMUs
  1116.         if (!d3d_TMUs[i].enabled || !d3d_TMUs[i].boundtexture)
  1117.         {
  1118.             // explicitly disable alpha and color ops in this and subsequent stages
  1119.             D3D_SetTextureState (i, D3DTSS_COLOROP, D3DTOP_DISABLE);
  1120.             D3D_SetTextureState (i, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
  1121.             D3D_SetTexture (i, NULL);
  1122.             // done
  1123.             break;
  1124.         }
  1125.  
  1126.         // set up texcoord sizes
  1127.         d3d_TexCoordSizes |= D3DFVF_TEXCOORDSIZE2 (i);
  1128.  
  1129.         // check for dirty states (this is needed as OpenGL sets state per-texture as well as per-stage)
  1130.         D3D_CheckDirtyTextureStates (i);
  1131.  
  1132.         // bind the texture (now with added filtering!)
  1133.         D3D_SetTexture (i, d3d_TMUs[i].boundtexture->teximg);
  1134.     }
  1135.  
  1136.     // set the correct vertex shader for the number of enabled TMUs
  1137.     D3D_SetVertexShader (d3d_VertexShader | d3d_TMUShader[i] | d3d_TexCoordSizes);
  1138.  
  1139.     // draw the verts - these are the only modes we support for Quake
  1140.     // per the spec, GL_FRONT_AND_BACK still allows lines and points through
  1141.     switch (d3d_PrimitiveMode)
  1142.     {
  1143.     case GL_TRIANGLES:
  1144.         //OutputDebugString("GL_TRIANGLES\n");
  1145.         // D3DPT_TRIANGLELIST models GL_TRIANGLES when used for either a single triangle or multiple triangles
  1146. //      if (gl_CullMode != GL_FRONT_AND_BACK && d3d_NumVerts % 3 == 0 && d3d_NumVerts != 0) IDirect3DDevice8_DrawPrimitiveUP (d3d_Device, D3DPT_TRIANGLELIST, d3d_NumVerts / 3, d3d_Vertexes, sizeof (gl_vertex_t));
  1147.         if (gl_CullMode != GL_FRONT_AND_BACK && d3d_NumVerts != 0) IDirect3DDevice8_DrawVerticesUP (d3d_Device, D3DPT_TRIANGLELIST, d3d_NumVerts, d3d_Vertexes, sizeof (gl_vertex_t));
  1148.         break;
  1149.  
  1150.     case GL_TRIANGLE_STRIP:
  1151.         //OutputDebugString("GL_TRIANGLE_STRIP\n");
  1152.         // regular tristrip
  1153. //      if (gl_CullMode != GL_FRONT_AND_BACK) IDirect3DDevice8_DrawPrimitiveUP (d3d_Device, D3DPT_TRIANGLESTRIP, d3d_NumVerts - 2, d3d_Vertexes, sizeof (gl_vertex_t));
  1154.         if (gl_CullMode != GL_FRONT_AND_BACK) IDirect3DDevice8_DrawVerticesUP (d3d_Device, D3DPT_TRIANGLESTRIP, d3d_NumVerts, d3d_Vertexes, sizeof (gl_vertex_t));
  1155.         break;
  1156.  
  1157.     case GL_POLYGON:
  1158.         //OutputDebugString("GL_POLYGON\n");
  1159.         // a GL_POLYGON has the same vertex layout and order as a trifan, and can be used interchangably in OpenGL
  1160.     case GL_TRIANGLE_FAN:
  1161.         //OutputDebugString("GL_TRIANGLE_FAN\n");
  1162.         // regular trifan
  1163. //      if (gl_CullMode != GL_FRONT_AND_BACK) IDirect3DDevice8_DrawPrimitiveUP (d3d_Device, D3DPT_TRIANGLEFAN, d3d_NumVerts - 2, d3d_Vertexes, sizeof (gl_vertex_t));
  1164.         if (gl_CullMode != GL_FRONT_AND_BACK) IDirect3DDevice8_DrawVerticesUP (d3d_Device, D3DPT_TRIANGLEFAN, d3d_NumVerts, d3d_Vertexes, sizeof (gl_vertex_t));
  1165.         break;
  1166.  
  1167.     case GL_QUADS:
  1168.         //OutputDebugString("GL_QUADS\n");
  1169.  
  1170.         if (gl_CullMode == GL_FRONT_AND_BACK) break;
  1171.  
  1172. #ifdef _XBOX // Use special D3DPT_QUADLIST Xbox extension for speed
  1173.         IDirect3DDevice8_DrawVerticesUP(d3d_Device, D3DPT_QUADLIST, d3d_NumVerts, d3d_Vertexes, sizeof (gl_vertex_t));
  1174. #else
  1175.         // quads are a special case of trifans where each quad (numverts / 4) represents a trifan with 2 prims in it
  1176.         for (i = 0; i < d3d_NumVerts; i += 4)
  1177.             IDirect3DDevice8_DrawPrimitiveUP (d3d_Device, D3DPT_TRIANGLEFAN, 2, &d3d_Vertexes[i], sizeof (gl_vertex_t));
  1178. #endif
  1179.         break;
  1180.  
  1181.     case GL_LINES:
  1182. //      IDirect3DDevice8_DrawPrimitiveUP (d3d_Device, D3DPT_LINELIST, d3d_NumVerts, d3d_Vertexes, sizeof (gl_vertex_t));
  1183.         IDirect3DDevice8_DrawVerticesUP (d3d_Device, D3DPT_LINELIST, d3d_NumVerts, d3d_Vertexes, sizeof (gl_vertex_t));
  1184.         break;
  1185.  
  1186.     case GL_QUAD_STRIP:
  1187. #ifdef _XBOX // Use special D3DPT_QUADSTRIP Xbox extension for speed
  1188.         IDirect3DDevice8_DrawVerticesUP(d3d_Device, D3DPT_QUADSTRIP, d3d_NumVerts, d3d_Vertexes, sizeof (gl_vertex_t));
  1189. #else
  1190.         // not as optimal as it could be, so hopefully it won't be used too often!!!
  1191.         if (gl_CullMode == GL_FRONT_AND_BACK) break;
  1192.  
  1193.         for (i = 0; ; i += 2)
  1194.         {
  1195.             short quadindexes[4];
  1196.  
  1197.             if (i > (d3d_NumVerts - 3)) break;
  1198.  
  1199.             quadindexes[0] = i;
  1200.             quadindexes[1] = i + 1;
  1201.             quadindexes[2] = i + 3;
  1202.             quadindexes[3] = i + 2;
  1203.  
  1204.             IDirect3DDevice8_DrawIndexedPrimitiveUP
  1205.             (
  1206.                 d3d_Device,
  1207.                 D3DPT_TRIANGLEFAN,
  1208.                 quadindexes[0],
  1209.                 4,
  1210.                 2,
  1211.                 quadindexes,
  1212.                 D3DFMT_INDEX16,
  1213.                 d3d_Vertexes,
  1214.                 sizeof (gl_vertex_t)
  1215.             );
  1216.         }
  1217. #endif
  1218.         break;
  1219.  
  1220.     default:
  1221.         // unsupported mode
  1222.         break;
  1223.     }
  1224.  
  1225.     // begin a new primitive
  1226.     d3d_NumVerts = 0;
  1227. }
  1228.  
  1229.  
  1230. void glVertex2fv (const GLfloat *v)
  1231. {
  1232.     glVertex3f (v[0], v[1], 0);
  1233. }
  1234.  
  1235.  
  1236. void glVertex2f (GLfloat x, GLfloat y)
  1237. {
  1238.     glVertex3f (x, y, 0);
  1239. }
  1240.  
  1241.  
  1242. void glVertex3fv (const GLfloat *v)
  1243. {
  1244.     glVertex3f (v[0], v[1], v[2]);
  1245. }
  1246.  
  1247.  
  1248. void glVertex3f (GLfloat x, GLfloat y, GLfloat z)
  1249. {
  1250.     int i;
  1251.  
  1252.     // add a new vertex to the list with the specified xyz and inheriting the current normal, color and texcoords
  1253.     // (per spec at http://www.opengl.org/sdk/docs/man/xhtml/glVertex.xml)
  1254.     d3d_Vertexes[d3d_NumVerts].position.x = x;
  1255.     d3d_Vertexes[d3d_NumVerts].position.y = y;
  1256.     d3d_Vertexes[d3d_NumVerts].position.z = z;
  1257.  
  1258. //  d3d_Vertexes[d3d_NumVerts].normal.x = d3d_CurrentNormal.x;
  1259. //  d3d_Vertexes[d3d_NumVerts].normal.y = d3d_CurrentNormal.y;
  1260. //  d3d_Vertexes[d3d_NumVerts].normal.z = d3d_CurrentNormal.z;
  1261.  
  1262.     d3d_Vertexes[d3d_NumVerts].c = d3d_CurrentColor;
  1263.  
  1264.     for (i = 0; i < D3D_MAX_TMUS; i++)
  1265.     {
  1266.         d3d_Vertexes[d3d_NumVerts].st[i].s = d3d_CurrentTexCoord[i].s;
  1267.         d3d_Vertexes[d3d_NumVerts].st[i].t = d3d_CurrentTexCoord[i].t;
  1268.     }
  1269.  
  1270.     // go to a new vertex
  1271.     d3d_NumVerts++;
  1272.  
  1273.     // check for end of vertexes
  1274.     if (d3d_NumVerts == D3D_MAX_VERTEXES)
  1275.     {
  1276.         if (d3d_PrimitiveMode == GL_TRIANGLES || d3d_PrimitiveMode == GL_QUADS)
  1277.         {
  1278.             // triangles and quads are discrete primitives and as such can begin a new batch
  1279.             GL_SubmitVertexes ();
  1280.         }
  1281.         else
  1282.         {
  1283.             // other primitives need to extend the vertex storage
  1284.         }
  1285.  
  1286.         d3d_NumVerts = 0;
  1287.     }
  1288. }
  1289.  
  1290.  
  1291. void glTexCoord2f (GLfloat s, GLfloat t)
  1292. {
  1293.     d3d_CurrentTexCoord[0].s = s;
  1294.     d3d_CurrentTexCoord[0].t = t;
  1295. }
  1296.  
  1297.  
  1298. void glTexCoord2fv (const GLfloat *v)
  1299. {
  1300.     d3d_CurrentTexCoord[0].s = v[0];
  1301.     d3d_CurrentTexCoord[0].t = v[1];
  1302. }
  1303.  
  1304.  
  1305. void GL_SetColor (int red, int green, int blue, int alpha)
  1306. {
  1307.     // overwrite color incase verts set it
  1308.     d3d_CurrentColor = D3DCOLOR_ARGB
  1309.     (
  1310.         BYTE_CLAMP (alpha),
  1311.         BYTE_CLAMP (red),
  1312.         BYTE_CLAMP (green),
  1313.         BYTE_CLAMP (blue)
  1314.     );
  1315. }
  1316.  
  1317.  
  1318. void glColor3f (GLfloat red, GLfloat green, GLfloat blue)
  1319. {
  1320.     GL_SetColor (red * 255, green * 255, blue * 255, 255);
  1321. }
  1322.  
  1323.  
  1324. void glColor3fv (const GLfloat *v)
  1325. {
  1326.     GL_SetColor (v[0] * 255, v[1] * 255, v[2] * 255, 255);
  1327. }
  1328.  
  1329.  
  1330. void glColor3ubv (const GLubyte *v)
  1331. {
  1332.     GL_SetColor (v[0], v[1], v[2], 255);
  1333. }
  1334.  
  1335.  
  1336. void glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
  1337. {
  1338.     GL_SetColor (red * 255, green * 255, blue * 255, alpha * 255);
  1339. }
  1340.  
  1341.  
  1342. void glColor4fv (const GLfloat *v)
  1343. {
  1344.     GL_SetColor (v[0] * 255, v[1] * 255, v[2] * 255, v[3] * 255);
  1345. }
  1346.  
  1347.  
  1348. void glColor4ubv (const GLubyte *v)
  1349. {
  1350.     GL_SetColor (v[0], v[1], v[2], v[3]);
  1351. }
  1352.  
  1353.  
  1354. void glColor4ub (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)
  1355. {
  1356.     GL_SetColor (red, green, blue, alpha);
  1357. }
  1358.  
  1359.  
  1360. void glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz)
  1361. {
  1362. //  d3d_CurrentNormal.x = nx;
  1363. //  d3d_CurrentNormal.y = ny;
  1364. //  d3d_CurrentNormal.z = nz;
  1365. }
  1366.  
  1367.  
  1368. void glBegin (GLenum mode)
  1369. {
  1370.     // just store out the mode, all heavy lifting is done in glEnd
  1371.     d3d_PrimitiveMode = mode;
  1372.  
  1373.     // begin a new primitive
  1374.     //d3d_NumVerts = 0;
  1375. }
  1376.  
  1377.  
  1378. void glEnd (void)
  1379. {
  1380.     // submit, bitch
  1381.     GL_SubmitVertexes ();
  1382. }
  1383.  
  1384.  
  1385. /*
  1386. ===================================================================================================================
  1387.  
  1388.             VERTEX ARRAYS
  1389.  
  1390. ===================================================================================================================
  1391. */
  1392.  
  1393. typedef struct gl_varray_pointer_s
  1394. {
  1395.     GLint size;
  1396.     GLenum type;
  1397.     GLsizei stride;
  1398.     GLvoid *pointer;
  1399. } gl_varray_pointer_t;
  1400.  
  1401. gl_varray_pointer_t d3d_VertexPointer;
  1402. gl_varray_pointer_t d3d_ColorPointer;
  1403. gl_varray_pointer_t d3d_TexCoordPointer[D3D_MAX_TMUS];
  1404. int d3d_VArray_TMU = 0;
  1405.  
  1406. void WINAPI GL_ClientActiveTexture (GLenum texture)
  1407. {
  1408.     d3d_VArray_TMU = D3D_TMUForTexture (texture);
  1409. }
  1410.  
  1411.  
  1412. void glEnableClientState (GLenum array)
  1413. {
  1414.     switch (array)
  1415.     {
  1416.     case GL_VERTEX_ARRAY:
  1417.     case GL_COLOR_ARRAY:
  1418.     case GL_TEXTURE_COORD_ARRAY:
  1419.         // doesn't need to do anything
  1420.         break;
  1421.  
  1422.     default:
  1423.         SysMessage ("Invalid Vertex Array Spec...!");
  1424.     }
  1425. }
  1426.  
  1427.  
  1428. void glDrawArrays (GLenum mode, GLint first, GLsizei count)
  1429. {
  1430.     int i;
  1431.     int v;
  1432.     int tmu;
  1433.     byte *vp;
  1434.     byte *stp[D3D_MAX_TMUS];
  1435.  
  1436.     // required by the spec
  1437.     if (!d3d_VertexPointer.pointer) return;
  1438.  
  1439.     vp = ((byte *) d3d_VertexPointer.pointer + first);
  1440.  
  1441.     for (tmu = 0; tmu < D3D_MAX_TMUS; tmu++)
  1442.     {
  1443.         if (d3d_TexCoordPointer[tmu].pointer)
  1444.             stp[tmu] = ((byte *) d3d_TexCoordPointer[tmu].pointer + first);
  1445.         else stp[tmu] = NULL;
  1446.     }
  1447.  
  1448.     // send through standard begin/end processing
  1449.     glBegin (mode);
  1450.  
  1451.     for (i = 0, v = first; i < count; i++, v++)
  1452.     {
  1453.         for (tmu = 0; tmu < D3D_MAX_TMUS; tmu++)
  1454.         {
  1455.             if (stp[tmu])
  1456.             {
  1457.                 d3d_CurrentTexCoord[tmu].s = ((float *) stp[tmu])[0];
  1458.                 d3d_CurrentTexCoord[tmu].t = ((float *) stp[tmu])[1];
  1459.  
  1460.                 stp[tmu] += d3d_TexCoordPointer[tmu].stride;
  1461.             }
  1462.         }
  1463.  
  1464.         if (d3d_VertexPointer.size == 2)
  1465.             glVertex2fv ((float *) vp);
  1466.         else if (d3d_VertexPointer.size == 3)
  1467.             glVertex3fv ((float *) vp);
  1468.  
  1469.         vp += d3d_VertexPointer.stride;
  1470.     }
  1471.  
  1472.     glEnd ();
  1473. }
  1474.  
  1475.  
  1476. void glVertexPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
  1477. {
  1478.     if (type != GL_FLOAT) SysMessage ("Unimplemented vertex pointer type");
  1479.  
  1480.     d3d_VertexPointer.size = size;
  1481.     d3d_VertexPointer.type = type;
  1482.     d3d_VertexPointer.stride = stride;
  1483.     d3d_VertexPointer.pointer = (GLvoid *) pointer;
  1484. }
  1485.  
  1486.  
  1487. void glColorPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
  1488. {
  1489.     if (type != GL_FLOAT) SysMessage ("Unimplemented color pointer type");
  1490.  
  1491.     d3d_ColorPointer.size = size;
  1492.     d3d_ColorPointer.type = type;
  1493.     d3d_ColorPointer.stride = stride;
  1494.     d3d_ColorPointer.pointer = (GLvoid *) pointer;
  1495. }
  1496.  
  1497.  
  1498. void glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
  1499. {
  1500.     if (type != GL_FLOAT) SysMessage ("Unimplemented texcoord pointer type");
  1501.  
  1502.     d3d_TexCoordPointer[d3d_VArray_TMU].size = size;
  1503.     d3d_TexCoordPointer[d3d_VArray_TMU].type = type;
  1504.     d3d_TexCoordPointer[d3d_VArray_TMU].stride = stride;
  1505.     d3d_TexCoordPointer[d3d_VArray_TMU].pointer = (GLvoid *) pointer;
  1506. }
  1507.  
  1508.  
  1509. void glDisableClientState (GLenum array)
  1510. {
  1511.     // switch the pointer to NULL
  1512.     switch (array)
  1513.     {
  1514.     case GL_VERTEX_ARRAY:
  1515.         d3d_VertexPointer.pointer = NULL;
  1516.         break;
  1517.  
  1518.     case GL_COLOR_ARRAY:
  1519.         d3d_ColorPointer.pointer = NULL;
  1520.         break;
  1521.  
  1522.     case GL_TEXTURE_COORD_ARRAY:
  1523.         d3d_TexCoordPointer[d3d_VArray_TMU].pointer = NULL;
  1524.         break;
  1525.  
  1526.     default:
  1527.         SysMessage ("Invalid Vertex Array Spec...!");
  1528.     }
  1529. }
  1530.  
  1531. /*
  1532. ===================================================================================================================
  1533.  
  1534.             TEXTURE HASHMAP
  1535.  
  1536. ===================================================================================================================
  1537. */
  1538.  
  1539. #define HASHMAPSIZE 500
  1540.  
  1541. struct sNode
  1542. {
  1543.     int iKey;
  1544.     d3d_texture_t* pValue;
  1545.     struct sNode *pNext;
  1546. };
  1547.  
  1548. struct sTable
  1549. {
  1550.     int iSize;
  1551.     struct sNode **pList;
  1552. };
  1553.  
  1554. struct sTable *g_pTable = NULL;
  1555.  
  1556. struct sTable* HMCreateTable(int iSize)
  1557. {
  1558.     int i;
  1559.  
  1560.     struct sTable *pTable = (struct sTable*)malloc(sizeof(struct sTable));
  1561.     pTable->iSize = iSize;
  1562.    
  1563.     pTable->pList = (struct sNode**)malloc(sizeof(struct node*)*iSize);
  1564.    
  1565.     for(i = 0; i < iSize; i++)
  1566.         pTable->pList[i] = NULL;
  1567.        
  1568.     return pTable;
  1569. }
  1570.  
  1571. void HMSetupHashTable()
  1572. {
  1573.     g_pTable = HMCreateTable(HASHMAPSIZE);
  1574. }
  1575.  
  1576. void HMDeleteHashTable()
  1577. {
  1578.     if(g_pTable) free(g_pTable);
  1579. }
  1580.  
  1581. int HMHashFunc(int iKey)
  1582. {
  1583.     if(iKey < 0)
  1584.         return -(iKey % g_pTable->iSize);
  1585.        
  1586.     return iKey % g_pTable->iSize;
  1587. }
  1588.  
  1589. void HMInsertTexture(int iKey, d3d_texture_t* pTexture)
  1590. {
  1591.     int iPos = HMHashFunc(iKey);
  1592.    
  1593.     struct sNode *pList = g_pTable->pList[iPos];
  1594.     struct sNode *pNewNode = NULL;
  1595.     struct sNode *pTemp = pList;
  1596.    
  1597.     while(pTemp)
  1598.     {
  1599.         if(pTemp->iKey == iKey)
  1600.         {
  1601.             pTemp->pValue = pTexture;
  1602.             return;
  1603.         }
  1604.         pTemp = pTemp->pNext;
  1605.     }
  1606.  
  1607.     pNewNode = (struct sNode*)malloc(sizeof(struct sNode));
  1608.     pNewNode->iKey = iKey;
  1609.     pNewNode->pValue = pTexture;
  1610.     pNewNode->pNext = pList;
  1611.     g_pTable->pList[iPos] = pNewNode;
  1612. }
  1613.  
  1614. d3d_texture_t* HMRemoveTexture(int iKey)
  1615. {
  1616.     int iPos = HMHashFunc(iKey);
  1617.     d3d_texture_t* pTexture = NULL;
  1618.    
  1619.     if (g_pTable->pList[iPos] != NULL)
  1620.     {      
  1621.         struct sNode *pPrev = NULL;
  1622.         struct sNode *pCurr = g_pTable->pList[iPos];
  1623.  
  1624.         while(pCurr->pNext != NULL && pCurr->iKey != iKey)
  1625.         {
  1626.             pPrev = pCurr;
  1627.             pCurr = pCurr->pNext;
  1628.         }
  1629.  
  1630.         if (pCurr->iKey == iKey)
  1631.         {
  1632.             struct sNode *pNextEntry = pCurr->pNext;
  1633.            
  1634.             if (pPrev)
  1635.                 pPrev->pNext = pNextEntry;
  1636.             else g_pTable->pList[iPos] = pNextEntry;
  1637.  
  1638.             pTexture = pCurr->pValue;
  1639.             if(pCurr) free(pCurr);
  1640.  
  1641.             return pTexture;
  1642.         }
  1643.         else if (pCurr->pNext != NULL)
  1644.             return NULL; // Not found!
  1645.     }
  1646.     return NULL;
  1647. }
  1648.  
  1649. extern void DeleteSubImageCache(int iNum);
  1650.  
  1651. void HMRemoveAllTextures()
  1652. {
  1653.     int i;
  1654.  
  1655.     for(i = 0; i < g_pTable->iSize; i++)
  1656.     {
  1657.         struct sNode *pList = g_pTable->pList[i];
  1658.         struct sNode *pTemp = pList;
  1659.        
  1660.         while(pTemp)
  1661.         {
  1662.             struct sNode *pCurr = pTemp;
  1663.             pTemp = pTemp->pNext;
  1664.  
  1665.             if(pCurr)
  1666.             {
  1667.                 DeleteSubImageCache(pCurr->pValue->glnum);
  1668.  
  1669.                 // Release the texture
  1670.                 if(pCurr->pValue->teximg)
  1671.                 {
  1672.                     IDirect3DTexture8_Release(pCurr->pValue->teximg);
  1673.                     pCurr->pValue->teximg = NULL;
  1674.                 }
  1675.  
  1676.                 free(pCurr);
  1677.                 pCurr = NULL;
  1678.             }
  1679.         }
  1680.     }
  1681. }
  1682.  
  1683. d3d_texture_t* HMLookupTexture(int iKey)
  1684. {
  1685.     int iPos = HMHashFunc(iKey);
  1686.    
  1687.     struct sNode *pList = g_pTable->pList[iPos];
  1688.     struct sNode *pTemp = pList;
  1689.    
  1690.     while(pTemp)
  1691.     {
  1692.         if(pTemp->iKey == iKey)
  1693.             return pTemp->pValue;
  1694.        
  1695.         pTemp = pTemp->pNext;
  1696.     }
  1697.     return NULL;
  1698. }
  1699.  
  1700. /*
  1701. ===================================================================================================================
  1702.  
  1703.             TEXTURES
  1704.  
  1705. ===================================================================================================================
  1706. */
  1707.  
  1708. d3d_texture_t *D3D_AllocTexture (int iTextureID)
  1709. {
  1710.     d3d_texture_t *tex;
  1711.  
  1712.     // We are not reusing textures ATM, they are removed
  1713.     // from the hashmap and freed
  1714.    
  1715.     // We should prob be reusing the texture IDs from
  1716.     // freed textures but we just keep increasing the
  1717.     // texture ID number in glGenTextures() atm
  1718. /*
  1719.     // Find a free texture
  1720.     for (tex = d3d_Textures; tex; tex = tex->next)
  1721.     {
  1722.         // If either of these are 0 (or NULL) we just reuse it
  1723.         if (!tex->teximg)
  1724.         {
  1725.             D3D_InitTexture (tex);
  1726.             return tex;
  1727.         }
  1728.  
  1729.         if (!tex->glnum)
  1730.         {
  1731.             D3D_InitTexture (tex);
  1732.             return tex;
  1733.         }
  1734.     }
  1735. */
  1736.     // Nothing to reuse so create a new one
  1737.     // Clear to 0 is required so that D3D_SAFE_RELEASE is valid
  1738.     tex = (d3d_texture_t *) malloc (sizeof (d3d_texture_t));
  1739.     memset (tex, 0, sizeof (d3d_texture_t));
  1740.  
  1741.     D3D_InitTexture (tex);
  1742.  
  1743.     // Add to our hashmap
  1744.     HMInsertTexture(iTextureID, tex);
  1745.  
  1746.     // Return the new one
  1747.     return tex;
  1748. }
  1749.  
  1750.  
  1751. /*
  1752. ======================
  1753. D3D_CheckTextureFormat
  1754.  
  1755. Ensures that a given texture format will be available
  1756. ======================
  1757. */
  1758. BOOL D3D_CheckTextureFormat (D3DFORMAT TextureFormat, D3DFORMAT AdapterFormat)
  1759. {
  1760.     hr = IDirect3D8_CheckDeviceFormat
  1761.     (
  1762.         d3d_Object,
  1763.         D3DADAPTER_DEFAULT,
  1764.         D3DDEVTYPE_HAL,
  1765.         AdapterFormat,
  1766.         0,
  1767.         D3DRTYPE_TEXTURE,
  1768.         TextureFormat
  1769.     );
  1770.  
  1771.     return SUCCEEDED (hr);
  1772. }
  1773.  
  1774.  
  1775. void glTexEnvf (GLenum target, GLenum pname, GLfloat param)
  1776. {
  1777.     if (target != GL_TEXTURE_ENV) SysMessage ("glTexEnvf: unimplemented target");
  1778.  
  1779.     d3d_TMUs[d3d_CurrentTMU].texenvdirty = TRUE;
  1780.  
  1781.     switch (pname)
  1782.     {
  1783.     case GL_TEXTURE_ENV_MODE:
  1784.         // this is the default mode
  1785.         switch ((GLint) param)
  1786.         {
  1787.         case GLD3D_COMBINE:
  1788.             // flag a combine
  1789.             //d3d_TMUs[d3d_CurrentTMU].combine = TRUE;
  1790.             break;
  1791.  
  1792.         case GL_ADD:
  1793.             d3d_TMUs[d3d_CurrentTMU].colorop = D3DTOP_ADD;
  1794.             d3d_TMUs[d3d_CurrentTMU].colorarg1 = D3DTA_TEXTURE;
  1795.             d3d_TMUs[d3d_CurrentTMU].colorarg2 = (d3d_CurrentTMU == 0 ? D3DTA_DIFFUSE : D3DTA_CURRENT);
  1796.  
  1797.             d3d_TMUs[d3d_CurrentTMU].alphaop = D3DTOP_ADD;
  1798.             d3d_TMUs[d3d_CurrentTMU].alphaarg1 = D3DTA_TEXTURE;
  1799.             d3d_TMUs[d3d_CurrentTMU].alphaarg2 = D3DTA_DIFFUSE;
  1800.  
  1801.             //d3d_TMUs[d3d_CurrentTMU].combine = FALSE;
  1802.             break;
  1803.  
  1804.         case GL_REPLACE:
  1805.             // there was a reason why i changed this to modulate but i can't remember it :(
  1806.             // anyway, it needs to be D3DTOP_SELECTARG1 for Quake, so D3DTOP_SELECTARG1 it is...
  1807.             d3d_TMUs[d3d_CurrentTMU].colorop = D3DTOP_SELECTARG1;
  1808.             d3d_TMUs[d3d_CurrentTMU].colorarg1 = D3DTA_TEXTURE;
  1809.             d3d_TMUs[d3d_CurrentTMU].colorarg2 = D3DTA_DIFFUSE;
  1810.  
  1811.             d3d_TMUs[d3d_CurrentTMU].alphaop = D3DTOP_SELECTARG1;
  1812.             d3d_TMUs[d3d_CurrentTMU].alphaarg1 = D3DTA_TEXTURE;
  1813.             d3d_TMUs[d3d_CurrentTMU].alphaarg2 = D3DTA_DIFFUSE;
  1814.  
  1815.             //d3d_TMUs[d3d_CurrentTMU].combine = FALSE;
  1816.             break;
  1817.  
  1818.         case GL_MODULATE:
  1819.             d3d_TMUs[d3d_CurrentTMU].colorop = D3DTOP_MODULATE;
  1820.             d3d_TMUs[d3d_CurrentTMU].colorarg1 = D3DTA_TEXTURE;
  1821.             d3d_TMUs[d3d_CurrentTMU].colorarg2 = (d3d_CurrentTMU == 0 ? D3DTA_DIFFUSE : D3DTA_CURRENT);
  1822.  
  1823.             d3d_TMUs[d3d_CurrentTMU].alphaop = D3DTOP_MODULATE;
  1824.             d3d_TMUs[d3d_CurrentTMU].alphaarg1 = D3DTA_TEXTURE;
  1825.             d3d_TMUs[d3d_CurrentTMU].alphaarg2 = D3DTA_DIFFUSE;
  1826.  
  1827.             //d3d_TMUs[d3d_CurrentTMU].combine = FALSE;
  1828.             break;
  1829.  
  1830.         case GL_DECAL:
  1831.             d3d_TMUs[d3d_CurrentTMU].colorop = D3DTOP_BLENDTEXTUREALPHA;
  1832.             d3d_TMUs[d3d_CurrentTMU].colorarg1 = D3DTA_TEXTURE;
  1833.             d3d_TMUs[d3d_CurrentTMU].colorarg2 = (d3d_CurrentTMU == 0 ? D3DTA_DIFFUSE : D3DTA_CURRENT);
  1834.  
  1835.             d3d_TMUs[d3d_CurrentTMU].alphaop = D3DTOP_SELECTARG1;
  1836.             d3d_TMUs[d3d_CurrentTMU].alphaarg1 = D3DTA_TEXTURE;
  1837.             d3d_TMUs[d3d_CurrentTMU].alphaarg2 = D3DTA_DIFFUSE;
  1838.  
  1839.             //d3d_TMUs[d3d_CurrentTMU].combine = FALSE;
  1840.             break;
  1841.  
  1842.         case GL_BLEND:
  1843.             d3d_TMUs[d3d_CurrentTMU].colorop = D3DTOP_MODULATE;
  1844.             d3d_TMUs[d3d_CurrentTMU].colorarg1 = D3DTA_TEXTURE | D3DTA_COMPLEMENT;
  1845.             d3d_TMUs[d3d_CurrentTMU].colorarg2 = (d3d_CurrentTMU == 0 ? D3DTA_DIFFUSE : D3DTA_CURRENT);
  1846.  
  1847.             d3d_TMUs[d3d_CurrentTMU].alphaop = D3DTOP_SELECTARG1;
  1848.             d3d_TMUs[d3d_CurrentTMU].alphaarg1 = D3DTA_TEXTURE;
  1849.             d3d_TMUs[d3d_CurrentTMU].alphaarg2 = D3DTA_DIFFUSE;
  1850.  
  1851.             //d3d_TMUs[d3d_CurrentTMU].combine = FALSE;
  1852.             break;
  1853.  
  1854.         default:
  1855.             SysMessage ("glTexEnvf: unimplemented param");
  1856.             break;
  1857.         }
  1858.  
  1859.         break;
  1860.  
  1861.     case GLD3D_COMBINE_RGB:
  1862.         //if ((int) param == GL_MODULATE)
  1863.         //  d3d_TMUs[d3d_CurrentTMU].combstate.colorop = D3DTOP_MODULATE;
  1864.         //else SysMessage ("glTexEnvf: unimplemented param");
  1865.         break;
  1866.  
  1867.     case GLD3D_SOURCE0_RGB:
  1868.         //if ((int) param == GL_TEXTURE)
  1869.         //  d3d_TMUs[d3d_CurrentTMU].combstate.colorarg1 = D3DTA_TEXTURE;
  1870.         //else if ((int) param == GLD3D_PREVIOUS)
  1871.         //  d3d_TMUs[d3d_CurrentTMU].combstate.colorarg1 = D3DTA_CURRENT;
  1872.         //else SysMessage ("glTexEnvf: unimplemented param");
  1873.         break;
  1874.  
  1875.     case GLD3D_SOURCE1_RGB:
  1876.         //if ((int) param == GL_TEXTURE)
  1877.         //  d3d_TMUs[d3d_CurrentTMU].combstate.colorarg2 = D3DTA_TEXTURE;
  1878.         //else if ((int) param == GLD3D_PRIMARY_COLOR)
  1879.         //  d3d_TMUs[d3d_CurrentTMU].combstate.colorarg2 = D3DTA_DIFFUSE;
  1880.         //else SysMessage ("glTexEnvf: unimplemented param");
  1881.         break;
  1882.  
  1883.     case GLD3D_RGB_SCALE:
  1884.         // d3d only allows 1/2/4 x scale and in practice so do most OpenGL implementations
  1885.         // (this is actually required by the spec: see http://www.opengl.org/sdk/docs/man/xhtml/glTexEnv.xml)
  1886.         //if (param > 2)
  1887.         //  d3d_TMUs[d3d_CurrentTMU].combstate.colorscale = 4;
  1888.         //else if (param > 1)
  1889.         //  d3d_TMUs[d3d_CurrentTMU].combstate.colorscale = 2;
  1890.         //else d3d_TMUs[d3d_CurrentTMU].combstate.colorscale = 1;
  1891.         break;
  1892.  
  1893.     default:
  1894.         SysMessage ("glTexEnvf: unimplemented pname");
  1895.         break;
  1896.     }
  1897. }
  1898.  
  1899.  
  1900. void glTexEnvi (GLenum target, GLenum pname, GLint param)
  1901. {
  1902.     if (target != GL_TEXTURE_ENV) return;
  1903.  
  1904.     glTexEnvf (target, pname, param);
  1905. }
  1906.  
  1907. #if 0
  1908. void D3D_FillTextureLevel (LPDIRECT3DTEXTURE8 texture, int level, GLint internalformat, int width, int height, GLint format, const void *pixels)
  1909. {
  1910.     int i;
  1911.     int srcbytes = 0;
  1912.     int dstbytes = 0;
  1913.     byte *srcdata;
  1914.     byte *dstdata;
  1915.     D3DLOCKED_RECT lockrect;
  1916.  
  1917.     if (format == 1 || format == GL_LUMINANCE)
  1918.         srcbytes = 1;
  1919.     else if (format == 3 || format == GL_RGB)
  1920.         srcbytes = 3;
  1921.     else if (format == 4 || format == GL_RGBA)
  1922.         srcbytes = 4;
  1923.     else SysMessage ("D3D_FillTextureLevel: illegal format");
  1924.  
  1925.     // d3d doesn't have an internal RGB only format
  1926.     // (neither do most OpenGL implementations, they just let you specify it as RGB but expand internally to 4 component)
  1927.     if (internalformat == 1 || internalformat == GL_LUMINANCE)
  1928.         dstbytes = 1;
  1929.     else if (internalformat == 3 || internalformat == GL_RGB)
  1930.         dstbytes = 4;
  1931.     else if (internalformat == 4 || internalformat == GL_RGBA)
  1932.         dstbytes = 4;
  1933.     else SysMessage ("D3D_FillTextureLevel: illegal internalformat");
  1934.  
  1935.     IDirect3DTexture8_LockRect (texture, level, &lockrect, NULL, 0);
  1936.  
  1937.     srcdata = (byte *) pixels;
  1938.     dstdata = lockrect.pBits;
  1939.  
  1940.     for (i = 0; i < width * height; i++)
  1941.     {
  1942.         if (srcbytes == 1)
  1943.         {
  1944.             if (dstbytes == 1)
  1945.                 dstdata[0] = srcdata[0];
  1946.             else if (dstbytes == 4)
  1947.             {
  1948.                 dstdata[0] = srcdata[0];
  1949.                 dstdata[1] = srcdata[0];
  1950.                 dstdata[2] = srcdata[0];
  1951.                 dstdata[3] = srcdata[0];
  1952.             }
  1953.         }
  1954.         else if (srcbytes == 3)
  1955.         {
  1956.             if (dstbytes == 1)
  1957.                 dstdata[0] = ((int) srcdata[0] + (int) srcdata[1] + (int) srcdata[2]) / 3;
  1958.             else if (dstbytes == 4)
  1959.             {
  1960.                 dstdata[0] = srcdata[2];
  1961.                 dstdata[1] = srcdata[1];
  1962.                 dstdata[2] = srcdata[0];
  1963.                 dstdata[3] = 255;
  1964.             }
  1965.         }
  1966.         else if (srcbytes == 4)
  1967.         {
  1968.             if (dstbytes == 1)
  1969.                 dstdata[0] = ((int) srcdata[0] + (int) srcdata[1] + (int) srcdata[2]) / 3;
  1970.             else if (dstbytes == 4)
  1971.             {
  1972.                 dstdata[0] = srcdata[2];
  1973.                 dstdata[1] = srcdata[1];
  1974.                 dstdata[2] = srcdata[0];
  1975.                 dstdata[3] = srcdata[3];
  1976.             }
  1977.         }
  1978.  
  1979.         // advance
  1980.         srcdata += srcbytes;
  1981.         dstdata += dstbytes;
  1982.     }
  1983.  
  1984.     IDirect3DTexture8_UnlockRect (texture, level);
  1985. }
  1986. #endif
  1987.  
  1988. #if 1 // Swizzled
  1989. void D3D_FillTextureLevel (LPDIRECT3DTEXTURE8 texture, int level, GLint internalformat, int width, int height, GLint format, const void *pixels)
  1990. {
  1991.     int i;
  1992.     int srcbytes = 0;
  1993.     int dstbytes = 0;
  1994.     byte *srcdata;
  1995.     byte *dstdata;
  1996.     D3DLOCKED_RECT lockrect;
  1997.  
  1998.     D3DLOCKED_RECT lr, lr2;
  1999.     D3DSURFACE_DESC desc;
  2000.     LPDIRECT3DSURFACE8 surface;
  2001.     LPDIRECT3DSURFACE8 surfaceTemp;
  2002.  
  2003.     if (format == 1 || format == GL_LUMINANCE || format == GL_LUMINANCE8 )
  2004.         srcbytes = 1;
  2005.     else if (format == 3 || format == GL_RGB)
  2006.         srcbytes = 3;
  2007.     else if (format == 4 || format == GL_RGBA)
  2008.         srcbytes = 4;
  2009.     else SysMessage ("D3D_FillTextureLevel: illegal format");
  2010.  
  2011.     // d3d doesn't have an internal RGB only format
  2012.     // (neither do most OpenGL implementations, they just let you specify it as RGB but expand internally to 4 component)
  2013.     if (internalformat == 1 || internalformat == GL_LUMINANCE || internalformat == GL_LUMINANCE8 )
  2014.         dstbytes = 1;
  2015.     else if (internalformat == 3 || internalformat == GL_RGB)
  2016.         dstbytes = 4;
  2017.     else if (internalformat == 4 || internalformat == GL_RGBA)
  2018.         dstbytes = 4;
  2019.     else SysMessage ("D3D_FillTextureLevel: illegal internalformat");
  2020.  
  2021.     IDirect3DTexture8_LockRect (texture, level, &lockrect, NULL, 0);
  2022.  
  2023.     srcdata = (byte *) pixels;
  2024.     dstdata = (byte *) lockrect.pBits;
  2025.  
  2026.     for (i = 0; i < width * height; i++)
  2027.     {
  2028.         if (srcbytes == 1)
  2029.         {
  2030.             if (dstbytes == 1)
  2031.                 dstdata[0] = srcdata[0];
  2032.             else if (dstbytes == 4)
  2033.             {
  2034.                 dstdata[0] = srcdata[0];
  2035.                 dstdata[1] = srcdata[0];
  2036.                 dstdata[2] = srcdata[0];
  2037.                 dstdata[3] = srcdata[0];
  2038.             }
  2039.         }
  2040.         else if (srcbytes == 3)
  2041.         {
  2042.             if (dstbytes == 1)
  2043.                 dstdata[0] = ((int) srcdata[0] + (int) srcdata[1] + (int) srcdata[2]) / 3;
  2044.             else if (dstbytes == 4)
  2045.             {
  2046.                 dstdata[0] = srcdata[2];
  2047.                 dstdata[1] = srcdata[1];
  2048.                 dstdata[2] = srcdata[0];
  2049.                 dstdata[3] = 255;
  2050.             }
  2051.         }
  2052.         else if (srcbytes == 4)
  2053.         {
  2054.             if (dstbytes == 1)
  2055.                 dstdata[0] = ((int) srcdata[0] + (int) srcdata[1] + (int) srcdata[2]) / 3;
  2056.             else if (dstbytes == 4)
  2057.             {
  2058.                 dstdata[0] = srcdata[2];
  2059.                 dstdata[1] = srcdata[1];
  2060.                 dstdata[2] = srcdata[0];
  2061.                 dstdata[3] = srcdata[3];
  2062.             }
  2063.         }
  2064.  
  2065.         // advance
  2066.         srcdata += srcbytes;
  2067.         dstdata += dstbytes;
  2068.     }
  2069.  
  2070.     IDirect3DTexture8_GetLevelDesc(texture, level, &desc);
  2071.  
  2072.     //Create temporary surface
  2073.     IDirect3DDevice8_CreateImageSurface (d3d_Device, desc.Width, desc.Height, desc.Format, &surfaceTemp);
  2074.  
  2075.     //Lock the texture
  2076.     IDirect3DTexture8_LockRect (texture, 0, &lr, NULL, 0);
  2077.  
  2078.     //go down to surface level
  2079.     IDirect3DTexture8_GetSurfaceLevel(texture, level, &surface);
  2080.  
  2081.     //copy surf to temp surf
  2082.     D3DXLoadSurfaceFromSurface(surfaceTemp, NULL, NULL, surface, NULL, NULL, D3DX_FILTER_NONE, 0);
  2083.  
  2084.     IDirect3DSurface8_LockRect (surfaceTemp, &lr2, NULL, 0);
  2085.  
  2086.     // Xbox textures need to be swizzled
  2087.     XGSwizzleRect(
  2088.                   lr2.pBits,      // pSource,
  2089.                   lr2.Pitch,      // Pitch,
  2090.                   NULL,           // pRect,
  2091.                   lr.pBits,       // pDest,
  2092.                   desc.Width,     // Width,
  2093.                   desc.Height,    // Height,
  2094.                   NULL,           // pPoint,
  2095.                   dstbytes );     // BytesPerPixel
  2096.  
  2097.     IDirect3DSurface8_UnlockRect (surfaceTemp);
  2098.     IDirect3DSurface8_Release(surfaceTemp);
  2099.  
  2100.     IDirect3DSurface8_Release(surface);
  2101.     IDirect3DTexture8_UnlockRect (texture, level);
  2102. }
  2103. #endif
  2104.  
  2105. void D3D_CopyTextureLevel (LPDIRECT3DTEXTURE8 srctex, int srclevel, LPDIRECT3DTEXTURE8 dsttex, int dstlevel)
  2106. {
  2107.     LPDIRECT3DSURFACE8 srcsurf;
  2108.     LPDIRECT3DSURFACE8 dstsurf;
  2109.  
  2110.     IDirect3DTexture8_GetSurfaceLevel (srctex, srclevel, &srcsurf);
  2111.     IDirect3DTexture8_GetSurfaceLevel (dsttex, dstlevel, &dstsurf);
  2112.  
  2113.     D3DXLoadSurfaceFromSurface (dstsurf, NULL, NULL, srcsurf, NULL, NULL, D3DX_FILTER_POINT, 0);
  2114.  
  2115. //  D3D_SAFE_RELEASE (srcsurf);
  2116.     IDirect3DSurface8_Release(srcsurf);
  2117. //  D3D_SAFE_RELEASE (dstsurf);
  2118.     IDirect3DSurface8_Release(dstsurf);
  2119. }
  2120.  
  2121.  
  2122. void glGetTexImage (GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels)
  2123. {
  2124.     int i;
  2125.     int dstbytes = 0;
  2126.     unsigned char *srcdata;
  2127.     unsigned char *dstdata;
  2128.     LPDIRECT3DSURFACE8 texsurf;
  2129.     LPDIRECT3DSURFACE8 locksurf;
  2130.     D3DLOCKED_RECT lockrect;
  2131.     D3DSURFACE_DESC desc;
  2132.  
  2133.     if (target != GL_TEXTURE_2D) return;
  2134.     if (type != GL_UNSIGNED_BYTE) return;
  2135.  
  2136.     if (format == GL_RGB)
  2137.         dstbytes = 3;
  2138.     else if (format == GL_RGBA)
  2139.         dstbytes = 4;
  2140.     else SysMessage ("glGetTexImage: invalid format");
  2141.  
  2142.     hr = IDirect3DTexture8_GetSurfaceLevel (d3d_TMUs[d3d_CurrentTMU].boundtexture->teximg, level, &texsurf);
  2143.  
  2144.     if (FAILED (hr) || !texsurf)
  2145.     {
  2146.         SysMessage ("glGetTexImage: failed to access back buffer\n");
  2147.         return;
  2148.     }
  2149.  
  2150.     // because textures can be different formats we create it as one big enough to hold them all
  2151.     hr = IDirect3DSurface8_GetDesc (texsurf, &desc);
  2152.     hr = IDirect3DDevice8_CreateImageSurface (d3d_Device, desc.Width, desc.Height, D3DFMT_A8R8G8B8, &locksurf);
  2153.     hr = D3DXLoadSurfaceFromSurface (locksurf, NULL, NULL, texsurf, NULL, NULL, D3DX_FILTER_NONE, 0);
  2154.  
  2155.     // now we have a surface we can lock
  2156.     hr = IDirect3DSurface8_LockRect (locksurf, &lockrect, NULL, D3DLOCK_READONLY);
  2157.     srcdata = (unsigned char *) lockrect.pBits;
  2158.     dstdata = (unsigned char *) pixels;
  2159.  
  2160.     for (i = 0; i < desc.Width * desc.Height; i++)
  2161.     {
  2162.         // swap back
  2163.         dstdata[0] = srcdata[2];
  2164.         dstdata[1] = srcdata[1];
  2165.         dstdata[2] = srcdata[0];
  2166.  
  2167.         if (dstbytes == 4) dstdata[3] = srcdata[3];
  2168.  
  2169.         srcdata += 4;
  2170.         dstdata += dstbytes;
  2171.     }
  2172.  
  2173.     // done
  2174.     IDirect3DSurface8_UnlockRect (locksurf);
  2175.     //D3D_SAFE_RELEASE (locksurf);
  2176.     IDirect3DSurface8_Release(locksurf);
  2177.     //D3D_SAFE_RELEASE (texsurf);
  2178.     IDirect3DSurface8_Release(texsurf);
  2179. }
  2180.  
  2181.  
  2182. void glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
  2183. {
  2184.     D3DFORMAT texformat = D3DFMT_X8R8G8B8;
  2185.  
  2186.     // validate format
  2187.     switch (internalformat)
  2188.     {
  2189.     case 1:
  2190.     case GL_LUMINANCE:
  2191.     case GL_LUMINANCE8: //MARTY
  2192.         texformat = D3DFMT_L8;
  2193.         break;
  2194.  
  2195.     case 3:
  2196.     case GL_RGB:
  2197.         texformat = D3DFMT_X8R8G8B8;
  2198.         break;
  2199.  
  2200.     case 4:
  2201.     case GL_RGBA:
  2202.         texformat = D3DFMT_A8R8G8B8;
  2203.         break;
  2204.  
  2205.     default:
  2206.         SysMessage ("invalid texture internal format");
  2207.     }
  2208.  
  2209.     if (type != GL_UNSIGNED_BYTE) SysMessage ("glTexImage2D: Unrecognised pixel format");
  2210.  
  2211.     // ensure that it's valid to create textures
  2212.     if (target != GL_TEXTURE_2D) return;
  2213.     if (!d3d_TMUs[d3d_CurrentTMU].boundtexture) return;
  2214.  
  2215.     if (level == 0)
  2216.     {
  2217.         // in THEORY an OpenGL texture can have different formats and internal formats for each miplevel
  2218.         // in practice I don't think anyone uses it...
  2219.         d3d_TMUs[d3d_CurrentTMU].boundtexture->internalformat = internalformat;
  2220.  
  2221.         // overwrite an existing texture - just release it so that we can recreate
  2222.         //D3D_SAFE_RELEASE (d3d_TMUs[d3d_CurrentTMU].boundtexture->teximg);
  2223.  
  2224.         if(d3d_TMUs[d3d_CurrentTMU].boundtexture->teximg)
  2225.         {
  2226.             IDirect3DTexture8_Release(d3d_TMUs[d3d_CurrentTMU].boundtexture->teximg);
  2227.             d3d_TMUs[d3d_CurrentTMU].boundtexture->teximg = NULL;
  2228.         }  
  2229.  
  2230.         // create the texture from the data
  2231.         // initially just create a single mipmap level (assume that the texture isn't mipped)
  2232.         hr = IDirect3DDevice8_CreateTexture
  2233.         (
  2234.             d3d_Device,
  2235.             width,
  2236.             height,
  2237.             1,
  2238.             0,
  2239.             texformat,
  2240.             D3DPOOL_MANAGED,
  2241.             &d3d_TMUs[d3d_CurrentTMU].boundtexture->teximg
  2242.         );
  2243.  
  2244.         if (FAILED (hr)) SysMessage ("glTexImage2D: unable to create a texture");
  2245.  
  2246.         D3D_FillTextureLevel (d3d_TMUs[d3d_CurrentTMU].boundtexture->teximg, 0, internalformat, width, height, format, pixels);
  2247.     }
  2248.     else if (level == 1)
  2249.     {
  2250.         // we're creating subsequent miplevels so we need to recreate this texture
  2251.         LPDIRECT3DTEXTURE8 newtexture;
  2252.  
  2253.         // this is miplevel 1 and we're recreating level 0, so double width and height
  2254.         hr = IDirect3DDevice8_CreateTexture
  2255.         (
  2256.             d3d_Device,
  2257.             width * 2,
  2258.             height * 2,
  2259.             0,
  2260.             0,
  2261.             texformat,
  2262.             D3DPOOL_MANAGED,
  2263.             &newtexture
  2264.         );
  2265.  
  2266.         if (FAILED (hr)) SysMessage ("glTexImage2D: unable to create a texture");
  2267.  
  2268.         // copy level 0 across to the new texture
  2269.         D3D_CopyTextureLevel (d3d_TMUs[d3d_CurrentTMU].boundtexture->teximg, 0, newtexture, 0);
  2270.  
  2271.         // release the former level 0 texture and reset to the new one
  2272.  
  2273.         //D3D_SAFE_RELEASE (d3d_TMUs[d3d_CurrentTMU].boundtexture->teximg);
  2274.  
  2275.         if(d3d_TMUs[d3d_CurrentTMU].boundtexture->teximg)
  2276.         {
  2277.             IDirect3DTexture8_Release(d3d_TMUs[d3d_CurrentTMU].boundtexture->teximg);
  2278.             d3d_TMUs[d3d_CurrentTMU].boundtexture->teximg = NULL;
  2279.         }  
  2280.        
  2281.         d3d_TMUs[d3d_CurrentTMU].boundtexture->teximg = newtexture;
  2282.  
  2283.         D3D_FillTextureLevel (d3d_TMUs[d3d_CurrentTMU].boundtexture->teximg, 1, internalformat, width, height, format, pixels);
  2284.     }
  2285.     else
  2286.     {
  2287.         // the texture has already been created so no need to do any more
  2288.         D3D_FillTextureLevel (d3d_TMUs[d3d_CurrentTMU].boundtexture->teximg, level, internalformat, width, height, format, pixels);
  2289.     }
  2290. }
  2291.  
  2292.  
  2293. void glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params)
  2294. {
  2295.     if (!d3d_TMUs[d3d_CurrentTMU].boundtexture) return;
  2296.     if (target != GL_TEXTURE_2D) return;
  2297.  
  2298.     switch (pname)
  2299.     {
  2300.     case GLD3D_TEXTURE_MAX_ANISOTROPY_EXT:
  2301.         params[0] = d3d_TMUs[d3d_CurrentTMU].boundtexture->anisotropy;
  2302.         break;
  2303.  
  2304.     default:
  2305.         break;
  2306.     }
  2307. }
  2308.  
  2309. void glTexParameterf (GLenum target, GLenum pname, GLfloat param)
  2310. {
  2311.     if (!d3d_TMUs[d3d_CurrentTMU].boundtexture) return;
  2312.     if (target != GL_TEXTURE_2D) return;
  2313.  
  2314.     d3d_TMUs[d3d_CurrentTMU].texparamdirty = TRUE;
  2315.  
  2316.     switch (pname)
  2317.     {
  2318.     case GL_TEXTURE_MIN_FILTER:
  2319.         if ((int) param == GL_NEAREST_MIPMAP_NEAREST)
  2320.         {
  2321.             d3d_TMUs[d3d_CurrentTMU].boundtexture->minfilter = D3DTEXF_POINT;
  2322.             d3d_TMUs[d3d_CurrentTMU].boundtexture->mipfilter = D3DTEXF_POINT;
  2323.         }
  2324.         else if ((int) param == GL_LINEAR_MIPMAP_NEAREST)
  2325.         {
  2326.             d3d_TMUs[d3d_CurrentTMU].boundtexture->minfilter = D3DTEXF_LINEAR;
  2327.             d3d_TMUs[d3d_CurrentTMU].boundtexture->mipfilter = D3DTEXF_POINT;
  2328.         }
  2329.         else if ((int) param == GL_NEAREST_MIPMAP_LINEAR)
  2330.         {
  2331.             d3d_TMUs[d3d_CurrentTMU].boundtexture->minfilter = D3DTEXF_POINT;
  2332.             d3d_TMUs[d3d_CurrentTMU].boundtexture->mipfilter = D3DTEXF_LINEAR;
  2333.         }
  2334.         else if ((int) param == GL_LINEAR_MIPMAP_LINEAR)
  2335.         {
  2336.             d3d_TMUs[d3d_CurrentTMU].boundtexture->minfilter = D3DTEXF_LINEAR;
  2337.             d3d_TMUs[d3d_CurrentTMU].boundtexture->mipfilter = D3DTEXF_LINEAR;
  2338.         }
  2339.         else if ((int) param == GL_LINEAR)
  2340.         {
  2341.             d3d_TMUs[d3d_CurrentTMU].boundtexture->minfilter = D3DTEXF_LINEAR;
  2342.             d3d_TMUs[d3d_CurrentTMU].boundtexture->mipfilter = D3DTEXF_NONE;
  2343.         }
  2344.         else
  2345.         {
  2346.             // GL_NEAREST
  2347.             d3d_TMUs[d3d_CurrentTMU].boundtexture->minfilter = D3DTEXF_POINT;
  2348.             d3d_TMUs[d3d_CurrentTMU].boundtexture->mipfilter = D3DTEXF_NONE;
  2349.         }
  2350.         break;
  2351.  
  2352.     case GL_TEXTURE_MAG_FILTER:
  2353.         if ((int) param == GL_LINEAR)
  2354.             d3d_TMUs[d3d_CurrentTMU].boundtexture->magfilter = D3DTEXF_LINEAR;
  2355.         else d3d_TMUs[d3d_CurrentTMU].boundtexture->magfilter = D3DTEXF_POINT;
  2356.         break;
  2357.  
  2358.     case GL_TEXTURE_WRAP_S:
  2359.         if ((int) param == GL_CLAMP)
  2360.             d3d_TMUs[d3d_CurrentTMU].boundtexture->addressu = D3DTADDRESS_CLAMP;
  2361.         else d3d_TMUs[d3d_CurrentTMU].boundtexture->addressu = D3DTADDRESS_WRAP;
  2362.         break;
  2363.  
  2364.     case GL_TEXTURE_WRAP_T:
  2365.         if ((int) param == GL_CLAMP)
  2366.             d3d_TMUs[d3d_CurrentTMU].boundtexture->addressv = D3DTADDRESS_CLAMP;
  2367.         else d3d_TMUs[d3d_CurrentTMU].boundtexture->addressv = D3DTADDRESS_WRAP;
  2368.         break;
  2369.  
  2370.     case GLD3D_TEXTURE_MAX_ANISOTROPY_EXT:
  2371.         // this is a texparam in OpenGL
  2372.         if (d3d_Caps.MaxAnisotropy > 1)
  2373.             d3d_TMUs[d3d_CurrentTMU].boundtexture->anisotropy = (int) param;
  2374.         else d3d_TMUs[d3d_CurrentTMU].boundtexture->anisotropy = 1;
  2375.         break;
  2376.  
  2377.     default:
  2378.         break;
  2379.     }
  2380. }
  2381.  
  2382. void glTexParameteri (GLenum target, GLenum pname, GLint param)
  2383. {
  2384.     if(target != GL_TEXTURE_2D) return;
  2385.     if(!d3d_TMUs[d3d_CurrentTMU].boundtexture) return;
  2386.  
  2387.     glTexParameterf(target, pname, param);
  2388. }
  2389.  
  2390. SubImage_t* GetSubImageCache(int iTexNum)
  2391. {
  2392.     SubImage_t *tex;
  2393.  
  2394.     // find a free texture
  2395.     for (tex = SubImageCache; tex; tex = tex->next)
  2396.     {
  2397.         if(tex->iTextureNum == iTexNum)
  2398.         return tex;
  2399.     }
  2400.  
  2401.     tex = (SubImage_t *) malloc (sizeof (SubImage_t));
  2402.     memset (tex, 0, sizeof (SubImage_t));
  2403.  
  2404.     tex->iTextureNum = iTexNum;
  2405.  
  2406.     IDirect3DDevice8_CreateImageSurface (d3d_Device, 256, 256, D3DFMT_A8R8G8B8, &tex->texture);
  2407.  
  2408.     // link in
  2409.     tex->next = SubImageCache;
  2410.     SubImageCache = tex;
  2411.  
  2412.     // return the new one
  2413.     return tex;
  2414. }
  2415.  
  2416. void DeleteSubImageCache(int iNum)
  2417. {
  2418.     SubImage_t *tex;
  2419.  
  2420.     while(SubImageCache != NULL)
  2421.     {  
  2422.         tex = SubImageCache;
  2423.  
  2424.         SubImageCache = SubImageCache->next;
  2425.  
  2426.         tex->iTextureNum = 0;
  2427.         IDirect3DSurface8_Release(tex->texture);
  2428.         free(tex);
  2429.         tex = NULL;
  2430.     }
  2431. }
  2432.  
  2433. #if 0
  2434. void glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
  2435. {
  2436.     int x, y;
  2437.     int srcbytes = 0;
  2438.     int dstbytes = 0;
  2439.     byte *srcdata;
  2440.     byte *dstdata;
  2441.     D3DLOCKED_RECT lockrect;
  2442.  
  2443.     if (format == 1 || format == GL_LUMINANCE)
  2444.         srcbytes = 1;
  2445.     else if (format == 3 || format == GL_RGB)
  2446.         srcbytes = 3;
  2447.     else if (format == 4 || format == GL_RGBA)
  2448.         srcbytes = 4;
  2449.     else SysMessage ("D3D_FillTextureLevel: illegal format");
  2450.  
  2451.     // d3d doesn't have an internal RGB only format
  2452.     // (neither do most OpenGL implementations, they just let you specify it as RGB but expand internally to 4 component)
  2453.     if (d3d_TMUs[d3d_CurrentTMU].boundtexture->internalformat == 1 || d3d_TMUs[d3d_CurrentTMU].boundtexture->internalformat == GL_LUMINANCE)
  2454.         dstbytes = 1;
  2455.     else if (d3d_TMUs[d3d_CurrentTMU].boundtexture->internalformat == 3 || d3d_TMUs[d3d_CurrentTMU].boundtexture->internalformat == GL_RGB)
  2456.         dstbytes = 4;
  2457.     else if (d3d_TMUs[d3d_CurrentTMU].boundtexture->internalformat == 4 || d3d_TMUs[d3d_CurrentTMU].boundtexture->internalformat == GL_RGBA)
  2458.         dstbytes = 4;
  2459.     else SysMessage ("D3D_FillTextureLevel: illegal internalformat");
  2460.  
  2461.     IDirect3DTexture8_LockRect (d3d_TMUs[d3d_CurrentTMU].boundtexture->teximg, level, &lockrect, NULL, 0);
  2462.  
  2463.     srcdata = (byte *) pixels;
  2464.     dstdata = lockrect.pBits;
  2465.     dstdata += (yoffset * width + xoffset) * dstbytes;
  2466.  
  2467.     for (y = yoffset; y < (yoffset + height); y++)
  2468.     {
  2469.         for (x = xoffset; x < (xoffset + width); x++)
  2470.         {
  2471.             if (srcbytes == 1)
  2472.             {
  2473.                 if (dstbytes == 1)
  2474.                     dstdata[0] = srcdata[0];
  2475.                 else if (dstbytes == 4)
  2476.                 {
  2477.                     dstdata[0] = srcdata[0];
  2478.                     dstdata[1] = srcdata[0];
  2479.                     dstdata[2] = srcdata[0];
  2480.                     dstdata[3] = srcdata[0];
  2481.                 }
  2482.             }
  2483.             else if (srcbytes == 3)
  2484.             {
  2485.                 if (dstbytes == 1)
  2486.                     dstdata[0] = ((int) srcdata[0] + (int) srcdata[1] + (int) srcdata[2]) / 3;
  2487.                 else if (dstbytes == 4)
  2488.                 {
  2489.                     dstdata[0] = srcdata[2];
  2490.                     dstdata[1] = srcdata[1];
  2491.                     dstdata[2] = srcdata[0];
  2492.                     dstdata[3] = 255;
  2493.                 }
  2494.             }
  2495.             else if (srcbytes == 4)
  2496.             {
  2497.                 if (dstbytes == 1)
  2498.                     dstdata[0] = ((int) srcdata[0] + (int) srcdata[1] + (int) srcdata[2]) / 3;
  2499.                 else if (dstbytes == 4)
  2500.                 {
  2501.                     dstdata[0] = srcdata[2];
  2502.                     dstdata[1] = srcdata[1];
  2503.                     dstdata[2] = srcdata[0];
  2504.                     dstdata[3] = srcdata[3];
  2505.                 }
  2506.             }
  2507.  
  2508.             // advance
  2509.             srcdata += srcbytes;
  2510.             dstdata += dstbytes;
  2511.         }
  2512.     }
  2513.  
  2514.     IDirect3DTexture8_UnlockRect (d3d_TMUs[d3d_CurrentTMU].boundtexture->teximg, level);
  2515. }
  2516. #endif
  2517.  
  2518. #if 1 // Swizzled
  2519. void glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
  2520. {
  2521.     int x, y;
  2522.     int srcbytes = 4;
  2523.     int dstbytes = 4;
  2524.     byte *srcdata;
  2525.     byte *dstdata;
  2526.  
  2527.     D3DLOCKED_RECT lr;
  2528. //  D3DSURFACE_DESC desc;
  2529.  
  2530.     POINT point;
  2531.     RECT rect;
  2532.  
  2533.     SubImage_t* texSelect;
  2534.     D3DLOCKED_RECT lrunswiz;
  2535.  
  2536.     int iElement; // For saving time in the loop!
  2537.  
  2538.     rect.left = point.x = xoffset;
  2539.     rect.top = point.y = yoffset;
  2540.     rect.right = xoffset + width;
  2541.     rect.bottom = yoffset + height;
  2542.  
  2543. /*  if (format == 1 || format == GL_LUMINANCE) // FIXME: Dont assume the scrbytes, just hardcoded for speed atm
  2544.         srcbytes = 1;
  2545.     else if (format == 3 || format == GL_RGB)
  2546.         srcbytes = 3;
  2547.     else if (format == 4 || format == GL_RGBA)
  2548.         srcbytes = 4;
  2549.     else SysMessage ("D3D_FillTextureLevel: illegal format");
  2550.  
  2551.     // d3d doesn't have an internal RGB only format
  2552.     // (neither do most OpenGL implementations, they just let you specify it as RGB but expand internally to 4 component)
  2553.     if (d3d_TMUs[d3d_CurrentTMU].boundtexture->internalformat == 1 || d3d_TMUs[d3d_CurrentTMU].boundtexture->internalformat == GL_LUMINANCE)
  2554.         dstbytes = 1;
  2555.     else if (d3d_TMUs[d3d_CurrentTMU].boundtexture->internalformat == 3 || d3d_TMUs[d3d_CurrentTMU].boundtexture->internalformat == GL_RGB)
  2556.         dstbytes = 4;
  2557.     else if (d3d_TMUs[d3d_CurrentTMU].boundtexture->internalformat == 4 || d3d_TMUs[d3d_CurrentTMU].boundtexture->internalformat == GL_RGBA)
  2558.         dstbytes = 4;
  2559.     else SysMessage ("D3D_FillTextureLevel: illegal internalformat");
  2560. */
  2561.     texSelect = GetSubImageCache(d3d_TMUs[d3d_CurrentTMU].boundtexture->glnum);
  2562.  
  2563.     IDirect3DSurface8_LockRect (texSelect->texture, &lrunswiz, NULL, 0);   
  2564.  
  2565.     srcdata = (byte *) pixels;
  2566.     dstdata = (byte *) lrunswiz.pBits;
  2567.  
  2568.     // Saves doing addition in the loop
  2569.     height += yoffset;
  2570.     width += xoffset;
  2571.  
  2572.     for (y = yoffset; y < height; y++)
  2573.     {
  2574.         for (x = xoffset; x < width; x++)
  2575.         {
  2576.             iElement = lrunswiz.Pitch * y + dstbytes * x;
  2577.  
  2578.             dstdata[iElement] = srcdata[2];
  2579.             dstdata[iElement + 1] = srcdata[1];
  2580.             dstdata[iElement + 2] = srcdata[0];
  2581.             dstdata[iElement + 3] = srcdata[3];
  2582.  
  2583.             srcdata += srcbytes;
  2584.         }
  2585.     }
  2586.  
  2587.     IDirect3DSurface8_UnlockRect (texSelect->texture);
  2588.  
  2589. //  IDirect3DTexture8_GetLevelDesc(d3d_TMUs[d3d_CurrentTMU].boundtexture->teximg, level, &desc);
  2590.  
  2591.     // Lock the texture
  2592.     IDirect3DTexture8_LockRect (d3d_TMUs[d3d_CurrentTMU].boundtexture->teximg, level, &lr, NULL, 0);
  2593.  
  2594.     // XBox textures need to be swizzled
  2595.     XGSwizzleRect(
  2596.                   lrunswiz.pBits,         // pSource,
  2597.                   lrunswiz.Pitch,         // Pitch,
  2598.                   &rect,                  // pRect,
  2599.                   lr.pBits,               // pDest,
  2600.                   /*desc.Width*/256,      // Width,         // FIXME: Don't hardcode these sizes!
  2601.                   /*desc.Height*/256,     // Height,        //        It's ok for now tho as all PSX
  2602.                   &point,                 // pPoint,        //        textures are 256 and we need the speed!
  2603.                   dstbytes );             // BytesPerPixel
  2604.  
  2605.     IDirect3DTexture8_UnlockRect (d3d_TMUs[d3d_CurrentTMU].boundtexture->teximg, level);
  2606. }
  2607. #endif
  2608.  
  2609. void glBindTexture (GLenum target, GLuint texture)
  2610. {
  2611.     d3d_texture_t *tex;
  2612.  
  2613.     if(g_iCurrentTextureID == texture) // Saves speed not binding the same texture
  2614.         return;
  2615.  
  2616.     if (target != GL_TEXTURE_2D)
  2617.         return;
  2618.  
  2619.     // Use no texture
  2620.     if (texture == 0)
  2621.     {
  2622.         d3d_TMUs[d3d_CurrentTMU].boundtexture = NULL;
  2623.         return;
  2624.     }
  2625.  
  2626.     // Find the texture in the hashmap
  2627.     tex = HMLookupTexture(texture);
  2628.  
  2629.     if (tex->glnum == texture)
  2630.     {
  2631.         d3d_TMUs[d3d_CurrentTMU].boundtexture = tex;
  2632.         g_iCurrentTextureID = texture;
  2633.     }
  2634.    
  2635.     // Did we find it?
  2636.     if (!d3d_TMUs[d3d_CurrentTMU].boundtexture)
  2637.     {
  2638.         // Nope, so fill in a new one (this will make it work with texture_extension_number)
  2639.         // (i don't know if the spec formally allows this but id seem to have gotten away with it...)
  2640.         d3d_TMUs[d3d_CurrentTMU].boundtexture = D3D_AllocTexture(texture);
  2641.  
  2642.         // Reserve this slot
  2643.         d3d_TMUs[d3d_CurrentTMU].boundtexture->glnum = texture;
  2644.  
  2645.         // Ensure that it won't be reused
  2646.         if (texture > d3d_TextureExtensionNumber) d3d_TextureExtensionNumber = texture;
  2647.     }
  2648.  
  2649.     // This should never happen
  2650.     if (!d3d_TMUs[d3d_CurrentTMU].boundtexture) SysMessage ("glBindTexture: out of textures!!!");
  2651.  
  2652.     // Dirty the params
  2653.     d3d_TMUs[d3d_CurrentTMU].texparamdirty = TRUE;
  2654. }
  2655.  
  2656.  
  2657. void glGenTextures (GLsizei n, GLuint *textures)
  2658. {
  2659.     int i;
  2660.  
  2661.     for (i = 0; i < n; i++)
  2662.     {
  2663.         // either take a free slot or alloc a new one
  2664.         d3d_texture_t *tex = D3D_AllocTexture(d3d_TextureExtensionNumber);
  2665.         tex->glnum = textures[i] = d3d_TextureExtensionNumber;
  2666.        
  2667.         d3d_TextureExtensionNumber++;
  2668.     }
  2669. }
  2670.  
  2671.  
  2672. void glDeleteTextures (GLsizei n, const GLuint *textures)
  2673. {
  2674.     int i;
  2675.     d3d_texture_t *tex;
  2676.  
  2677.     for (i = 0; i < n; i++)
  2678.     {
  2679.         tex = HMLookupTexture(textures[i]);
  2680.        
  2681.         if(tex)
  2682.         {
  2683.             if (tex->glnum == textures[i])
  2684.             {
  2685.                 DeleteSubImageCache(tex->glnum);
  2686.  
  2687.                 // Release the texture
  2688.                 if(tex->teximg)
  2689.                 {
  2690.                     IDirect3DTexture8_Release(tex->teximg);
  2691.                     tex->teximg = NULL;
  2692.                 }  
  2693.                
  2694.                 // Remove from the hashmap
  2695.                 HMRemoveTexture(tex->glnum);
  2696.                
  2697.                 // Free it now
  2698.                 free(tex);
  2699.             }
  2700.         }
  2701.     }
  2702. }
  2703.  
  2704.  
  2705. /*
  2706. ===================================================================================================================
  2707.  
  2708.             VIDEO SETUP
  2709.  
  2710. ===================================================================================================================
  2711. */
  2712.  
  2713. /*
  2714. ==================
  2715. D3D_GetDepthFormat
  2716.  
  2717. Gets a valid depth format for a given adapter format
  2718. ==================
  2719. */
  2720. D3DFORMAT D3D_GetDepthFormat (D3DFORMAT AdapterFormat)
  2721. {
  2722.     // valid depth formats
  2723.     int i;
  2724.     D3DFORMAT d3d_DepthFormats[] = {/*D3DFMT_D32, D3DFMT_D24X8,*/ D3DFMT_D24S8, /*D3DFMT_D24X4S4,*/ D3DFMT_D16, D3DFMT_UNKNOWN};
  2725.  
  2726.     if (d3d_RequestStencil)
  2727.     {
  2728.         // switch to formats with a stencil buffer available at the head of the list
  2729.         d3d_DepthFormats[0] = D3DFMT_D24S8;
  2730. //      d3d_DepthFormats[1] = D3DFMT_D24X4S4;
  2731. //      d3d_DepthFormats[2] = D3DFMT_D32;
  2732. //      d3d_DepthFormats[3] = D3DFMT_D24X8;
  2733.         d3d_DepthFormats[4] = D3DFMT_D16;
  2734.         d3d_DepthFormats[5] = D3DFMT_UNKNOWN;
  2735.     }
  2736.  
  2737.     for (i = 0; ; i++)
  2738.     {
  2739.         if (d3d_DepthFormats[i] == D3DFMT_UNKNOWN)
  2740.             break;
  2741.  
  2742.         hr = IDirect3D8_CheckDeviceFormat
  2743.         (
  2744.             d3d_Object,
  2745.             D3DADAPTER_DEFAULT,
  2746.             D3DDEVTYPE_HAL,
  2747.             AdapterFormat,
  2748.             D3DUSAGE_DEPTHSTENCIL,
  2749.             D3DRTYPE_SURFACE,
  2750.             d3d_DepthFormats[i]
  2751.         );
  2752.  
  2753.         // return the first format that succeeds
  2754.         if (SUCCEEDED (hr)) return d3d_DepthFormats[i];
  2755.     }
  2756.  
  2757.     // didn't get one
  2758.     return D3DFMT_UNKNOWN;
  2759. }
  2760.  
  2761.  
  2762. /*
  2763. ========================
  2764. D3D_GetAdapterModeFormat
  2765.  
  2766. returns a usable adapter mode for the given width, height and bpp
  2767. ========================
  2768. */
  2769. D3DFORMAT D3D_GetAdapterModeFormat (int width, int height, int bpp)
  2770. {
  2771.     int i;
  2772.  
  2773.     // fill these in depending on bpp
  2774.     D3DFORMAT d3d_Formats[4];
  2775.  
  2776.     // these are the orders in which we prefer our formats
  2777.     if (bpp == -1)
  2778.     {
  2779.         // unspecified bpp uses the desktop mode format
  2780.         d3d_Formats[0] = d3d_DesktopMode.Format;
  2781.         d3d_Formats[1] = D3DFMT_UNKNOWN;
  2782.     }
  2783.     else if (bpp == 16)
  2784.     {
  2785.         d3d_Formats[0] = D3DFMT_R5G6B5;
  2786.         d3d_Formats[1] = D3DFMT_X1R5G5B5;
  2787.         d3d_Formats[2] = D3DFMT_A1R5G5B5;
  2788.         d3d_Formats[3] = D3DFMT_UNKNOWN;
  2789.     }
  2790.     else
  2791.     {
  2792.         d3d_Formats[0] = D3DFMT_X8R8G8B8;
  2793.         d3d_Formats[1] = D3DFMT_A8R8G8B8;
  2794.         d3d_Formats[2] = D3DFMT_UNKNOWN;
  2795.     }
  2796.  
  2797.     for (i = 0; ; i++)
  2798.     {
  2799.         UINT modecount;
  2800.         UINT m;
  2801.  
  2802.         // no more modes
  2803.         if (d3d_Formats[i] == D3DFMT_UNKNOWN) break;
  2804.  
  2805.         // get and validate the number of modes for this format; we expect that this will succeed first time
  2806.         modecount = IDirect3D8_GetAdapterModeCount (d3d_Object, D3DADAPTER_DEFAULT);
  2807.         if (!modecount) continue;
  2808.  
  2809.         // check each mode in turn to find a match
  2810.         for (m = 0; m < modecount; m++)
  2811.         {
  2812.             // get this mode
  2813.             D3DDISPLAYMODE mode;
  2814.             hr = IDirect3D8_EnumAdapterModes (d3d_Object, D3DADAPTER_DEFAULT, m, &mode);
  2815.  
  2816.             // should never happen
  2817.             if (FAILED (hr)) continue;
  2818.  
  2819.             // d3d8 doesn't specify a format when enumerating so we need to restrict this to the correct format
  2820.             if (mode.Format != d3d_Formats[i]);
  2821.  
  2822.             // ensure that we can get a depth buffer
  2823.             if (D3D_GetDepthFormat (d3d_Formats[i]) == D3DFMT_UNKNOWN) continue;
  2824.  
  2825.             // ensure that the texture formats we want to create exist
  2826.             if (!D3D_CheckTextureFormat (D3DFMT_L8, d3d_Formats[i])) continue;
  2827.             if (!D3D_CheckTextureFormat (D3DFMT_X8R8G8B8, d3d_Formats[i])) continue;
  2828.             if (!D3D_CheckTextureFormat (D3DFMT_A8R8G8B8, d3d_Formats[i])) continue;
  2829.  
  2830.             // check it against the requested mode
  2831.             if (mode.Width == width && mode.Height == height)
  2832.             {
  2833.                 // copy it out and return the mode we got
  2834.                 memcpy (&d3d_CurrentMode, &mode, sizeof (D3DDISPLAYMODE));
  2835.                 return mode.Format;
  2836.             }
  2837.         }
  2838.     }
  2839.  
  2840.     // didn't find a format
  2841.     return D3DFMT_UNKNOWN;
  2842. }
  2843.  
  2844.  
  2845. BOOL WINAPI SetPixelFormat (HDC hdc, int format, CONST /*PIXELFORMATDESCRIPTOR*/int * ppfd)
  2846. {
  2847.    /*
  2848.     if (ppfd->cStencilBits)
  2849.         d3d_RequestStencil = TRUE;
  2850.     else*/
  2851.         d3d_RequestStencil = FALSE;
  2852.  
  2853.     // just silently pass the PFD through unmodified
  2854.     return TRUE;
  2855. }
  2856.  
  2857.  
  2858. void D3D_SetupPresentParams (int width, int height, int bpp, BOOL windowed)
  2859. {
  2860.     DWORD videoFlags = XGetVideoFlags();
  2861.  
  2862.     D3DFORMAT fmt;
  2863.     // clear present params to NULL
  2864.     memset (&d3d_PresentParams, 0, sizeof (D3DPRESENT_PARAMETERS));
  2865.  
  2866. #ifndef _XBOX
  2867.     // popup windows are fullscreen always
  2868.     if (windowed)
  2869.     {
  2870.         // defaults for windowed mode - also need to store out clientrect.right and clientrect.bottom
  2871.         // (d3d_BPP is only used for fullscreen modes and is retrieved from our CDS override)
  2872.         d3d_CurrentMode.Format = d3d_DesktopMode.Format;
  2873.         d3d_CurrentMode.Width = width;
  2874.         d3d_CurrentMode.Height = height;
  2875.         d3d_CurrentMode.RefreshRate = 0;
  2876.     }
  2877.     else
  2878. #endif
  2879.     {
  2880.         // also fills in d3d_CurrentMode
  2881.         fmt = d3d_CurrentMode.Format = D3DFMT_A8R8G8B8;//D3D_GetAdapterModeFormat (width, height, d3d_BPP);
  2882.  
  2883.         // ensure that we got a good format
  2884.         if (fmt == D3DFMT_UNKNOWN)
  2885.             SysMessage ("failed to get fullscreen mode");
  2886.     }
  2887.  
  2888.     // fill in mode-dependent stuff
  2889.     d3d_PresentParams.BackBufferFormat = fmt;//d3d_CurrentMode.Format;
  2890.     d3d_PresentParams.FullScreen_RefreshRateInHz = d3d_CurrentMode.RefreshRate = 60;//d3d_CurrentMode.RefreshRate;
  2891.     d3d_PresentParams.Windowed = windowed;
  2892.  
  2893.     // request 1 backbuffer
  2894.     d3d_PresentParams.BackBufferCount = 1;
  2895.     d3d_PresentParams.BackBufferWidth = d3d_CurrentMode.Width = width;
  2896.     d3d_PresentParams.BackBufferHeight = d3d_CurrentMode.Height = height;
  2897.  
  2898.     d3d_PresentParams.EnableAutoDepthStencil = TRUE;
  2899.     d3d_PresentParams.AutoDepthStencilFormat = D3DFMT_D16;//D3D_GetDepthFormat (d3d_CurrentMode.Format);
  2900.     d3d_PresentParams.MultiSampleType = D3DMULTISAMPLE_4_SAMPLES_MULTISAMPLE_LINEAR;//D3DMULTISAMPLE_NONE;
  2901.     d3d_PresentParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
  2902.     //d3d_PresentParams.hDeviceWindow = d3d_Window;
  2903.  
  2904.     // Now check if player is a PAL 60 user
  2905.     if(XGetVideoStandard() == XC_VIDEO_STANDARD_PAL_I)
  2906.     {
  2907.         if(videoFlags & XC_VIDEO_FLAGS_PAL_60Hz) // PAL 60 user
  2908.             d3d_PresentParams.FullScreen_RefreshRateInHz = 60;
  2909.         else
  2910.             d3d_PresentParams.FullScreen_RefreshRateInHz = 50;
  2911.     }
  2912.    
  2913.     // Use progressive mode if possible
  2914.     if(g_bHDEnabled)
  2915.     {
  2916.         if(videoFlags & XC_VIDEO_FLAGS_HDTV_1080i && width == 1920 && height == 1080)
  2917.         {
  2918.             // Out of memory very likely!
  2919.             d3d_PresentParams.Flags = D3DPRESENTFLAG_INTERLACED | D3DPRESENTFLAG_WIDESCREEN;
  2920.         }
  2921.         else if(videoFlags & XC_VIDEO_FLAGS_HDTV_720p && width == 1280 && height == 720)
  2922.         {
  2923.             d3d_PresentParams.Flags = D3DPRESENTFLAG_PROGRESSIVE | D3DPRESENTFLAG_WIDESCREEN;
  2924.         }
  2925.         else if(videoFlags & XC_VIDEO_FLAGS_HDTV_480p && width == 640 && height == 480)
  2926.         {
  2927.             d3d_PresentParams.Flags = D3DPRESENTFLAG_PROGRESSIVE;
  2928.         }
  2929.         else if(videoFlags & XC_VIDEO_FLAGS_HDTV_480p)
  2930.         {
  2931.             // Force valid resolution and at least try progressive mode
  2932.             width = 640;
  2933.             height = 480;
  2934.             d3d_PresentParams.Flags = D3DPRESENTFLAG_PROGRESSIVE;
  2935.         }
  2936.     }
  2937.     else // No component cables detected
  2938.     {
  2939.         if(videoFlags & XC_VIDEO_FLAGS_HDTV_480p)
  2940.             d3d_PresentParams.Flags = D3DPRESENTFLAG_PROGRESSIVE;
  2941.         else
  2942.             d3d_PresentParams.Flags = D3DPRESENTFLAG_INTERLACED;
  2943.  
  2944.         d3d_PresentParams.BackBufferWidth = width = 640;
  2945.         d3d_PresentParams.BackBufferHeight = height = 480;
  2946.     }
  2947. }
  2948.  
  2949.  
  2950. BOOL WINAPI wglMakeCurrent (HDC hdc, HGLRC hglrc)
  2951. {
  2952. #ifndef _XBOX
  2953.     RECT clientrect;
  2954.     LONG winstyle;
  2955.  
  2956.     // if we're making NULL current we just return TRUE
  2957.  
  2958.     if (!hdc || !hglrc)
  2959.     {
  2960.         // delete the device, the object and all other objects
  2961.         // this is required because engines may decide to destroy the window which is not good for D3D
  2962.         wglDeleteContext (hglrc);
  2963.         return TRUE;
  2964.     }
  2965. #endif  
  2966.  
  2967.     // if there is no D3D Object we must return FALSE
  2968.     // d3d_Object is created in wglCreateContext so this behaviour will enforce wglCreateContext to be called before wglMakeCurrent
  2969.     // note that this will break in sitauions where there is more than one active context and we're switching between them...
  2970.     if (!d3d_Object) return FALSE;
  2971.  
  2972.     // if a device was previously set up, force a subsequent request to MakeCurrent to fail
  2973.     if (d3d_Device) return FALSE;
  2974.  
  2975. #ifndef _XBOX
  2976.     // we can't extern mainwindow as it may be called something else depending on the codebase used
  2977.     if (!(d3d_Window = WindowFromDC (hdc))) SysMessage ("wglCreateContext: could not determine application window");
  2978.  
  2979.     // get the dimensions of the window
  2980.     GetClientRect (d3d_Window, &clientrect);
  2981.  
  2982.     // see are we fullscreen
  2983.     winstyle = GetWindowLong (d3d_Window, GWL_STYLE);
  2984.  
  2985.     // get the format for the desktop mode
  2986.     if (FAILED (hr = IDirect3D8_GetAdapterDisplayMode (d3d_Object, D3DADAPTER_DEFAULT, &d3d_DesktopMode)))
  2987.         SysMessage ("Failed to get desktop mode");
  2988. #endif
  2989.  
  2990.     if (FAILED (hr = IDirect3D8_GetDeviceCaps (d3d_Object, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3d_Caps)))
  2991.         SysMessage ("failed to get object caps");
  2992.  
  2993.     // setup our present parameters (popup windows are fullscreen always)
  2994.     //D3D_SetupPresentParams (clientrect.right, clientrect.bottom, d3d_BPP, !(winstyle & WS_POPUP));
  2995.     D3D_SetupPresentParams(g_iWidth, g_iHeight, 32, FALSE);
  2996.  
  2997.     // here we use D3DCREATE_FPU_PRESERVE to maintain the resolution of Quake's timers (this is a serious problem)
  2998.     // and D3DCREATE_DISABLE_DRIVER_MANAGEMENT to protect us from rogue drivers (call it honest paranoia).  first
  2999.     // we attempt to create a hardware vp device.
  3000.     // --------------------------------------------------------------------------------------------------------
  3001.     // NOTE re pure devices: we intentionally DON'T request a pure device, EVEN if one is available, as we need
  3002.     // to support certain glGet functions that would be broken if we used one.
  3003.     // --------------------------------------------------------------------------------------------------------
  3004.     // NOTE re D3DCREATE_FPU_PRESERVE - this can be avoided if we use a timer that's not subject to FPU drift,
  3005.     // such as timeGetTime (with timeBeginTime (1)); by default Quake's times *ARE* prone to FPU drift as they
  3006.     // use doubles for storing the last time, which gradually creeps up to be nearer to the current time each
  3007.     // frame.  Not using doubles for the stored times (i.e. switching them all to floats) would also help here.
  3008.     hr = IDirect3D8_CreateDevice
  3009.     (
  3010.         d3d_Object,
  3011.         D3DADAPTER_DEFAULT,
  3012.         D3DDEVTYPE_HAL,
  3013.         NULL,//d3d_Window,
  3014.         D3DCREATE_HARDWARE_VERTEXPROCESSING /*| D3DCREATE_FPU_PRESERVE | D3DCREATE_DISABLE_DRIVER_MANAGEMENT*/,
  3015.         &d3d_PresentParams,
  3016.         &d3d_Device
  3017.     );
  3018.  
  3019.     if (FAILED (hr))
  3020.     {
  3021.         // it's OK, we may not have hardware vp available, so create a software vp device
  3022.         hr = IDirect3D8_CreateDevice
  3023.         (
  3024.             d3d_Object,
  3025.             D3DADAPTER_DEFAULT,
  3026.             D3DDEVTYPE_HAL,
  3027.             NULL,//d3d_Window,
  3028.             D3DCREATE_SOFTWARE_VERTEXPROCESSING /*| D3DCREATE_FPU_PRESERVE | D3DCREATE_DISABLE_DRIVER_MANAGEMENT*/,
  3029.             &d3d_PresentParams,
  3030.             &d3d_Device
  3031.         );
  3032.  
  3033.         // oh shit
  3034.         if (hr == D3DERR_INVALIDCALL)
  3035.             SysMessage ("IDirect3D8_CreateDevice with D3DERR_INVALIDCALL");
  3036.         else if (hr == D3DERR_NOTAVAILABLE)
  3037.             SysMessage ("IDirect3D8_CreateDevice with D3DERR_NOTAVAILABLE");
  3038.         else if (hr == D3DERR_OUTOFVIDEOMEMORY)
  3039.             SysMessage ("IDirect3D8_CreateDevice with D3DERR_INVALIDCALL");
  3040.         else if (FAILED (hr)) SysMessage ("failed to create Direct3D device");
  3041.     }
  3042.  
  3043.     if (d3d_Device == NULL) SysMessage ("created NULL Direct3D device");
  3044.  
  3045.     SetGUID3DDevice(d3d_Device, d3d_PresentParams);
  3046.  
  3047.     g_bScissorTest = FALSE;
  3048.  
  3049.     HMRemoveAllTextures();
  3050.  
  3051.     // initialize state
  3052.     D3D_InitStates ();
  3053.  
  3054.     // disable lighting
  3055.     D3D_SetRenderState (D3DRS_LIGHTING, FALSE);
  3056.  
  3057.     // default zbias
  3058.     // D3D uses values of 0 to 16, with 0 being the default and higher values coming nearer
  3059.     // because we want to push out further too, we pick an intermediate value as our new default
  3060.     D3D_SetRenderState (D3DRS_ZBIAS, 0);
  3061.  
  3062.     // fd perf test
  3063.     _controlfp(_PC_24,_MCW_PC);
  3064.     D3D_SetRenderState(D3DRS_SWATHWIDTH, D3DSWATH_8);
  3065.  
  3066.     // Apply visual improvements
  3067.     IDirect3DDevice8_SetFlickerFilter(d3d_Device, 1);
  3068.     IDirect3DDevice8_SetSoftDisplayFilter(d3d_Device, TRUE);
  3069.  
  3070.     // set projection and world to dirty, beginning of stack and identity
  3071.     D3D_InitializeMatrix (&d3d_ModelViewMatrix);
  3072.     D3D_InitializeMatrix (&d3d_ProjectionMatrix);
  3073.  
  3074.     // clear the device to black on creation
  3075.     IDirect3DDevice8_Clear(d3d_Device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 1, 1);
  3076.  
  3077.     return TRUE;
  3078. }
  3079.  
  3080.  
  3081. HGLRC WINAPI wglCreateContext (HDC hdc)
  3082. {
  3083.     // initialize direct3d and get object capabilities
  3084.     if (!(d3d_Object = Direct3DCreate8 (D3D_SDK_VERSION)))
  3085.     {
  3086.         SysMessage ("Failed to create Direct3D Object");
  3087.         return (HGLRC)0;
  3088.     }
  3089.  
  3090.     HMSetupHashTable();
  3091.  
  3092.     return (HGLRC)1;
  3093. }
  3094.  
  3095.  
  3096. BOOL WINAPI wglDeleteContext (HGLRC hglrc)
  3097. {
  3098.     // Release all textures
  3099.     HMRemoveAllTextures();
  3100.  
  3101.     HMDeleteHashTable();
  3102.  
  3103.     // Release device and object
  3104.     if(d3d_Device)
  3105.         IDirect3DDevice8_Release(d3d_Device);
  3106.  
  3107.     if(d3d_Object)
  3108.         IDirect3D8_Release(d3d_Object);
  3109.  
  3110.     // Success
  3111.     return TRUE;
  3112. }
  3113.  
  3114.  
  3115. HGLRC WINAPI wglGetCurrentContext (VOID)
  3116. {
  3117.     return (HGLRC)1;
  3118. }
  3119.  
  3120.  
  3121. HDC WINAPI wglGetCurrentDC (VOID)
  3122. {
  3123.     return 0;
  3124. }
  3125.  
  3126.  
  3127. /*
  3128. ===================================================================================================================
  3129.  
  3130.             COMPARISON TEST AND FUNCTION
  3131.  
  3132.     Just DepthFunc and AlphaFunc really
  3133.  
  3134. ===================================================================================================================
  3135. */
  3136.  
  3137. void GL_SetCompFunc (DWORD mode, GLenum func)
  3138. {
  3139.     switch (func)
  3140.     {
  3141.     case GL_NEVER:
  3142.         D3D_SetRenderState ((D3DRENDERSTATETYPE)mode, D3DCMP_NEVER);
  3143.         break;
  3144.  
  3145.     case GL_LESS:
  3146.         D3D_SetRenderState ((D3DRENDERSTATETYPE)mode, D3DCMP_LESS);
  3147.         break;
  3148.  
  3149.     case GL_LEQUAL:
  3150.         D3D_SetRenderState ((D3DRENDERSTATETYPE)mode, D3DCMP_LESSEQUAL);
  3151.         break;
  3152.  
  3153.     case GL_EQUAL:
  3154.         D3D_SetRenderState ((D3DRENDERSTATETYPE)mode, D3DCMP_EQUAL);
  3155.         break;
  3156.  
  3157.     case GL_GREATER:
  3158.         D3D_SetRenderState ((D3DRENDERSTATETYPE)mode, D3DCMP_GREATER);
  3159.         break;
  3160.  
  3161.     case GL_NOTEQUAL:
  3162.         D3D_SetRenderState ((D3DRENDERSTATETYPE)mode, D3DCMP_NOTEQUAL);
  3163.         break;
  3164.  
  3165.     case GL_GEQUAL:
  3166.         D3D_SetRenderState ((D3DRENDERSTATETYPE)mode, D3DCMP_GREATEREQUAL);
  3167.         break;
  3168.  
  3169.     case GL_ALWAYS:
  3170.     default:
  3171.         D3D_SetRenderState ((D3DRENDERSTATETYPE)mode, D3DCMP_ALWAYS);
  3172.         break;
  3173.     }
  3174. }
  3175.  
  3176.  
  3177. void glDepthFunc (GLenum func)
  3178. {
  3179.     GL_SetCompFunc (D3DRS_ZFUNC, func);
  3180. }
  3181.  
  3182.  
  3183. void glAlphaFunc (GLenum func, GLclampf ref)
  3184. {
  3185.     GL_SetCompFunc (D3DRS_ALPHAFUNC, func);
  3186.     D3D_SetRenderState (D3DRS_ALPHAREF, BYTE_CLAMP ((int) (ref * 255)));
  3187. }
  3188.  
  3189.  
  3190. /*
  3191. ===================================================================================================================
  3192.  
  3193.             FRAMEBUFFER
  3194.  
  3195. ===================================================================================================================
  3196. */
  3197.  
  3198.  
  3199. void glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
  3200. {
  3201.     DWORD mask = 0;
  3202.  
  3203.     if (red) mask |= D3DCOLORWRITEENABLE_RED;
  3204.     if (green) mask |= D3DCOLORWRITEENABLE_GREEN;
  3205.     if (blue) mask |= D3DCOLORWRITEENABLE_BLUE;
  3206.     if (alpha) mask |= D3DCOLORWRITEENABLE_ALPHA;
  3207.  
  3208.     D3D_SetRenderState (D3DRS_COLORWRITEENABLE, mask);
  3209. }
  3210.  
  3211.  
  3212. void glDepthRange (GLclampd zNear, GLclampd zFar)
  3213. {
  3214.     // update the viewport
  3215.     d3d_Viewport.MinZ = zNear;
  3216.     d3d_Viewport.MaxZ = zFar;
  3217.  
  3218.     IDirect3DDevice8_SetViewport (d3d_Device, &d3d_Viewport);
  3219.     D3D_DirtyAllStates ();
  3220. }
  3221.  
  3222.  
  3223. void glDepthMask (GLboolean flag)
  3224. {
  3225.     // if only they were all so easy...
  3226.     D3D_SetRenderState (D3DRS_ZWRITEENABLE, flag == GL_TRUE ? TRUE : FALSE);
  3227. }
  3228.  
  3229.  
  3230. void GL_Blend (D3DRENDERSTATETYPE rs, GLenum factor)
  3231. {
  3232.     D3DBLEND blend = D3DBLEND_ONE;
  3233.  
  3234.     switch (factor)
  3235.     {
  3236.     case GL_ZERO:
  3237.         blend = D3DBLEND_ZERO;
  3238.         break;
  3239.  
  3240.     case GL_ONE:
  3241.         blend = D3DBLEND_ONE;
  3242.         break;
  3243.  
  3244.     case GL_SRC_COLOR:
  3245.         blend = D3DBLEND_SRCCOLOR;
  3246.         break;
  3247.  
  3248.     case GL_ONE_MINUS_SRC_COLOR:
  3249.         blend = D3DBLEND_INVSRCCOLOR;
  3250.         break;
  3251.  
  3252.     case GL_DST_COLOR:
  3253.         blend = D3DBLEND_DESTCOLOR;
  3254.         break;
  3255.  
  3256.     case GL_ONE_MINUS_DST_COLOR:
  3257.         blend = D3DBLEND_INVDESTCOLOR;
  3258.         break;
  3259.  
  3260.     case GL_SRC_ALPHA:
  3261.         blend = D3DBLEND_SRCALPHA;
  3262.         break;
  3263.  
  3264.     case GL_ONE_MINUS_SRC_ALPHA:
  3265.         blend = D3DBLEND_INVSRCALPHA;
  3266.         break;
  3267.  
  3268.     case GL_DST_ALPHA:
  3269.         blend = D3DBLEND_DESTALPHA;
  3270.         break;
  3271.  
  3272.     case GL_ONE_MINUS_DST_ALPHA:
  3273.         blend = D3DBLEND_INVDESTALPHA;
  3274.         break;
  3275.  
  3276.     case GL_SRC_ALPHA_SATURATE:
  3277.         blend = D3DBLEND_SRCALPHASAT;
  3278.         break;
  3279.  
  3280.     default:
  3281.         SysMessage ("glBlendFunc: unknown factor");
  3282.     }
  3283.  
  3284.     D3D_SetRenderState (rs, blend);
  3285. }
  3286.  
  3287.  
  3288. void glBlendFunc (GLenum sfactor, GLenum dfactor)
  3289. {
  3290.     GL_Blend (D3DRS_SRCBLEND, sfactor);
  3291.     GL_Blend (D3DRS_DESTBLEND, dfactor);
  3292. }
  3293.  
  3294.  
  3295. void glClear (GLbitfield mask)
  3296. {
  3297.     DWORD clearflags = 0;
  3298.  
  3299.     // no accumulation buffer in d3d
  3300.     if (mask & GL_COLOR_BUFFER_BIT) clearflags |= D3DCLEAR_TARGET;
  3301.     if (mask & GL_DEPTH_BUFFER_BIT) clearflags |= D3DCLEAR_ZBUFFER;
  3302.     if (mask & GL_STENCIL_BUFFER_BIT) clearflags |= D3DCLEAR_STENCIL;
  3303.  
  3304.     // back to normal operation
  3305.     IDirect3DDevice8_Clear (d3d_Device, 0, NULL, clearflags, d3d_ClearColor, 1, 1);
  3306. }
  3307.  
  3308.  
  3309. void glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
  3310. {
  3311.     d3d_ClearColor = GL_ColorToD3D (red, green, blue, alpha);
  3312. }
  3313.  
  3314.  
  3315. void glFinish (void)
  3316. {
  3317.     // we force a Present in our SwapBuffers function so this is unneeded
  3318. }
  3319.  
  3320.  
  3321. void glReadBuffer (GLenum mode)
  3322. {
  3323.     // d3d doesn't like us messing with the front buffer, which is all glquake uses this for, so here
  3324.     // we just silently ignore requests to change the draw buffer
  3325. }
  3326.  
  3327.  
  3328. void glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
  3329. {
  3330.     int row;
  3331.     int col;
  3332.     unsigned char *srcdata;
  3333.     unsigned char *dstdata = (unsigned char *) pixels;
  3334.     LPDIRECT3DSURFACE8 bbsurf;
  3335.     LPDIRECT3DSURFACE8 locksurf;
  3336.     D3DLOCKED_RECT lockrect;
  3337.     D3DSURFACE_DESC desc;
  3338.  
  3339.     if (format != GL_RGB || type != GL_UNSIGNED_BYTE)
  3340.     {
  3341.         SysMessage ("glReadPixels: invalid format or type\n");
  3342.         return;
  3343.     }
  3344.  
  3345.     hr = IDirect3DDevice8_GetBackBuffer (d3d_Device, 0, D3DBACKBUFFER_TYPE_MONO, &bbsurf);
  3346.  
  3347.     if (FAILED (hr) || !bbsurf)
  3348.     {
  3349.         SysMessage ("glReadPixels: failed to access back buffer\n");
  3350.         return;
  3351.     }
  3352.  
  3353.     // because we don't have a lockable backbuffer we instead copy it off to an image surface
  3354.     // this will also handle translation between different backbuffer formats
  3355.     hr = IDirect3DSurface8_GetDesc (bbsurf, &desc);
  3356.     hr = IDirect3DDevice8_CreateImageSurface (d3d_Device, desc.Width, desc.Height, /*D3DFMT_R8G8B8*/D3DFMT_LIN_X8R8G8B8, &locksurf); //CHECKME: Linear/Compressed format ?
  3357.     hr = D3DXLoadSurfaceFromSurface (locksurf, NULL, NULL, bbsurf, NULL, NULL, D3DX_FILTER_NONE, 0);
  3358.  
  3359.     // now we have a surface we can lock
  3360.     hr = IDirect3DSurface8_LockRect (locksurf, &lockrect, NULL, D3DLOCK_READONLY);
  3361.     srcdata = (unsigned char *) lockrect.pBits;
  3362.  
  3363.     for (row = y; row < (y + height); row++)
  3364.     {
  3365.         for (col = x; col < (x + width); col++)
  3366.         {
  3367.             int srcpos = row * width + col;
  3368.  
  3369.             dstdata[0] = srcdata[srcpos * 4 + 0];
  3370.             dstdata[1] = srcdata[srcpos * 4 + 1];
  3371.             dstdata[2] = srcdata[srcpos * 4 + 2];
  3372.  
  3373.             dstdata += 3;
  3374.         }
  3375.     }
  3376.  
  3377.     hr = IDirect3DSurface8_UnlockRect (locksurf);
  3378. //  D3D_SAFE_RELEASE (locksurf);
  3379.     IDirect3DSurface8_Release(locksurf);
  3380. //  D3D_SAFE_RELEASE (bbsurf);
  3381.     IDirect3DSurface8_Release(bbsurf);
  3382. }
  3383.  
  3384.  
  3385. void glViewport (GLint x, GLint y, GLsizei width, GLsizei height)
  3386. {
  3387.     // translate from OpenGL bottom-left to D3D top-left
  3388.     y = d3d_CurrentMode.Height - (height + y);
  3389.  
  3390.     // always take the full depth range
  3391.     d3d_Viewport.X = x;
  3392.     d3d_Viewport.Y = y;
  3393.     d3d_Viewport.Width = width;
  3394.     d3d_Viewport.Height = height;
  3395.     d3d_Viewport.MinZ = 0;
  3396.     d3d_Viewport.MaxZ = 1;
  3397.  
  3398.     IDirect3DDevice8_SetViewport (d3d_Device, &d3d_Viewport);
  3399.  
  3400.     // dirty all states
  3401.     D3D_DirtyAllStates ();
  3402. }
  3403.  
  3404.  
  3405. void D3D_PostResetRestore (void)
  3406. {
  3407.     // set projection and world to dirty, beginning of stack and identity
  3408.     D3D_InitializeMatrix (&d3d_ModelViewMatrix);
  3409.     D3D_InitializeMatrix (&d3d_ProjectionMatrix);
  3410.  
  3411.     // force all states back to the way they were
  3412.     D3D_SetRenderStates ();
  3413.     D3D_SetTextureStates ();
  3414.  
  3415.     // set viewport to invalid
  3416.     d3d_Viewport.Width = -1;
  3417.     d3d_Viewport.Height = -1;
  3418. }
  3419.  
  3420. void D3D_SetMode(int iWidth, int iHeight, BOOL bHDEnabled)
  3421. {
  3422.     g_iWidth = iWidth;
  3423.     g_iHeight = iHeight;
  3424.     g_bHDEnabled = bHDEnabled;
  3425. }
  3426.  
  3427. void D3D_ResetMode (int width, int height, int bpp, BOOL windowed)
  3428. {
  3429. #ifndef _XBOX  
  3430.     RECT winrect;
  3431.     int winstyle;
  3432.     int winexstyle;
  3433.  
  3434.     while (1)
  3435.     {
  3436.         // here we get the current status of the device
  3437.         hr = IDirect3DDevice8_TestCooperativeLevel (d3d_Device);
  3438.  
  3439.         if (hr == D3D_OK) break;
  3440.  
  3441.         Sleep (10);
  3442.     }
  3443.  
  3444.     // reset present params
  3445.     D3D_SetupPresentParams (width, height, bpp, windowed);
  3446.  
  3447.     // reset device
  3448.     IDirect3DDevice8_Reset (d3d_Device, &d3d_PresentParams);
  3449.  
  3450.     while (1)
  3451.     {
  3452.         // here we get the current status of the device
  3453.         hr = IDirect3DDevice8_TestCooperativeLevel (d3d_Device);
  3454.  
  3455.         if (hr == D3D_OK) break;
  3456.  
  3457.         Sleep (10);
  3458.     }
  3459.  
  3460.     winrect.left = 0;
  3461.     winrect.right = width;
  3462.     winrect.top = 0;
  3463.     winrect.bottom = height;
  3464.  
  3465.     winexstyle = 0;
  3466.     winstyle = windowed ? WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX : WS_POPUP;
  3467.  
  3468.     // reset stuff
  3469.     SetWindowLong (d3d_PresentParams.hDeviceWindow, GWL_EXSTYLE, winexstyle);
  3470.     SetWindowLong (d3d_PresentParams.hDeviceWindow, GWL_STYLE, winstyle);
  3471.     AdjustWindowRectEx (&winrect, winstyle, FALSE, 0);
  3472.  
  3473.     // repaint all windows
  3474.     InvalidateRect (NULL, NULL, TRUE);
  3475.  
  3476.     // resize the window; also reposition it as we don't know if it's going to go down below the taskbar area
  3477.     // or not, so we just err on the side of caution here.
  3478.     SetWindowPos
  3479.     (
  3480.         d3d_PresentParams.hDeviceWindow,
  3481.         NULL,
  3482.         windowed ? (d3d_DesktopMode.Width - (winrect.right - winrect.left)) / 2 : 0,
  3483.         windowed ? (d3d_DesktopMode.Height - (winrect.bottom - winrect.top)) / 2 : 0,
  3484.         winrect.right - winrect.left,
  3485.         winrect.bottom - winrect.top,
  3486.         SWP_NOOWNERZORDER | SWP_NOREPOSITION | SWP_NOZORDER | SWP_SHOWWINDOW
  3487.     );
  3488.  
  3489.     // ensure
  3490.     SetForegroundWindow (d3d_PresentParams.hDeviceWindow);
  3491.  
  3492.     // clean up states/etc
  3493.     D3D_PostResetRestore ();
  3494.  
  3495.     // because a lot of things are now bouncing around the system we take a breather
  3496.     Sleep (500);
  3497.  
  3498.     // give some user feedback here
  3499.     SysMessage ("Set %s mode %ix%ix%i\n", windowed ? "windowed" : "fullscreen", width, height, bpp);
  3500. #endif  
  3501. }
  3502.  
  3503.  
  3504. int FakeSwapBuffers (void)
  3505. {
  3506. #ifndef _XBOX // We don't need this on XBox
  3507.     // if we lost the device (e.g. on a mode switch, alt-tab, etc) we must try to recover it
  3508.     if (d3d_DeviceLost)
  3509.     {
  3510.         // here we get the current status of the device
  3511.         hr = IDirect3DDevice8_TestCooperativeLevel (d3d_Device);
  3512.  
  3513.         switch (hr)
  3514.         {
  3515.         case D3D_OK:
  3516.             // device is recovered
  3517.             d3d_DeviceLost = FALSE;
  3518.             D3D_PostResetRestore ();
  3519.             break;
  3520.  
  3521.         case D3DERR_DEVICELOST:
  3522.             // device is still lost
  3523.             break;
  3524.  
  3525.         case D3DERR_DEVICENOTRESET:
  3526.             // device is ready to be reset
  3527.             IDirect3DDevice8_Reset (d3d_Device, &d3d_PresentParams);
  3528.             break;
  3529.  
  3530.         default:
  3531.             break;
  3532.         }
  3533.  
  3534.         // yield the CPU a little
  3535.         Sleep (10);
  3536.  
  3537.         // don't bother this frame
  3538.         return;
  3539.     }
  3540. #endif
  3541.     if (d3d_SceneBegun)
  3542.     {
  3543. #if 0 // Disabled atm to try save as much CPU time as possible
  3544.         // see do we need to reset the viewport as D3D restricts present to the client viewport
  3545.         // this is needed as some engines (hello FitzQuake) set multiple smaller viewports for
  3546.         // different on-screen elements (e.g. menus)
  3547.         BOOL vpreset = FALSE;
  3548.  
  3549.         // test dimensions for a change; we don't just blindly reset it as this may not happen every frame
  3550.         if (d3d_Viewport.X != 0) vpreset = TRUE;
  3551.         if (d3d_Viewport.Y != 0) vpreset = TRUE;
  3552.         if (d3d_Viewport.Width != d3d_CurrentMode.Width) vpreset = TRUE;
  3553.         if (d3d_Viewport.Height != d3d_CurrentMode.Height) vpreset = TRUE;
  3554.  
  3555.         if (vpreset)
  3556.         {
  3557.             // now reset it to full window dimensions so that the full window will present
  3558.             d3d_Viewport.X = 0;
  3559.             d3d_Viewport.Y = 0;
  3560.             d3d_Viewport.Width = d3d_CurrentMode.Width;
  3561.             d3d_Viewport.Height = d3d_CurrentMode.Height;
  3562.             IDirect3DDevice8_SetViewport (d3d_Device, &d3d_Viewport);
  3563.         }
  3564. #endif
  3565.         // endscene and present are only required if a scene was begun (i.e. if something was actually drawn)
  3566. #ifndef _XBOX // Not used on Xbox
  3567.         IDirect3DDevice8_EndScene (d3d_Device);
  3568. #endif
  3569.         d3d_SceneBegun = FALSE;
  3570.  
  3571.         // present the display
  3572.         /*hr = */IDirect3DDevice8_Present (d3d_Device, NULL, NULL, NULL, NULL);
  3573.  
  3574. #ifndef _XBOX
  3575.         if (hr == D3DERR_DEVICELOST)
  3576.         {
  3577.             // flag a lost device
  3578.             d3d_DeviceLost = TRUE;
  3579.         }
  3580.         else if (FAILED (hr))
  3581.         {
  3582.             // something else bad happened
  3583.             SysMessage ("FAILED (hr) on IDirect3DDevice8_Present");
  3584.             return FALSE;
  3585.         }
  3586. #endif
  3587.         return TRUE;
  3588.     }
  3589.     return FALSE;
  3590. }
  3591.  
  3592.  
  3593. /*
  3594. ===================================================================================================================
  3595.  
  3596.             OTHER
  3597.  
  3598. ===================================================================================================================
  3599. */
  3600.  
  3601. void GL_UpdateCull (void)
  3602. {
  3603.     if (gl_CullEnable == GL_FALSE)
  3604.     {
  3605.         // disable culling
  3606.         D3D_SetRenderState (D3DRS_CULLMODE, D3DCULL_NONE);
  3607.         return;
  3608.     }
  3609.  
  3610.     if (gl_FrontFace == GL_CCW)
  3611.     {
  3612.         if (gl_CullMode == GL_BACK)
  3613.             D3D_SetRenderState (D3DRS_CULLMODE, D3DCULL_CW);
  3614.         else if (gl_CullMode == GL_FRONT)
  3615.             D3D_SetRenderState (D3DRS_CULLMODE, D3DCULL_CCW);
  3616.         else if (gl_CullMode == GL_FRONT_AND_BACK)
  3617.             ; // do nothing; we cull in software in GL_SubmitVertexes instead
  3618.         else SysMessage ("GL_UpdateCull: illegal glCullFace");
  3619.     }
  3620.     else if (gl_FrontFace == GL_CW)
  3621.     {
  3622.         if (gl_CullMode == GL_BACK)
  3623.             D3D_SetRenderState (D3DRS_CULLMODE, D3DCULL_CCW);
  3624.         else if (gl_CullMode == GL_FRONT)
  3625.             D3D_SetRenderState (D3DRS_CULLMODE, D3DCULL_CW);
  3626.         else if (gl_CullMode == GL_FRONT_AND_BACK)
  3627.             ; // do nothing; we cull in software in GL_SubmitVertexes instead
  3628.         else SysMessage ("GL_UpdateCull: illegal glCullFace");
  3629.     }
  3630.     else SysMessage ("GL_UpdateCull: illegal glFrontFace");
  3631. }
  3632.  
  3633.  
  3634. void glFrontFace (GLenum mode)
  3635. {
  3636.     gl_FrontFace = mode;
  3637.     GL_UpdateCull ();
  3638. }
  3639.  
  3640.  
  3641. void glCullFace (GLenum mode)
  3642. {
  3643.     gl_CullMode = mode;
  3644.     GL_UpdateCull ();
  3645. }
  3646.  
  3647.  
  3648. void glScissor (GLint x, GLint y, GLsizei width, GLsizei height)
  3649. {
  3650.     // Translate from OpenGL bottom-left to D3D top-left
  3651.     y = d3d_CurrentMode.Height - (height + y);
  3652.    
  3653.     g_ScissorRect.x1 = x;
  3654.     g_ScissorRect.y1 = y;
  3655.  
  3656.     g_ScissorRect.x2 = x + width;
  3657.     g_ScissorRect.y2 = y + height;
  3658. }
  3659.  
  3660.  
  3661. void GL_EnableDisable (GLenum cap, BOOL enabled)
  3662. {
  3663.     DWORD d3d_RS;
  3664.  
  3665.     switch (cap)
  3666.     {
  3667.     case GL_SCISSOR_TEST:
  3668.         g_bScissorTest = enabled;
  3669.         return;
  3670.  
  3671.     case GL_BLEND:
  3672.         d3d_RS = D3DRS_ALPHABLENDENABLE;
  3673.         break;
  3674.  
  3675.     case GL_ALPHA_TEST:
  3676.         d3d_RS = D3DRS_ALPHATESTENABLE;
  3677.         break;
  3678.  
  3679.     case GL_TEXTURE_2D:
  3680.         // this is a texture stage state rather than a render state
  3681.         if (enabled)
  3682.             d3d_TMUs[d3d_CurrentTMU].enabled = TRUE;
  3683.         else d3d_TMUs[d3d_CurrentTMU].enabled = FALSE;
  3684.  
  3685.         d3d_TMUs[d3d_CurrentTMU].texenvdirty = TRUE;
  3686.         d3d_TMUs[d3d_CurrentTMU].texparamdirty = TRUE;
  3687.  
  3688.         // we're not setting state yet here...
  3689.         return;
  3690.  
  3691.     case GL_CULL_FACE:
  3692.         gl_CullEnable = enabled ? GL_TRUE : GL_FALSE;
  3693.         GL_UpdateCull ();
  3694.  
  3695.         // we're not setting state yet here...
  3696.         return;
  3697.  
  3698.     case GL_FOG:
  3699.         d3d_RS = D3DRS_FOGENABLE;
  3700.         break;
  3701.  
  3702.     case GL_DEPTH_TEST:
  3703.         d3d_RS = D3DRS_ZENABLE;
  3704.         if (enabled) enabled = D3DZB_TRUE; else enabled = D3DZB_FALSE;
  3705.         break;
  3706.  
  3707.     case GL_POLYGON_OFFSET_FILL:
  3708.     case GL_POLYGON_OFFSET_LINE:
  3709.         d3d_PolyOffsetEnabled = enabled;
  3710.         d3d_PolyOffsetSwitched = FALSE;
  3711.  
  3712.         // we're not setting state yet here...
  3713.         return;
  3714.  
  3715.     default:
  3716.         return;
  3717.     }
  3718.  
  3719.     D3D_SetRenderState ((D3DRENDERSTATETYPE)d3d_RS, enabled);
  3720. }
  3721.  
  3722.  
  3723. void glDisable (GLenum cap)
  3724. {
  3725.     GL_EnableDisable (cap, FALSE);
  3726. }
  3727.  
  3728.  
  3729. void glEnable (GLenum cap)
  3730. {
  3731.     GL_EnableDisable (cap, TRUE);
  3732. }
  3733.  
  3734.  
  3735. void glGetFloatv (GLenum pname, GLfloat *params)
  3736. {
  3737.     switch (pname)
  3738.     {
  3739.     case GL_MODELVIEW_MATRIX:
  3740.         memcpy (params, d3d_ModelViewMatrix.stack[d3d_ModelViewMatrix.stackdepth].m, g_fSize16);
  3741.         break;
  3742.  
  3743.     case GLD3D_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
  3744.         params[0] = (float) d3d_Caps.MaxAnisotropy;
  3745.         break;
  3746.  
  3747.     default:
  3748.         break;
  3749.     }
  3750. }
  3751.  
  3752.  
  3753. void glPolygonMode (GLenum face, GLenum mode)
  3754. {
  3755.     // we don't have the ability to specify which side of the poly is filled, so just do it
  3756.     // the way that it's specified and hope for the best!
  3757.     if (mode == GL_LINE)
  3758.         D3D_SetRenderState (D3DRS_FILLMODE, D3DFILL_WIREFRAME);
  3759.     else if (mode == GL_POINT)
  3760.         D3D_SetRenderState (D3DRS_FILLMODE, D3DFILL_POINT);
  3761.     else D3D_SetRenderState (D3DRS_FILLMODE, D3DFILL_SOLID);
  3762. }
  3763.  
  3764.  
  3765. void glShadeModel (GLenum mode)
  3766. {
  3767.     // easy peasy
  3768.     D3D_SetRenderState (D3DRS_SHADEMODE, mode == GL_FLAT ? D3DSHADE_FLAT : D3DSHADE_GOURAUD);
  3769. }
  3770.  
  3771.  
  3772. void glGetIntegerv (GLenum pname, GLint *params)
  3773. {
  3774.     // here we only bother getting the values that glquake uses
  3775.     switch (pname)
  3776.     {
  3777.     case GL_MAX_TEXTURE_SIZE:
  3778.         // D3D allows both to be different so return the lowest
  3779.         params[0] = (d3d_Caps.MaxTextureWidth > d3d_Caps.MaxTextureHeight ? d3d_Caps.MaxTextureHeight : d3d_Caps.MaxTextureWidth);
  3780.         break;
  3781.  
  3782.     case GL_VIEWPORT:
  3783.         params[0] = d3d_Viewport.X;
  3784.         params[1] = d3d_Viewport.Y;
  3785.         params[2] = d3d_Viewport.Width;
  3786.         params[3] = d3d_Viewport.Height;
  3787.         break;
  3788.  
  3789.     case GL_STENCIL_BITS:
  3790.         if (d3d_PresentParams.AutoDepthStencilFormat == D3DFMT_D24S8)
  3791.             params[0] = 8;
  3792. /*      else if (d3d_PresentParams.AutoDepthStencilFormat == D3DFMT_D24X4S4)
  3793.             params[0] = 4;*/
  3794.         else params[0] = 0;
  3795.  
  3796.         break;
  3797.  
  3798.     default:
  3799.         params[0] = 0;
  3800.         return;
  3801.     }
  3802. }
  3803.  
  3804. GLenum glGetError (void) //MARTY - Dummy function
  3805. {
  3806.     return GL_NO_ERROR;
  3807. }
  3808.  
  3809. LONG ChangeDisplaySettings (/*LPDEVMODE*/int lpDevMode, DWORD dwflags)
  3810. {
  3811. #ifndef _XBOX
  3812.     if (dwflags & CDS_TEST)
  3813.     {
  3814.         // if we're testing we want to do it for real
  3815.         return ChangeDisplaySettingsA (lpDevMode, dwflags);
  3816.     }
  3817.     else if (!lpDevMode)
  3818.     {
  3819.         // this signals a return to the desktop display mode
  3820.  
  3821.         // always signal success
  3822.         return DISP_CHANGE_SUCCESSFUL;
  3823.     }
  3824.     else
  3825.     {
  3826.         // this code path is only used for fullscreen modes that are not the same as the desktop mode
  3827.         d3d_BPP = lpDevMode->dmBitsPerPel;
  3828.  
  3829.         // always signal success
  3830.         return DISP_CHANGE_SUCCESSFUL;
  3831.     }
  3832. #endif
  3833.    return 0;
  3834. }
  3835.  
  3836.  
  3837. /*
  3838. ===================================================================================================================
  3839.  
  3840.             FOG
  3841.  
  3842. ===================================================================================================================
  3843. */
  3844.  
  3845. void glFogf (GLenum pname, GLfloat param)
  3846. {
  3847.     switch (pname)
  3848.     {
  3849.     case GL_FOG_MODE:
  3850.         glFogi (pname, param);
  3851.         break;
  3852.  
  3853.     case GL_FOG_DENSITY:
  3854.         D3D_SetRenderState (D3DRS_FOGDENSITY, D3D_FloatToDWORD (param));
  3855.         break;
  3856.  
  3857.     case GL_FOG_START:
  3858.         D3D_SetRenderState (D3DRS_FOGSTART, D3D_FloatToDWORD (param));
  3859.         break;
  3860.  
  3861.     case GL_FOG_END:
  3862.         D3D_SetRenderState (D3DRS_FOGEND, D3D_FloatToDWORD (param));
  3863.         break;
  3864.  
  3865.     case GL_FOG_COLOR:
  3866.         break;
  3867.  
  3868.     default:
  3869.         break;
  3870.     }
  3871. }
  3872.  
  3873.  
  3874. void glFogfv (GLenum pname, const GLfloat *params)
  3875. {
  3876.     switch (pname)
  3877.     {
  3878.     case GL_FOG_COLOR:
  3879.         D3D_SetRenderState (D3DRS_FOGCOLOR, GL_ColorToD3D (params[0], params[1], params[2], params[3]));
  3880.         break;
  3881.  
  3882.     default:
  3883.         glFogf (pname, params[0]);
  3884.         break;
  3885.     }
  3886. }
  3887.  
  3888.  
  3889. void glFogi (GLenum pname, GLint param)
  3890. {
  3891.     switch (pname)
  3892.     {
  3893.     case GL_FOG_MODE:
  3894.         // fixme - make these dependent on a glHint...
  3895.         if (param == GL_LINEAR)
  3896.         {
  3897.             if (d3d_Fog_Hint == GL_NICEST)
  3898.             {
  3899.                 D3D_SetRenderState (D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
  3900. //              D3D_SetRenderState (D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
  3901.             }
  3902.             else
  3903.             {
  3904.                 D3D_SetRenderState (D3DRS_FOGTABLEMODE, D3DFOG_NONE);
  3905. //              D3D_SetRenderState (D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
  3906.             }
  3907.         }
  3908.         else if (param == GL_EXP)
  3909.         {
  3910.             if (d3d_Fog_Hint == GL_NICEST)
  3911.             {
  3912.                 D3D_SetRenderState (D3DRS_FOGTABLEMODE, D3DFOG_EXP);
  3913. //              D3D_SetRenderState (D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
  3914.             }
  3915.             else
  3916.             {
  3917.                 D3D_SetRenderState (D3DRS_FOGTABLEMODE, D3DFOG_NONE);
  3918. //              D3D_SetRenderState (D3DRS_FOGVERTEXMODE, D3DFOG_EXP);
  3919.             }
  3920.         }
  3921.         else
  3922.         {
  3923.             if (d3d_Fog_Hint == GL_NICEST)
  3924.             {
  3925.                 D3D_SetRenderState (D3DRS_FOGTABLEMODE, D3DFOG_EXP2);
  3926. //              D3D_SetRenderState (D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
  3927.             }
  3928.             else
  3929.             {
  3930.                 D3D_SetRenderState (D3DRS_FOGTABLEMODE, D3DFOG_NONE);
  3931. //              D3D_SetRenderState (D3DRS_FOGVERTEXMODE, D3DFOG_EXP2);
  3932.             }
  3933.         }
  3934.         break;
  3935.  
  3936.     default:
  3937.         glFogf (pname, param);
  3938.         break;
  3939.     }
  3940. }
  3941.  
  3942.  
  3943. void glFogiv (GLenum pname, const GLint *params)
  3944. {
  3945.     switch (pname)
  3946.     {
  3947.     case GL_FOG_COLOR:
  3948.         // the spec isn't too clear on how these map to the fp values... oh well...
  3949.         D3D_SetRenderState (D3DRS_FOGCOLOR, D3DCOLOR_ARGB (BYTE_CLAMP (params[3]), BYTE_CLAMP (params[0]), BYTE_CLAMP (params[1]), BYTE_CLAMP (params[2])));
  3950.         break;
  3951.  
  3952.     default:
  3953.         glFogi (pname, params[0]);
  3954.         break;
  3955.     }
  3956. }
  3957.  
  3958.  
  3959. /*
  3960. ===================================================================================================================
  3961.  
  3962.             MULTITEXTURE
  3963.  
  3964. ===================================================================================================================
  3965. */
  3966.  
  3967. void WINAPI GL_ActiveTexture (GLenum texture)
  3968. {
  3969.     d3d_CurrentTMU = D3D_TMUForTexture (texture);
  3970. }
  3971.  
  3972.  
  3973. void WINAPI GL_MultiTexCoord2f (GLenum target, GLfloat s, GLfloat t)
  3974. {
  3975.     int TMU = D3D_TMUForTexture (target);
  3976.  
  3977.     d3d_CurrentTexCoord[TMU].s = s;
  3978.     d3d_CurrentTexCoord[TMU].t = t;
  3979. }
  3980.  
  3981.  
  3982. void WINAPI GL_MultiTexCoord1f (GLenum target, GLfloat s)
  3983. {
  3984.     int TMU = D3D_TMUForTexture (target);
  3985.  
  3986.     d3d_CurrentTexCoord[TMU].s = s;
  3987.     d3d_CurrentTexCoord[TMU].t = 0;
  3988. }
  3989.  
  3990. /*
  3991. ===================================================================================================================
  3992.  
  3993.             Blend Equation Extension
  3994.  
  3995. ===================================================================================================================
  3996. */
  3997.  
  3998. void WINAPI glBlendEquationExtFgl(GLenum mode)
  3999. {
  4000.     switch(mode)
  4001.     {
  4002.     case GL_FUNC_ADD_EXT:
  4003.         D3D_SetRenderState (D3DRS_BLENDOP, D3DBLENDOP_ADD);
  4004.         break;
  4005.  
  4006.     case GL_FUNC_SUBTRACT_EXT:
  4007.         D3D_SetRenderState (D3DRS_BLENDOP, D3DBLENDOP_SUBTRACT);
  4008.         break;
  4009.  
  4010.     case D3DBLENDOP_REVSUBTRACT:
  4011.         D3D_SetRenderState (D3DRS_BLENDOP, D3DBLENDOP_REVSUBTRACT);
  4012.         break;
  4013.  
  4014.     case GL_MIN_EXT:
  4015.         D3D_SetRenderState (D3DRS_BLENDOP, D3DBLENDOP_MIN);
  4016.         break;
  4017.  
  4018.     case GL_MAX_EXT:
  4019.         D3D_SetRenderState (D3DRS_BLENDOP, D3DBLENDOP_MAX);
  4020.         break;
  4021.  
  4022.     default:
  4023.         SysMessage ("glBlendEquationExt: unknown mode");
  4024.     }
  4025. }
  4026.  
  4027. /*
  4028. ===================================================================================================================
  4029.  
  4030.             EXTENSIONS
  4031.  
  4032. ===================================================================================================================
  4033. */
  4034.  
  4035. // we advertise ourselves as version 1.1 so that as few assumptions about capability as possible are made
  4036. static char *GL_VersionString = "1.1";
  4037.  
  4038. // these are the extensions we want to export
  4039. // right now GL_ARB_texture_env_combine is implemented but causes substantial perf hitches
  4040. // note: we advertise GL_EXT_texture_filter_anisotropic but we also do a double-check with the D3D caps when setting it for real
  4041. static char *GL_ExtensionString =
  4042. "GL_ARB_multitexture \
  4043. GL_ARB_texture_env_add \
  4044. GL_EXT_blend_subtract \
  4045. GL_EXT_texture_filter_anisotropic ";
  4046.  
  4047. D3DADAPTER_IDENTIFIER8 d3d_AdapterID;
  4048.  
  4049. const GLubyte *glGetString (GLenum name)
  4050. {
  4051.     IDirect3D8_GetAdapterIdentifier (d3d_Object, 0, D3DENUM_NO_WHQL_LEVEL, &d3d_AdapterID);
  4052.  
  4053.     switch (name)
  4054.     {
  4055.     case GL_VENDOR:
  4056.         return (GLubyte*)d3d_AdapterID.Description;
  4057.     case GL_RENDERER:
  4058.         return (GLubyte*)d3d_AdapterID.Driver;
  4059.     case GL_VERSION:
  4060.         return (const GLubyte*)GL_VersionString;
  4061.     case GL_EXTENSIONS:
  4062.  
  4063.     default:
  4064.         return (const GLubyte*)GL_ExtensionString;
  4065.     }
  4066. }
  4067.  
  4068.  
  4069. // type cast unsafe conversion from
  4070. #pragma warning (push)
  4071. #pragma warning (disable: 4191)
  4072.  
  4073. typedef struct gld3d_entrypoint_s
  4074. {
  4075.     char *funcname;
  4076.     PROC funcproc;
  4077. } gld3d_entrypoint_t;
  4078.  
  4079. gld3d_entrypoint_t d3d_EntryPoints[] =
  4080. {
  4081.     {"glActiveTexture", (PROC) GL_ActiveTexture},
  4082.     {"glActiveTextureARB", (PROC) GL_ActiveTexture},
  4083.     {"glBindTexture", (PROC) glBindTexture},
  4084.     {"glMultiTexCoord1f", (PROC) GL_MultiTexCoord1f},
  4085.     {"glMultiTexCoord1fARB", (PROC) GL_MultiTexCoord1f},
  4086.     {"glMultiTexCoord2f", (PROC) GL_MultiTexCoord2f},
  4087.     {"glMultiTexCoord2fARB", (PROC) GL_MultiTexCoord2f},
  4088.     {"glClientActiveTexture", (PROC) GL_ClientActiveTexture},
  4089.     {"glClientActiveTextureARB", (PROC) GL_ClientActiveTexture},
  4090.     {"glBlendEquationEXT", (PROC) glBlendEquationExtFgl},
  4091.     {NULL, NULL}
  4092. };
  4093.  
  4094.  
  4095. PROC APIENTRY wglGetProcAddress (LPCSTR strExtension)
  4096. {
  4097.     int i;
  4098.  
  4099.     // check all of our entrypoints
  4100.     for (i = 0; ; i++)
  4101.     {
  4102.         // no more entrypoints
  4103.         if (!d3d_EntryPoints[i].funcname) break;
  4104.  
  4105.         if (!strcmp (strExtension, d3d_EntryPoints[i].funcname))
  4106.         {
  4107.             return d3d_EntryPoints[i].funcproc;
  4108.         }
  4109.     }
  4110.  
  4111.     // LocalDebugBreak();
  4112.     return NULL;
  4113. }
  4114.  
  4115. #pragma warning (pop)
  4116.  
  4117. #endif //_USEFAKEGLX_09
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement