1 /****************************************************************************
3 * Mesa 3-D graphics library
4 * Direct3D Driver Interface
6 * ========================================================================
8 * Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
25 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 * ======================================================================
31 * Environment: Windows 9x/2000/XP/XBox (Win32)
33 * Description: Driver interface code to Mesa
35 ****************************************************************************/
37 //#include <windows.h>
38 #include "dglcontext.h"
46 #include "extensions.h"
52 #include "texformat.h"
56 #include "swrast_setup/swrast_setup.h"
57 #include "swrast_setup/ss_context.h"
59 #include "tnl/t_context.h"
60 #include "tnl/t_pipeline.h"
62 extern BOOL
dglSwapBuffers(HDC hDC
);
64 // HACK: Hack the _33 member of the OpenGL perspective projection matrix
65 const float _fPersp_33
= 1.6f
;
67 //---------------------------------------------------------------------------
69 //---------------------------------------------------------------------------
71 void _gld_mesa_warning(
72 __struct gl_context
*gc
,
75 // Intercept Mesa's internal warning mechanism
76 gldLogPrintf(GLDLOG_WARN
, "Mesa warning: %s", str
);
79 //---------------------------------------------------------------------------
82 __struct gl_context
*gc
,
85 // Intercept Mesa's internal fatal-message mechanism
86 gldLogPrintf(GLDLOG_CRITICAL
, "Mesa FATAL: %s", str
);
88 // Mesa calls abort(0) here.
93 //---------------------------------------------------------------------------
95 D3DSTENCILOP
_gldConvertStencilOp(
98 // Used by Stencil: pass, fail and zfail
102 return D3DSTENCILOP_KEEP
;
104 return D3DSTENCILOP_ZERO
;
106 return D3DSTENCILOP_REPLACE
;
108 return D3DSTENCILOP_INCRSAT
;
110 return D3DSTENCILOP_DECRSAT
;
112 return D3DSTENCILOP_INVERT
;
113 case GL_INCR_WRAP_EXT
: // GL_EXT_stencil_wrap
114 return D3DSTENCILOP_INCR
;
115 case GL_DECR_WRAP_EXT
: // GL_EXT_stencil_wrap
116 return D3DSTENCILOP_DECR
;
120 gldLogMessage(GLDLOG_ERROR
, "_gldConvertStencilOp: Unknown StencilOp\n");
123 return D3DSTENCILOP_KEEP
;
126 //---------------------------------------------------------------------------
128 D3DCMPFUNC
_gldConvertCompareFunc(
131 // Used for Alpha func, depth func and stencil func.
141 return D3DCMP_LESSEQUAL
;
143 return D3DCMP_GREATER
;
145 return D3DCMP_NOTEQUAL
;
147 return D3DCMP_GREATEREQUAL
;
149 return D3DCMP_ALWAYS
;
153 gldLogMessage(GLDLOG_ERROR
, "_gldConvertCompareFunc: Unknown CompareFunc\n");
156 return D3DCMP_ALWAYS
;
159 //---------------------------------------------------------------------------
161 D3DBLEND
_gldConvertBlendFunc(
167 return D3DBLEND_ZERO
;
171 return D3DBLEND_DESTCOLOR
;
173 return D3DBLEND_SRCCOLOR
;
174 case GL_ONE_MINUS_DST_COLOR
:
175 return D3DBLEND_INVDESTCOLOR
;
176 case GL_ONE_MINUS_SRC_COLOR
:
177 return D3DBLEND_INVSRCCOLOR
;
179 return D3DBLEND_SRCALPHA
;
180 case GL_ONE_MINUS_SRC_ALPHA
:
181 return D3DBLEND_INVSRCALPHA
;
183 return D3DBLEND_DESTALPHA
;
184 case GL_ONE_MINUS_DST_ALPHA
:
185 return D3DBLEND_INVDESTALPHA
;
186 case GL_SRC_ALPHA_SATURATE
:
187 return D3DBLEND_SRCALPHASAT
;
191 gldLogMessage(GLDLOG_ERROR
, "_gldConvertBlendFunc: Unknown BlendFunc\n");
197 //---------------------------------------------------------------------------
199 //---------------------------------------------------------------------------
202 struct gl_context
*ctx
)
205 gldLogMessage(GLDLOG_ERROR
, "gld_Noop called!\n");
209 //---------------------------------------------------------------------------
212 struct gl_context
*ctx
)
216 // gldLogMessage(GLDLOG_ERROR, "ctx->Driver.Error called!\n");
220 //---------------------------------------------------------------------------
221 // Required Mesa functions
222 //---------------------------------------------------------------------------
224 static GLboolean
gld_set_draw_buffer_DX9(
225 struct gl_context
*ctx
,
229 if ((mode
==GL_FRONT_LEFT
) || (mode
== GL_BACK_LEFT
)) {
237 //---------------------------------------------------------------------------
239 static void gld_set_read_buffer_DX9(
240 struct gl_context
*ctx
,
241 struct gl_framebuffer
*buffer
,
244 /* separate read buffer not supported */
246 ASSERT(buffer == ctx->DrawBuffer);
247 ASSERT(mode == GL_FRONT_LEFT);
251 //---------------------------------------------------------------------------
254 struct gl_context
*ctx
,
262 GLD_context
*gldCtx
= GLD_GET_CONTEXT(ctx
);
263 GLD_driver_dx9
*gld
= GLD_GET_DX9_DRIVER(gldCtx
);
269 D3DRECT d3dClearRect
;
272 const GLuint
*colorMask
= (GLuint
*) &ctx
->Color
.ColorMask
[0];
277 if (mask
& (DD_FRONT_LEFT_BIT
| DD_BACK_LEFT_BIT
)) {
279 CLAMPED_FLOAT_TO_UBYTE(col
[0], ctx
->Color
.ClearColor
[0]);
280 CLAMPED_FLOAT_TO_UBYTE(col
[1], ctx
->Color
.ClearColor
[1]);
281 CLAMPED_FLOAT_TO_UBYTE(col
[2], ctx
->Color
.ClearColor
[2]);
282 CLAMPED_FLOAT_TO_UBYTE(col
[3], ctx
->Color
.ClearColor
[3]);
283 dwFlags
|= D3DCLEAR_TARGET
;
284 Color
= D3DCOLOR_RGBA(col
[0], col
[1], col
[2], col
[3]);
287 if (mask
& DD_DEPTH_BIT
) {
288 // D3D8 will fail the Clear call if we try and clear a
289 // depth buffer and we haven't created one.
290 // Also, some apps try and clear a depth buffer,
291 // when a depth buffer hasn't been requested by the app.
292 if (ctx
->Visual
.depthBits
== 0) {
293 mask
&= ~DD_DEPTH_BIT
; // Remove depth bit from mask
295 dwFlags
|= D3DCLEAR_ZBUFFER
;
296 Z
= ctx
->Depth
.Clear
;
300 if (mask
& DD_STENCIL_BIT
) {
301 if (ctx
->Visual
.stencilBits
== 0) {
302 // No stencil bits in depth buffer
303 mask
&= ~DD_STENCIL_BIT
; // Remove stencil bit from mask
305 dwFlags
|= D3DCLEAR_STENCIL
;
306 Stencil
= ctx
->Stencil
.Clear
;
310 // Some apps do really weird things with the rect, such as Quake3.
311 if ((x
< 0) || (y
< 0) || (width
<= 0) || (height
<= 0)) {
316 // Calculate clear subrect
318 d3dClearRect
.y1
= gldCtx
->dwHeight
- (y
+ height
);
319 d3dClearRect
.x2
= x
+ width
;
320 d3dClearRect
.y2
= d3dClearRect
.y1
+ height
;
321 // gldLogPrintf(GLDLOG_INFO, "Rect %d,%d %d,%d", x,y,width,height);
324 // dwFlags will be zero if there's nothing to clear
329 all
? NULL
: &d3dClearRect
,
334 if (mask
& DD_ACCUM_BIT
) {
335 // Clear accumulation buffer
339 //---------------------------------------------------------------------------
341 // Mesa 5: Parameter change
342 static void gld_buffer_size_DX9(
343 // struct gl_context *ctx,
344 struct gl_framebuffer
*fb
,
348 // GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
350 *width
= fb
->Width
; // gldCtx->dwWidth;
351 *height
= fb
->Height
; // gldCtx->dwHeight;
354 //---------------------------------------------------------------------------
356 static void gld_Finish_DX9(
357 struct gl_context
*ctx
)
361 //---------------------------------------------------------------------------
363 static void gld_Flush_DX9(
364 struct gl_context
*ctx
)
366 GLD_context
*gld
= GLD_GET_CONTEXT(ctx
);
368 // TODO: Detect apps that glFlush() then SwapBuffers() ?
370 if (gld
->EmulateSingle
) {
371 // Emulating a single-buffered context.
372 // [Direct3D doesn't allow rendering to front buffer]
373 dglSwapBuffers(gld
->hDC
);
377 //---------------------------------------------------------------------------
379 void gld_NEW_STENCIL(
380 struct gl_context
*ctx
)
382 GLD_context
*gldCtx
= GLD_GET_CONTEXT(ctx
);
383 GLD_driver_dx9
*gld
= GLD_GET_DX9_DRIVER(gldCtx
);
385 // Two-sided stencil. New for Mesa 5
386 const GLuint uiFace
= 0UL;
388 struct gl_stencil_attrib
*pStencil
= &ctx
->Stencil
;
390 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_STENCILENABLE
, pStencil
->Enabled
? TRUE
: FALSE
));
391 if (pStencil
->Enabled
) {
392 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_STENCILFUNC
, _gldConvertCompareFunc(pStencil
->Function
[uiFace
])));
393 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_STENCILREF
, pStencil
->Ref
[uiFace
]));
394 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_STENCILMASK
, pStencil
->ValueMask
[uiFace
]));
395 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_STENCILWRITEMASK
, pStencil
->WriteMask
[uiFace
]));
396 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_STENCILFAIL
, _gldConvertStencilOp(pStencil
->FailFunc
[uiFace
])));
397 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_STENCILZFAIL
, _gldConvertStencilOp(pStencil
->ZFailFunc
[uiFace
])));
398 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_STENCILPASS
, _gldConvertStencilOp(pStencil
->ZPassFunc
[uiFace
])));
402 //---------------------------------------------------------------------------
405 struct gl_context
*ctx
)
407 GLD_context
*gldCtx
= GLD_GET_CONTEXT(ctx
);
408 GLD_driver_dx9
*gld
= GLD_GET_DX9_DRIVER(gldCtx
);
415 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_ALPHAFUNC
, _gldConvertCompareFunc(ctx
->Color
.AlphaFunc
)));
416 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_ALPHAREF
, (DWORD
)ctx
->Color
.AlphaRef
));
417 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_ALPHATESTENABLE
, ctx
->Color
.AlphaEnabled
));
420 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_ALPHABLENDENABLE
, ctx
->Color
.BlendEnabled
));
421 src
= _gldConvertBlendFunc(ctx
->Color
.BlendSrcRGB
, GL_ONE
);
422 dest
= _gldConvertBlendFunc(ctx
->Color
.BlendDstRGB
, GL_ZERO
);
423 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_SRCBLEND
, src
));
424 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_DESTBLEND
, dest
));
427 if (ctx
->Color
.ColorMask
[0][0]) dwFlags
|= D3DCOLORWRITEENABLE_RED
;
428 if (ctx
->Color
.ColorMask
[0][1]) dwFlags
|= D3DCOLORWRITEENABLE_GREEN
;
429 if (ctx
->Color
.ColorMask
[0][2]) dwFlags
|= D3DCOLORWRITEENABLE_BLUE
;
430 if (ctx
->Color
.ColorMask
[0][3]) dwFlags
|= D3DCOLORWRITEENABLE_ALPHA
;
431 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_COLORWRITEENABLE
, dwFlags
));
434 //---------------------------------------------------------------------------
437 struct gl_context
*ctx
)
439 GLD_context
*gldCtx
= GLD_GET_CONTEXT(ctx
);
440 GLD_driver_dx9
*gld
= GLD_GET_DX9_DRIVER(gldCtx
);
442 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_ZENABLE
, ctx
->Depth
.Test
? D3DZB_TRUE
: D3DZB_FALSE
));
443 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_ZFUNC
, _gldConvertCompareFunc(ctx
->Depth
.Func
)));
444 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_ZWRITEENABLE
, ctx
->Depth
.Mask
? TRUE
: FALSE
));
447 //---------------------------------------------------------------------------
449 void gld_NEW_POLYGON(
450 struct gl_context
*ctx
)
452 GLD_context
*gldCtx
= GLD_GET_CONTEXT(ctx
);
453 GLD_driver_dx9
*gld
= GLD_GET_DX9_DRIVER(gldCtx
);
455 D3DFILLMODE d3dFillMode
= D3DFILL_SOLID
;
456 D3DCULL d3dCullMode
= D3DCULL_NONE
;
457 float fOffset
= 0; // Changed from int to float for DX9
460 switch (ctx
->Polygon
.FrontMode
) {
462 d3dFillMode
= D3DFILL_POINT
;
465 d3dFillMode
= D3DFILL_WIREFRAME
;
468 d3dFillMode
= D3DFILL_SOLID
;
471 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_FILLMODE
, d3dFillMode
));
473 if (ctx
->Polygon
.CullFlag
) {
474 switch (ctx
->Polygon
.CullFaceMode
) {
476 if (ctx
->Polygon
.FrontFace
== GL_CCW
)
477 d3dCullMode
= D3DCULL_CW
;
479 d3dCullMode
= D3DCULL_CCW
;
482 if (ctx
->Polygon
.FrontFace
== GL_CCW
)
483 d3dCullMode
= D3DCULL_CCW
;
485 d3dCullMode
= D3DCULL_CW
;
487 case GL_FRONT_AND_BACK
:
488 d3dCullMode
= D3DCULL_NONE
;
494 d3dCullMode
= D3DCULL_NONE
;
496 // d3dCullMode = D3DCULL_NONE; // FOR DEBUGGING
497 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_CULLMODE
, d3dCullMode
));
500 // ZBIAS ranges from 0 to 16 and can only move towards the viewer
501 // Mesa5: ctx->Polygon._OffsetAny removed
502 if (ctx
->Polygon
.OffsetFill
) {
503 fOffset
= ctx
->Polygon
.OffsetUnits
;
504 // if (iOffset < 0.0f)
505 // iOffset = -iOffset;
507 // iOffset = 0.0f; // D3D can't push away
509 // NOTE: SetRenderState() required a DWORD, so need to cast
510 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_DEPTHBIAS
, *((DWORD
*)&fOffset
)));
513 //---------------------------------------------------------------------------
516 struct gl_context
*ctx
)
518 GLD_context
*gldCtx
= GLD_GET_CONTEXT(ctx
);
519 GLD_driver_dx9
*gld
= GLD_GET_DX9_DRIVER(gldCtx
);
521 D3DCOLOR d3dFogColour
;
522 D3DFOGMODE d3dFogMode
= D3DFOG_LINEAR
;
524 // TODO: Fog is calculated seperately in the Mesa pipeline
525 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_FOGENABLE
, FALSE
));
529 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_FOGENABLE
, ctx
->Fog
.Enabled
));
530 if (!ctx
->Fog
.Enabled
) {
531 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_FOGTABLEMODE
, D3DFOG_NONE
));
532 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_FOGVERTEXMODE
, D3DFOG_NONE
));
533 return; // If disabled, don't bother setting any fog state
537 d3dFogColour
= D3DCOLOR_COLORVALUE( ctx
->Fog
.Color
[0],
541 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_FOGCOLOR
, d3dFogColour
));
544 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_FOGDENSITY
, *((DWORD
*) (&ctx
->Fog
.Density
))));
547 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_FOGSTART
, *((DWORD
*) (&ctx
->Fog
.Start
))));
550 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_FOGEND
, *((DWORD
*) (&ctx
->Fog
.End
))));
553 switch (ctx
->Fog
.Mode
) {
555 d3dFogMode
= D3DFOG_LINEAR
;
558 d3dFogMode
= D3DFOG_EXP
;
561 d3dFogMode
= D3DFOG_EXP2
;
564 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_FOGTABLEMODE
, d3dFogMode
));
565 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_FOGVERTEXMODE
, D3DFOG_NONE
));
568 //---------------------------------------------------------------------------
571 struct gl_context
*ctx
)
573 GLD_context
*gldCtx
= GLD_GET_CONTEXT(ctx
);
574 GLD_driver_dx9
*gld
= GLD_GET_DX9_DRIVER(gldCtx
);
575 DWORD dwSpecularEnable
;
578 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_SHADEMODE
, (ctx
->Light
.ShadeModel
== GL_SMOOTH
) ? D3DSHADE_GOURAUD
: D3DSHADE_FLAT
));
580 // Separate specular colour
581 if (ctx
->Light
.Enabled
)
582 dwSpecularEnable
= (ctx
->_TriangleCaps
& DD_SEPARATE_SPECULAR
) ? TRUE
: FALSE
;
584 dwSpecularEnable
= FALSE
;
585 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_SPECULARENABLE
, dwSpecularEnable
));
588 //---------------------------------------------------------------------------
590 void gld_NEW_MODELVIEW(
591 struct gl_context
*ctx
)
593 GLD_context
*gldCtx
= GLD_GET_CONTEXT(ctx
);
594 GLD_driver_dx9
*gld
= GLD_GET_DX9_DRIVER(gldCtx
);
597 //GLfloat *pM = ctx->ModelView.m;
598 // Mesa5: Model-view is now a stack
599 GLfloat
*pM
= ctx
->ModelviewMatrixStack
.Top
->m
;
617 gld
->matModelView
= m
;
620 //---------------------------------------------------------------------------
622 void gld_NEW_PROJECTION(
623 struct gl_context
*ctx
)
625 GLD_context
*gldCtx
= GLD_GET_CONTEXT(ctx
);
626 GLD_driver_dx9
*gld
= GLD_GET_DX9_DRIVER(gldCtx
);
629 //GLfloat *pM = ctx->ProjectionMatrix.m;
630 // Mesa 5: Now a stack
631 GLfloat
*pM
= ctx
->ProjectionMatrixStack
.Top
->m
;
644 m
._33
= pM
[10] / _fPersp_33
; // / 1.6f;
649 m
._43
= pM
[14] / 2.0f
;
652 gld
->matProjection
= m
;
655 //---------------------------------------------------------------------------
657 void gldFrustumHook_DX9(
665 GET_CURRENT_CONTEXT(ctx);
666 GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
667 GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
669 // Pass values on to Mesa first (in case we mess with them)
670 _mesa_Frustum(left, right, bottom, top, nearval, farval);
672 _fPersp_33 = farval / (nearval - farval);
674 // ddlogPrintf(GLDLOG_SYSTEM, "Frustum: %f", farval/nearval);
677 //---------------------------------------------------------------------------
679 void gldOrthoHook_DX9(
687 GET_CURRENT_CONTEXT(ctx);
688 GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
689 GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
691 // Pass values on to Mesa first (in case we mess with them)
692 _mesa_Ortho(left, right, bottom, top, nearval, farval);
696 // ddlogPrintf(GLDLOG_SYSTEM, "Ortho: %f", farval/nearval);
699 //---------------------------------------------------------------------------
701 void gld_NEW_VIEWPORT(
702 struct gl_context
*ctx
)
704 GLD_context
*gldCtx
= GLD_GET_CONTEXT(ctx
);
705 GLD_driver_dx9
*gld
= GLD_GET_DX9_DRIVER(gldCtx
);
712 _GLD_DX9_DEV(GetViewport(gld
->pDev
, &d3dvp
));
713 // D3D can't do Quake1/Quake2 z-trick
714 if (ctx
->Viewport
.Near
<= ctx
->Viewport
.Far
) {
715 d3dvp
.MinZ
= ctx
->Viewport
.Near
;
716 d3dvp
.MaxZ
= ctx
->Viewport
.Far
;
718 d3dvp
.MinZ
= ctx
->Viewport
.Far
;
719 d3dvp
.MaxZ
= ctx
->Viewport
.Near
;
721 /* x = ctx->Viewport.X;
723 w = ctx->Viewport.Width;
724 h = ctx->Viewport.Height;
727 if (w > gldCtx->dwWidth) w = gldCtx->dwWidth;
728 if (h > gldCtx->dwHeight) h = gldCtx->dwHeight;
729 // Ditto for D3D viewport dimensions
730 if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x;
731 if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y;
733 d3dvp.Y = gldCtx->dwHeight - (y + h);
736 _GLD_DX9_DEV(SetViewport(gld
->pDev
, &d3dvp
));
738 // gld->fFlipWindowY = (float)gldCtx->dwHeight;
741 //---------------------------------------------------------------------------
743 void gld_NEW_SCISSOR(
744 struct gl_context
*ctx
)
746 GLD_context
*gldCtx
= GLD_GET_CONTEXT(ctx
);
747 GLD_driver_dx9
*gld
= GLD_GET_DX9_DRIVER(gldCtx
);
749 // Bail if IHV driver cannot scissor
750 if (!gld
->bCanScissor
)
754 if (ctx
->Scissor
.Enabled
) {
756 // Keep in mind that RECT's need an extra row and column
757 rcRect
.left
= ctx
->Scissor
.X
;
758 rcRect
.right
= ctx
->Scissor
.X
+ ctx
->Scissor
.Width
; // + 1;
759 rcRect
.top
= gldCtx
->dwHeight
- (ctx
->Scissor
.Y
+ ctx
->Scissor
.Height
);
760 rcRect
.bottom
= rcRect
.top
+ ctx
->Scissor
.Height
;
761 IDirect3DDevice9_SetScissorRect(gld
->pDev
, &rcRect
);
764 // Enable/disable scissor as required
765 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_SCISSORTESTENABLE
, ctx
->Scissor
.Enabled
));
768 //---------------------------------------------------------------------------
770 __inline BOOL
_gldAnyEvalEnabled(
771 struct gl_context
*ctx
)
773 struct gl_eval_attrib
*eval
= &ctx
->Eval
;
775 if ((eval
->AutoNormal
) ||
776 (eval
->Map1Color4
) ||
778 (eval
->Map1Normal
) ||
779 (eval
->Map1TextureCoord1
) ||
780 (eval
->Map1TextureCoord2
) ||
781 (eval
->Map1TextureCoord3
) ||
782 (eval
->Map1TextureCoord4
) ||
783 (eval
->Map1Vertex3
) ||
784 (eval
->Map1Vertex4
) ||
785 (eval
->Map2Color4
) ||
787 (eval
->Map2Normal
) ||
788 (eval
->Map2TextureCoord1
) ||
789 (eval
->Map2TextureCoord2
) ||
790 (eval
->Map2TextureCoord3
) ||
791 (eval
->Map2TextureCoord4
) ||
792 (eval
->Map2Vertex3
) ||
800 //---------------------------------------------------------------------------
802 BOOL
_gldChooseInternalPipeline(
803 struct gl_context
*ctx
,
806 // return TRUE; // DEBUGGING: ALWAYS USE MESA
807 // return FALSE; // DEBUGGING: ALWAYS USE D3D
809 if ((glb
.dwTnL
== GLDS_TNL_MESA
) || (gld
->bHasHWTnL
== FALSE
))
811 gld
->PipelineUsage
.qwMesa
.QuadPart
++;
812 return TRUE
; // Force Mesa TnL
815 if ((ctx
->Light
.Enabled
) ||
817 (ctx
->Texture
._TexGenEnabled
) ||
818 (ctx
->Texture
._TexMatEnabled
) ||
819 // (ctx->Transform._AnyClip) ||
820 (ctx
->Scissor
.Enabled
) ||
821 _gldAnyEvalEnabled(ctx
) // Put this last so we can early-out
824 gld
->PipelineUsage
.qwMesa
.QuadPart
++;
828 gld
->PipelineUsage
.qwD3DFVF
.QuadPart
++;
831 /* // Force Mesa pipeline?
832 if (glb.dwTnL == GLDS_TNL_MESA) {
833 gld->PipelineUsage.dwMesa.QuadPart++;
834 return GLD_PIPELINE_MESA;
837 // Test for functionality not exposed in the D3D pathways
838 if ((ctx->Texture._GenFlags)) {
839 gld->PipelineUsage.dwMesa.QuadPart++;
840 return GLD_PIPELINE_MESA;
843 // Now decide if vertex shader can be used.
844 // If two sided lighting is enabled then we must either
845 // use Mesa TnL or the vertex shader
846 if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
847 if (gld->VStwosidelight.hShader && !ctx->Fog.Enabled) {
849 gld->PipelineUsage.dwD3D2SVS.QuadPart++;
850 return GLD_PIPELINE_D3D_VS_TWOSIDE;
853 gld->PipelineUsage.dwMesa.QuadPart++;
854 return GLD_PIPELINE_MESA;
858 // Must be D3D fixed-function pipeline
859 gld->PipelineUsage.dwD3DFVF.QuadPart++;
860 return GLD_PIPELINE_D3D_FVF;
864 //---------------------------------------------------------------------------
866 void gld_update_state_DX9(
867 struct gl_context
*ctx
,
870 GLD_context
*gldCtx
= GLD_GET_CONTEXT(ctx
);
871 GLD_driver_dx9
*gld
= GLD_GET_DX9_DRIVER(gldCtx
);
872 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
875 if (!gld
|| !gld
->pDev
)
878 _swsetup_InvalidateState( ctx
, new_state
);
879 _vbo_InvalidateState( ctx
, new_state
);
880 _tnl_InvalidateState( ctx
, new_state
);
882 // SetupIndex will be used in the pipelines for choosing setup function
883 if ((ctx
->_TriangleCaps
& (DD_TRI_LIGHT_TWOSIDE
| DD_SEPARATE_SPECULAR
)) ||
886 if (ctx
->_TriangleCaps
& DD_FLATSHADE
)
887 gld
->iSetupFunc
= GLD_SI_FLAT_EXTRAS
;
889 gld
->iSetupFunc
= GLD_SI_SMOOTH_EXTRAS
;
891 if (ctx
->_TriangleCaps
& DD_FLATSHADE
)
892 gld
->iSetupFunc
= GLD_SI_FLAT
; // Setup flat shade + texture
894 gld
->iSetupFunc
= GLD_SI_SMOOTH
; // Setup smooth shade + texture
897 gld
->bUseMesaTnL
= _gldChooseInternalPipeline(ctx
, gld
);
898 if (gld
->bUseMesaTnL
) {
900 _GLD_DX9_DEV(SetSoftwareVertexProcessing(gld
->pDev
, TRUE
));
901 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_CLIPPING
, FALSE
));
902 _GLD_DX9_DEV(SetVertexShader(gld
->pDev
, NULL
));
903 _GLD_DX9_DEV(SetFVF(gld
->pDev
, gldPB
->dwFVF
));
906 _GLD_DX9_DEV(SetRenderState(gld
->pDev
, D3DRS_CLIPPING
, TRUE
));
907 // if (gld->TnLPipeline == GLD_PIPELINE_D3D_VS_TWOSIDE) {
908 // _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->VStwosidelight.bHardware));
909 // _GLD_DX9_DEV(SetVertexShader(gld->pDev, gld->VStwosidelight.hShader));
911 // _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->bHasHWTnL));
912 _GLD_DX9_DEV(SetSoftwareVertexProcessing(gld
->pDev
, !gld
->bHasHWTnL
));
913 _GLD_DX9_DEV(SetVertexShader(gld
->pDev
, NULL
));
914 _GLD_DX9_DEV(SetFVF(gld
->pDev
, gldPB
->dwFVF
));
918 #define _GLD_TEST_STATE(a) \
919 if (new_state & (a)) { \
924 #define _GLD_TEST_STATE_DX9(a) \
925 if (new_state & (a)) { \
930 #define _GLD_IGNORE_STATE(a) new_state &= ~(a);
932 // if (!gld->bUseMesaTnL) {
933 // Not required if Mesa is doing the TnL.
934 // Problem: If gld->bUseMesaTnL is TRUE when these are signaled,
935 // then we'll miss updating the D3D TnL pipeline.
936 // Therefore, don't test for gld->bUseMesaTnL
937 _GLD_TEST_STATE(_NEW_MODELVIEW
);
938 _GLD_TEST_STATE(_NEW_PROJECTION
);
941 _GLD_TEST_STATE_DX9(_NEW_TEXTURE
); // extern, so guard with _DX9
942 _GLD_TEST_STATE(_NEW_COLOR
);
943 _GLD_TEST_STATE(_NEW_DEPTH
);
944 _GLD_TEST_STATE(_NEW_POLYGON
);
945 _GLD_TEST_STATE(_NEW_STENCIL
);
946 _GLD_TEST_STATE(_NEW_FOG
);
947 _GLD_TEST_STATE(_NEW_LIGHT
);
948 _GLD_TEST_STATE(_NEW_VIEWPORT
);
950 _GLD_IGNORE_STATE(_NEW_TRANSFORM
);
952 // Scissor Test: New for DX9
953 _GLD_TEST_STATE(_NEW_SCISSOR
);
955 // Stubs for future use.
956 /* _GLD_TEST_STATE(_NEW_TEXTURE_MATRIX);
957 _GLD_TEST_STATE(_NEW_COLOR_MATRIX);
958 _GLD_TEST_STATE(_NEW_ACCUM);
959 _GLD_TEST_STATE(_NEW_EVAL);
960 _GLD_TEST_STATE(_NEW_HINT);
961 _GLD_TEST_STATE(_NEW_LINE);
962 _GLD_TEST_STATE(_NEW_PIXEL);
963 _GLD_TEST_STATE(_NEW_POINT);
964 _GLD_TEST_STATE(_NEW_POLYGONSTIPPLE);
965 _GLD_TEST_STATE(_NEW_PACKUNPACK);
966 _GLD_TEST_STATE(_NEW_ARRAY);
967 _GLD_TEST_STATE(_NEW_RENDERMODE);
968 _GLD_TEST_STATE(_NEW_BUFFERS);
969 _GLD_TEST_STATE(_NEW_MULTISAMPLE);
974 #define _GLD_TEST_UNHANDLED_STATE(a) \
975 if (new_state & (a)) { \
976 gldLogMessage(GLDLOG_ERROR, "Unhandled " #a "\n"); \
978 _GLD_TEST_UNHANDLED_STATE(_NEW_TEXTURE_MATRIX
);
979 _GLD_TEST_UNHANDLED_STATE(_NEW_COLOR_MATRIX
);
980 _GLD_TEST_UNHANDLED_STATE(_NEW_ACCUM
);
981 _GLD_TEST_UNHANDLED_STATE(_NEW_EVAL
);
982 _GLD_TEST_UNHANDLED_STATE(_NEW_HINT
);
983 _GLD_TEST_UNHANDLED_STATE(_NEW_LINE
);
984 _GLD_TEST_UNHANDLED_STATE(_NEW_PIXEL
);
985 _GLD_TEST_UNHANDLED_STATE(_NEW_POINT
);
986 _GLD_TEST_UNHANDLED_STATE(_NEW_POLYGONSTIPPLE
);
987 // _GLD_TEST_UNHANDLED_STATE(_NEW_SCISSOR);
988 _GLD_TEST_UNHANDLED_STATE(_NEW_PACKUNPACK
);
989 _GLD_TEST_UNHANDLED_STATE(_NEW_ARRAY
);
990 _GLD_TEST_UNHANDLED_STATE(_NEW_RENDERMODE
);
991 _GLD_TEST_UNHANDLED_STATE(_NEW_BUFFERS
);
992 _GLD_TEST_UNHANDLED_STATE(_NEW_MULTISAMPLE
);
993 #undef _GLD_UNHANDLED_STATE
996 #undef _GLD_TEST_STATE
999 //---------------------------------------------------------------------------
1001 //---------------------------------------------------------------------------
1003 void gld_Viewport_DX9(
1004 struct gl_context
*ctx
,
1010 GLD_context
*gldCtx
= GLD_GET_CONTEXT(ctx
);
1011 GLD_driver_dx9
*gld
= GLD_GET_DX9_DRIVER(gldCtx
);
1015 if (!gld
|| !gld
->pDev
)
1018 // This is a hack. When the app is minimized, Mesa passes
1019 // w=1 and h=1 for viewport dimensions. Without this test
1020 // we get a GPF in gld_wgl_resize_buffers().
1021 if ((w
==1) && (h
==1))
1024 // Call ResizeBuffersMESA. This function will early-out
1025 // if no resize is needed.
1026 //ctx->Driver.ResizeBuffersMESA(ctx);
1027 // Mesa 5: Changed parameters
1028 ctx
->Driver
.ResizeBuffers(gldCtx
->glBuffer
);
1031 ddlogPrintf(GLDLOG_SYSTEM
, ">> Viewport x=%d y=%d w=%d h=%d", x
,y
,w
,h
);
1034 // ** D3D viewport must not be outside the render target surface **
1035 // Sanity check the GL viewport dimensions
1038 if (w
> gldCtx
->dwWidth
) w
= gldCtx
->dwWidth
;
1039 if (h
> gldCtx
->dwHeight
) h
= gldCtx
->dwHeight
;
1040 // Ditto for D3D viewport dimensions
1041 if (w
+x
> gldCtx
->dwWidth
) w
= gldCtx
->dwWidth
-x
;
1042 if (h
+y
> gldCtx
->dwHeight
) h
= gldCtx
->dwHeight
-y
;
1045 d3dvp
.Y
= gldCtx
->dwHeight
- (y
+ h
);
1048 if (ctx
->Viewport
.Near
<= ctx
->Viewport
.Far
) {
1049 d3dvp
.MinZ
= ctx
->Viewport
.Near
;
1050 d3dvp
.MaxZ
= ctx
->Viewport
.Far
;
1052 d3dvp
.MinZ
= ctx
->Viewport
.Far
;
1053 d3dvp
.MaxZ
= ctx
->Viewport
.Near
;
1057 // d3dvp.MinZ = 0.0f;
1058 // d3dvp.MaxZ = 1.0f;
1060 _GLD_DX9_DEV(SetViewport(gld
->pDev
, &d3dvp
));
1064 //---------------------------------------------------------------------------
1066 extern BOOL
dglWglResizeBuffers(struct gl_context
*ctx
, BOOL bDefaultDriver
);
1068 // Mesa 5: Parameter change
1069 void gldResizeBuffers_DX9(
1070 // struct gl_context *ctx)
1071 struct gl_framebuffer
*fb
)
1073 GET_CURRENT_CONTEXT(ctx
);
1074 dglWglResizeBuffers(ctx
, TRUE
);
1077 //---------------------------------------------------------------------------
1079 // This is only for debugging.
1080 // To use, plug into ctx->Driver.Enable pointer below.
1082 struct gl_context
*ctx
,
1087 sprintf(buf
, "Enable: %s (%s)\n", _mesa_lookup_enum_by_nr(e
), b
?"TRUE":"FALSE");
1088 ddlogMessage(DDLOG_SYSTEM
, buf
);
1091 //---------------------------------------------------------------------------
1092 // Driver pointer setup
1093 //---------------------------------------------------------------------------
1095 extern const GLubyte
* _gldGetStringGeneric(struct gl_context
*, GLenum
);
1097 void gldSetupDriverPointers_DX9(
1098 struct gl_context
*ctx
)
1100 GLD_context
*gldCtx
= GLD_GET_CONTEXT(ctx
);
1101 GLD_driver_dx9
*gld
= GLD_GET_DX9_DRIVER(gldCtx
);
1103 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1105 // Mandatory functions
1106 ctx
->Driver
.GetString
= _gldGetStringGeneric
;
1107 ctx
->Driver
.UpdateState
= gld_update_state_DX9
;
1108 ctx
->Driver
.Clear
= gld_Clear_DX9
;
1109 ctx
->Driver
.DrawBuffer
= gld_set_draw_buffer_DX9
;
1110 ctx
->Driver
.GetBufferSize
= gld_buffer_size_DX9
;
1111 ctx
->Driver
.Finish
= gld_Finish_DX9
;
1112 ctx
->Driver
.Flush
= gld_Flush_DX9
;
1113 ctx
->Driver
.Error
= gld_Error_DX9
;
1115 // Hardware accumulation buffer
1116 ctx
->Driver
.Accum
= NULL
; // TODO: gld_Accum;
1119 ctx
->Driver
.CopyPixels
= gld_CopyPixels_DX9
;
1120 ctx
->Driver
.DrawPixels
= gld_DrawPixels_DX9
;
1121 ctx
->Driver
.ReadPixels
= gld_ReadPixels_DX9
;
1122 ctx
->Driver
.Bitmap
= gld_Bitmap_DX9
;
1125 ctx
->Driver
.ResizeBuffers
= gldResizeBuffers_DX9
;
1127 // Texture image functions
1128 ctx
->Driver
.ChooseTextureFormat
= gld_ChooseTextureFormat_DX9
;
1129 ctx
->Driver
.TexImage1D
= gld_TexImage1D_DX9
;
1130 ctx
->Driver
.TexImage2D
= gld_TexImage2D_DX9
;
1131 ctx
->Driver
.TexImage3D
= _mesa_store_teximage3d
;
1132 ctx
->Driver
.TexSubImage1D
= gld_TexSubImage1D_DX9
;
1133 ctx
->Driver
.TexSubImage2D
= gld_TexSubImage2D_DX9
;
1134 ctx
->Driver
.TexSubImage3D
= _mesa_store_texsubimage3d
;
1136 ctx
->Driver
.CopyTexImage1D
= gldCopyTexImage1D_DX9
; //NULL;
1137 ctx
->Driver
.CopyTexImage2D
= gldCopyTexImage2D_DX9
; //NULL;
1138 ctx
->Driver
.CopyTexSubImage1D
= gldCopyTexSubImage1D_DX9
; //NULL;
1139 ctx
->Driver
.CopyTexSubImage2D
= gldCopyTexSubImage2D_DX9
; //NULL;
1140 ctx
->Driver
.CopyTexSubImage3D
= gldCopyTexSubImage3D_DX9
;
1141 ctx
->Driver
.TestProxyTexImage
= _mesa_test_proxy_teximage
;
1143 // Texture object functions
1144 ctx
->Driver
.BindTexture
= NULL
;
1145 ctx
->Driver
.NewTextureObject
= NULL
; // Not yet implemented by Mesa!;
1146 ctx
->Driver
.DeleteTexture
= gld_DeleteTexture_DX9
;
1147 ctx
->Driver
.PrioritizeTexture
= NULL
;
1149 // Imaging functionality
1150 ctx
->Driver
.CopyColorTable
= NULL
;
1151 ctx
->Driver
.CopyColorSubTable
= NULL
;
1152 ctx
->Driver
.CopyConvolutionFilter1D
= NULL
;
1153 ctx
->Driver
.CopyConvolutionFilter2D
= NULL
;
1155 // State changing functions
1156 ctx
->Driver
.AlphaFunc
= NULL
; //gld_AlphaFunc;
1157 ctx
->Driver
.BlendFuncSeparate
= NULL
; //gld_BlendFunc;
1158 ctx
->Driver
.ClearColor
= NULL
; //gld_ClearColor;
1159 ctx
->Driver
.ClearDepth
= NULL
; //gld_ClearDepth;
1160 ctx
->Driver
.ClearStencil
= NULL
; //gld_ClearStencil;
1161 ctx
->Driver
.ColorMask
= NULL
; //gld_ColorMask;
1162 ctx
->Driver
.CullFace
= NULL
; //gld_CullFace;
1163 ctx
->Driver
.ClipPlane
= NULL
; //gld_ClipPlane;
1164 ctx
->Driver
.FrontFace
= NULL
; //gld_FrontFace;
1165 ctx
->Driver
.DepthFunc
= NULL
; //gld_DepthFunc;
1166 ctx
->Driver
.DepthMask
= NULL
; //gld_DepthMask;
1167 ctx
->Driver
.DepthRange
= NULL
;
1168 ctx
->Driver
.Enable
= NULL
; //gld_Enable;
1169 ctx
->Driver
.Fogfv
= NULL
; //gld_Fogfv;
1170 ctx
->Driver
.Hint
= NULL
; //gld_Hint;
1171 ctx
->Driver
.Lightfv
= NULL
; //gld_Lightfv;
1172 ctx
->Driver
.LightModelfv
= NULL
; //gld_LightModelfv;
1173 ctx
->Driver
.LineStipple
= NULL
; //gld_LineStipple;
1174 ctx
->Driver
.LineWidth
= NULL
; //gld_LineWidth;
1175 ctx
->Driver
.LogicOpcode
= NULL
; //gld_LogicOpcode;
1176 ctx
->Driver
.PointParameterfv
= NULL
; //gld_PointParameterfv;
1177 ctx
->Driver
.PointSize
= NULL
; //gld_PointSize;
1178 ctx
->Driver
.PolygonMode
= NULL
; //gld_PolygonMode;
1179 ctx
->Driver
.PolygonOffset
= NULL
; //gld_PolygonOffset;
1180 ctx
->Driver
.PolygonStipple
= NULL
; //gld_PolygonStipple;
1181 ctx
->Driver
.RenderMode
= NULL
; //gld_RenderMode;
1182 ctx
->Driver
.Scissor
= NULL
; //gld_Scissor;
1183 ctx
->Driver
.ShadeModel
= NULL
; //gld_ShadeModel;
1184 ctx
->Driver
.StencilFunc
= NULL
; //gld_StencilFunc;
1185 ctx
->Driver
.StencilMask
= NULL
; //gld_StencilMask;
1186 ctx
->Driver
.StencilOp
= NULL
; //gld_StencilOp;
1187 ctx
->Driver
.TexGen
= NULL
; //gld_TexGen;
1188 ctx
->Driver
.TexEnv
= NULL
;
1189 ctx
->Driver
.TexParameter
= NULL
;
1190 ctx
->Driver
.TextureMatrix
= NULL
; //gld_TextureMatrix;
1191 ctx
->Driver
.Viewport
= gld_Viewport_DX9
;
1193 _swsetup_Wakeup(ctx
);
1195 tnl
->Driver
.RunPipeline
= _tnl_run_pipeline
;
1196 tnl
->Driver
.Render
.ResetLineStipple
= gld_ResetLineStipple_DX9
;
1197 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
1198 tnl
->Driver
.Render
.ClippedLine
= _tnl_RenderClippedLine
;
1200 // Hook into glFrustum() and glOrtho()
1201 // ctx->Exec->Frustum = gldFrustumHook_DX9;
1202 // ctx->Exec->Ortho = gldOrthoHook_DX9;
1206 //---------------------------------------------------------------------------