summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/windows
diff options
context:
space:
mode:
authorAlan Hourihane <alanh@tungstengraphics.com>2004-04-20 11:13:11 +0000
committerAlan Hourihane <alanh@tungstengraphics.com>2004-04-20 11:13:11 +0000
commit485438e2be08c6d57110101f76dd41a5f484a4ee (patch)
tree1d36515d92b864caddfa1d7bb05a9e235ef218a9 /src/mesa/drivers/windows
parent319f5fd5ec85b4ca845028e6cdb94cca0a00d3d5 (diff)
add SciTech's GLDirect driver for Windows.
This code is donated to Mesa which allows the usage of a Direct3D layer (DX7, DX8, DX9 or complete software fallback). No build system exists for this code yet, that will come.....
Diffstat (limited to 'src/mesa/drivers/windows')
-rw-r--r--src/mesa/drivers/windows/gldirect/ddlog.c192
-rw-r--r--src/mesa/drivers/windows/gldirect/ddlog.h109
-rw-r--r--src/mesa/drivers/windows/gldirect/dglcontext.c2213
-rw-r--r--src/mesa/drivers/windows/gldirect/dglcontext.h281
-rw-r--r--src/mesa/drivers/windows/gldirect/dglglobals.c149
-rw-r--r--src/mesa/drivers/windows/gldirect/dglglobals.h198
-rw-r--r--src/mesa/drivers/windows/gldirect/dglmacros.h91
-rw-r--r--src/mesa/drivers/windows/gldirect/dglpf.c620
-rw-r--r--src/mesa/drivers/windows/gldirect/dglpf.h77
-rw-r--r--src/mesa/drivers/windows/gldirect/dglwgl.c2958
-rw-r--r--src/mesa/drivers/windows/gldirect/dglwgl.h102
-rw-r--r--src/mesa/drivers/windows/gldirect/dll_main.c816
-rw-r--r--src/mesa/drivers/windows/gldirect/dllmain.h64
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c1195
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_dx7.h292
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_dxerr7.h77
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_ext_dx7.c346
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_pipeline_dx7.c77
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c1448
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_texture_dx7.c2054
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_vb_d3d_render_dx7.c288
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_vb_mesa_render_dx7.c490
-rw-r--r--src/mesa/drivers/windows/gldirect/dx7/gld_wgl_dx7.c1611
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c1175
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_dx8.h324
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_dxerr8.h77
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_ext_dx8.c344
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_pipeline_dx8.c77
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c1446
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_texture_dx8.c1907
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_vb_d3d_render_dx8.c281
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_vb_mesa_render_dx8.c513
-rw-r--r--src/mesa/drivers/windows/gldirect/dx8/gld_wgl_dx8.c1335
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c1205
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_dx9.h327
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_dxerr9.h77
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_ext_dx9.c344
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_pipeline_dx9.c77
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c1446
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_texture_dx9.c1965
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_vb_d3d_render_dx9.c281
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_vb_mesa_render_dx9.c510
-rw-r--r--src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c1345
-rw-r--r--src/mesa/drivers/windows/gldirect/gld_debug_clip.c40
-rw-r--r--src/mesa/drivers/windows/gldirect/gld_debug_norm.c40
-rw-r--r--src/mesa/drivers/windows/gldirect/gld_debug_xform.c42
-rw-r--r--src/mesa/drivers/windows/gldirect/gld_dispatch.c73
-rw-r--r--src/mesa/drivers/windows/gldirect/gld_driver.c279
-rw-r--r--src/mesa/drivers/windows/gldirect/gld_driver.h90
-rw-r--r--src/mesa/drivers/windows/gldirect/gldirect.rc43
-rw-r--r--src/mesa/drivers/windows/gldirect/gldlame8.c181
-rw-r--r--src/mesa/drivers/windows/gldirect/mesasw/colors.h523
-rw-r--r--src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c1718
-rw-r--r--src/mesa/drivers/windows/gldirect/opengl32.def488
-rw-r--r--src/mesa/drivers/windows/gldirect/opengl32.ref495
-rw-r--r--src/mesa/drivers/windows/gldirect/pixpack.h108
56 files changed, 34924 insertions, 0 deletions
diff --git a/src/mesa/drivers/windows/gldirect/ddlog.c b/src/mesa/drivers/windows/gldirect/ddlog.c
new file mode 100644
index 0000000000..4ae79e2fda
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/ddlog.c
@@ -0,0 +1,192 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Logging functions.
+*
+****************************************************************************/
+
+#define STRICT
+#include <windows.h>
+
+#include "ddlog.h"
+#include "gld_driver.h"
+
+// ***********************************************************************
+
+static char ddlogbuf[256];
+static FILE* fpDDLog = NULL; // Log file pointer
+static char szDDLogName[_MAX_PATH] = {"gldirect.log"}; // Filename of the log
+static DDLOG_loggingMethodType ddlogLoggingMethod = DDLOG_NONE; // Default to No Logging
+static DDLOG_severityType ddlogDebugLevel;
+static BOOL bUIWarning = FALSE; // MessageBox warning ?
+
+// ***********************************************************************
+
+void ddlogOpen(
+ DDLOG_loggingMethodType LoggingMethod,
+ DDLOG_severityType Severity)
+{
+ if (fpDDLog != NULL) {
+ // Tried to re-open the log
+ ddlogMessage(DDLOG_WARN, "Tried to re-open the log file\n");
+ return;
+ }
+
+ ddlogLoggingMethod = LoggingMethod;
+ ddlogDebugLevel = Severity;
+
+ if (ddlogLoggingMethod == DDLOG_NORMAL) {
+ fpDDLog = fopen(szDDLogName, "wt");
+ if (fpDDLog == NULL)
+ return;
+ }
+
+ ddlogMessage(DDLOG_SYSTEM, "\n");
+ ddlogMessage(DDLOG_SYSTEM, "-> Logging Started\n");
+}
+
+// ***********************************************************************
+
+void ddlogClose()
+{
+ // Determine whether the log is already closed
+ if (fpDDLog == NULL && ddlogLoggingMethod == DDLOG_NORMAL)
+ return; // Nothing to do.
+
+ ddlogMessage(DDLOG_SYSTEM, "<- Logging Ended\n");
+
+ if (ddlogLoggingMethod == DDLOG_NORMAL) {
+ fclose(fpDDLog);
+ fpDDLog = NULL;
+ }
+}
+
+// ***********************************************************************
+
+void ddlogMessage(
+ DDLOG_severityType severity,
+ LPSTR message)
+{
+ char buf[256];
+
+ // Bail if logging is disabled
+ if (ddlogLoggingMethod == DDLOG_NONE)
+ return;
+
+ if (ddlogLoggingMethod == DDLOG_CRASHPROOF)
+ fpDDLog = fopen(szDDLogName, "at");
+
+ if (fpDDLog == NULL)
+ return;
+
+ if (severity >= ddlogDebugLevel) {
+ sprintf(buf, "DDLog: (%s) %s", ddlogSeverityMessages[severity], message);
+ fputs(buf, fpDDLog); // Write string to file
+ OutputDebugString(buf); // Echo to debugger
+ }
+
+ if (ddlogLoggingMethod == DDLOG_CRASHPROOF) {
+ fflush(fpDDLog); // Write info to disk
+ fclose(fpDDLog);
+ fpDDLog = NULL;
+ }
+
+ // Popup message box if critical error
+ if (bUIWarning && severity == DDLOG_CRITICAL) {
+ MessageBox(NULL, buf, "GLDirect", MB_OK | MB_ICONWARNING | MB_TASKMODAL);
+ }
+}
+
+// ***********************************************************************
+
+// Write a string value to the log file
+void ddlogError(
+ DDLOG_severityType severity,
+ LPSTR message,
+ HRESULT hResult)
+{
+#ifdef _USE_GLD3_WGL
+ char dxErrStr[1024];
+ _gldDriver.GetDXErrorString(hResult, &dxErrStr[0], sizeof(dxErrStr));
+ if (FAILED(hResult)) {
+ sprintf(ddlogbuf, "DDLog: %s %8x:[ %s ]\n", message, hResult, dxErrStr);
+ } else
+ sprintf(ddlogbuf, "DDLog: %s\n", message);
+#else
+ if (FAILED(hResult)) {
+ sprintf(ddlogbuf, "DDLog: %s %8x:[ %s ]\n", message, hResult, DDErrorToString(hResult));
+ } else
+ sprintf(ddlogbuf, "DDLog: %s\n", message);
+#endif
+ ddlogMessage(severity, ddlogbuf);
+}
+
+// ***********************************************************************
+
+void ddlogPrintf(
+ DDLOG_severityType severity,
+ LPSTR message,
+ ...)
+{
+ va_list args;
+
+ va_start(args, message);
+ vsprintf(ddlogbuf, message, args);
+ va_end(args);
+
+ lstrcat(ddlogbuf, "\n");
+
+ ddlogMessage(severity, ddlogbuf);
+}
+
+// ***********************************************************************
+
+void ddlogWarnOption(
+ BOOL bWarnOption)
+{
+ bUIWarning = bWarnOption;
+}
+
+// ***********************************************************************
+
+void ddlogPathOption(
+ LPSTR szPath)
+{
+ char szPathName[_MAX_PATH];
+
+ strcpy(szPathName, szPath);
+ strcat(szPathName, "\\");
+ strcat(szPathName, szDDLogName);
+ strcpy(szDDLogName, szPathName);
+}
+
+// ***********************************************************************
diff --git a/src/mesa/drivers/windows/gldirect/ddlog.h b/src/mesa/drivers/windows/gldirect/ddlog.h
new file mode 100644
index 0000000000..d64067e224
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/ddlog.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Logging functions.
+*
+****************************************************************************/
+
+#ifndef __DDLOG_H
+#define __DDLOG_H
+
+#include <stdio.h>
+
+#ifndef _USE_GLD3_WGL
+#include "dderrstr.h" // ddraw/d3d error string
+#endif
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+typedef enum {
+ DDLOG_NONE = 0, // No log output
+ DDLOG_NORMAL = 1, // Log is kept open
+ DDLOG_CRASHPROOF = 2, // Log is closed and flushed
+ DDLOG_METHOD_FORCE_DWORD = 0x7fffffff,
+} DDLOG_loggingMethodType;
+
+// Denotes type of message sent to the logging functions
+typedef enum {
+ DDLOG_INFO = 0, // Information only
+ DDLOG_WARN = 1, // Warning only
+ DDLOG_ERROR = 2, // Notify user of an error
+ DDLOG_CRITICAL = 3, // Exceptionally severe error
+ DDLOG_SYSTEM = 4, // System message. Not an error
+ // but must always be printed.
+ DDLOG_SEVERITY_FORCE_DWORD = 0x7fffffff, // Make enum dword
+} DDLOG_severityType;
+
+#ifdef _USE_GLD3_WGL
+// Synomyms
+#define GLDLOG_INFO DDLOG_INFO
+#define GLDLOG_WARN DDLOG_WARN
+#define GLDLOG_ERROR DDLOG_ERROR
+#define GLDLOG_CRITICAL DDLOG_CRITICAL
+#define GLDLOG_SYSTEM DDLOG_SYSTEM
+#endif
+
+// The message that will be output to the log
+static const char *ddlogSeverityMessages[] = {
+ "INFO",
+ "WARN",
+ "ERROR",
+ "*CRITICAL*",
+ "System",
+};
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void ddlogOpen(DDLOG_loggingMethodType LoggingMethod, DDLOG_severityType Severity);
+void ddlogClose();
+void ddlogMessage(DDLOG_severityType severity, LPSTR message);
+void ddlogError(DDLOG_severityType severity, LPSTR message, HRESULT hResult);
+void ddlogPrintf(DDLOG_severityType severity, LPSTR message, ...);
+void ddlogWarnOption(BOOL bWarnOption);
+void ddlogPathOption(LPSTR szPath);
+
+#ifdef _USE_GLD3_WGL
+// Synomyms
+#define gldLogMessage ddlogMessage
+#define gldLogError ddlogError
+#define gldLogPrintf ddlogPrintf
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/mesa/drivers/windows/gldirect/dglcontext.c b/src/mesa/drivers/windows/gldirect/dglcontext.c
new file mode 100644
index 0000000000..c504be58ac
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dglcontext.c
@@ -0,0 +1,2213 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Context handling.
+*
+****************************************************************************/
+
+#include "dglcontext.h"
+
+// Get compile errors without this. KeithH
+#include "scitech.h" // ibool, etc.
+
+#ifdef _USE_GLD3_WGL
+#include "gld_driver.h"
+
+extern void _gld_mesa_warning(GLcontext *, char *);
+extern void _gld_mesa_fatal(GLcontext *, char *);
+#endif // _USE_GLD3_WGL
+
+// TODO: Clean out old DX6-specific code from GLD 2.x CAD driver
+// if it is no longer being built as part of GLDirect. (DaveM)
+
+// ***********************************************************************
+
+#define GLDERR_NONE 0
+#define GLDERR_MEM 1
+#define GLDERR_DDRAW 2
+#define GLDERR_D3D 3
+#define GLDERR_BPP 4
+
+char szResourceWarning[] =
+"GLDirect does not have enough video memory resources\n"
+"to support the requested OpenGL rendering context.\n\n"
+"You may have to reduce the current display resolution\n"
+"to obtain satisfactory OpenGL performance.\n";
+
+char szDDrawWarning[] =
+"GLDirect is unable to initialize DirectDraw for the\n"
+"requested OpenGL rendering context.\n\n"
+"You will have to check the DirectX control panel\n"
+"for further information.\n";
+
+char szD3DWarning[] =
+"GLDirect is unable to initialize Direct3D for the\n"
+"requested OpenGL rendering context.\n\n"
+"You may have to change the display mode resolution\n"
+"color depth or check the DirectX control panel for\n"
+"further information.\n";
+
+char szBPPWarning[] =
+"GLDirect is unable to use the selected color depth for\n"
+"the requested OpenGL rendering context.\n\n"
+"You will have to change the display mode resolution\n"
+"color depth with the Display Settings control panel.\n";
+
+int nContextError = GLDERR_NONE;
+
+// ***********************************************************************
+
+#define VENDORID_ATI 0x1002
+
+static DWORD devATIRagePro[] = {
+ 0x4742, // 3D RAGE PRO BGA AGP 1X/2X
+ 0x4744, // 3D RAGE PRO BGA AGP 1X only
+ 0x4749, // 3D RAGE PRO BGA PCI 33 MHz
+ 0x4750, // 3D RAGE PRO PQFP PCI 33 MHz
+ 0x4751, // 3D RAGE PRO PQFP PCI 33 MHz limited 3D
+ 0x4C42, // 3D RAGE LT PRO BGA-312 AGP 133 MHz
+ 0x4C44, // 3D RAGE LT PRO BGA-312 AGP 66 MHz
+ 0x4C49, // 3D RAGE LT PRO BGA-312 PCI 33 MHz
+ 0x4C50, // 3D RAGE LT PRO BGA-256 PCI 33 MHz
+ 0x4C51, // 3D RAGE LT PRO BGA-256 PCI 33 MHz limited 3D
+};
+
+static DWORD devATIRageIIplus[] = {
+ 0x4755, // 3D RAGE II+
+ 0x4756, // 3D RAGE IIC PQFP PCI
+ 0x4757, // 3D RAGE IIC BGA AGP
+ 0x475A, // 3D RAGE IIC PQFP AGP
+ 0x4C47, // 3D RAGE LT-G
+};
+
+// ***********************************************************************
+
+#ifndef _USE_GLD3_WGL
+extern DGL_mesaFuncs mesaFuncs;
+#endif
+
+extern DWORD dwLogging;
+
+#ifdef GLD_THREADS
+#pragma message("compiling DGLCONTEXT.C vars for multi-threaded support")
+CRITICAL_SECTION CriticalSection; // for serialized access
+DWORD dwTLSCurrentContext = 0xFFFFFFFF; // TLS index for current context
+DWORD dwTLSPixelFormat = 0xFFFFFFFF; // TLS index for current pixel format
+#endif
+HGLRC iCurrentContext = 0; // Index of current context (static)
+BOOL bContextReady = FALSE; // Context state ready ?
+
+DGL_ctx ctxlist[DGL_MAX_CONTEXTS]; // Context list
+
+// ***********************************************************************
+
+static BOOL bHaveWin95 = FALSE;
+static BOOL bHaveWinNT = FALSE;
+static BOOL bHaveWin2K = FALSE;
+
+/****************************************************************************
+REMARKS:
+Detect the installed OS type.
+****************************************************************************/
+static void DetectOS(void)
+{
+ OSVERSIONINFO VersionInformation;
+ LPOSVERSIONINFO lpVersionInformation = &VersionInformation;
+
+ VersionInformation.dwOSVersionInfoSize = sizeof(VersionInformation);
+
+ GetVersionEx(lpVersionInformation);
+
+ switch (VersionInformation.dwPlatformId) {
+ case VER_PLATFORM_WIN32_WINDOWS:
+ bHaveWin95 = TRUE;
+ bHaveWinNT = FALSE;
+ bHaveWin2K = FALSE;
+ break;
+ case VER_PLATFORM_WIN32_NT:
+ bHaveWin95 = FALSE;
+ if (VersionInformation.dwMajorVersion <= 4) {
+ bHaveWinNT = TRUE;
+ bHaveWin2K = FALSE;
+ }
+ else {
+ bHaveWinNT = FALSE;
+ bHaveWin2K = TRUE;
+ }
+ break;
+ case VER_PLATFORM_WIN32s:
+ bHaveWin95 = FALSE;
+ bHaveWinNT = FALSE;
+ bHaveWin2K = FALSE;
+ break;
+ }
+}
+
+// ***********************************************************************
+
+HWND hWndEvent = NULL; // event monitor window
+HWND hWndLastActive = NULL; // last active client window
+LONG __stdcall GLD_EventWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
+
+// ***********************************************************************
+
+// Checks if the HGLRC is valid in range of context list.
+BOOL dglIsValidContext(
+ HGLRC a)
+{
+ return ((int)a > 0 && (int)a <= DGL_MAX_CONTEXTS);
+}
+
+// ***********************************************************************
+
+// Convert a HGLRC to a pointer into the context list.
+DGL_ctx* dglGetContextAddress(
+ const HGLRC a)
+{
+ if (dglIsValidContext(a))
+ return &ctxlist[(int)a-1];
+ return NULL;
+}
+
+// ***********************************************************************
+
+// Return the current HGLRC (however it may be stored for multi-threading).
+HGLRC dglGetCurrentContext(void)
+{
+#ifdef GLD_THREADS
+ HGLRC hGLRC;
+ // load from thread-specific instance
+ if (glb.bMultiThreaded) {
+ // protect against calls from arbitrary threads
+ __try {
+ hGLRC = (HGLRC)TlsGetValue(dwTLSCurrentContext);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ hGLRC = iCurrentContext;
+ }
+ }
+ // load from global static var
+ else {
+ hGLRC = iCurrentContext;
+ }
+ return hGLRC;
+#else
+ return iCurrentContext;
+#endif
+}
+
+// ***********************************************************************
+
+// Set the current HGLRC (however it may be stored for multi-threading).
+void dglSetCurrentContext(HGLRC hGLRC)
+{
+#ifdef GLD_THREADS
+ // store in thread-specific instance
+ if (glb.bMultiThreaded) {
+ // protect against calls from arbitrary threads
+ __try {
+ TlsSetValue(dwTLSCurrentContext, (LPVOID)hGLRC);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ iCurrentContext = hGLRC;
+ }
+ }
+ // store in global static var
+ else {
+ iCurrentContext = hGLRC;
+ }
+#else
+ iCurrentContext = hGLRC;
+#endif
+}
+
+// ***********************************************************************
+
+// Return the current HDC only for a currently active HGLRC.
+HDC dglGetCurrentDC(void)
+{
+ HGLRC hGLRC;
+ DGL_ctx* lpCtx;
+
+ hGLRC = dglGetCurrentContext();
+ if (hGLRC) {
+ lpCtx = dglGetContextAddress(hGLRC);
+ return lpCtx->hDC;
+ }
+ return 0;
+}
+
+// ***********************************************************************
+
+void dglInitContextState()
+{
+ int i;
+ WNDCLASS wc;
+
+#ifdef GLD_THREADS
+ // Allocate thread local storage indexes for current context and pixel format
+ dwTLSCurrentContext = TlsAlloc();
+ dwTLSPixelFormat = TlsAlloc();
+#endif
+
+ dglSetCurrentContext(NULL); // No current rendering context
+
+ // Clear all context data
+ ZeroMemory(ctxlist, sizeof(ctxlist[0]) * DGL_MAX_CONTEXTS);
+
+ for (i=0; i<DGL_MAX_CONTEXTS; i++)
+ ctxlist[i].bAllocated = FALSE; // Flag context as unused
+
+ // This section of code crashes the dll in circumstances where the app
+ // creates and destroys contexts.
+/*
+ // Register the class for our event monitor window
+ wc.style = 0;
+ wc.lpfnWndProc = GLD_EventWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = GetModuleHandle(NULL);
+ wc.hIcon = LoadIcon(GetModuleHandle(NULL), IDI_APPLICATION);
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = "GLDIRECT";
+ RegisterClass(&wc);
+
+ // Create the non-visible window to monitor all broadcast messages
+ hWndEvent = CreateWindowEx(
+ WS_EX_TOOLWINDOW,"GLDIRECT","GLDIRECT",WS_POPUP,
+ 0,0,0,0,
+ NULL,NULL,GetModuleHandle(NULL),NULL);
+*/
+
+#ifdef GLD_THREADS
+ // Create a critical section object for serializing access to
+ // DirectDraw and DDStereo create/destroy functions in multiple threads
+ if (glb.bMultiThreaded)
+ InitializeCriticalSection(&CriticalSection);
+#endif
+
+ // Context state is now initialized and ready
+ bContextReady = TRUE;
+}
+
+// ***********************************************************************
+
+void dglDeleteContextState()
+{
+ int i;
+ static BOOL bOnceIsEnough = FALSE;
+
+ // Only call once, from either DGL_exitDriver(), or DLL_PROCESS_DETACH
+ if (bOnceIsEnough)
+ return;
+ bOnceIsEnough = TRUE;
+
+ for (i=0; i<DGL_MAX_CONTEXTS; i++) {
+ if (ctxlist[i].bAllocated == TRUE) {
+ ddlogPrintf(DDLOG_WARN, "** Context %i not deleted - cleaning up.", (i+1));
+ dglDeleteContext((HGLRC)(i+1));
+ }
+ }
+
+ // Context state is no longer ready
+ bContextReady = FALSE;
+
+ // If executed when DLL unloads, DDraw objects may be invalid.
+ // So catch any page faults with this exception handler.
+__try {
+
+ // Release final DirectDraw interfaces
+ if (glb.bDirectDrawPersistant) {
+// RELEASE(glb.lpGlobalPalette);
+// RELEASE(glb.lpDepth4);
+// RELEASE(glb.lpBack4);
+// RELEASE(glb.lpPrimary4);
+// RELEASE(glb.lpDD4);
+ }
+}
+__except(EXCEPTION_EXECUTE_HANDLER) {
+ ddlogPrintf(DDLOG_WARN, "Exception raised in dglDeleteContextState.");
+}
+
+ // Destroy our event monitor window
+ if (hWndEvent) {
+ DestroyWindow(hWndEvent);
+ hWndEvent = hWndLastActive = NULL;
+ }
+
+#ifdef GLD_THREADS
+ // Destroy the critical section object
+ if (glb.bMultiThreaded)
+ DeleteCriticalSection(&CriticalSection);
+
+ // Release thread local storage indexes for current HGLRC and pixel format
+ TlsFree(dwTLSPixelFormat);
+ TlsFree(dwTLSCurrentContext);
+#endif
+}
+
+// ***********************************************************************
+
+// Application Window message handler interception
+static LONG __stdcall dglWndProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ DGL_ctx* lpCtx = NULL;
+ LONG lpfnWndProc = 0L;
+ int i;
+ HGLRC hGLRC;
+ RECT rect;
+ PAINTSTRUCT ps;
+ BOOL bQuit = FALSE;
+ BOOL bMain = FALSE;
+ LONG rc;
+
+ // Get the window's message handler *before* it is unhooked in WM_DESTROY
+
+ // Is this the main window?
+ if (hwnd == glb.hWndActive) {
+ bMain = TRUE;
+ lpfnWndProc = glb.lpfnWndProc;
+ }
+ // Search for DGL context matching window handle
+ for (i=0; i<DGL_MAX_CONTEXTS; i++) {
+ if (ctxlist[i].hWnd == hwnd) {
+ lpCtx = &ctxlist[i];
+ lpfnWndProc = lpCtx->lpfnWndProc;
+ break;
+ }
+ }
+ // Not one of ours...
+ if (!lpfnWndProc)
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+
+ // Intercept messages amd process *before* passing on to window
+ switch (msg) {
+#ifdef _USE_GLD3_WGL
+ case WM_DISPLAYCHANGE:
+ glb.bPixelformatsDirty = TRUE;
+ break;
+#endif
+ case WM_ACTIVATEAPP:
+ glb.bAppActive = (BOOL)wParam;
+ ddlogPrintf(DDLOG_INFO, "Calling app has been %s", glb.bAppActive ? "activated" : "de-activated");
+ break;
+ case WM_ERASEBKGND:
+ // Eat the GDI erase event for the GL window
+ if (!lpCtx || !lpCtx->bHasBeenCurrent)
+ break;
+ lpCtx->bGDIEraseBkgnd = TRUE;
+ return TRUE;
+ case WM_PAINT:
+ // Eat the invalidated update region if render scene is in progress
+ if (!lpCtx || !lpCtx->bHasBeenCurrent)
+ break;
+ if (lpCtx->bFrameStarted) {
+ if (GetUpdateRect(hwnd, &rect, FALSE)) {
+ BeginPaint(hwnd, &ps);
+ EndPaint(hwnd, &ps);
+ ValidateRect(hwnd, &rect);
+ return TRUE;
+ }
+ }
+ break;
+ }
+ // Call the appropriate window message handler
+ rc = CallWindowProc((WNDPROC)lpfnWndProc, hwnd, msg, wParam, lParam);
+
+ // Intercept messages and process *after* passing on to window
+ switch (msg) {
+ case WM_QUIT:
+ case WM_DESTROY:
+ bQuit = TRUE;
+ if (lpCtx && lpCtx->bAllocated) {
+ ddlogPrintf(DDLOG_WARN, "WM_DESTROY detected for HWND=%X, HDC=%X, HGLRC=%d", hwnd, lpCtx->hDC, i+1);
+ dglDeleteContext((HGLRC)(i+1));
+ }
+ break;
+#if 0
+ case WM_SIZE:
+ // Resize surfaces to fit window but not viewport (in case app did not bother)
+ if (!lpCtx || !lpCtx->bHasBeenCurrent)
+ break;
+ w = LOWORD(lParam);
+ h = HIWORD(lParam);
+ if (lpCtx->dwWidth < w || lpCtx->dwHeight < h) {
+ if (!dglWglResizeBuffers(lpCtx->glCtx, TRUE))
+ dglWglResizeBuffers(lpCtx->glCtx, FALSE);
+ }
+ break;
+#endif
+ }
+
+ // If the main window is quitting, then so should we...
+ if (bMain && bQuit) {
+ ddlogPrintf(DDLOG_SYSTEM, "shutting down after WM_DESTROY detected for main HWND=%X", hwnd);
+ dglDeleteContextState();
+ dglExitDriver();
+ }
+
+ return rc;
+}
+
+// ***********************************************************************
+
+// Driver Window message handler
+static LONG __stdcall GLD_EventWndProc(
+ HWND hwnd,
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch (msg) {
+ // May be sent by splash screen dialog on exit
+ case WM_ACTIVATE:
+ if (LOWORD(wParam) == WA_ACTIVE && glb.hWndActive) {
+ SetForegroundWindow(glb.hWndActive);
+ return 0;
+ }
+ break;
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+// ***********************************************************************
+
+// Intercepted Keyboard handler for detecting hot keys.
+LRESULT CALLBACK dglKeyProc(
+ int code,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ HWND hWnd, hWndFrame;
+ HGLRC hGLRC = NULL;
+ DGL_ctx* lpCtx = NULL;
+ int cmd = 0, dx1 = 0, dx2 = 0, i;
+ static ibool bAltPressed = false;
+ static ibool bCtrlPressed = false;
+ static ibool bShiftPressed = false;
+ RECT r, rf, rc;
+ POINT pt;
+ ibool bForceReshape = false;
+
+ return CallNextHookEx(hKeyHook, code, wParam, lParam);
+}
+
+// ***********************************************************************
+
+HWND hWndMatch;
+
+// Window handle enumeration procedure.
+BOOL CALLBACK dglEnumChildProc(
+ HWND hWnd,
+ LPARAM lParam)
+{
+ RECT rect;
+
+ // Find window handle with matching client rect.
+ GetClientRect(hWnd, &rect);
+ if (EqualRect(&rect, (RECT*)lParam)) {
+ hWndMatch = hWnd;
+ return FALSE;
+ }
+ // Continue with next child window.
+ return TRUE;
+}
+
+// ***********************************************************************
+
+// Find window handle with matching client rect.
+HWND dglFindWindowRect(
+ RECT* pRect)
+{
+ hWndMatch = NULL;
+ EnumChildWindows(GetForegroundWindow(), dglEnumChildProc, (LPARAM)pRect);
+ return hWndMatch;
+}
+
+// ***********************************************************************
+#ifndef _USE_GLD3_WGL
+void dglChooseDisplayMode(
+ DGL_ctx *lpCtx)
+{
+ // Note: Choose an exact match if possible.
+
+ int i;
+ DWORD area;
+ DWORD bestarea;
+ DDSURFACEDESC2 *lpDDSD = NULL; // Mode list pointer
+ DDSURFACEDESC2 *lpBestDDSD = NULL; // Pointer to best
+
+ lpDDSD = glb.lpDisplayModes;
+ for (i=0; i<glb.nDisplayModeCount; i++, lpDDSD++) {
+ if ((lpDDSD->dwWidth == lpCtx->dwWidth) &&
+ (lpDDSD->dwHeight == lpCtx->dwHeight))
+ goto matched; // Mode has been exactly matched
+ // Choose modes that are larger in both dimensions than
+ // the window, but smaller in area than the current best.
+ if ( (lpDDSD->dwWidth >= lpCtx->dwWidth) &&
+ (lpDDSD->dwHeight >= lpCtx->dwHeight))
+ {
+ if (lpBestDDSD == NULL) {
+ lpBestDDSD = lpDDSD;
+ bestarea = lpDDSD->dwWidth * lpDDSD->dwHeight;
+ continue;
+ }
+ area = lpDDSD->dwWidth * lpDDSD->dwHeight;
+ if (area < bestarea) {
+ lpBestDDSD = lpDDSD;
+ bestarea = area;
+ }
+ }
+ }
+
+ // Safety check
+ if (lpBestDDSD == NULL) {
+ ddlogMessage(DDLOG_CRITICAL, "dglChooseDisplayMode");
+ return;
+ }
+
+ lpCtx->dwModeWidth = lpBestDDSD->dwWidth;
+ lpCtx->dwModeHeight = lpBestDDSD->dwHeight;
+matched:
+ ddlogPrintf(DDLOG_INFO, "Matched (%ldx%ld) to (%ldx%ld)",
+ lpCtx->dwWidth, lpCtx->dwHeight, lpCtx->dwModeWidth, lpCtx->dwModeHeight);
+}
+#endif // _USE_GLD3_WGL
+// ***********************************************************************
+
+static BOOL IsDevice(
+ DWORD *lpDeviceIdList,
+ DWORD dwDeviceId,
+ int count)
+{
+ int i;
+
+ for (i=0; i<count; i++)
+ if (dwDeviceId == lpDeviceIdList[i])
+ return TRUE;
+
+ return FALSE;
+}
+
+// ***********************************************************************
+
+void dglTestForBrokenCards(
+ DGL_ctx *lpCtx)
+{
+#ifndef _GLD3
+ DDDEVICEIDENTIFIER dddi; // DX6 device identifier
+
+ // Sanity check.
+ if (lpCtx == NULL) {
+ // Testing for broken cards is sensitive area, so we don't want
+ // anything saying "broken cards" in the error message. ;)
+ ddlogMessage(DDLOG_ERROR, "Null context passed to TFBC\n");
+ return;
+ }
+
+ if (lpCtx->lpDD4 == NULL) {
+ // Testing for broken cards is sensitive area, so we don't want
+ // anything saying "broken cards" in the error message. ;)
+ ddlogMessage(DDLOG_ERROR, "Null DD4 passed to TFBC\n");
+ return;
+ }
+
+ // Microsoft really fucked up with the GetDeviceIdentifier function
+ // on Windows 2000, since it locks up on stock driers on the CD. Updated
+ // drivers from vendors appear to work, but we can't identify the drivers
+ // without this function!!! For now we skip these tests on Windows 2000.
+ if ((GetVersion() & 0x80000000UL) == 0)
+ return;
+
+ // Obtain device info
+ if (FAILED(IDirectDraw4_GetDeviceIdentifier(lpCtx->lpDD4, &dddi, 0)))
+ return;
+
+ // Useful info. Log it.
+ ddlogPrintf(DDLOG_INFO, "DirectDraw: VendorId=0x%x, DeviceId=0x%x", dddi.dwVendorId, dddi.dwDeviceId);
+
+ // Vendor 1: ATI
+ if (dddi.dwVendorId == VENDORID_ATI) {
+ // Test A: ATI Rage PRO
+ if (IsDevice(devATIRagePro, dddi.dwDeviceId, sizeof(devATIRagePro)))
+ glb.bUseMipmaps = FALSE;
+ // Test B: ATI Rage II+
+ if (IsDevice(devATIRageIIplus, dddi.dwDeviceId, sizeof(devATIRageIIplus)))
+ glb.bEmulateAlphaTest = TRUE;
+ }
+
+ // Vendor 2: Matrox
+ if (dddi.dwVendorId == 0x102B) {
+ // Test: Matrox G400 stencil buffer support does not work for AutoCAD
+ if (dddi.dwDeviceId == 0x0525) {
+ lpCtx->lpPF->pfd.cStencilBits = 0;
+ if (lpCtx->lpPF->iZBufferPF != -1) {
+ glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwStencilBitDepth = 0;
+ glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwStencilBitMask = 0;
+ glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwFlags &= ~DDPF_STENCILBUFFER;
+ }
+ }
+ }
+#endif // _GLD3
+}
+
+// ***********************************************************************
+
+BOOL dglCreateContextBuffers(
+ HDC a,
+ DGL_ctx *lpCtx,
+ BOOL bFallback)
+{
+ HRESULT hResult;
+
+ int i;
+// HGLRC hGLRC;
+// DGL_ctx* lpCtx;
+
+#ifndef _USE_GLD3_WGL
+ DWORD dwFlags;
+ DDSURFACEDESC2 ddsd2;
+ DDSCAPS2 ddscaps2;
+ LPDIRECTDRAWCLIPPER lpddClipper;
+ D3DDEVICEDESC D3DHWDevDesc; // Direct3D Hardware description
+ D3DDEVICEDESC D3DHELDevDesc; // Direct3D Hardware Emulation Layer
+#endif // _USE_GLD3_WGL
+
+ float inv_aspect;
+
+ GLenum bDoubleBuffer; // TRUE if double buffer required
+ GLenum bDepthBuffer; // TRUE if depth buffer required
+
+ const PIXELFORMATDESCRIPTOR *lpPFD = &lpCtx->lpPF->pfd;
+
+ // Vars for Mesa visual
+ DWORD dwDepthBits = 0;
+ DWORD dwStencilBits = 0;
+ DWORD dwAlphaBits = 0;
+ DWORD bAlphaSW = GL_FALSE;
+ DWORD bDouble = GL_FALSE;
+
+ DDSURFACEDESC2 ddsd2DisplayMode;
+ BOOL bFullScrnWin = FALSE; // fullscreen-size window ?
+ DDBLTFX ddbltfx;
+ DWORD dwMemoryType = (bFallback) ? DDSCAPS_SYSTEMMEMORY : glb.dwMemoryType;
+ BOOL bBogusWindow = FALSE; // non-drawable window ?
+ DWORD dwColorRef = 0; // GDI background color
+ RECT rcDst; // GDI window rect
+ POINT pt; // GDI window point
+
+ // Palette used for creating default global palette
+ PALETTEENTRY ppe[256];
+
+#ifndef _USE_GLD3_WGL
+ // Vertex buffer description. Used for creation of vertex buffers
+ D3DVERTEXBUFFERDESC vbufdesc;
+#endif // _USE_GLD3_WGL
+
+#define DDLOG_CRITICAL_OR_WARN (bFallback ? DDLOG_CRITICAL : DDLOG_WARN)
+
+ ddlogPrintf(DDLOG_SYSTEM, "dglCreateContextBuffers for HDC=%X", a);
+ nContextError = GLDERR_NONE;
+
+#ifdef GLD_THREADS
+ // Serialize access to DirectDraw object creation or DDS start
+ if (glb.bMultiThreaded)
+ EnterCriticalSection(&CriticalSection);
+#endif
+
+ // Check for back buffer
+ bDoubleBuffer = GL_TRUE; //(lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE;
+ // Since we always do back buffering, check if we emulate front buffering
+ lpCtx->EmulateSingle =
+ (lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? FALSE : TRUE;
+#if 0 // Don't have to mimic MS OpenGL behavior for front-buffering (DaveM)
+ lpCtx->EmulateSingle |=
+ (lpPFD->dwFlags & PFD_SUPPORT_GDI) ? TRUE : FALSE;
+#endif
+
+ // Check for depth buffer
+ bDepthBuffer = (lpPFD->cDepthBits) ? GL_TRUE : GL_FALSE;
+
+ lpCtx->bDoubleBuffer = bDoubleBuffer;
+ lpCtx->bDepthBuffer = bDepthBuffer;
+
+ // Set the Fullscreen flag for the context.
+// lpCtx->bFullscreen = glb.bFullscreen;
+
+ // Obtain the dimensions of the rendering window
+ lpCtx->hDC = a; // Cache DC
+ lpCtx->hWnd = WindowFromDC(lpCtx->hDC);
+ // Check for non-window DC = memory DC ?
+ if (lpCtx->hWnd == NULL) {
+ // bitmap memory contexts are always single-buffered
+ lpCtx->EmulateSingle = TRUE;
+ bBogusWindow = TRUE;
+ ddlogPrintf(DDLOG_INFO, "Non-Window Memory Device Context");
+ if (GetClipBox(lpCtx->hDC, &lpCtx->rcScreenRect) == ERROR) {
+ ddlogMessage(DDLOG_WARN, "GetClipBox failed in dglCreateContext\n");
+ SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
+ }
+ }
+ else if (!GetClientRect(lpCtx->hWnd, &lpCtx->rcScreenRect)) {
+ bBogusWindow = TRUE;
+ ddlogMessage(DDLOG_WARN, "GetClientRect failed in dglCreateContext\n");
+ SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
+ }
+ lpCtx->dwWidth = lpCtx->rcScreenRect.right - lpCtx->rcScreenRect.left;
+ lpCtx->dwHeight = lpCtx->rcScreenRect.bottom - lpCtx->rcScreenRect.top;
+
+ ddlogPrintf(DDLOG_INFO, "Input window %X: w=%i, h=%i",
+ lpCtx->hWnd, lpCtx->dwWidth, lpCtx->dwHeight);
+
+ // What if app only zeroes one dimension instead of both? (DaveM)
+ if ( (lpCtx->dwWidth == 0) || (lpCtx->dwHeight == 0) ) {
+ // Make the buffer size something sensible
+ lpCtx->dwWidth = 8;
+ lpCtx->dwHeight = 8;
+ }
+
+ // Set defaults
+ lpCtx->dwModeWidth = lpCtx->dwWidth;
+ lpCtx->dwModeHeight = lpCtx->dwHeight;
+/*
+ // Find best display mode for fullscreen
+ if (glb.bFullscreen || !glb.bPrimary) {
+ dglChooseDisplayMode(lpCtx);
+ }
+*/
+ // Misc initialisation
+ lpCtx->bCanRender = FALSE; // No rendering allowed yet
+ lpCtx->bSceneStarted = FALSE;
+ lpCtx->bFrameStarted = FALSE;
+
+ // Detect OS (specifically 'Windows 2000' or 'Windows XP')
+ DetectOS();
+
+ // NOTE: WinNT not supported
+ ddlogPrintf(DDLOG_INFO, "OS: %s", bHaveWin95 ? "Win9x" : (bHaveWin2K ? "Win2000/XP" : "Unsupported") );
+
+ // Test for Fullscreen
+ if (bHaveWin95) { // Problems with fullscreen on Win2K/XP
+ if ((GetSystemMetrics(SM_CXSCREEN) == lpCtx->dwWidth) &&
+ (GetSystemMetrics(SM_CYSCREEN) == lpCtx->dwHeight))
+ {
+ // Workaround for some apps that crash when going fullscreen.
+ //lpCtx->bFullscreen = TRUE;
+ }
+
+ }
+
+#ifdef _USE_GLD3_WGL
+ _gldDriver.CreateDrawable(lpCtx, glb.bDirectDrawPersistant, glb.bPersistantBuffers);
+#else
+ // Check if DirectDraw has already been created by original GLRC (DaveM)
+ if (glb.bDirectDrawPersistant && glb.bDirectDraw) {
+ lpCtx->lpDD4 = glb.lpDD4;
+ IDirectDraw4_AddRef(lpCtx->lpDD4);
+ goto SkipDirectDrawCreate;
+ }
+
+ // Create DirectDraw object
+ if (glb.bPrimary)
+ hResult = DirectDrawCreate(NULL, &lpCtx->lpDD1, NULL);
+ else {
+ // A non-primary device is to be used.
+ // Force context to be Fullscreen, secondary adaptors can not
+ // be used in a window.
+ hResult = DirectDrawCreate(&glb.ddGuid, &lpCtx->lpDD1, NULL);
+ lpCtx->bFullscreen = TRUE;
+ }
+ if (FAILED(hResult)) {
+ MessageBox(NULL, "Unable to initialize DirectDraw", "GLDirect", MB_OK);
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create DirectDraw interface", hResult);
+ nContextError = GLDERR_DDRAW;
+ goto return_with_error;
+ }
+
+ // Query for DX6 IDirectDraw4.
+ hResult = IDirectDraw_QueryInterface(lpCtx->lpDD1,
+ &IID_IDirectDraw4,
+ (void**)&lpCtx->lpDD4);
+ if (FAILED(hResult)) {
+ MessageBox(NULL, "GLDirect requires DirectX 6.0 or above", "GLDirect", MB_OK);
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create DirectDraw4 interface", hResult);
+ nContextError = GLDERR_DDRAW;
+ goto return_with_error;
+ }
+
+ // Cache DirectDraw interface for subsequent GLRCs
+ if (glb.bDirectDrawPersistant && !glb.bDirectDraw) {
+ glb.lpDD4 = lpCtx->lpDD4;
+ IDirectDraw4_AddRef(glb.lpDD4);
+ glb.bDirectDraw = TRUE;
+ }
+SkipDirectDrawCreate:
+
+ // Now we have a DD4 interface we can check for broken cards
+ dglTestForBrokenCards(lpCtx);
+
+ // Test if primary device can use flipping instead of blitting
+ ZeroMemory(&ddsd2DisplayMode, sizeof(ddsd2DisplayMode));
+ ddsd2DisplayMode.dwSize = sizeof(ddsd2DisplayMode);
+ hResult = IDirectDraw4_GetDisplayMode(
+ lpCtx->lpDD4,
+ &ddsd2DisplayMode);
+ if (SUCCEEDED(hResult)) {
+ if ( (lpCtx->dwWidth == ddsd2DisplayMode.dwWidth) &&
+ (lpCtx->dwHeight == ddsd2DisplayMode.dwHeight) ) {
+ // We have a fullscreen-size window
+ bFullScrnWin = TRUE;
+ // OK to use DirectDraw fullscreen mode ?
+ if (glb.bPrimary && !glb.bFullscreenBlit && !lpCtx->EmulateSingle && !glb.bDirectDrawPersistant) {
+ lpCtx->bFullscreen = TRUE;
+ ddlogMessage(DDLOG_INFO, "Primary upgraded to page flipping.\n");
+ }
+ }
+ // Cache the display mode dimensions
+ lpCtx->dwModeWidth = ddsd2DisplayMode.dwWidth;
+ lpCtx->dwModeHeight = ddsd2DisplayMode.dwHeight;
+ }
+
+ // Clamp the effective window dimensions to primary surface.
+ // We need to do this for D3D viewport dimensions even if wide
+ // surfaces are supported. This also is a good idea for handling
+ // whacked-out window dimensions passed for non-drawable windows
+ // like Solid Edge. (DaveM)
+ if (lpCtx->dwWidth > ddsd2DisplayMode.dwWidth)
+ lpCtx->dwWidth = ddsd2DisplayMode.dwWidth;
+ if (lpCtx->dwHeight > ddsd2DisplayMode.dwHeight)
+ lpCtx->dwHeight = ddsd2DisplayMode.dwHeight;
+
+ // Check for non-RGB desktop resolution
+ if (!lpCtx->bFullscreen && ddsd2DisplayMode.ddpfPixelFormat.dwRGBBitCount <= 8) {
+ ddlogPrintf(DDLOG_CRITICAL_OR_WARN, "Desktop color depth %d bpp not supported",
+ ddsd2DisplayMode.ddpfPixelFormat.dwRGBBitCount);
+ nContextError = GLDERR_BPP;
+ goto return_with_error;
+ }
+#endif // _USE_GLD3_WGL
+
+ ddlogPrintf(DDLOG_INFO, "Window: w=%i, h=%i (%s)",
+ lpCtx->dwWidth,
+ lpCtx->dwHeight,
+ lpCtx->bFullscreen ? "fullscreen" : "windowed");
+
+#ifndef _USE_GLD3_WGL
+ // Obtain ddraw caps
+ ZeroMemory(&lpCtx->ddCaps, sizeof(DDCAPS));
+ lpCtx->ddCaps.dwSize = sizeof(DDCAPS);
+ if (glb.bHardware) {
+ // Get HAL caps
+ IDirectDraw4_GetCaps(lpCtx->lpDD4, &lpCtx->ddCaps, NULL);
+ } else {
+ // Get HEL caps
+ IDirectDraw4_GetCaps(lpCtx->lpDD4, NULL, &lpCtx->ddCaps);
+ }
+
+ // If this flag is present then we can't default to Mesa
+ // SW rendering between BeginScene() and EndScene().
+ if (lpCtx->ddCaps.dwCaps2 & DDCAPS2_NO2DDURING3DSCENE) {
+ ddlogMessage(DDLOG_INFO,
+ "Warning : No 2D allowed during 3D scene.\n");
+ }
+
+ // Query for DX6 Direct3D3 interface
+ hResult = IDirectDraw4_QueryInterface(lpCtx->lpDD4,
+ &IID_IDirect3D3,
+ (void**)&lpCtx->lpD3D3);
+ if (FAILED(hResult)) {
+ MessageBox(NULL, "Unable to initialize Direct3D", "GLDirect", MB_OK);
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D interface", hResult);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Context creation
+ if (lpCtx->bFullscreen) {
+ // FULLSCREEN
+
+ // Disable warning popups when in fullscreen mode
+ ddlogWarnOption(FALSE);
+
+ // Have to release persistant primary surface if fullscreen mode
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
+ RELEASE(glb.lpPrimary4);
+ glb.bDirectDrawPrimary = FALSE;
+ }
+
+ dwFlags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT;
+ if (glb.bFastFPU)
+ dwFlags |= DDSCL_FPUSETUP; // fast FPU setup optional (DaveM)
+ hResult = IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, lpCtx->hWnd, dwFlags);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to set Exclusive Fullscreen mode", hResult);
+ goto return_with_error;
+ }
+
+ hResult = IDirectDraw4_SetDisplayMode(lpCtx->lpDD4,
+ lpCtx->dwModeWidth,
+ lpCtx->dwModeHeight,
+ lpPFD->cColorBits,
+ 0,
+ 0);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "SetDisplayMode failed", hResult);
+ goto return_with_error;
+ }
+
+ // ** The display mode has changed, so dont use MessageBox! **
+
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+
+ if (bDoubleBuffer) {
+ // Double buffered
+ // Primary surface
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
+ DDSCAPS_FLIP |
+ DDSCAPS_COMPLEX |
+ DDSCAPS_3DDEVICE |
+ dwMemoryType;
+ ddsd2.dwBackBufferCount = 1;
+
+ hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+
+ // Render target surface
+ ZeroMemory(&ddscaps2, sizeof(ddscaps2)); // Clear the entire struct.
+ ddscaps2.dwCaps = DDSCAPS_BACKBUFFER;
+ hResult = IDirectDrawSurface4_GetAttachedSurface(lpCtx->lpFront4, &ddscaps2, &lpCtx->lpBack4);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "GetAttachedSurface failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+ } else {
+ // Single buffered
+ // Primary surface
+ ddsd2.dwFlags = DDSD_CAPS;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
+ //DDSCAPS_3DDEVICE |
+ dwMemoryType;
+
+ hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+
+ lpCtx->lpBack4 = NULL;
+ }
+ } else {
+ // WINDOWED
+
+ // OK to enable warning popups in windowed mode
+ ddlogWarnOption(glb.bMessageBoxWarnings);
+
+ dwFlags = DDSCL_NORMAL;
+ if (glb.bMultiThreaded)
+ dwFlags |= DDSCL_MULTITHREADED;
+ if (glb.bFastFPU)
+ dwFlags |= DDSCL_FPUSETUP; // fast FPU setup optional (DaveM)
+ hResult = IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4,
+ lpCtx->hWnd,
+ dwFlags);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to set Normal coop level", hResult);
+ goto return_with_error;
+ }
+ // Has Primary surface already been created for original GLRC ?
+ // Note this can only be applicable for windowed modes
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
+ lpCtx->lpFront4 = glb.lpPrimary4;
+ IDirectDrawSurface4_AddRef(lpCtx->lpFront4);
+ // Update the window on the default clipper
+ IDirectDrawSurface4_GetClipper(lpCtx->lpFront4, &lpddClipper);
+ IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
+ IDirectDrawClipper_Release(lpddClipper);
+ goto SkipPrimaryCreate;
+ }
+
+ // Primary surface
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (primary) failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+
+ // Cache Primary surface for subsequent GLRCs
+ // Note this can only be applicable to subsequent windowed modes
+ if (glb.bDirectDrawPersistant && !glb.bDirectDrawPrimary) {
+ glb.lpPrimary4 = lpCtx->lpFront4;
+ IDirectDrawSurface4_AddRef(glb.lpPrimary4);
+ glb.bDirectDrawPrimary = TRUE;
+ }
+
+ // Clipper object
+ hResult = DirectDrawCreateClipper(0, &lpddClipper, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateClipper failed", hResult);
+ goto return_with_error;
+ }
+ hResult = IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
+ if (FAILED(hResult)) {
+ RELEASE(lpddClipper);
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "SetHWnd failed", hResult);
+ goto return_with_error;
+ }
+ hResult = IDirectDrawSurface4_SetClipper(lpCtx->lpFront4, lpddClipper);
+ RELEASE(lpddClipper); // We have finished with it.
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "SetClipper failed", hResult);
+ goto return_with_error;
+ }
+SkipPrimaryCreate:
+
+ if (bDoubleBuffer) {
+ // Render target surface
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
+ ddsd2.dwWidth = lpCtx->dwWidth;
+ ddsd2.dwHeight = lpCtx->dwHeight;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE |
+ DDSCAPS_OFFSCREENPLAIN |
+ dwMemoryType;
+
+ // Reserve the entire desktop size for persistant buffers option
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
+ ddsd2.dwWidth = ddsd2DisplayMode.dwWidth;
+ ddsd2.dwHeight = ddsd2DisplayMode.dwHeight;
+ }
+ // Re-use original back buffer if persistant buffers exist
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpBack4)
+ hResult = IDirectDrawSurface4_AddRef(lpCtx->lpBack4 = glb.lpBack4);
+ else
+ hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpBack4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Create Backbuffer failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpBack4)
+ IDirectDrawSurface4_AddRef(glb.lpBack4 = lpCtx->lpBack4);
+ } else {
+ lpCtx->lpBack4 = NULL;
+ }
+ }
+
+ //
+ // Now create the Z-buffer
+ //
+ lpCtx->bStencil = FALSE; // Default to no stencil buffer
+ if (bDepthBuffer && (lpCtx->lpPF->iZBufferPF != -1)) {
+ // Get z-buffer dimensions from the render target
+ // Setup the surface desc for the z-buffer.
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | dwMemoryType;
+ ddsd2.dwWidth = lpCtx->dwWidth;
+ ddsd2.dwHeight = lpCtx->dwHeight;
+ memcpy(&ddsd2.ddpfPixelFormat,
+ &glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF],
+ sizeof(DDPIXELFORMAT) );
+
+ // Reserve the entire desktop size for persistant buffers option
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
+ ddsd2.dwWidth = ddsd2DisplayMode.dwWidth;
+ ddsd2.dwHeight = ddsd2DisplayMode.dwHeight;
+ }
+
+ // Create a z-buffer
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpDepth4)
+ hResult = IDirectDrawSurface4_AddRef(lpCtx->lpDepth4 = glb.lpDepth4);
+ else
+ hResult = IDirectDraw4_CreateSurface(lpCtx->lpDD4, &ddsd2, &lpCtx->lpDepth4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateSurface (ZBuffer) failed", hResult);
+ nContextError = GLDERR_MEM;
+ goto return_with_error;
+ }
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpDepth4)
+ IDirectDrawSurface4_AddRef(glb.lpDepth4 = lpCtx->lpDepth4);
+ else if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpDepth4 && glb.lpBack4)
+ IDirectDrawSurface4_DeleteAttachedSurface(glb.lpBack4, 0, glb.lpDepth4);
+
+ // Attach Zbuffer to render target
+ TRY(IDirectDrawSurface4_AddAttachedSurface(
+ bDoubleBuffer ? lpCtx->lpBack4 : lpCtx->lpFront4,
+ lpCtx->lpDepth4),
+ "dglCreateContext: Attach Zbuffer");
+ if (glb.lpZBufferPF[lpCtx->lpPF->iZBufferPF].dwFlags & DDPF_STENCILBUFFER) {
+ lpCtx->bStencil = TRUE;
+ ddlogMessage(DDLOG_INFO, "Depth buffer has stencil\n");
+ }
+ }
+
+ // Clear all back buffers and Z-buffers in case of memory recycling.
+ ZeroMemory(&ddbltfx, sizeof(ddbltfx));
+ ddbltfx.dwSize = sizeof(ddbltfx);
+ IDirectDrawSurface4_Blt(lpCtx->lpBack4, NULL, NULL, NULL,
+ DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
+ if (lpCtx->lpDepth4)
+ IDirectDrawSurface4_Blt(lpCtx->lpDepth4, NULL, NULL, NULL,
+ DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
+
+ // Now that we have a Z-buffer we can create the 3D device
+ hResult = IDirect3D3_CreateDevice(lpCtx->lpD3D3,
+ &glb.d3dGuid,
+ bDoubleBuffer ? lpCtx->lpBack4 : lpCtx->lpFront4,
+ &lpCtx->lpDev3,
+ NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D device", hResult);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // We must do this as soon as the device is created
+ dglInitStateCaches(lpCtx);
+
+ // Obtain the D3D Device Description
+ D3DHWDevDesc.dwSize = D3DHELDevDesc.dwSize = sizeof(D3DDEVICEDESC);
+ TRY(IDirect3DDevice3_GetCaps(lpCtx->lpDev3,
+ &D3DHWDevDesc,
+ &D3DHELDevDesc),
+ "dglCreateContext: GetCaps failed");
+
+ // Choose the relevant description and cache it in the context.
+ // We will use this description later for caps checking
+ memcpy( &lpCtx->D3DDevDesc,
+ glb.bHardware ? &D3DHWDevDesc : &D3DHELDevDesc,
+ sizeof(D3DDEVICEDESC));
+
+ // Now we can examine the texture formats
+ if (!dglBuildTextureFormatList(lpCtx->lpDev3)) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "dglBuildTextureFormatList failed\n");
+ goto return_with_error;
+ }
+
+ // Get the pixel format of the back buffer
+ lpCtx->ddpfRender.dwSize = sizeof(lpCtx->ddpfRender);
+ if (bDoubleBuffer)
+ hResult = IDirectDrawSurface4_GetPixelFormat(
+ lpCtx->lpBack4,
+ &lpCtx->ddpfRender);
+ else
+ hResult = IDirectDrawSurface4_GetPixelFormat(
+ lpCtx->lpFront4,
+ &lpCtx->ddpfRender);
+
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "GetPixelFormat failed", hResult);
+ goto return_with_error;
+ }
+ // Find a pixel packing function suitable for this surface
+ pxClassifyPixelFormat(&lpCtx->ddpfRender,
+ &lpCtx->fnPackFunc,
+ &lpCtx->fnUnpackFunc,
+ &lpCtx->fnPackSpanFunc);
+
+ // Viewport
+ hResult = IDirect3D3_CreateViewport(lpCtx->lpD3D3, &lpCtx->lpViewport3, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateViewport failed", hResult);
+ goto return_with_error;
+ }
+
+ hResult = IDirect3DDevice3_AddViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "AddViewport failed", hResult);
+ goto return_with_error;
+ }
+
+ // Initialise the viewport
+ // Note screen coordinates are used for viewport clipping since D3D
+ // transform operations are not used in the GLD CAD driver. (DaveM)
+ inv_aspect = (float)lpCtx->dwHeight/(float)lpCtx->dwWidth;
+
+ lpCtx->d3dViewport.dwSize = sizeof(lpCtx->d3dViewport);
+ lpCtx->d3dViewport.dwX = 0;
+ lpCtx->d3dViewport.dwY = 0;
+ lpCtx->d3dViewport.dwWidth = lpCtx->dwWidth;
+ lpCtx->d3dViewport.dwHeight = lpCtx->dwHeight;
+ lpCtx->d3dViewport.dvClipX = 0; // -1.0f;
+ lpCtx->d3dViewport.dvClipY = 0; // inv_aspect;
+ lpCtx->d3dViewport.dvClipWidth = lpCtx->dwWidth; // 2.0f;
+ lpCtx->d3dViewport.dvClipHeight = lpCtx->dwHeight; // 2.0f * inv_aspect;
+ lpCtx->d3dViewport.dvMinZ = 0.0f;
+ lpCtx->d3dViewport.dvMaxZ = 1.0f;
+ TRY(IDirect3DViewport3_SetViewport2(lpCtx->lpViewport3, &lpCtx->d3dViewport), "dglCreateContext: SetViewport2");
+
+ hResult = IDirect3DDevice3_SetCurrentViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "SetCurrentViewport failed", hResult);
+ goto return_with_error;
+ }
+
+ lpCtx->dwBPP = lpPFD->cColorBits;
+ lpCtx->iZBufferPF = lpCtx->lpPF->iZBufferPF;
+
+ // Set last texture to NULL
+ for (i=0; i<MAX_TEXTURE_UNITS; i++) {
+ lpCtx->ColorOp[i] = D3DTOP_DISABLE;
+ lpCtx->AlphaOp[i] = D3DTOP_DISABLE;
+ lpCtx->tObj[i] = NULL;
+ }
+
+ // Default to perspective correct texture mapping
+ dglSetRenderState(lpCtx, D3DRENDERSTATE_TEXTUREPERSPECTIVE, TRUE, "TexturePersp");
+
+ // Set the default culling mode
+ lpCtx->cullmode = D3DCULL_NONE;
+ dglSetRenderState(lpCtx, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE, "CullMode");
+
+ // Disable specular
+ dglSetRenderState(lpCtx, D3DRENDERSTATE_SPECULARENABLE, FALSE, "SpecularEnable");
+ // Disable subpixel correction
+// dglSetRenderState(lpCtx, D3DRENDERSTATE_SUBPIXEL, FALSE, "SubpixelEnable");
+ // Disable dithering
+ dglSetRenderState(lpCtx, D3DRENDERSTATE_DITHERENABLE, FALSE, "DitherEnable");
+
+ // Initialise the primitive caches
+// lpCtx->dwNextLineVert = 0;
+// lpCtx->dwNextTriVert = 0;
+
+ // Init the global texture palette
+ lpCtx->lpGlobalPalette = NULL;
+
+ // Init the HW/SW usage counters
+// lpCtx->dwHWUsageCount = lpCtx->dwSWUsageCount = 0L;
+
+ //
+ // Create two D3D vertex buffers.
+ // One will hold the pre-transformed data with the other one
+ // being used to hold the post-transformed & clipped verts.
+ //
+#if 0 // never used (DaveM)
+ vbufdesc.dwSize = sizeof(D3DVERTEXBUFFERDESC);
+ vbufdesc.dwCaps = D3DVBCAPS_WRITEONLY;
+ if (glb.bHardware == FALSE)
+ vbufdesc.dwCaps = D3DVBCAPS_SYSTEMMEMORY;
+ vbufdesc.dwNumVertices = 32768; // For the time being
+
+ // Source vertex buffer
+ vbufdesc.dwFVF = DGL_LVERTEX;
+ hResult = IDirect3D3_CreateVertexBuffer(lpCtx->lpD3D3, &vbufdesc, &lpCtx->m_vbuf, 0, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateVertexBuffer(src) failed", hResult);
+ goto return_with_error;
+ }
+
+ // Destination vertex buffer
+ vbufdesc.dwFVF = (glb.bMultitexture == FALSE) ? D3DFVF_TLVERTEX : (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX2);
+ hResult = IDirect3D3_CreateVertexBuffer(lpCtx->lpD3D3, &vbufdesc, &lpCtx->m_pvbuf, 0, NULL);
+ if(FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "CreateVertexBuffer(dst) failed", hResult);
+ goto return_with_error;
+ }
+#endif
+
+#endif _USE_GLD3_WGL
+
+ //
+ // Now create the Mesa context
+ //
+
+ // Create the Mesa visual
+ if (lpPFD->cDepthBits)
+ dwDepthBits = 16;
+ if (lpPFD->cStencilBits)
+ dwStencilBits = 8;
+ if (lpPFD->cAlphaBits) {
+ dwAlphaBits = 8;
+ bAlphaSW = GL_TRUE;
+ }
+ if (lpPFD->dwFlags & PFD_DOUBLEBUFFER)
+ bDouble = GL_TRUE;
+// lpCtx->EmulateSingle =
+// (lpPFD->dwFlags & PFD_DOUBLEBUFFER) ? FALSE : TRUE;
+
+#ifdef _USE_GLD3_WGL
+ lpCtx->glVis = _mesa_create_visual(
+ GL_TRUE, // RGB mode
+ bDouble, /* double buffer */
+ GL_FALSE, // stereo
+ lpPFD->cRedBits,
+ lpPFD->cGreenBits,
+ lpPFD->cBlueBits,
+ dwAlphaBits,
+ 0, // index bits
+ dwDepthBits,
+ dwStencilBits,
+ lpPFD->cAccumRedBits, // accum bits
+ lpPFD->cAccumGreenBits, // accum bits
+ lpPFD->cAccumBlueBits, // accum bits
+ lpPFD->cAccumAlphaBits, // accum alpha bits
+ 1 // num samples
+ );
+#else // _USE_GLD3_WGL
+ lpCtx->glVis = (*mesaFuncs.gl_create_visual)(
+ GL_TRUE, // RGB mode
+ bAlphaSW, // Is an alpha buffer required?
+ bDouble, // Is an double-buffering required?
+ GL_FALSE, // stereo
+ dwDepthBits, // depth_size
+ dwStencilBits, // stencil_size
+ lpPFD->cAccumBits, // accum_size
+ 0, // colour-index bits
+ lpPFD->cRedBits, // Red bit count
+ lpPFD->cGreenBits, // Green bit count
+ lpPFD->cBlueBits, // Blue bit count
+ dwAlphaBits // Alpha bit count
+ );
+#endif // _USE_GLD3_WGL
+
+ if (lpCtx->glVis == NULL) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_visual failed\n");
+ goto return_with_error;
+ }
+
+#ifdef _USE_GLD3_WGL
+ lpCtx->glCtx = _mesa_create_context(lpCtx->glVis, NULL, (void *)lpCtx, GL_TRUE);
+#else
+ // Create the Mesa context
+ lpCtx->glCtx = (*mesaFuncs.gl_create_context)(
+ lpCtx->glVis, // Mesa visual
+ NULL, // share list context
+ (void *)lpCtx, // Pointer to our driver context
+ GL_TRUE // Direct context flag
+ );
+#endif // _USE_GLD3_WGL
+
+ if (lpCtx->glCtx == NULL) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_context failed\n");
+ goto return_with_error;
+ }
+
+ // Create the Mesa framebuffer
+#ifdef _USE_GLD3_WGL
+ lpCtx->glBuffer = _mesa_create_framebuffer(
+ lpCtx->glVis,
+ lpCtx->glVis->depthBits > 0,
+ lpCtx->glVis->stencilBits > 0,
+ lpCtx->glVis->accumRedBits > 0,
+ GL_FALSE //swalpha
+ );
+#else
+ lpCtx->glBuffer = (*mesaFuncs.gl_create_framebuffer)(lpCtx->glVis);
+#endif // _USE_GLD3_WGL
+
+ if (lpCtx->glBuffer == NULL) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "gl_create_framebuffer failed\n");
+ goto return_with_error;
+ }
+
+#ifdef _USE_GLD3_WGL
+ // Init Mesa internals
+ _swrast_CreateContext( lpCtx->glCtx );
+ _ac_CreateContext( lpCtx->glCtx );
+ _tnl_CreateContext( lpCtx->glCtx );
+ _swsetup_CreateContext( lpCtx->glCtx );
+
+ _gldDriver.InitialiseMesa(lpCtx);
+
+ lpCtx->glCtx->imports.warning = _gld_mesa_warning;
+ lpCtx->glCtx->imports.fatal = _gld_mesa_fatal;
+
+#else
+ // Tell Mesa how many texture stages we have
+ glb.wMaxSimultaneousTextures = lpCtx->D3DDevDesc.wMaxSimultaneousTextures;
+ // Only use as many Units as the spec requires
+ if (glb.wMaxSimultaneousTextures > MAX_TEXTURE_UNITS)
+ glb.wMaxSimultaneousTextures = MAX_TEXTURE_UNITS;
+ lpCtx->glCtx->Const.MaxTextureUnits = glb.wMaxSimultaneousTextures;
+ ddlogPrintf(DDLOG_INFO, "Texture stages : %d", glb.wMaxSimultaneousTextures);
+
+ // Set the max texture size.
+ // NOTE: clamped to a max of 1024 for extra performance!
+ lpCtx->dwMaxTextureSize = (lpCtx->D3DDevDesc.dwMaxTextureWidth <= 1024) ? lpCtx->D3DDevDesc.dwMaxTextureWidth : 1024;
+
+// Texture resize takes place elsewhere. KH
+// NOTE: This was added to workaround an issue with the Intel app.
+#if 0
+ lpCtx->glCtx->Const.MaxTextureSize = lpCtx->dwMaxTextureSize;
+#else
+ lpCtx->glCtx->Const.MaxTextureSize = 1024;
+#endif
+
+ // Setup the Display Driver pointers
+ dglSetupDDPointers(lpCtx->glCtx);
+
+ // Initialise all the Direct3D renderstates
+ dglInitStateD3D(lpCtx->glCtx);
+
+#if 0
+ // Signal a reload of texture state on next glBegin
+ lpCtx->m_texHandleValid = FALSE;
+ lpCtx->m_mtex = FALSE;
+ lpCtx->m_texturing = FALSE;
+#else
+ // Set default texture unit state
+// dglSetTexture(lpCtx, 0, NULL);
+// dglSetTexture(lpCtx, 1, NULL);
+#endif
+
+ //
+ // Set the global texture palette to default values.
+ //
+
+ // Clear the entire palette
+ ZeroMemory(ppe, sizeof(PALETTEENTRY) * 256);
+
+ // Fill the palette with a default colour.
+ // A garish colour is used to catch bugs. Here Magenta is used.
+ for (i=0; i < 256; i++) {
+ ppe[i].peRed = 255;
+ ppe[i].peGreen = 0;
+ ppe[i].peBlue = 255;
+ }
+
+ RELEASE(lpCtx->lpGlobalPalette);
+
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && glb.lpGlobalPalette)
+ hResult = IDirectDrawPalette_AddRef(lpCtx->lpGlobalPalette = glb.lpGlobalPalette);
+ else
+ hResult = IDirectDraw4_CreatePalette(
+ lpCtx->lpDD4,
+ DDPCAPS_INITIALIZE | DDPCAPS_8BIT | DDPCAPS_ALLOW256,
+ ppe,
+ &(lpCtx->lpGlobalPalette),
+ NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_ERROR, "Default CreatePalette failed\n", hResult);
+ lpCtx->lpGlobalPalette = NULL;
+ goto return_with_error;
+ }
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers && !glb.lpGlobalPalette)
+ IDirectDrawPalette_AddRef(glb.lpGlobalPalette = lpCtx->lpGlobalPalette);
+
+#endif // _USE_GLD3_WGL
+
+ // ** If we have made it to here then we can enable rendering **
+ lpCtx->bCanRender = TRUE;
+
+// ddlogMessage(DDLOG_SYSTEM, "dglCreateContextBuffers succeded\n");
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ return TRUE;
+
+return_with_error:
+ // Clean up before returning.
+ // This is critical for secondary devices.
+
+ lpCtx->bCanRender = FALSE;
+
+#ifdef _USE_GLD3_WGL
+ // Destroy the Mesa context
+ if (lpCtx->glBuffer)
+ _mesa_destroy_framebuffer(lpCtx->glBuffer);
+ if (lpCtx->glCtx)
+ _mesa_destroy_context(lpCtx->glCtx);
+ if (lpCtx->glVis)
+ _mesa_destroy_visual(lpCtx->glVis);
+
+ // Destroy driver data
+ _gldDriver.DestroyDrawable(lpCtx);
+#else
+ // Destroy the Mesa context
+ if (lpCtx->glBuffer)
+ (*mesaFuncs.gl_destroy_framebuffer)(lpCtx->glBuffer);
+ if (lpCtx->glCtx)
+ (*mesaFuncs.gl_destroy_context)(lpCtx->glCtx);
+ if (lpCtx->glVis)
+ (*mesaFuncs.gl_destroy_visual)(lpCtx->glVis);
+
+ RELEASE(lpCtx->m_pvbuf); // Release D3D vertex buffer
+ RELEASE(lpCtx->m_vbuf); // Release D3D vertex buffer
+
+ if (lpCtx->lpViewport3) {
+ if (lpCtx->lpDev3) IDirect3DDevice3_DeleteViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
+ RELEASE(lpCtx->lpViewport3);
+ lpCtx->lpViewport3 = NULL;
+ }
+
+ RELEASE(lpCtx->lpDev3);
+ if (lpCtx->lpDepth4) {
+ if (lpCtx->lpBack4)
+ IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpBack4, 0L, lpCtx->lpDepth4);
+ else
+ IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpFront4, 0L, lpCtx->lpDepth4);
+ RELEASE(lpCtx->lpDepth4);
+ lpCtx->lpDepth4 = NULL;
+ }
+ RELEASE(lpCtx->lpBack4);
+ RELEASE(lpCtx->lpFront4);
+ else
+ if (lpCtx->bFullscreen) {
+ IDirectDraw4_RestoreDisplayMode(lpCtx->lpDD4);
+ IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, NULL, DDSCL_NORMAL);
+ }
+ RELEASE(lpCtx->lpD3D3);
+ RELEASE(lpCtx->lpDD4);
+ RELEASE(lpCtx->lpDD1);
+#endif // _USE_GLD3_WGL
+
+ lpCtx->bAllocated = FALSE;
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ return FALSE;
+
+#undef DDLOG_CRITICAL_OR_WARN
+}
+
+// ***********************************************************************
+
+HGLRC dglCreateContext(
+ HDC a,
+ const DGL_pixelFormat *lpPF)
+{
+ int i;
+ HGLRC hGLRC;
+ DGL_ctx* lpCtx;
+ static BOOL bWarnOnce = TRUE;
+ DWORD dwThreadId = GetCurrentThreadId();
+ char szMsg[256];
+ HWND hWnd;
+ LONG lpfnWndProc;
+
+ // Validate license
+ if (!dglValidate())
+ return NULL;
+
+ // Is context state ready ?
+ if (!bContextReady)
+ return NULL;
+
+ ddlogPrintf(DDLOG_SYSTEM, "dglCreateContext for HDC=%X, ThreadId=%X", a, dwThreadId);
+
+ // Find next free context.
+ // Also ensure that only one Fullscreen context is created at any one time.
+ hGLRC = 0; // Default to Not Found
+ for (i=0; i<DGL_MAX_CONTEXTS; i++) {
+ if (ctxlist[i].bAllocated) {
+ if (/*glb.bFullscreen && */ctxlist[i].bFullscreen)
+ break;
+ } else {
+ hGLRC = (HGLRC)(i+1);
+ break;
+ }
+ }
+
+ // Bail if no GLRC was found
+ if (!hGLRC)
+ return NULL;
+
+ // Set the context pointer
+ lpCtx = dglGetContextAddress(hGLRC);
+ // Make sure that context is zeroed before we do anything.
+ // MFC and C++ apps call wglCreateContext() and wglDeleteContext() multiple times,
+ // even though only one context is ever used by the app, so keep it clean. (DaveM)
+ ZeroMemory(lpCtx, sizeof(DGL_ctx));
+ lpCtx->bAllocated = TRUE;
+ // Flag that buffers need creating on next wglMakeCurrent call.
+ lpCtx->bHasBeenCurrent = FALSE;
+ lpCtx->lpPF = (DGL_pixelFormat *)lpPF; // cache pixel format
+ lpCtx->bCanRender = FALSE;
+
+ // Create all the internal resources here, not in dglMakeCurrent().
+ // We do a re-size check in dglMakeCurrent in case of re-allocations. (DaveM)
+ // We now try context allocations twice, first with video memory,
+ // then again with system memory. This is similar to technique
+ // used for dglWglResizeBuffers(). (DaveM)
+ if (lpCtx->bHasBeenCurrent == FALSE) {
+ if (!dglCreateContextBuffers(a, lpCtx, FALSE)) {
+ if (glb.bMessageBoxWarnings && bWarnOnce && dwLogging) {
+ bWarnOnce = FALSE;
+ switch (nContextError) {
+ case GLDERR_DDRAW: strcpy(szMsg, szDDrawWarning); break;
+ case GLDERR_D3D: strcpy(szMsg, szD3DWarning); break;
+ case GLDERR_MEM: strcpy(szMsg, szResourceWarning); break;
+ case GLDERR_BPP: strcpy(szMsg, szBPPWarning); break;
+ default: strcpy(szMsg, "");
+ }
+ if (strlen(szMsg))
+ MessageBox(NULL, szMsg, "GLDirect", MB_OK | MB_ICONWARNING);
+ }
+ // Only need to try again if memory error
+ if (nContextError == GLDERR_MEM) {
+ ddlogPrintf(DDLOG_WARN, "dglCreateContext failed 1st time with video memory");
+ }
+ else {
+ ddlogPrintf(DDLOG_ERROR, "dglCreateContext failed");
+ return NULL;
+ }
+ }
+ }
+
+ // Now that we have a hWnd, we can intercept the WindowProc.
+ hWnd = lpCtx->hWnd;
+ if (hWnd) {
+ // Only hook individual window handler once if not hooked before.
+ lpfnWndProc = GetWindowLong(hWnd, GWL_WNDPROC);
+ if (lpfnWndProc != (LONG)dglWndProc) {
+ lpCtx->lpfnWndProc = lpfnWndProc;
+ SetWindowLong(hWnd, GWL_WNDPROC, (LONG)dglWndProc);
+ }
+ // Find the parent window of the app too.
+ if (glb.hWndActive == NULL) {
+ while (hWnd != NULL) {
+ glb.hWndActive = hWnd;
+ hWnd = GetParent(hWnd);
+ }
+ // Hook the parent window too.
+ lpfnWndProc = GetWindowLong(glb.hWndActive, GWL_WNDPROC);
+ if (glb.hWndActive == lpCtx->hWnd)
+ glb.lpfnWndProc = lpCtx->lpfnWndProc;
+ else if (lpfnWndProc != (LONG)dglWndProc)
+ glb.lpfnWndProc = lpfnWndProc;
+ if (glb.lpfnWndProc)
+ SetWindowLong(glb.hWndActive, GWL_WNDPROC, (LONG)dglWndProc);
+ }
+ }
+
+ ddlogPrintf(DDLOG_SYSTEM, "dglCreateContext succeeded for HGLRC=%d", (int)hGLRC);
+
+ return hGLRC;
+}
+
+// ***********************************************************************
+// Make a DirectGL context current
+// Used by wgl functions and dgl functions
+BOOL dglMakeCurrent(
+ HDC a,
+ HGLRC b)
+{
+ int context;
+ DGL_ctx* lpCtx;
+ HWND hWnd;
+ BOOL bNeedResize = FALSE;
+ BOOL bWindowChanged, bContextChanged;
+ LPDIRECTDRAWCLIPPER lpddClipper;
+ DWORD dwThreadId = GetCurrentThreadId();
+ LONG lpfnWndProc;
+
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ // Is context state ready ?
+ if (!bContextReady)
+ return FALSE;
+
+ context = (int)b; // This is as a result of STRICT!
+ ddlogPrintf(DDLOG_SYSTEM, "dglMakeCurrent: HDC=%X, HGLRC=%d, ThreadId=%X", a, context, dwThreadId);
+
+ // If the HGLRC is NULL then make no context current;
+ // Ditto if the HDC is NULL either. (DaveM)
+ if (context == 0 || a == 0) {
+ // Corresponding Mesa operation
+#ifdef _USE_GLD3_WGL
+ _mesa_make_current(NULL, NULL);
+#else
+ (*mesaFuncs.gl_make_current)(NULL, NULL);
+#endif
+ dglSetCurrentContext(0);
+ return TRUE;
+ }
+
+ // Make sure the HGLRC is in range
+ if ((context > DGL_MAX_CONTEXTS) || (context < 0)) {
+ ddlogMessage(DDLOG_ERROR, "dglMakeCurrent: HGLRC out of range\n");
+ return FALSE;
+ }
+
+ // Find address of context and make sure that it has been allocated
+ lpCtx = dglGetContextAddress(b);
+ if (!lpCtx->bAllocated) {
+ ddlogMessage(DDLOG_ERROR, "dglMakeCurrent: Context not allocated\n");
+// return FALSE;
+ return TRUE; // HACK: Shuts up "WebLab Viewer Pro". KeithH
+ }
+
+#ifdef GLD_THREADS
+ // Serialize access to DirectDraw or DDS operations
+ if (glb.bMultiThreaded)
+ EnterCriticalSection(&CriticalSection);
+#endif
+
+ // Check if window has changed
+ hWnd = (a != lpCtx->hDC) ? WindowFromDC(a) : lpCtx->hWnd;
+ bWindowChanged = (hWnd != lpCtx->hWnd) ? TRUE : FALSE;
+ bContextChanged = (b != dglGetCurrentContext()) ? TRUE : FALSE;
+
+ // If the window has changed, make sure the clipper is updated. (DaveM)
+ if (glb.bDirectDrawPersistant && !lpCtx->bFullscreen && (bWindowChanged || bContextChanged)) {
+ lpCtx->hWnd = hWnd;
+#ifndef _USE_GLD3_WGL
+ IDirectDrawSurface4_GetClipper(lpCtx->lpFront4, &lpddClipper);
+ IDirectDrawClipper_SetHWnd(lpddClipper, 0, lpCtx->hWnd);
+ IDirectDrawClipper_Release(lpddClipper);
+#endif // _USE_GLD3_WGL
+ }
+
+ // Make sure hDC and hWnd is current. (DaveM)
+ // Obtain the dimensions of the rendering window
+ lpCtx->hDC = a; // Cache DC
+ lpCtx->hWnd = hWnd;
+ hWndLastActive = hWnd;
+
+ // Check for non-window DC = memory DC ?
+ if (hWnd == NULL) {
+ if (GetClipBox(a, &lpCtx->rcScreenRect) == ERROR) {
+ ddlogMessage(DDLOG_WARN, "GetClipBox failed in dglMakeCurrent\n");
+ SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
+ }
+ }
+ else if (!GetClientRect(lpCtx->hWnd, &lpCtx->rcScreenRect)) {
+ ddlogMessage(DDLOG_WARN, "GetClientRect failed in dglMakeCurrent\n");
+ SetRect(&lpCtx->rcScreenRect, 0, 0, 0, 0);
+ }
+ // Check if buffers need to be re-sized;
+ // If so, wait until Mesa GL stuff is setup before re-sizing;
+ if (lpCtx->dwWidth != lpCtx->rcScreenRect.right - lpCtx->rcScreenRect.left ||
+ lpCtx->dwHeight != lpCtx->rcScreenRect.bottom - lpCtx->rcScreenRect.top)
+ bNeedResize = TRUE;
+
+ // Now we can update our globals
+ dglSetCurrentContext(b);
+
+ // Corresponding Mesa operation
+#ifdef _USE_GLD3_WGL
+ _mesa_make_current(lpCtx->glCtx, lpCtx->glBuffer);
+ lpCtx->glCtx->Driver.UpdateState(lpCtx->glCtx, _NEW_ALL);
+ if (bNeedResize) {
+ // Resize buffers (Note Mesa GL needs to be setup beforehand);
+ // Resize Mesa internal buffer too via glViewport() command,
+ // which subsequently calls dglWglResizeBuffers() too.
+ lpCtx->glCtx->Driver.Viewport(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+ lpCtx->bHasBeenCurrent = TRUE;
+ }
+#else
+ (*mesaFuncs.gl_make_current)(lpCtx->glCtx, lpCtx->glBuffer);
+
+ dglSetupDDPointers(lpCtx->glCtx);
+
+ // Insure DirectDraw surfaces fit current window DC
+ if (bNeedResize) {
+ // Resize buffers (Note Mesa GL needs to be setup beforehand);
+ // Resize Mesa internal buffer too via glViewport() command,
+ // which subsequently calls dglWglResizeBuffers() too.
+ (*mesaFuncs.gl_Viewport)(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+ lpCtx->bHasBeenCurrent = TRUE;
+ }
+#endif // _USE_GLD3_WGL
+ ddlogPrintf(DDLOG_SYSTEM, "dglMakeCurrent: width = %d, height = %d", lpCtx->dwWidth, lpCtx->dwHeight);
+
+ // We have to clear D3D back buffer and render state if emulated front buffering
+ // for different window (but not context) like in Solid Edge.
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers
+ && (bWindowChanged /* || bContextChanged */) && lpCtx->EmulateSingle) {
+#ifdef _USE_GLD3_WGL
+// IDirect3DDevice8_EndScene(lpCtx->pDev);
+// lpCtx->bSceneStarted = FALSE;
+ lpCtx->glCtx->Driver.Clear(lpCtx->glCtx, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
+ GL_TRUE, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+#else
+ IDirect3DDevice3_EndScene(lpCtx->lpDev3);
+ lpCtx->bSceneStarted = FALSE;
+ dglClearD3D(lpCtx->glCtx, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
+ GL_TRUE, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+#endif // _USE_GLD3_WGL
+ }
+
+ // The first time we call MakeCurrent we set the initial viewport size
+ if (lpCtx->bHasBeenCurrent == FALSE)
+#ifdef _USE_GLD3_WGL
+ lpCtx->glCtx->Driver.Viewport(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+#else
+ (*mesaFuncs.gl_Viewport)(lpCtx->glCtx, 0, 0, lpCtx->dwWidth, lpCtx->dwHeight);
+#endif // _USE_GLD3_WGL
+ lpCtx->bHasBeenCurrent = TRUE;
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ return TRUE;
+}
+
+// ***********************************************************************
+
+BOOL dglDeleteContext(
+ HGLRC a)
+{
+ DGL_ctx* lpCtx;
+ DWORD dwThreadId = GetCurrentThreadId();
+ char argstr[256];
+
+#if 0 // We have enough trouble throwing exceptions as it is... (DaveM)
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+#endif
+
+ // Is context state ready ?
+ if (!bContextReady)
+ return FALSE;
+
+ ddlogPrintf(DDLOG_SYSTEM, "dglDeleteContext: Deleting context HGLRC=%d, ThreadId=%X", (int)a, dwThreadId);
+
+ // Make sure the HGLRC is in range
+ if (((int) a> DGL_MAX_CONTEXTS) || ((int)a < 0)) {
+ ddlogMessage(DDLOG_ERROR, "dglDeleteCurrent: HGLRC out of range\n");
+ return FALSE;
+ }
+
+ // Make sure context is valid
+ lpCtx = dglGetContextAddress(a);
+ if (!lpCtx->bAllocated) {
+ ddlogPrintf(DDLOG_WARN, "Tried to delete unallocated context HGLRC=%d", (int)a);
+// return FALSE;
+ return TRUE; // HACK: Shuts up "WebLab Viewer Pro". KeithH
+ }
+
+ // Make sure context is de-activated
+ if (a == dglGetCurrentContext()) {
+ ddlogPrintf(DDLOG_WARN, "dglDeleteContext: context HGLRC=%d still active", (int)a);
+ dglMakeCurrent(NULL, NULL);
+ }
+
+#ifdef GLD_THREADS
+ // Serialize access to DirectDraw or DDS operations
+ if (glb.bMultiThreaded)
+ EnterCriticalSection(&CriticalSection);
+#endif
+
+ // We are about to destroy all Direct3D objects.
+ // Therefore we must disable rendering
+ lpCtx->bCanRender = FALSE;
+
+ // This exception handler was installed to catch some
+ // particularly nasty apps. Console apps that call exit()
+ // fall into this catagory (i.e. Win32 Glut).
+
+ // VC cannot successfully implement multiple exception handlers
+ // if more than one exception occurs. Therefore reverting back to
+ // single exception handler as Keith originally had it. (DaveM)
+
+#define WARN_MESSAGE(p) strcpy(argstr, (#p));
+#define SAFE_RELEASE(p) WARN_MESSAGE(p); RELEASE(p);
+
+__try {
+#ifdef _USE_GLD3_WGL
+ WARN_MESSAGE(gl_destroy_framebuffer);
+ if (lpCtx->glBuffer)
+ _mesa_destroy_framebuffer(lpCtx->glBuffer);
+ WARN_MESSAGE(gl_destroy_context);
+ if (lpCtx->glCtx)
+ _mesa_destroy_context(lpCtx->glCtx);
+ WARN_MESSAGE(gl_destroy_visual);
+ if (lpCtx->glVis)
+ _mesa_destroy_visual(lpCtx->glVis);
+
+ _gldDriver.DestroyDrawable(lpCtx);
+#else
+ // Destroy the Mesa context
+ WARN_MESSAGE(gl_destroy_framebuffer);
+ if (lpCtx->glBuffer)
+ (*mesaFuncs.gl_destroy_framebuffer)(lpCtx->glBuffer);
+ WARN_MESSAGE(gl_destroy_context);
+ if (lpCtx->glCtx)
+ (*mesaFuncs.gl_destroy_context)(lpCtx->glCtx);
+ WARN_MESSAGE(gl_destroy_visual);
+ if (lpCtx->glVis)
+ (*mesaFuncs.gl_destroy_visual)(lpCtx->glVis);
+
+ SAFE_RELEASE(lpCtx->m_pvbuf); // release D3D vertex buffer
+ SAFE_RELEASE(lpCtx->m_vbuf); // release D3D vertex buffer
+
+ // Delete the global palette
+ SAFE_RELEASE(lpCtx->lpGlobalPalette);
+
+ // Clean up.
+ if (lpCtx->lpViewport3) {
+ if (lpCtx->lpDev3) IDirect3DDevice3_DeleteViewport(lpCtx->lpDev3, lpCtx->lpViewport3);
+ SAFE_RELEASE(lpCtx->lpViewport3);
+ lpCtx->lpViewport3 = NULL;
+ }
+
+ SAFE_RELEASE(lpCtx->lpDev3);
+ if (lpCtx->lpDepth4) {
+ if (lpCtx->lpBack4)
+ IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpBack4, 0L, lpCtx->lpDepth4);
+ else
+ IDirectDrawSurface4_DeleteAttachedSurface(lpCtx->lpFront4, 0L, lpCtx->lpDepth4);
+ SAFE_RELEASE(lpCtx->lpDepth4);
+ lpCtx->lpDepth4 = NULL;
+ }
+ SAFE_RELEASE(lpCtx->lpBack4);
+ SAFE_RELEASE(lpCtx->lpFront4);
+ if (lpCtx->bFullscreen) {
+ IDirectDraw4_RestoreDisplayMode(lpCtx->lpDD4);
+ IDirectDraw4_SetCooperativeLevel(lpCtx->lpDD4, NULL, DDSCL_NORMAL);
+ }
+ SAFE_RELEASE(lpCtx->lpD3D3);
+ SAFE_RELEASE(lpCtx->lpDD4);
+ SAFE_RELEASE(lpCtx->lpDD1);
+#endif // _ULSE_GLD3_WGL
+
+}
+__except(EXCEPTION_EXECUTE_HANDLER) {
+ ddlogPrintf(DDLOG_WARN, "Exception raised in dglDeleteContext: %s", argstr);
+}
+
+ // Restore the window message handler because this context may be used
+ // again by another window with a *different* message handler. (DaveM)
+ if (lpCtx->lpfnWndProc) {
+ SetWindowLong(lpCtx->hWnd, GWL_WNDPROC, (LONG)lpCtx->lpfnWndProc);
+ lpCtx->lpfnWndProc = (LONG)NULL;
+ }
+
+ lpCtx->bAllocated = FALSE; // This context is now free for use
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ return TRUE;
+}
+
+// ***********************************************************************
+
+BOOL dglSwapBuffers(
+ HDC hDC)
+{
+ RECT rSrcRect; // Source rectangle
+ RECT rDstRect; // Destination rectangle
+ POINT pt;
+ HRESULT hResult;
+
+ DDBLTFX bltFX;
+ DWORD dwBlitFlags;
+ DDBLTFX *lpBltFX;
+
+// DWORD dwThreadId = GetCurrentThreadId();
+ HGLRC hGLRC = dglGetCurrentContext();
+ DGL_ctx *lpCtx = dglGetContextAddress(hGLRC);
+ HWND hWnd;
+
+ HDC hDCAux; // for memory DC
+ int x,y,w,h; // for memory DC BitBlt
+
+#if 0 // Perhaps not a good idea. Called too often. KH
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+#endif
+
+ if (!lpCtx) {
+ return TRUE; //FALSE; // No current context
+ }
+
+ if (!lpCtx->bCanRender) {
+ // Don't return false else some apps will bail.
+ return TRUE;
+ }
+
+ hWnd = lpCtx->hWnd;
+ if (hDC != lpCtx->hDC) {
+ ddlogPrintf(DDLOG_WARN, "dglSwapBuffers: HDC=%X does not match HDC=%X for HGLRC=%d", hDC, lpCtx->hDC, hGLRC);
+ hWnd = WindowFromDC(hDC);
+ }
+
+#ifndef _USE_GLD3_WGL
+ // Ensure that the surfaces exist before we tell
+ // the device to render to them.
+ IDirectDraw4_RestoreAllSurfaces(lpCtx->lpDD4);
+
+ // Make sure that the vertex caches have been emptied
+// dglStateChange(lpCtx);
+
+ // Some OpenGL programs don't issue a glFinish - check for it here.
+ if (lpCtx->bSceneStarted) {
+ IDirect3DDevice3_EndScene(lpCtx->lpDev3);
+ lpCtx->bSceneStarted = FALSE;
+ }
+#endif
+
+#if 0
+ // If the calling app is not active then we don't need to Blit/Flip.
+ // We can therefore simply return TRUE.
+ if (!glb.bAppActive)
+ return TRUE;
+ // Addendum: This is WRONG! We should bail if the app is *minimized*,
+ // not merely if the app is just plain 'not active'.
+ // KeithH, 27/May/2000.
+#endif
+
+ // Check for non-window DC = memory DC ?
+ if (hWnd == NULL) {
+ if (GetClipBox(hDC, &rSrcRect) == ERROR)
+ return TRUE;
+ // Use GDI BitBlt instead from compatible DirectDraw DC
+ x = rSrcRect.left;
+ y = rSrcRect.top;
+ w = rSrcRect.right - rSrcRect.left;
+ h = rSrcRect.bottom - rSrcRect.top;
+
+ // Ack. DX8 does not have a GetDC() function...
+ // TODO: Defer to DX7 or DX9 drivers... (DaveM)
+ return TRUE;
+ }
+
+ // Bail if window client region is not drawable, like in Solid Edge
+ if (!IsWindow(hWnd) /* || !IsWindowVisible(hWnd) */ || !GetClientRect(hWnd, &rSrcRect))
+ return TRUE;
+
+#ifdef GLD_THREADS
+ // Serialize access to DirectDraw or DDS operations
+ if (glb.bMultiThreaded)
+ EnterCriticalSection(&CriticalSection);
+#endif
+
+#ifdef _USE_GLD3_WGL
+ // Notify Mesa of impending swap, so Mesa can flush internal buffers.
+ _mesa_notifySwapBuffers(lpCtx->glCtx);
+ // Now perform driver buffer swap
+ _gldDriver.SwapBuffers(lpCtx, hDC, hWnd);
+#else
+ if (lpCtx->bFullscreen) {
+ // Sync with retrace if required
+ if (glb.bWaitForRetrace) {
+ IDirectDraw4_WaitForVerticalBlank(
+ lpCtx->lpDD4,
+ DDWAITVB_BLOCKBEGIN,
+ 0);
+ }
+
+ // Perform the fullscreen flip
+ TRY(IDirectDrawSurface4_Flip(
+ lpCtx->lpFront4,
+ NULL,
+ DDFLIP_WAIT),
+ "dglSwapBuffers: Flip");
+ } else {
+ // Calculate current window position and size
+ pt.x = pt.y = 0;
+ ClientToScreen(hWnd, &pt);
+ GetClientRect(hWnd, &rDstRect);
+ if (rDstRect.right > lpCtx->dwModeWidth)
+ rDstRect.right = lpCtx->dwModeWidth;
+ if (rDstRect.bottom > lpCtx->dwModeHeight)
+ rDstRect.bottom = lpCtx->dwModeHeight;
+ OffsetRect(&rDstRect, pt.x, pt.y);
+ rSrcRect.left = rSrcRect.top = 0;
+ rSrcRect.right = lpCtx->dwWidth;
+ rSrcRect.bottom = lpCtx->dwHeight;
+ if (rSrcRect.right > lpCtx->dwModeWidth)
+ rSrcRect.right = lpCtx->dwModeWidth;
+ if (rSrcRect.bottom > lpCtx->dwModeHeight)
+ rSrcRect.bottom = lpCtx->dwModeHeight;
+
+ if (glb.bWaitForRetrace) {
+ // Sync the blit to the vertical retrace
+ ZeroMemory(&bltFX, sizeof(bltFX));
+ bltFX.dwSize = sizeof(bltFX);
+ bltFX.dwDDFX = DDBLTFX_NOTEARING;
+ dwBlitFlags = DDBLT_WAIT | DDBLT_DDFX;
+ lpBltFX = &bltFX;
+ } else {
+ dwBlitFlags = DDBLT_WAIT;
+ lpBltFX = NULL;
+ }
+
+ // Perform the actual blit
+ TRY(IDirectDrawSurface4_Blt(
+ lpCtx->lpFront4,
+ &rDstRect,
+ lpCtx->lpBack4, // Blit source
+ &rSrcRect,
+ dwBlitFlags,
+ lpBltFX),
+ "dglSwapBuffers: Blt");
+ }
+#endif // _USE_GLD3_WGL
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ // TODO: Re-instate rendering bitmap snapshot feature??? (DaveM)
+
+ // Render frame is completed
+ ValidateRect(hWnd, NULL);
+ lpCtx->bFrameStarted = FALSE;
+
+ return TRUE;
+}
+
+// ***********************************************************************
diff --git a/src/mesa/drivers/windows/gldirect/dglcontext.h b/src/mesa/drivers/windows/gldirect/dglcontext.h
new file mode 100644
index 0000000000..5c433b857e
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dglcontext.h
@@ -0,0 +1,281 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: OpenGL context handling.
+*
+****************************************************************************/
+
+#ifndef __DGLCONTEXT_H
+#define __DGLCONTEXT_H
+
+// Disable compiler complaints about DLL linkage
+#pragma warning (disable:4273)
+
+// Macros to control compilation
+#ifndef STRICT
+#define STRICT
+#endif // STRICT
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <GL\gl.h>
+
+#ifdef _USE_GLD3_WGL
+ #include "dglmacros.h"
+ #include "dglglobals.h"
+ #include "pixpack.h"
+ #include "ddlog.h"
+ #include "dglpf.h"
+ #include "context.h" // Mesa context
+#else
+ #include <ddraw.h>
+ #include <d3d.h>
+
+ #include "dglmacros.h"
+ #include "dglglobals.h"
+ #include "pixpack.h"
+ #include "ddlog.h"
+ #include "dglpf.h"
+ #include "d3dvertex.h"
+
+ #include "DirectGL.h"
+
+ #include "context.h" // Mesa context
+ #include "vb.h" // Mesa vertex buffer
+#endif // _USE_GLD3_WGL
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+// TODO: Use a list instead of this constant!
+#define DGL_MAX_CONTEXTS 32
+
+// Structure for describing an OpenGL context
+#ifdef _USE_GLD3_WGL
+typedef struct {
+ BOOL bHasBeenCurrent;
+ DGL_pixelFormat *lpPF;
+
+ // Pointer to private driver data (this also contains the drawable).
+ void *glPriv;
+
+ // Mesa vars:
+ GLcontext *glCtx; // The core Mesa context
+ GLvisual *glVis; // Describes the color buffer
+ GLframebuffer *glBuffer; // Ancillary buffers
+
+ GLuint ClearIndex;
+ GLuint CurrentIndex;
+ GLubyte ClearColor[4];
+ GLubyte CurrentColor[4];
+
+ BOOL EmulateSingle; // Emulate single-buffering
+ BOOL bDoubleBuffer;
+ BOOL bDepthBuffer;
+
+ // Shared driver vars:
+ BOOL bAllocated;
+ BOOL bFullscreen; // Is this a fullscreen context?
+ BOOL bSceneStarted; // Has a lpDev->BeginScene been issued?
+ BOOL bCanRender; // Flag: states whether rendering is OK
+ BOOL bFrameStarted; // Has frame update started at all?
+ BOOL bStencil; // TRUE if this context has stencil
+ BOOL bGDIEraseBkgnd; // GDI Erase Background command
+
+ // Window information
+ HWND hWnd; // Window handle
+ HDC hDC; // Windows' Device Context of the window
+ DWORD dwWidth; // Window width
+ DWORD dwHeight; // Window height
+ DWORD dwBPP; // Window bits-per-pixel;
+ RECT rcScreenRect; // Screen rectangle
+ DWORD dwModeWidth; // Display mode width
+ DWORD dwModeHeight; // Display mode height
+ float dvClipX;
+ float dvClipY;
+ LONG lpfnWndProc; // window message handler function
+
+} DGL_ctx;
+
+#define GLD_context DGL_ctx
+#define GLD_GET_CONTEXT(c) (GLD_context*)(c)->DriverCtx
+
+#else // _USE_GLD3_WGL
+
+typedef struct {
+ BOOL bHasBeenCurrent;
+ DGL_pixelFormat *lpPF;
+ //
+ // Mesa context vars:
+ //
+ GLcontext *glCtx; // The core Mesa context
+ GLvisual *glVis; // Describes the color buffer
+ GLframebuffer *glBuffer; // Ancillary buffers
+
+ GLuint ClearIndex;
+ GLuint CurrentIndex;
+ GLubyte ClearColor[4];
+ GLubyte CurrentColor[4];
+
+ BOOL EmulateSingle; // Emulate single-buffering
+ BOOL bDoubleBuffer;
+ BOOL bDepthBuffer;
+ int iZBufferPF; // Index of Zbuffer pixel format
+
+ // Vertex buffer: one-to-one correlation with Mesa's vertex buffer.
+ // This will be filled by our setup function (see d3dvsetup.c)
+ DGL_TLvertex gWin[VB_SIZE]; // Transformed and lit vertices
+// DGL_Lvertex gObj[VB_SIZE]; // Lit vertices in object coordinates.
+
+ // Indices for DrawIndexedPrimitive.
+ // Clipped quads are drawn seperately, so use VB_SIZE.
+ // 6 indices are needed to make 2 triangles for each possible quad
+// WORD wIndices[(VB_SIZE / 4) * 6];
+ WORD wIndices[32768];
+
+ //
+ // Device driver vars:
+ //
+ BOOL bAllocated;
+ BOOL bFullscreen; // Is this a fullscreen context?
+ BOOL bSceneStarted; // Has a lpDev->BeginScene been issued?
+ BOOL bCanRender; // Flag: states whether rendering is OK
+ BOOL bFrameStarted; // Has frame update started at all?
+
+ // DirectX COM interfaces, postfixed with the interface number
+ IDirectDraw *lpDD1;
+ IDirectDraw4 *lpDD4;
+ IDirect3D3 *lpD3D3;
+ IDirect3DDevice3 *lpDev3;
+ IDirect3DViewport3 *lpViewport3;
+ IDirectDrawSurface4 *lpFront4;
+ IDirectDrawSurface4 *lpBack4;
+ IDirectDrawSurface4 *lpDepth4;
+
+ // Vertex buffers
+ BOOL bD3DPipeline; // True if using D3D geometry pipeline
+ IDirect3DVertexBuffer *m_vbuf; // Unprocessed vertices
+ IDirect3DVertexBuffer *m_pvbuf; // Processed vertices ready to be rendered
+
+ D3DTEXTUREOP ColorOp[MAX_TEXTURE_UNITS]; // Used for re-enabling texturing
+ D3DTEXTUREOP AlphaOp[MAX_TEXTURE_UNITS]; // Used for re-enabling texturing
+ struct gl_texture_object *tObj[MAX_TEXTURE_UNITS];
+
+ DDCAPS ddCaps; // DirectDraw caps
+ D3DDEVICEDESC D3DDevDesc; // Direct3D Device description
+
+ DDPIXELFORMAT ddpfRender; // Pixel format of the render buffer
+ DDPIXELFORMAT ddpfDepth; // Pixel format of the depth buffer
+
+ BOOL bStencil; // TRUE is this context has stencil
+
+ PX_packFunc fnPackFunc; // Pixel packing function for SW
+ PX_unpackFunc fnUnpackFunc; // Pixel unpacking function for SW
+ PX_packSpanFunc fnPackSpanFunc; // Pixel span packer
+
+ D3DVIEWPORT2 d3dViewport; // D3D Viewport object
+
+ D3DCULL cullmode; // Direct3D cull mode
+ D3DCOLOR curcolor; // Current color
+ DWORD dwColorPF; // Current color, in format of target surface
+ D3DCOLOR d3dClearColor; // Clear color
+ D3DCOLOR ConstantColor; // For flat shading
+ DWORD dwClearColorPF; // Clear color, in format of target surface
+ BOOL bGDIEraseBkgnd; // GDI Erase Background command
+
+ // Primitive caches
+// DGL_vertex LineCache[DGL_MAX_LINE_VERTS];
+// DGL_vertex TriCache[DGL_MAX_TRI_VERTS];
+// DWORD dwNextLineVert;
+// DWORD dwNextTriVert;
+
+ // Window information
+ HWND hWnd; // Window handle
+ HDC hDC; // Windows' Device Context of the window
+ DWORD dwWidth; // Window width
+ DWORD dwHeight; // Window height
+ DWORD dwBPP; // Window bits-per-pixel;
+ RECT rcScreenRect; // Screen rectangle
+ DWORD dwModeWidth; // Display mode width
+ DWORD dwModeHeight; // Display mode height
+ float dvClipX;
+ float dvClipY;
+ LONG lpfnWndProc; // window message handler function
+
+ // Shared texture palette
+ IDirectDrawPalette *lpGlobalPalette;
+
+ // Usage counters.
+ // One of these counters will be incremented when we choose
+ // between hardware and software rendering functions.
+// DWORD dwHWUsageCount; // Hardware usage count
+// DWORD dwSWUsageCount; // Software usage count
+
+ // Texture state flags.
+// BOOL m_texturing; // TRUE is texturing
+// BOOL m_mtex; // TRUE if multitexture
+// BOOL m_texHandleValid; // TRUE if tex state valid
+
+ // Renderstate caches to ensure no redundant state changes
+ DWORD dwRS[256]; // Renderstates
+ DWORD dwTSS[2][24]; // Texture-stage states
+ LPDIRECT3DTEXTURE2 lpTex[2]; // Texture (1 per stage)
+
+ DWORD dwMaxTextureSize; // Max texture size:
+ // clamped to 1024.
+
+} DGL_ctx;
+#endif // _USE_GLD3_WGL
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HHOOK hKeyHook;
+LRESULT CALLBACK dglKeyProc(int code,WPARAM wParam,LPARAM lParam);
+
+void dglInitContextState();
+void dglDeleteContextState();
+BOOL dglIsValidContext(HGLRC a);
+DGL_ctx* dglGetContextAddress(const HGLRC a);
+HDC dglGetCurrentDC(void);
+HGLRC dglGetCurrentContext(void);
+HGLRC dglCreateContext(HDC a, const DGL_pixelFormat *lpPF);
+BOOL dglMakeCurrent(HDC a, HGLRC b);
+BOOL dglDeleteContext(HGLRC a);
+BOOL dglSwapBuffers(HDC hDC);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/mesa/drivers/windows/gldirect/dglglobals.c b/src/mesa/drivers/windows/gldirect/dglglobals.c
new file mode 100644
index 0000000000..c633e3bcfa
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dglglobals.c
@@ -0,0 +1,149 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Global variables.
+*
+****************************************************************************/
+
+#include "dglglobals.h"
+
+// =======================================================================
+// Global Variables
+// =======================================================================
+
+char szCopyright[] = "Copyright (c) 1998 SciTech Software, Inc.";
+char szDllName[] = "Scitech GLDirect";
+char szErrorTitle[] = "GLDirect Error";
+
+DGL_globals glb;
+
+// Shared result variable
+HRESULT hResult;
+
+// ***********************************************************************
+
+// Patch function for missing function in Mesa
+int finite(
+ double x)
+{
+ return _finite(x);
+};
+
+// ***********************************************************************
+
+void dglInitGlobals()
+{
+ // Zero all fields just in case
+ memset(&glb, 0, sizeof(glb));
+
+ // Set the global defaults
+ glb.bPrimary = FALSE; // Not the primary device
+ glb.bHardware = FALSE; // Not a hardware device
+// glb.bFullscreen = FALSE; // Not running fullscreen
+ glb.bSquareTextures = FALSE; // Device does not need sq
+ glb.bPAL8 = FALSE; // Device cannot do 8bit
+ glb.dwMemoryType = DDSCAPS_SYSTEMMEMORY;
+ glb.dwRendering = DGL_RENDER_D3D;
+
+ glb.bWaitForRetrace = TRUE; // Sync to vertical retrace
+ glb.bFullscreenBlit = FALSE;
+
+ glb.nPixelFormatCount = 0;
+ glb.lpPF = NULL; // Pixel format list
+#ifndef _USE_GLD3_WGL
+ glb.nZBufferPFCount = 0;
+ glb.lpZBufferPF = NULL;
+ glb.nDisplayModeCount = 0;
+ glb.lpDisplayModes = NULL;
+ glb.nTextureFormatCount = 0;
+ glb.lpTextureFormat = NULL;
+#endif // _USE_GLD3_WGL
+
+ glb.wMaxSimultaneousTextures = 1;
+
+ // Enable support for multitexture, if available.
+ glb.bMultitexture = TRUE;
+
+ // Enable support for mipmapping
+ glb.bUseMipmaps = TRUE;
+
+ // Alpha emulation via chroma key
+ glb.bEmulateAlphaTest = FALSE;
+
+ // Use Mesa pipeline always (for compatibility)
+ glb.bForceMesaPipeline = FALSE;
+
+ // Init support for multiple GLRCs
+ glb.bDirectDraw = FALSE;
+ glb.bDirectDrawPrimary = FALSE;
+ glb.bDirect3D = FALSE;
+ glb.bDirect3DDevice = FALSE;
+ glb.bDirectDrawStereo = FALSE;
+ glb.iDirectDrawStereo = 0;
+ glb.hWndActive = NULL;
+ // Init DirectX COM interfaces for multiple GLRCs
+// glb.lpDD4 = NULL;
+// glb.lpPrimary4 = NULL;
+// glb.lpBack4 = NULL;
+// glb.lpDepth4 = NULL;
+// glb.lpGlobalPalette = NULL;
+
+ // Init special support options
+ glb.bMessageBoxWarnings = TRUE;
+ glb.bDirectDrawPersistant = FALSE;
+ glb.bPersistantBuffers = FALSE;
+
+ // Do not assume single-precision-only FPU (for compatibility)
+ glb.bFastFPU = FALSE;
+
+ // Allow hot-key support
+ glb.bHotKeySupport = TRUE;
+
+ // Default to single-threaded support (for simplicity)
+ glb.bMultiThreaded = FALSE;
+
+ // Use application-specific customizations (for end-user convenience)
+ glb.bAppCustomizations = TRUE;
+
+#ifdef _USE_GLD3_WGL
+ // Registry/ini-file settings for GLDirect 3.x
+ glb.dwAdapter = 0; // Primary DX8 adapter
+ glb.dwTnL = 1; // MesaSW TnL
+ glb.dwMultisample = 0; // Multisample Off
+ glb.dwDriver = 2; // Direct3D HW
+
+ // Signal a pixelformat list rebuild
+ glb.bPixelformatsDirty = TRUE;
+#endif
+}
+
+// ***********************************************************************
diff --git a/src/mesa/drivers/windows/gldirect/dglglobals.h b/src/mesa/drivers/windows/gldirect/dglglobals.h
new file mode 100644
index 0000000000..995f1cd5e4
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dglglobals.h
@@ -0,0 +1,198 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Globals.
+*
+****************************************************************************/
+
+#ifndef __DGLGLOBALS_H
+#define __DGLGLOBALS_H
+
+#include "dglcontext.h"
+#include "dglpf.h" // Pixel format
+#ifndef _USE_GLD3_WGL
+#include "d3dtexture.h"
+#endif
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+typedef enum {
+ DGL_RENDER_MESASW = 0,
+ DGL_RENDER_D3D = 1,
+ DGL_RENDER_FORCE_DWORD = 0x7ffffff,
+} DGL_renderType;
+
+#ifdef _USE_GLD3_WGL
+
+// Same as DGL_renderType? KeithH
+typedef enum {
+ GLDS_DRIVER_MESA_SW = 0, // Mesa SW rendering
+ GLDS_DRIVER_REF = 1, // Direct3D Reference Rasteriser
+ GLDS_DRIVER_HAL = 2, // Direct3D HW rendering
+} GLDS_DRIVER;
+
+typedef enum {
+ GLDS_TNL_DEFAULT = 0, // Choose best TnL method
+ GLDS_TNL_MESA = 1, // Mesa TnL
+ GLDS_TNL_D3DSW = 2, // D3D Software TnL
+ GLDS_TNL_D3DHW = 3, // D3D Hardware TnL
+} GLDS_TNL;
+
+typedef enum {
+ GLDS_MULTISAMPLE_NONE = 0,
+ GLDS_MULTISAMPLE_FASTEST = 1,
+ GLDS_MULTISAMPLE_NICEST = 2,
+} GLDS_MULTISAMPLE;
+#endif
+
+typedef struct {
+ // Registry settings
+ char szDDName[MAX_DDDEVICEID_STRING]; // DirectDraw device name
+ char szD3DName[MAX_DDDEVICEID_STRING]; // Direct3D driver name
+ BOOL bPrimary; // Is ddraw device the Primary device?
+ BOOL bHardware; // Is the d3d driver a Hardware driver?
+#ifndef _USE_GLD3_WGL
+ GUID ddGuid; // GUID of the ddraw device
+ GUID d3dGuid; // GUID of the direct3d driver
+#endif // _USE_GLD3_WGL
+// BOOL bFullscreen; // Force fullscreen - only useful for primary adaptors.
+ BOOL bSquareTextures; // Does this driver require square textures?
+ DWORD dwRendering; // Type of rendering required
+
+ BOOL bWaitForRetrace; // Sync to vertical retrace
+ BOOL bFullscreenBlit; // Use Blt instead of Flip in fullscreen modes
+
+ // Multitexture
+ BOOL bMultitexture;
+
+ BOOL bUseMipmaps;
+
+ DWORD dwMemoryType; // Sysmem or Vidmem
+
+ // Global palette
+ BOOL bPAL8;
+ DDPIXELFORMAT ddpfPAL8;
+
+ // Multitexture
+ WORD wMaxSimultaneousTextures;
+
+ // Win32 internals
+ BOOL bAppActive; // Keep track of Alt-Tab
+ LONG lpfnWndProc; // WndProc of calling app
+
+ // Pixel Format Descriptior list.
+ int nPixelFormatCount;
+ DGL_pixelFormat *lpPF;
+#ifndef _USE_GLD3_WGL
+ // ZBuffer pixel formats
+ int nZBufferPFCount; // Count of Zbuffer pixel formats
+ DDPIXELFORMAT *lpZBufferPF; // ZBuffer pixel formats
+
+ // Display modes (for secondary devices)
+ int nDisplayModeCount;
+ DDSURFACEDESC2 *lpDisplayModes;
+
+ // Texture pixel formats
+ int nTextureFormatCount;
+ DGL_textureFormat *lpTextureFormat;
+#endif // _USE_GLD3_WGL
+ // Alpha emulation via chroma key
+ BOOL bEmulateAlphaTest;
+
+ // Geom pipeline override.
+ // If this is set TRUE then the D3D pipeline will never be used,
+ // and the Mesa pipline will always be used.
+ BOOL bForceMesaPipeline;
+
+#ifdef _USE_GLD3_WGL
+ BOOL bPixelformatsDirty; // Signal a list rebuild
+#endif
+
+ // Additional globals to support multiple GL rendering contexts, GLRCs
+ BOOL bDirectDraw; // DirectDraw interface exists ?
+ BOOL bDirectDrawPrimary; // DirectDraw primary surface exists ?
+ BOOL bDirect3D; // Direct3D interface exists ?
+ BOOL bDirect3DDevice; // Direct3D device exists ?
+
+ BOOL bDirectDrawStereo; // DirectDraw Stereo driver started ?
+ int iDirectDrawStereo; // DirectDraw Stereo driver reference count
+ HWND hWndActive; // copy of active window
+
+ // Copies of DirectX COM interfaces for re-referencing across multiple GLRCs
+// IDirectDraw4 *lpDD4; // copy of DirectDraw interface
+// IDirectDrawSurface4 *lpPrimary4; // copy of DirectDraw primary surface
+// IDirectDrawSurface4 *lpBack4;
+// IDirectDrawSurface4 *lpDepth4;
+// IDirectDrawPalette *lpGlobalPalette;
+
+ // Aids for heavy-duty MFC-windowed OGL apps, like AutoCAD
+ BOOL bMessageBoxWarnings; // popup message box warning
+ BOOL bDirectDrawPersistant; // DirectDraw is persisitant
+ BOOL bPersistantBuffers; // DirectDraw buffers persisitant
+
+ // FPU setup option for CAD precision (AutoCAD) vs GAME speed (Quake)
+ BOOL bFastFPU; // single-precision-only FPU ?
+
+ // Hot-Key support, like for real-time stereo parallax adjustments
+ BOOL bHotKeySupport; // hot-key support ?
+
+ // Multi-threaded support, for apps like 3DStudio
+ BOOL bMultiThreaded; // multi-threaded ?
+
+ // Detect and use app-specific customizations for apps like 3DStudio
+ BOOL bAppCustomizations; // app customizations ?
+
+#ifdef _USE_GLD3_WGL
+ DWORD dwAdapter; // Primary DX8 adapter
+ DWORD dwTnL; // MesaSW TnL
+ DWORD dwMultisample; // Multisample Off
+ DWORD dwDriver; // Direct3D HW
+ void *pDrvPrivate; // Driver-specific data
+#endif
+
+} DGL_globals;
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+DGL_globals glb;
+
+void dglInitGlobals();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/mesa/drivers/windows/gldirect/dglmacros.h b/src/mesa/drivers/windows/gldirect/dglmacros.h
new file mode 100644
index 0000000000..aed0f2110e
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dglmacros.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Useful generic macros.
+*
+****************************************************************************/
+
+#ifndef __DGLMACROS_H
+#define __DGLMACROS_H
+
+#include <ddraw.h>
+
+// Define the relevant RELEASE macro depending on C or C++
+#if !defined(__cplusplus) || defined(CINTERFACE)
+ // Standard C version
+ #define RELEASE(x) if (x!=NULL) { x->lpVtbl->Release(x); x=NULL; }
+#else
+ // C++ version
+ #define RELEASE(x) if (x!=NULL) { x->Release(); x=NULL; }
+#endif
+
+// We don't want a message *every* time we call an unsupported function
+#define UNSUPPORTED(x) \
+ { \
+ static BOOL bFirstTime = TRUE; \
+ if (bFirstTime) { \
+ bFirstTime = FALSE; \
+ ddlogError(DDLOG_WARN, (x), DDERR_CURRENTLYNOTAVAIL); \
+ } \
+ }
+
+#define DGL_CHECK_CONTEXT \
+ if (ctx == NULL) return;
+
+// Don't render if bCanRender is not TRUE.
+#define DGL_CHECK_RENDER \
+ if (!dgl->bCanRender) return;
+
+#if 0
+#define TRY(a,b) (a)
+#define TRY_ERR(a,b) (a)
+#else
+// hResult should be defined in the function
+// Return codes should be checked via SUCCEDDED and FAILED macros
+#define TRY(a,b) \
+ { \
+ if (FAILED(hResult=(a))) \
+ ddlogError(DDLOG_ERROR, (b), hResult); \
+ }
+
+// hResult is a global
+// The label exit_with_error should be defined within the calling scope
+#define TRY_ERR(a,b) \
+ { \
+ if (FAILED(hResult=(a))) { \
+ ddlogError(DDLOG_ERROR, (b), hResult); \
+ goto exit_with_error; \
+ } \
+ }
+#endif // #if 1
+
+#endif
diff --git a/src/mesa/drivers/windows/gldirect/dglpf.c b/src/mesa/drivers/windows/gldirect/dglpf.c
new file mode 100644
index 0000000000..65e389d7a7
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dglpf.c
@@ -0,0 +1,620 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Pixel Formats.
+*
+****************************************************************************/
+
+#include "dglpf.h"
+
+#ifdef _USE_GLD3_WGL
+#include "gld_driver.h"
+#endif
+
+// ***********************************************************************
+
+char szColorDepthWarning[] =
+"GLDirect does not support the current desktop\n\
+color depth.\n\n\
+You may need to change the display resolution to\n\
+16 bits per pixel or higher color depth using\n\
+the Windows Display Settings control panel\n\
+before running this OpenGL application.\n";
+
+// ***********************************************************************
+// This pixel format will be used as a template when compiling the list
+// of pixel formats supported by the hardware. Many fields will be
+// filled in at runtime.
+// PFD flag defaults are upgraded to match ChoosePixelFormat() -- DaveM
+DGL_pixelFormat pfTemplateHW =
+{
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), // Size of the data structure
+ 1, // Structure version - should be 1
+ // Flags:
+ PFD_DRAW_TO_WINDOW | // The buffer can draw to a window or device surface.
+ PFD_DRAW_TO_BITMAP | // The buffer can draw to a bitmap. (DaveM)
+ PFD_SUPPORT_GDI | // The buffer supports GDI drawing. (DaveM)
+ PFD_SUPPORT_OPENGL | // The buffer supports OpenGL drawing.
+ PFD_DOUBLEBUFFER | // The buffer is double-buffered.
+ 0, // Placeholder for easy commenting of above flags
+ PFD_TYPE_RGBA, // Pixel type RGBA.
+ 16, // Total colour bitplanes (excluding alpha bitplanes)
+ 5, 0, // Red bits, shift
+ 5, 5, // Green bits, shift
+ 5, 10, // Blue bits, shift
+ 0, 0, // Alpha bits, shift (destination alpha)
+ 0, // Accumulator bits (total)
+ 0, 0, 0, 0, // Accumulator bits: Red, Green, Blue, Alpha
+ 0, // Depth bits
+ 0, // Stencil bits
+ 0, // Number of auxiliary buffers
+ 0, // Layer type
+ 0, // Specifies the number of overlay and underlay planes.
+ 0, // Layer mask
+ 0, // Specifies the transparent color or index of an underlay plane.
+ 0 // Damage mask
+ },
+ -1, // No depth/stencil buffer
+};
+
+// ***********************************************************************
+// Return the count of the number of bits in a Bit Mask.
+int BitCount(
+ DWORD dw)
+{
+ int i;
+
+ if (dw == 0)
+ return 0; // account for non-RGB mode
+
+ for (i=0; dw; dw=dw>>1)
+ i += (dw & 1);
+ return i;
+}
+
+// ***********************************************************************
+
+DWORD BitShift(
+ DWORD dwMaskIn)
+{
+ DWORD dwShift, dwMask;
+
+ if (dwMaskIn == 0)
+ return 0; // account for non-RGB mode
+
+ for (dwShift=0, dwMask=dwMaskIn; !(dwMask&1); dwShift++, dwMask>>=1);
+
+ return dwShift;
+}
+
+// ***********************************************************************
+
+BOOL IsValidPFD(int iPFD)
+{
+ DGL_pixelFormat *lpPF;
+
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ if ((glb.lpPF == NULL) ||
+ (glb.nPixelFormatCount == 0))
+ return FALSE;
+
+ // Check PFD range
+ if ( (iPFD < 1) || (iPFD > glb.nPixelFormatCount) ) {
+ ddlogMessage(DDLOG_ERROR, "PFD out of range\n");
+ return FALSE; // PFD is invalid
+ }
+
+ // Make a pointer to the pixel format
+ lpPF = &glb.lpPF[iPFD-1];
+
+ // Check size
+ if (lpPF->pfd.nSize != sizeof(PIXELFORMATDESCRIPTOR)) {
+ ddlogMessage(DDLOG_ERROR, "Bad PFD size\n");
+ return FALSE; // PFD is invalid
+ }
+
+ // Check version
+ if (lpPF->pfd.nVersion != 1) {
+ ddlogMessage(DDLOG_ERROR, "PFD is not Version 1\n");
+ return FALSE; // PFD is invalid
+ }
+
+ return TRUE; // PFD is valid
+}
+
+// ***********************************************************************
+
+#ifndef _USE_GLD3_WGL
+
+int iEnumCount; // Enumeration count
+DWORD dwDisplayBitDepth; // Bit depth of current display mode
+
+// ***********************************************************************
+
+HRESULT WINAPI EnumDisplayModesCallback(
+ DDSURFACEDESC2* pddsd,
+ void *pvContext)
+{
+ DWORD dwModeDepth;
+ DDSURFACEDESC2 *lpDisplayMode;
+ char buf[32];
+
+ // Check parameters
+ if (pddsd == NULL)
+ return DDENUMRET_CANCEL;
+
+ dwModeDepth = pddsd->ddpfPixelFormat.dwRGBBitCount;
+ lpDisplayMode = (DDSURFACEDESC2 *)pvContext;
+
+ // Check mode for compatability with device.
+ if (dwModeDepth != dwDisplayBitDepth)
+ return DDENUMRET_OK;
+
+ if (lpDisplayMode != NULL) {
+ memcpy(&lpDisplayMode[iEnumCount], pddsd, sizeof(DDSURFACEDESC2));
+ sprintf(buf, TEXT("Mode: %ld x %ld x %ld\n"),
+ pddsd->dwWidth, pddsd->dwHeight, dwModeDepth);
+ ddlogMessage(DDLOG_INFO, buf);
+ }
+
+ iEnumCount++;
+
+ return DDENUMRET_OK;
+}
+
+// ***********************************************************************
+
+HRESULT CALLBACK d3dEnumZBufferFormatsCallback(
+ DDPIXELFORMAT* pddpf,
+ VOID* lpZBufferPF )
+{
+ char buf[64];
+
+ if(pddpf == NULL)
+ return D3DENUMRET_CANCEL;
+
+ if (pddpf->dwFlags & DDPF_ZBUFFER) {
+ if (lpZBufferPF == NULL) {
+ // Pass 1. Merely counting the PF
+ glb.nZBufferPFCount++;
+ } else {
+ // Pass 2. Save the PF
+ if (pddpf->dwFlags & DDPF_STENCILBUFFER) {
+ sprintf(buf, " %d: Z=%d S=%d\n",
+ iEnumCount,
+ pddpf->dwZBufferBitDepth,
+ pddpf->dwStencilBitDepth);
+ } else {
+ sprintf(buf, " %d: Z=%d S=0\n",
+ iEnumCount,
+ pddpf->dwZBufferBitDepth);
+ }
+ ddlogMessage(DDLOG_INFO, buf);
+
+ memcpy(&glb.lpZBufferPF[iEnumCount++],
+ pddpf,
+ sizeof(DDPIXELFORMAT));
+ }
+ }
+
+ return D3DENUMRET_OK;
+}
+#endif // _USE_GLD3_WGL
+
+// ***********************************************************************
+
+BOOL IsStencilSupportBroken(LPDIRECTDRAW4 lpDD4)
+{
+ DDDEVICEIDENTIFIER dddi; // DX6 device identifier
+ BOOL bBroken = FALSE;
+
+ // Microsoft really fucked up with the GetDeviceIdentifier function
+ // on Windows 2000, since it locks up on stock driers on the CD. Updated
+ // drivers from vendors appear to work, but we can't identify the drivers
+ // without this function!!! For now we skip these tests on Windows 2000.
+ if ((GetVersion() & 0x80000000UL) == 0)
+ return FALSE;
+
+ // Obtain device info
+ if (FAILED(IDirectDraw4_GetDeviceIdentifier(lpDD4, &dddi, 0)))
+ return FALSE;
+
+ // Matrox G400 stencil buffer support does not draw anything in AutoCAD,
+ // but ordinary Z buffers draw shaded models fine. (DaveM)
+ if (dddi.dwVendorId == 0x102B) { // Matrox
+ if (dddi.dwDeviceId == 0x0525) { // G400
+ bBroken = TRUE;
+ }
+ }
+
+ return bBroken;
+}
+
+// ***********************************************************************
+
+void dglBuildPixelFormatList()
+{
+ int i;
+ char buf[128];
+ char cat[8];
+ HRESULT hRes;
+ DGL_pixelFormat *lpPF;
+
+#ifdef _USE_GLD3_WGL
+ _gldDriver.BuildPixelformatList();
+#else
+ IDirectDraw *lpDD1 = NULL;
+ IDirectDraw4 *lpDD4 = NULL;
+ IDirect3D3 *lpD3D3 = NULL;
+ DDSURFACEDESC2 ddsdDisplayMode;
+
+ DWORD dwRb, dwGb, dwBb, dwAb; // Bit counts
+ DWORD dwRs, dwGs, dwBs, dwAs; // Bit shifts
+ DWORD dwPixelType; // RGB or color index
+
+ // Set defaults
+ glb.nPixelFormatCount = 0;
+ glb.lpPF = NULL;
+ glb.nZBufferPFCount = 0;
+ glb.lpZBufferPF = NULL;
+ glb.nDisplayModeCount = 0;
+ glb.lpDisplayModes = NULL;
+
+ //
+ // Examine the hardware for depth and stencil
+ //
+
+ if (glb.bPrimary)
+ hRes = DirectDrawCreate(NULL, &lpDD1, NULL);
+ else
+ hRes = DirectDrawCreate(&glb.ddGuid, &lpDD1, NULL);
+
+ if (FAILED(hRes)) {
+ ddlogError(DDLOG_ERROR, "dglBPFL: DirectDrawCreate failed", hRes);
+ return;
+ }
+
+ // Query for DX6 IDirectDraw4.
+ hRes = IDirectDraw_QueryInterface(
+ lpDD1,
+ &IID_IDirectDraw4,
+ (void**)&lpDD4);
+ if (FAILED(hRes)) {
+ ddlogError(DDLOG_ERROR, "dglBPFL: QueryInterface (DD4) failed", hRes);
+ goto clean_up;
+ }
+
+
+ // Retrieve caps of current display mode
+ ZeroMemory(&ddsdDisplayMode, sizeof(ddsdDisplayMode));
+ ddsdDisplayMode.dwSize = sizeof(ddsdDisplayMode);
+ hRes = IDirectDraw4_GetDisplayMode(lpDD4, &ddsdDisplayMode);
+ if (FAILED(hRes))
+ goto clean_up;
+
+ dwDisplayBitDepth = ddsdDisplayMode.ddpfPixelFormat.dwRGBBitCount;
+ dwPixelType = (dwDisplayBitDepth <= 8) ? PFD_TYPE_COLORINDEX : PFD_TYPE_RGBA;
+ dwRb = BitCount(ddsdDisplayMode.ddpfPixelFormat.dwRBitMask);
+ dwGb = BitCount(ddsdDisplayMode.ddpfPixelFormat.dwGBitMask);
+ dwBb = BitCount(ddsdDisplayMode.ddpfPixelFormat.dwBBitMask);
+ dwRs = BitShift(ddsdDisplayMode.ddpfPixelFormat.dwRBitMask);
+ dwGs = BitShift(ddsdDisplayMode.ddpfPixelFormat.dwGBitMask);
+ dwBs = BitShift(ddsdDisplayMode.ddpfPixelFormat.dwBBitMask);
+
+ if (BitCount(ddsdDisplayMode.ddpfPixelFormat.dwRGBAlphaBitMask)) {
+ dwAb = BitCount(ddsdDisplayMode.ddpfPixelFormat.dwRGBAlphaBitMask);
+ dwAs = BitShift(ddsdDisplayMode.ddpfPixelFormat.dwRGBAlphaBitMask);
+ } else {
+ dwAb = 0;
+ dwAs = 0;
+ }
+
+ // Query for available display modes
+ ddlogMessage(DDLOG_INFO, "\n");
+ ddlogMessage(DDLOG_INFO, "Display Modes:\n");
+
+ // Pass 1: Determine count
+ iEnumCount = 0;
+ hRes = IDirectDraw4_EnumDisplayModes(
+ lpDD4,
+ 0,
+ NULL,
+ NULL,
+ EnumDisplayModesCallback);
+ if (FAILED(hRes)) {
+ ddlogError(DDLOG_ERROR, "dglBPFL: EnumDisplayModes failed", hRes);
+ goto clean_up;
+ }
+ if (iEnumCount == 0) {
+ ddlogMessage(DDLOG_ERROR, "dglBPFL: No display modes found");
+ goto clean_up;
+ }
+ glb.lpDisplayModes = (DDSURFACEDESC2 *)calloc(iEnumCount,
+ sizeof(DDSURFACEDESC2));
+ if (glb.lpDisplayModes == NULL) {
+ ddlogMessage(DDLOG_ERROR, "dglBPFL: DDSURFACEDESC2 calloc failed");
+ goto clean_up;
+ }
+ glb.nDisplayModeCount = iEnumCount;
+ // Pass 2: Save modes
+ iEnumCount = 0;
+ hRes = IDirectDraw4_EnumDisplayModes(
+ lpDD4,
+ 0,
+ NULL,
+ (void *)glb.lpDisplayModes,
+ EnumDisplayModesCallback);
+ if (FAILED(hRes)) {
+ ddlogError(DDLOG_ERROR, "dglBPFL: EnumDisplayModes failed", hRes);
+ goto clean_up;
+ }
+ // Query for IDirect3D3 interface
+ hRes = IDirectDraw4_QueryInterface(
+ lpDD4,
+ &IID_IDirect3D3,
+ (void**)&lpD3D3);
+ if (FAILED(hRes)) {
+ ddlogError(DDLOG_ERROR, "dglBPFL: QueryInterface (D3D3) failed", hRes);
+ goto clean_up;
+ }
+
+ ddlogMessage(DDLOG_INFO, "\n");
+ ddlogMessage(DDLOG_INFO, "ZBuffer formats:\n");
+
+ // Pass 1. Count the ZBuffer pixel formats
+ hRes = IDirect3D3_EnumZBufferFormats(
+ lpD3D3,
+ &glb.d3dGuid,
+ d3dEnumZBufferFormatsCallback,
+ NULL);
+
+ if (FAILED(hRes))
+ goto clean_up;
+
+ if (glb.nZBufferPFCount) {
+ glb.lpZBufferPF = (DDPIXELFORMAT *)calloc(glb.nZBufferPFCount,
+ sizeof(DDPIXELFORMAT));
+ if(glb.lpZBufferPF == NULL)
+ goto clean_up;
+
+ // Pass 2. Cache the ZBuffer pixel formats
+ iEnumCount = 0; // (Used by the enum function)
+ hRes = IDirect3D3_EnumZBufferFormats(
+ lpD3D3,
+ &glb.d3dGuid,
+ d3dEnumZBufferFormatsCallback,
+ glb.lpZBufferPF);
+
+ if (FAILED(hRes))
+ goto clean_up;
+ }
+
+ // Remove stencil support for boards which don't work for AutoCAD;
+ // Matrox G400 does not work, but NVidia TNT2 and ATI Rage128 do... (DaveM)
+ if (IsStencilSupportBroken(lpDD4)) {
+ for (i=0; i<iEnumCount; i++)
+ if (glb.lpZBufferPF[i].dwFlags & DDPF_STENCILBUFFER)
+ glb.nZBufferPFCount--;
+ }
+
+ // One each for every ZBuffer pixel format (including no depth buffer)
+ // Times-two because duplicated for single buffering (as opposed to double)
+ glb.nPixelFormatCount = 2 * (glb.nZBufferPFCount + 1);
+ glb.lpPF = (DGL_pixelFormat *)calloc(glb.nPixelFormatCount,
+ sizeof(DGL_pixelFormat));
+ if (glb.lpPF == NULL)
+ goto clean_up;
+ //
+ // Fill in the pixel formats
+ // Note: Depth buffer bits are really (dwZBufferBitDepth-dwStencilBitDepth)
+ // but this will pass wierd numbers to the OpenGL app. (?)
+ //
+
+ pfTemplateHW.pfd.iPixelType = dwPixelType;
+ pfTemplateHW.pfd.cColorBits = dwDisplayBitDepth;
+ pfTemplateHW.pfd.cRedBits = dwRb;
+ pfTemplateHW.pfd.cGreenBits = dwGb;
+ pfTemplateHW.pfd.cBlueBits = dwBb;
+ pfTemplateHW.pfd.cAlphaBits = dwAb;
+ pfTemplateHW.pfd.cRedShift = dwRs;
+ pfTemplateHW.pfd.cGreenShift = dwGs;
+ pfTemplateHW.pfd.cBlueShift = dwBs;
+ pfTemplateHW.pfd.cAlphaShift = dwAs;
+
+ lpPF = glb.lpPF;
+
+ // Fill in the double-buffered pixel formats
+ for (i=0; i<(glb.nZBufferPFCount + 1); i++, lpPF++) {
+ memcpy(lpPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ if (i) {
+ lpPF->iZBufferPF = i-1;
+ lpPF->pfd.cDepthBits = glb.lpZBufferPF[i-1].dwZBufferBitDepth;
+ lpPF->pfd.cStencilBits = glb.lpZBufferPF[i-1].dwStencilBitDepth;
+ }
+ }
+ // Fill in the single-buffered pixel formats
+ for (i=0; i<(glb.nZBufferPFCount + 1); i++, lpPF++) {
+ memcpy(lpPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ if (i) {
+ lpPF->iZBufferPF = i-1;
+ lpPF->pfd.cDepthBits = glb.lpZBufferPF[i-1].dwZBufferBitDepth;
+ lpPF->pfd.cStencilBits = glb.lpZBufferPF[i-1].dwStencilBitDepth;
+ }
+ // Remove double-buffer flag. Could use XOR instead...
+ lpPF->pfd.dwFlags &= (~(PFD_DOUBLEBUFFER));
+ // Insert GDI flag for single buffered format only.
+ lpPF->pfd.dwFlags |= PFD_SUPPORT_GDI;
+ }
+#endif // _USE_GLD3_WGL
+
+ // Lets dump the list to the log
+ // ** Based on "wglinfo" by Nate Robins **
+ ddlogMessage(DDLOG_INFO, "\n");
+ ddlogMessage(DDLOG_INFO, "Pixel Formats:\n");
+ ddlogMessage(DDLOG_INFO,
+ " visual x bf lv rg d st r g b a ax dp st accum buffs ms\n");
+ ddlogMessage(DDLOG_INFO,
+ " id dep cl sp sz l ci b ro sz sz sz sz bf th cl r g b a ns b\n");
+ ddlogMessage(DDLOG_INFO,
+ "-----------------------------------------------------------------\n");
+ for (i=0, lpPF = glb.lpPF; i<glb.nPixelFormatCount; i++, lpPF++) {
+ sprintf(buf, "0x%02x ", i+1);
+
+ sprintf(cat, "%2d ", lpPF->pfd.cColorBits);
+ strcat(buf, cat);
+ if(lpPF->pfd.dwFlags & PFD_DRAW_TO_WINDOW) sprintf(cat, "wn ");
+ else if(lpPF->pfd.dwFlags & PFD_DRAW_TO_BITMAP) sprintf(cat, "bm ");
+ else sprintf(cat, ". ");
+ strcat(buf, cat);
+
+ /* should find transparent pixel from LAYERPLANEDESCRIPTOR */
+ sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ sprintf(cat, "%2d ", lpPF->pfd.cColorBits);
+ strcat(buf, cat);
+
+ /* bReserved field indicates number of over/underlays */
+ if(lpPF->pfd.bReserved) sprintf(cat, " %d ", lpPF->pfd.bReserved);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ sprintf(cat, " %c ", lpPF->pfd.iPixelType == PFD_TYPE_RGBA ? 'r' : 'c');
+ strcat(buf, cat);
+
+ sprintf(cat, "%c ", lpPF->pfd.dwFlags & PFD_DOUBLEBUFFER ? 'y' : '.');
+ strcat(buf, cat);
+
+ sprintf(cat, " %c ", lpPF->pfd.dwFlags & PFD_STEREO ? 'y' : '.');
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cRedBits && lpPF->pfd.iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", lpPF->pfd.cRedBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cGreenBits && lpPF->pfd.iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", lpPF->pfd.cGreenBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cBlueBits && lpPF->pfd.iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", lpPF->pfd.cBlueBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cAlphaBits && lpPF->pfd.iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", lpPF->pfd.cAlphaBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cAuxBuffers) sprintf(cat, "%2d ", lpPF->pfd.cAuxBuffers);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cDepthBits) sprintf(cat, "%2d ", lpPF->pfd.cDepthBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cStencilBits) sprintf(cat, "%2d ", lpPF->pfd.cStencilBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cAccumRedBits) sprintf(cat, "%2d ", lpPF->pfd.cAccumRedBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cAccumGreenBits) sprintf(cat, "%2d ", lpPF->pfd.cAccumGreenBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cAccumBlueBits) sprintf(cat, "%2d ", lpPF->pfd.cAccumBlueBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(lpPF->pfd.cAccumAlphaBits) sprintf(cat, "%2d ", lpPF->pfd.cAccumAlphaBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ /* no multisample in Win32 */
+ sprintf(cat, " . .\n");
+ strcat(buf, cat);
+
+ ddlogMessage(DDLOG_INFO, buf);
+ }
+ ddlogMessage(DDLOG_INFO,
+ "-----------------------------------------------------------------\n");
+ ddlogMessage(DDLOG_INFO, "\n");
+
+#ifndef _USE_GLD3_WGL
+clean_up:
+ // Release COM objects
+ RELEASE(lpD3D3);
+ RELEASE(lpDD4);
+ RELEASE(lpDD1);
+
+ // Popup warning message if non RGB color mode
+ if (dwDisplayBitDepth <= 8) {
+ ddlogPrintf(DDLOG_WARN, "Current Color Depth %d bpp is not supported", dwDisplayBitDepth);
+ MessageBox(NULL, szColorDepthWarning, "GLDirect", MB_OK | MB_ICONWARNING);
+ }
+#endif // _USE_GLD3_WGL
+}
+
+// ***********************************************************************
+
+void dglReleasePixelFormatList()
+{
+ glb.nPixelFormatCount = 0;
+ if (glb.lpPF) {
+ free(glb.lpPF);
+ glb.lpPF = NULL;
+ }
+#ifndef _USE_GLD3_WGL
+ glb.nZBufferPFCount = 0;
+ if (glb.lpZBufferPF) {
+ free(glb.lpZBufferPF);
+ glb.lpZBufferPF = NULL;
+ }
+ glb.nDisplayModeCount = 0;
+ if (glb.lpDisplayModes) {
+ free(glb.lpDisplayModes);
+ glb.lpDisplayModes = NULL;
+ }
+#endif // _USE_GLD3_WGL
+}
+
+// ***********************************************************************
diff --git a/src/mesa/drivers/windows/gldirect/dglpf.h b/src/mesa/drivers/windows/gldirect/dglpf.h
new file mode 100644
index 0000000000..8a7e38c4b3
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dglpf.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Pixel Formats.
+*
+****************************************************************************/
+
+#ifndef __DGLPF_H
+#define __DGLPF_H
+
+#ifndef STRICT
+#define STRICT
+#endif // STRICT
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+typedef struct {
+ PIXELFORMATDESCRIPTOR pfd; // Win32 Pixel Format Descriptor
+#ifdef _USE_GLD3_WGL
+ // Driver-specific data.
+ // Example: The DX8 driver uses this to hold an index into a
+ // list of depth-stencil descriptions.
+ DWORD dwDriverData;
+#else
+ int iZBufferPF; // Index of depth buffer pixel format
+#endif
+} DGL_pixelFormat;
+
+#include "dglglobals.h"
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+BOOL IsValidPFD(int iPFD);
+void dglBuildPixelFormatList();
+void dglReleasePixelFormatList();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/mesa/drivers/windows/gldirect/dglwgl.c b/src/mesa/drivers/windows/gldirect/dglwgl.c
new file mode 100644
index 0000000000..a1b7e5dce0
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dglwgl.c
@@ -0,0 +1,2958 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: OpenGL window functions (wgl*).
+*
+****************************************************************************/
+
+#include "dglwgl.h"
+#ifdef _USE_GLD3_WGL
+#include "gld_driver.h"
+#endif
+
+#include "glu.h" // MUST USE MICROSOFT'S GLU32!
+
+#ifndef _USE_GLD3_WGL
+extern DGL_mesaFuncs mesaFuncs;
+#endif
+
+// Need to export wgl* functions if using GLD3,
+// otherwise export GLD2 DGL_* functions.
+#ifdef _USE_GLD3_WGL
+#define _GLD_WGL_EXPORT(a) wgl##a
+#else
+#define _GLD_WGL_EXPORT(a) DGL_##a
+#endif
+
+// Calls into Mesa 4.x are different
+#ifdef _USE_GLD3_WGL
+#include "dlist.h"
+#include "drawpix.h"
+#include "get.h"
+#include "matrix.h"
+// NOTE: All the _GLD* macros now call the gl* functions direct.
+// This ensures that the correct internal pathway is taken. KeithH
+#define _GLD_glNewList glNewList
+#define _GLD_glBitmap glBitmap
+#define _GLD_glEndList glEndList
+#define _GLD_glDeleteLists glDeleteLists
+#define _GLD_glGetError glGetError
+#define _GLD_glTranslatef glTranslatef
+#define _GLD_glBegin glBegin
+#define _GLD_glVertex2fv glVertex2fv
+#define _GLD_glEnd glEnd
+#define _GLD_glNormal3f glNormal3f
+#define _GLD_glVertex3f glVertex3f
+#define _GLD_glVertex3fv glVertex3fv
+#else // _USE_GLD3_WGL
+#define _GLD_glNewList (*mesaFuncs.glNewList)
+#define _GLD_glBitmap (*mesaFuncs.glBitmap)
+#define _GLD_glEndList (*mesaFuncs.glEndList)
+#define _GLD_glDeleteLists (*mesaFuncs.glDeleteLists)
+#define _GLD_glGetError (*mesaFuncs.glGetError)
+#define _GLD_glTranslatef (*mesaFuncs.glTranslatef)
+#define _GLD_glBegin (*mesaFuncs.glBegin)
+#define _GLD_glVertex2fv (*mesaFuncs.glVertex2fv)
+#define _GLD_glEnd (*mesaFuncs.glEnd)
+#define _GLD_glNormal3f (*mesaFuncs.glNormal3f)
+#define _GLD_glVertex3f (*mesaFuncs.glVertex3f)
+#define _GLD_glVertex3fv (*mesaFuncs.glVertex3fv)
+#endif // _USE_GLD3_WGL
+
+// ***********************************************************************
+
+// Emulate SGI DDK calls.
+#define __wglMalloc(a) GlobalAlloc(GPTR, (a))
+#define __wglFree(a) GlobalFree((a))
+
+// ***********************************************************************
+
+// Mesa glu.h and MS glu.h call these different things...
+//#define GLUtesselator GLUtriangulatorObj
+//#define GLU_TESS_VERTEX_DATA GLU_VERTEX_DATA
+
+// For wglFontOutlines
+
+typedef GLUtesselator *(APIENTRY *gluNewTessProto)(void);
+typedef void (APIENTRY *gluDeleteTessProto)(GLUtesselator *tess);
+typedef void (APIENTRY *gluTessBeginPolygonProto)(GLUtesselator *tess, void *polygon_data);
+typedef void (APIENTRY *gluTessBeginContourProto)(GLUtesselator *tess);
+typedef void (APIENTRY *gluTessVertexProto)(GLUtesselator *tess, GLdouble coords[3], void *data);
+typedef void (APIENTRY *gluTessEndContourProto)(GLUtesselator *tess);
+typedef void (APIENTRY *gluTessEndPolygonProto)(GLUtesselator *tess);
+typedef void (APIENTRY *gluTessPropertyProto)(GLUtesselator *tess, GLenum which, GLdouble value);
+typedef void (APIENTRY *gluTessNormalProto)(GLUtesselator *tess, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRY *gluTessCallbackProto)(GLUtesselator *tess, GLenum which, void (CALLBACK *)());
+
+static HINSTANCE gluModuleHandle;
+static gluNewTessProto gluNewTessProc;
+static gluDeleteTessProto gluDeleteTessProc;
+static gluTessBeginPolygonProto gluTessBeginPolygonProc;
+static gluTessBeginContourProto gluTessBeginContourProc;
+static gluTessVertexProto gluTessVertexProc;
+static gluTessEndContourProto gluTessEndContourProc;
+static gluTessEndPolygonProto gluTessEndPolygonProc;
+static gluTessPropertyProto gluTessPropertyProc;
+static gluTessNormalProto gluTessNormalProc;
+static gluTessCallbackProto gluTessCallbackProc;
+
+static HFONT hNewFont, hOldFont;
+static FLOAT ScaleFactor;
+
+#define LINE_BUF_QUANT 4000
+#define VERT_BUF_QUANT 4000
+
+static FLOAT* LineBuf;
+static DWORD LineBufSize;
+static DWORD LineBufIndex;
+static FLOAT* VertBuf;
+static DWORD VertBufSize;
+static DWORD VertBufIndex;
+static GLenum TessErrorOccurred;
+
+static int AppendToLineBuf(
+ FLOAT value);
+
+static int AppendToVertBuf(
+ FLOAT value);
+
+static int DrawGlyph(
+ UCHAR* glyphBuf,
+ DWORD glyphSize,
+ FLOAT chordalDeviation,
+ FLOAT extrusion,
+ INT format);
+
+static void FreeLineBuf(void);
+
+static void FreeVertBuf(void);
+
+static long GetWord(
+ UCHAR** p);
+
+static long GetDWord(
+ UCHAR** p);
+
+static double GetFixed(
+ UCHAR** p);
+
+static int InitLineBuf(void);
+
+static int InitVertBuf(void);
+
+static HFONT CreateHighResolutionFont(
+ HDC hDC);
+
+static int MakeDisplayListFromGlyph(
+ DWORD listName,
+ UCHAR* glyphBuf,
+ DWORD glyphSize,
+ LPGLYPHMETRICSFLOAT glyphMetricsFloat,
+ FLOAT chordalDeviation,
+ FLOAT extrusion,
+ INT format);
+
+static BOOL LoadGLUTesselator(void);
+static BOOL UnloadGLUTesselator(void);
+
+static int MakeLinesFromArc(
+ FLOAT x0,
+ FLOAT y0,
+ FLOAT x1,
+ FLOAT y1,
+ FLOAT x2,
+ FLOAT y2,
+ DWORD vertexCountIndex,
+ FLOAT chordalDeviationSquared);
+
+static int MakeLinesFromGlyph( UCHAR* glyphBuf,
+ DWORD glyphSize,
+ FLOAT chordalDeviation);
+
+static int MakeLinesFromTTLine( UCHAR** pp,
+ DWORD vertexCountIndex,
+ WORD pointCount);
+
+static int MakeLinesFromTTPolycurve( UCHAR** pp,
+ DWORD vertexCountIndex,
+ FLOAT chordalDeviation);
+
+static int MakeLinesFromTTPolygon( UCHAR** pp,
+ FLOAT chordalDeviation);
+
+static int MakeLinesFromTTQSpline( UCHAR** pp,
+ DWORD vertexCountIndex,
+ WORD pointCount,
+ FLOAT chordalDeviation);
+
+static void CALLBACK TessCombine( double coords[3],
+ void* vertex_data[4],
+ FLOAT weight[4],
+ void** outData);
+
+static void CALLBACK TessError( GLenum error);
+
+static void CALLBACK TessVertexOutData( FLOAT p[3],
+ GLfloat z);
+
+// ***********************************************************************
+
+#ifdef GLD_THREADS
+#pragma message("compiling DGLWGL.C vars for multi-threaded support")
+extern CRITICAL_SECTION CriticalSection;
+extern DWORD dwTLSPixelFormat; // TLS index for current pixel format
+#endif
+int curPFD = 0; // Current PFD (static)
+
+// ***********************************************************************
+
+int dglGetPixelFormat(void)
+{
+#ifdef GLD_THREADS
+ int iPixelFormat;
+ // get thread-specific instance
+ if (glb.bMultiThreaded) {
+ __try {
+ iPixelFormat = (int)TlsGetValue(dwTLSPixelFormat);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ iPixelFormat = curPFD;
+ }
+ }
+ // get global static var
+ else {
+ iPixelFormat = curPFD;
+ }
+ return iPixelFormat;
+#else
+ return curPFD;
+#endif
+}
+
+// ***********************************************************************
+
+void dglSetPixelFormat(int iPixelFormat)
+{
+#ifdef GLD_THREADS
+ // set thread-specific instance
+ if (glb.bMultiThreaded) {
+ __try {
+ TlsSetValue(dwTLSPixelFormat, (LPVOID)iPixelFormat);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ curPFD = iPixelFormat;
+ }
+ }
+ // set global static var
+ else {
+ curPFD = iPixelFormat;
+ }
+#else
+ curPFD = iPixelFormat;
+#endif
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(ChoosePixelFormat)(
+ HDC a,
+ CONST PIXELFORMATDESCRIPTOR *ppfd)
+{
+ DGL_pixelFormat *lpPF = glb.lpPF;
+
+ PIXELFORMATDESCRIPTOR ppfdBest;
+ int i;
+ int bestIndex = -1;
+ int numPixelFormats;
+ DWORD dwFlags;
+
+ char buf[128];
+ char cat[8];
+
+ DWORD dwAllFlags =
+ PFD_DRAW_TO_WINDOW |
+ PFD_DRAW_TO_BITMAP |
+ PFD_SUPPORT_GDI |
+ PFD_SUPPORT_OPENGL |
+ PFD_GENERIC_FORMAT |
+ PFD_NEED_PALETTE |
+ PFD_NEED_SYSTEM_PALETTE |
+ PFD_DOUBLEBUFFER |
+ PFD_STEREO |
+ /*PFD_SWAP_LAYER_BUFFERS |*/
+ PFD_DOUBLEBUFFER_DONTCARE |
+ PFD_STEREO_DONTCARE |
+ PFD_SWAP_COPY |
+ PFD_SWAP_EXCHANGE |
+ PFD_GENERIC_ACCELERATED |
+ 0;
+
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ // List may not be built until dglValidate() is called! KeithH
+ lpPF = glb.lpPF;
+
+ //
+ // Lets print the input pixel format to the log
+ // ** Based on "wglinfo" by Nate Robins **
+ //
+ ddlogMessage(DDLOG_SYSTEM, "ChoosePixelFormat:\n");
+ ddlogMessage(DDLOG_INFO, "Input pixel format for ChoosePixelFormat:\n");
+ ddlogMessage(DDLOG_INFO,
+ " visual x bf lv rg d st r g b a ax dp st accum buffs ms\n");
+ ddlogMessage(DDLOG_INFO,
+ " id dep cl sp sz l ci b ro sz sz sz sz bf th cl r g b a ns b\n");
+ ddlogMessage(DDLOG_INFO,
+ "-----------------------------------------------------------------\n");
+ sprintf(buf, " . ");
+
+ sprintf(cat, "%2d ", ppfd->cColorBits);
+ strcat(buf, cat);
+ if(ppfd->dwFlags & PFD_DRAW_TO_WINDOW) sprintf(cat, "wn ");
+ else if(ppfd->dwFlags & PFD_DRAW_TO_BITMAP) sprintf(cat, "bm ");
+ else sprintf(cat, ". ");
+ strcat(buf, cat);
+
+ /* should find transparent pixel from LAYERPLANEDESCRIPTOR */
+ sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ sprintf(cat, "%2d ", ppfd->cColorBits);
+ strcat(buf, cat);
+
+ /* bReserved field indicates number of over/underlays */
+ if(ppfd->bReserved) sprintf(cat, " %d ", ppfd->bReserved);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ sprintf(cat, " %c ", ppfd->iPixelType == PFD_TYPE_RGBA ? 'r' : 'c');
+ strcat(buf, cat);
+
+ sprintf(cat, "%c ", ppfd->dwFlags & PFD_DOUBLEBUFFER ? 'y' : '.');
+ strcat(buf, cat);
+
+ sprintf(cat, " %c ", ppfd->dwFlags & PFD_STEREO ? 'y' : '.');
+ strcat(buf, cat);
+
+ if(ppfd->cRedBits && ppfd->iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", ppfd->cRedBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cGreenBits && ppfd->iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", ppfd->cGreenBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cBlueBits && ppfd->iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", ppfd->cBlueBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAlphaBits && ppfd->iPixelType == PFD_TYPE_RGBA)
+ sprintf(cat, "%2d ", ppfd->cAlphaBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAuxBuffers) sprintf(cat, "%2d ", ppfd->cAuxBuffers);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cDepthBits) sprintf(cat, "%2d ", ppfd->cDepthBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cStencilBits) sprintf(cat, "%2d ", ppfd->cStencilBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAccumRedBits) sprintf(cat, "%2d ", ppfd->cAccumRedBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAccumGreenBits) sprintf(cat, "%2d ", ppfd->cAccumGreenBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAccumBlueBits) sprintf(cat, "%2d ", ppfd->cAccumBlueBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ if(ppfd->cAccumAlphaBits) sprintf(cat, "%2d ", ppfd->cAccumAlphaBits);
+ else sprintf(cat, " . ");
+ strcat(buf, cat);
+
+ /* no multisample in Win32 */
+ sprintf(cat, " . .\n");
+ strcat(buf, cat);
+
+ ddlogMessage(DDLOG_INFO, buf);
+ ddlogMessage(DDLOG_INFO,
+ "-----------------------------------------------------------------\n");
+ ddlogMessage(DDLOG_INFO, "\n");
+
+ //
+ // Examine the flags for correctness
+ //
+ dwFlags = ppfd->dwFlags;
+ if (dwFlags != (dwFlags & dwAllFlags))
+ {
+ /* error: bad dwFlags */
+ ddlogPrintf(DDLOG_WARN,
+ "ChoosePixelFormat: bad flags (0x%x)",
+ dwFlags & (~dwAllFlags));
+ // Mask illegal flags and continue
+ dwFlags = dwFlags & dwAllFlags;
+ }
+
+ switch (ppfd->iPixelType) {
+ case PFD_TYPE_RGBA:
+ case PFD_TYPE_COLORINDEX:
+ break;
+ default:
+ /* error: bad iPixelType */
+ ddlogMessage(DDLOG_WARN, "ChoosePixelFormat: bad pixel type\n");
+ return 0;
+ }
+
+ switch (ppfd->iLayerType) {
+ case PFD_MAIN_PLANE:
+ case PFD_OVERLAY_PLANE:
+ case PFD_UNDERLAY_PLANE:
+ break;
+ default:
+ /* error: bad iLayerType */
+ ddlogMessage(DDLOG_WARN, "ChoosePixelFormat: bad layer type\n");
+ return 0;
+ }
+
+ numPixelFormats = glb.nPixelFormatCount;
+
+ /* loop through candidate pixel format descriptors */
+ for (i=0; i<numPixelFormats; ++i) {
+ PIXELFORMATDESCRIPTOR ppfdCandidate;
+
+ memcpy(&ppfdCandidate, &lpPF[i].pfd, sizeof(PIXELFORMATDESCRIPTOR));
+
+ /*
+ ** Check attributes which must match
+ */
+ if (ppfd->iPixelType != ppfdCandidate.iPixelType) {
+ continue;
+ }
+
+ if (ppfd->iLayerType != ppfdCandidate.iLayerType) {
+ continue;
+ }
+
+ if (((dwFlags ^ ppfdCandidate.dwFlags) & dwFlags) &
+ (PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP |
+ PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL))
+ {
+ continue;
+ }
+
+ if (!(dwFlags & PFD_DOUBLEBUFFER_DONTCARE)) {
+ if ((dwFlags & PFD_DOUBLEBUFFER) !=
+ (ppfdCandidate.dwFlags & PFD_DOUBLEBUFFER))
+ {
+ continue;
+ }
+ }
+
+// if (!(dwFlags & PFD_STEREO_DONTCARE)) {
+ if ((dwFlags & PFD_STEREO) !=
+ (ppfdCandidate.dwFlags & PFD_STEREO))
+ {
+ continue;
+ }
+// }
+
+ if (ppfd->iPixelType==PFD_TYPE_RGBA
+ && ppfd->cAlphaBits && !ppfdCandidate.cAlphaBits) {
+ continue;
+ }
+
+ if (ppfd->iPixelType==PFD_TYPE_RGBA
+ && ppfd->cAccumBits && !ppfdCandidate.cAccumBits) {
+ continue;
+ }
+
+ if (ppfd->cDepthBits && !ppfdCandidate.cDepthBits) {
+ continue;
+ }
+
+ if (ppfd->cStencilBits && !ppfdCandidate.cStencilBits) {
+ continue;
+ }
+
+ if (ppfd->cAuxBuffers && !ppfdCandidate.cAuxBuffers) {
+ continue;
+ }
+
+ /*
+ ** See if candidate is better than the previous best choice
+ */
+ if (bestIndex == -1) {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if ((ppfd->cColorBits > ppfdBest.cColorBits &&
+ ppfdCandidate.cColorBits > ppfdBest.cColorBits) ||
+ (ppfd->cColorBits <= ppfdCandidate.cColorBits &&
+ ppfdCandidate.cColorBits < ppfdBest.cColorBits))
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if (ppfd->iPixelType==PFD_TYPE_RGBA
+ && ppfd->cAlphaBits
+ && ppfdCandidate.cAlphaBits > ppfdBest.cAlphaBits)
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if (ppfd->iPixelType==PFD_TYPE_RGBA
+ && ppfd->cAccumBits
+ && ppfdCandidate.cAccumBits > ppfdBest.cAccumBits)
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if ((ppfd->cDepthBits > ppfdBest.cDepthBits &&
+ ppfdCandidate.cDepthBits > ppfdBest.cDepthBits) ||
+ (ppfd->cDepthBits <= ppfdCandidate.cDepthBits &&
+ ppfdCandidate.cDepthBits < ppfdBest.cDepthBits))
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if (ppfd->cStencilBits &&
+ ppfdCandidate.cStencilBits > ppfdBest.cStencilBits)
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+
+ if (ppfd->cAuxBuffers &&
+ ppfdCandidate.cAuxBuffers > ppfdBest.cAuxBuffers)
+ {
+ ppfdBest = ppfdCandidate;
+ bestIndex = i;
+ continue;
+ }
+ }
+
+ if (bestIndex != -1) {
+ ddlogPrintf(DDLOG_SYSTEM, "Pixel Format %d chosen as best match", bestIndex+1);
+ return bestIndex + 1;
+ }
+
+ // Return the pixelformat that has the most capabilities.
+ // ** NOTE: This is only possible due to the way the list
+ // of pixelformats is built. **
+ // Now picks best pixelformat. KeithH
+ bestIndex = numPixelFormats; // most capable double buffer format
+ ddlogPrintf(DDLOG_SYSTEM, "Pixel Format %d chosen by default", bestIndex);
+ return (bestIndex);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(CopyContext)(
+ HGLRC a,
+ HGLRC b,
+ UINT c)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+ UNSUPPORTED("wglCopyContext")
+ return FALSE; // Failed
+}
+
+// ***********************************************************************
+
+HGLRC APIENTRY _GLD_WGL_EXPORT(CreateContext)(
+ HDC a)
+{
+ int ipf;
+
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ // Check that the current PFD is valid
+ ipf = dglGetPixelFormat();
+ if (!IsValidPFD(ipf))
+ return (HGLRC)0;
+
+ return dglCreateContext(a, &glb.lpPF[ipf-1]);
+}
+
+// ***********************************************************************
+
+HGLRC APIENTRY _GLD_WGL_EXPORT(CreateLayerContext)(
+ HDC a,
+ int b)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ UNSUPPORTED("wglCreateLayerContext")
+ return NULL; // Failed
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(DeleteContext)(
+ HGLRC a)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return dglDeleteContext(a);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(DescribeLayerPlane)(
+ HDC hDC,
+ int iPixelFormat,
+ int iLayerPlane,
+ UINT nBytes,
+ LPLAYERPLANEDESCRIPTOR plpd)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ UNSUPPORTED("DGL_DescribeLayerPlane")
+
+// gldLogPrintf(GLDLOG_INFO, "DescribeLayerPlane: %d, %d", iPixelFormat, iLayerPlane);
+
+ return FALSE;
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(DescribePixelFormat)(
+ HDC a,
+ int b,
+ UINT c,
+ LPPIXELFORMATDESCRIPTOR d)
+{
+ UINT nSize;
+
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ if (d == NULL) // Calling app requires max number of PF's
+ return glb.nPixelFormatCount;
+
+ // The supplied buffer may be larger than the info that we
+ // will be copying.
+ if (c > sizeof(PIXELFORMATDESCRIPTOR))
+ nSize = sizeof(PIXELFORMATDESCRIPTOR);
+ else
+ nSize = c;
+
+ // Setup an empty PFD before doing validation check
+ memset(d, 0, nSize);
+ d->nSize = nSize;
+ d->nVersion = 1;
+
+ if (!IsValidPFD(b))
+ return 0; // Bail if PFD index is invalid
+
+ memcpy(d, &glb.lpPF[b-1].pfd, nSize);
+
+ return glb.nPixelFormatCount;
+}
+
+// ***********************************************************************
+
+HGLRC APIENTRY _GLD_WGL_EXPORT(GetCurrentContext)(void)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ return dglGetCurrentContext();
+}
+
+// ***********************************************************************
+
+HDC APIENTRY _GLD_WGL_EXPORT(GetCurrentDC)(void)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ return dglGetCurrentDC();
+}
+
+// ***********************************************************************
+
+PROC APIENTRY _GLD_WGL_EXPORT(GetDefaultProcAddress)(
+ LPCSTR a)
+{
+ // Validate license
+ if (!dglValidate())
+ return NULL;
+
+ UNSUPPORTED("DGL_GetDefaultProcAddress")
+ return NULL;
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(GetLayerPaletteEntries)(
+ HDC a,
+ int b,
+ int c,
+ int d,
+ COLORREF *e)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ UNSUPPORTED("DGL_GetLayerPaletteEntries")
+ return 0;
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(GetPixelFormat)(
+ HDC a)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ return dglGetPixelFormat();
+}
+
+// ***********************************************************************
+
+PROC APIENTRY _GLD_WGL_EXPORT(GetProcAddress)(
+ LPCSTR a)
+{
+ PROC dglGetProcAddressD3D(LPCSTR a);
+
+ // Validate license
+ if (!dglValidate())
+ return NULL;
+
+#ifdef _USE_GLD3_WGL
+ return _gldDriver.wglGetProcAddress(a);
+#else
+ return dglGetProcAddressD3D(a);
+#endif
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(MakeCurrent)(
+ HDC a,
+ HGLRC b)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return dglMakeCurrent(a, b);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(RealizeLayerPalette)(
+ HDC a,
+ int b,
+ BOOL c)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ UNSUPPORTED("DGL_RealizeLayerPalette")
+ return FALSE;
+}
+
+// ***********************************************************************
+
+int APIENTRY _GLD_WGL_EXPORT(SetLayerPaletteEntries)(
+ HDC a,
+ int b,
+ int c,
+ int d,
+ CONST COLORREF *e)
+{
+ // Validate license
+ if (!dglValidate())
+ return 0;
+
+ UNSUPPORTED("DGL_SetLayerPaletteEntries")
+ return 0;
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(SetPixelFormat)(
+ HDC a,
+ int b,
+ CONST PIXELFORMATDESCRIPTOR *c)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ if (IsValidPFD(b)) {
+ ddlogPrintf(DDLOG_SYSTEM, "SetPixelFormat: PixelFormat %d has been set", b);
+ dglSetPixelFormat(b);
+ return TRUE;
+ } else {
+ ddlogPrintf(DDLOG_ERROR,
+ "SetPixelFormat: PixelFormat %d is invalid and cannot be set", b);
+ return FALSE;
+ }
+}
+
+// ***********************************************************************
+/*
+ * Share lists between two gl_context structures.
+ * This was added for WIN32 WGL function support, since wglShareLists()
+ * must be called *after* wglCreateContext() with valid GLRCs. (DaveM)
+ */
+//
+// Copied from GLD2.x. KeithH
+//
+static GLboolean _gldShareLists(
+ GLcontext *ctx1,
+ GLcontext *ctx2)
+{
+ /* Sanity check context pointers */
+ if (ctx1 == NULL || ctx2 == NULL)
+ return GL_FALSE;
+ /* Sanity check shared list pointers */
+ if (ctx1->Shared == NULL || ctx2->Shared == NULL)
+ return GL_FALSE;
+ /* Decrement reference count on sharee to release previous list */
+ ctx2->Shared->RefCount--;
+#if 0 /* 3DStudio exits on this memory release */
+ if (ctx2->Shared->RefCount == 0)
+ free_shared_state(ctx2, ctx2->Shared);
+#endif
+ /* Re-assign list from sharer to sharee and increment reference count */
+ ctx2->Shared = ctx1->Shared;
+ ctx1->Shared->RefCount++;
+ return GL_TRUE;
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(ShareLists)(
+ HGLRC a,
+ HGLRC b)
+{
+ DGL_ctx *dgl1, *dgl2;
+
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ // Mesa supports shared lists, but you need to supply the shared
+ // GL context info when calling gl_create_context(). An auxiliary
+ // function gl_share_lists() has been added to update the shared
+ // list info after the GL contexts have been created. (DaveM)
+ dgl1 = dglGetContextAddress(a);
+ dgl2 = dglGetContextAddress(b);
+ if (dgl1->bAllocated && dgl2->bAllocated) {
+#ifdef _USE_GLD3_WGL
+ return _gldShareLists(dgl1->glCtx, dgl2->glCtx);
+#else
+ return (*mesaFuncs.gl_share_lists)(dgl1->glCtx, dgl2->glCtx);
+#endif
+ }
+ return FALSE;
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(SwapBuffers)(
+ HDC a)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return dglSwapBuffers(a);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(SwapLayerBuffers)(
+ HDC a,
+ UINT b)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return dglSwapBuffers(a);
+}
+
+// ***********************************************************************
+
+// ***********************************************************************
+// Note: This ResizeBuffers() function may be called from
+// either MESA glViewport() or GLD wglMakeCurrent().
+
+BOOL dglWglResizeBuffers(
+ GLcontext *ctx,
+ BOOL bDefaultDriver)
+{
+ DGL_ctx *dgl = NULL;
+ RECT rcScreenRect;
+ DWORD dwWidth;
+ DWORD dwHeight;
+ DDSURFACEDESC2 ddsd2;
+ DDSCAPS2 ddscaps2;
+ IDirectDrawClipper *lpddClipper = NULL;
+ DWORD dwFlags;
+ HRESULT hResult;
+
+ DWORD dwMemoryType;
+
+ int i;
+ struct gl_texture_object *tObj;
+ struct gl_texture_image *image;
+
+ BOOL bWasFullscreen;
+ BOOL bSaveDesktop;
+ BOOL bFullScrnWin = FALSE;
+ DDSURFACEDESC2 ddsd2DisplayMode;
+
+ DDBLTFX ddbltfx;
+ POINT pt;
+ RECT rcDst;
+#ifdef _USE_GLD3_WGL
+ GLD_displayMode glddm;
+#endif
+
+#define DDLOG_CRITICAL_OR_WARN (bDefaultDriver ? DDLOG_WARN : DDLOG_CRITICAL)
+
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ // Sanity checks
+ if (ctx == NULL)
+ return FALSE;
+ dgl = ctx->DriverCtx;
+ if (dgl == NULL)
+ return FALSE;
+
+ // Get the window size and calculate its dimensions
+ if (dgl->hWnd == NULL) {
+ // Check for non-window DC = memory DC ?
+ if (GetClipBox(dgl->hDC, &rcScreenRect) == ERROR)
+ SetRect(&rcScreenRect, 0, 0, 0, 0);
+ }
+ else if (!GetClientRect(dgl->hWnd, &rcScreenRect))
+ SetRect(&rcScreenRect, 0, 0, 0, 0);
+ dwWidth = rcScreenRect.right - rcScreenRect.left;
+ dwHeight = rcScreenRect.bottom - rcScreenRect.top;
+ CopyRect(&dgl->rcScreenRect, &rcScreenRect);
+
+ // This will occur on Alt-Tab
+ if ((dwWidth == 0) && (dwHeight == 0)) {
+ //dgl->bCanRender = FALSE;
+ return TRUE; // No resize possible!
+ }
+
+ // Some apps zero only 1 dimension for non-visible window... (DaveM)
+ if ((dwWidth == 0) || (dwHeight == 0)) {
+ dwWidth = 8;
+ dwHeight = 8;
+ }
+
+ // Test to see if a resize is required.
+ // Note that the dimensions will be the same if a prior resize attempt failed.
+ if ((dwWidth == dgl->dwWidth) && (dwHeight == dgl->dwHeight) && bDefaultDriver) {
+ return TRUE; // No resize required
+ }
+
+ ddlogPrintf(DDLOG_SYSTEM, "dglResize: %dx%d", dwWidth, dwHeight);
+#ifndef _USE_GLD3_WGL
+ // Work out where we want our surfaces created
+ dwMemoryType = (bDefaultDriver) ? glb.dwMemoryType : DDSCAPS_SYSTEMMEMORY;
+#endif // _USE_GLD3_WGL
+
+ // Note previous fullscreen vs window display status
+ bWasFullscreen = dgl->bFullscreen;
+
+#ifdef _USE_GLD3_WGL
+ if (_gldDriver.GetDisplayMode(dgl, &glddm)) {
+ if ( (dwWidth == glddm.Width) &&
+ (dwHeight == glddm.Height) ) {
+ bFullScrnWin = TRUE;
+ }
+ if (bFullScrnWin && glb.bPrimary && !glb.bFullscreenBlit && !glb.bDirectDrawPersistant) {
+ dgl->bFullscreen = TRUE;
+ ddlogMessage(DDLOG_INFO, "Fullscreen window after resize.\n");
+ }
+ else {
+ dgl->bFullscreen = FALSE;
+ ddlogMessage(DDLOG_INFO, "Non-Fullscreen window after resize.\n");
+ }
+ // Cache the display mode dimensions
+ dgl->dwModeWidth = glddm.Width;
+ dgl->dwModeHeight = glddm.Height;
+ }
+
+ // Clamp the effective window dimensions to primary surface.
+ // We need to do this for D3D viewport dimensions even if wide
+ // surfaces are supported. This also is a good idea for handling
+ // whacked-out window dimensions passed for non-drawable windows
+ // like Solid Edge. (DaveM)
+ if (dgl->dwWidth > glddm.Width)
+ dgl->dwWidth = glddm.Width;
+ if (dgl->dwHeight > glddm.Height)
+ dgl->dwHeight = glddm.Height;
+#else // _USE_GLD3_WGL
+ // Window resize may have changed to fullscreen
+ ZeroMemory(&ddsd2DisplayMode, sizeof(ddsd2DisplayMode));
+ ddsd2DisplayMode.dwSize = sizeof(ddsd2DisplayMode);
+ hResult = IDirectDraw4_GetDisplayMode(
+ dgl->lpDD4,
+ &ddsd2DisplayMode);
+ if (SUCCEEDED(hResult)) {
+ if ( (dwWidth == ddsd2DisplayMode.dwWidth) &&
+ (dwHeight == ddsd2DisplayMode.dwHeight) ) {
+ bFullScrnWin = TRUE;
+ }
+ if (bFullScrnWin && glb.bPrimary && !glb.bFullscreenBlit && !glb.bDirectDrawPersistant) {
+ dgl->bFullscreen = TRUE;
+ ddlogMessage(DDLOG_INFO, "Fullscreen window after resize.\n");
+ }
+ else {
+ dgl->bFullscreen = FALSE;
+ ddlogMessage(DDLOG_INFO, "Non-Fullscreen window after resize.\n");
+ }
+ // Cache the display mode dimensions
+ dgl->dwModeWidth = ddsd2DisplayMode.dwWidth;
+ dgl->dwModeHeight = ddsd2DisplayMode.dwHeight;
+ }
+
+ // Clamp the effective window dimensions to primary surface.
+ // We need to do this for D3D viewport dimensions even if wide
+ // surfaces are supported. This also is a good idea for handling
+ // whacked-out window dimensions passed for non-drawable windows
+ // like Solid Edge. (DaveM)
+ if (dgl->dwWidth > ddsd2DisplayMode.dwWidth)
+ dgl->dwWidth = ddsd2DisplayMode.dwWidth;
+ if (dgl->dwHeight > ddsd2DisplayMode.dwHeight)
+ dgl->dwHeight = ddsd2DisplayMode.dwHeight;
+#endif // _USE_GLD3_WGL
+
+ // Note if fullscreen vs window display has changed?
+ bSaveDesktop = (!bWasFullscreen && !dgl->bFullscreen) ? TRUE : FALSE;
+ // Save the desktop primary surface from being destroyed
+ // whenever remaining in windowed mode, since the stereo mode
+ // switches are expensive...
+
+#ifndef _USE_GLD3_WGL
+ // Don't need to re-allocate persistant buffers. (DaveM)
+ // Though we should clear the back buffers to hide artifacts.
+ if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
+ dgl->dwWidth = dwWidth;
+ dgl->dwHeight = dwHeight;
+ ZeroMemory(&ddbltfx, sizeof(ddbltfx));
+ ddbltfx.dwSize = sizeof(ddbltfx);
+ ddbltfx.dwFillColor = dgl->dwClearColorPF;
+ IDirectDrawSurface4_Blt(dgl->lpBack4, &rcScreenRect, NULL, NULL,
+ DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);
+ return TRUE;
+ }
+
+ // Ensure all rendering is complete
+ if (ctx->Driver.Finish)
+ (*ctx->Driver.Finish)(ctx);
+ if (dgl->bSceneStarted == TRUE) {
+ IDirect3DDevice3_EndScene(dgl->lpDev3);
+ dgl->bSceneStarted = FALSE;
+ }
+#endif // _USE_GLD3_WGL
+ dgl->bCanRender = FALSE;
+
+#ifdef GLD_THREADS
+ // Serialize access to DirectDraw and DDS operations
+ if (glb.bMultiThreaded)
+ EnterCriticalSection(&CriticalSection);
+#endif
+
+#ifndef _USE_GLD3_WGL
+ // Release existing surfaces
+ RELEASE(dgl->lpDev3);
+ RELEASE(dgl->lpDepth4);
+ RELEASE(dgl->lpBack4);
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
+ ;
+ else
+ RELEASE(dgl->lpFront4);
+#endif // _USE_GLD3_WGL
+ dgl->dwWidth = dwWidth;
+ dgl->dwHeight = dwHeight;
+
+ // Set defaults
+ dgl->dwModeWidth = dgl->dwWidth;
+ dgl->dwModeHeight = dgl->dwHeight;
+
+#ifdef _USE_GLD3_WGL
+ if (!_gldDriver.ResizeDrawable(dgl, bDefaultDriver, glb.bDirectDrawPersistant, glb.bPersistantBuffers))
+ goto cleanup_and_return_with_error;
+#else // _USE_GLD3_WGL
+
+ if (dgl->bFullscreen) {
+ //
+ // FULLSCREEN
+ //
+
+ // Disable warning popups when in fullscreen mode
+ ddlogWarnOption(FALSE);
+
+ // Have to release the persistant DirectDraw primary surface
+ // if switching to fullscreen mode. So if application wants
+ // persistant display in fullscreen mode, a fullscreen-size
+ // window should be used instead via fullscreen-blit option.
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
+ RELEASE(glb.lpPrimary4);
+ glb.bDirectDrawPrimary = FALSE;
+ }
+
+ dwFlags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT;
+ if (glb.bFastFPU)
+ dwFlags |= DDSCL_FPUSETUP; // optional
+ hResult = IDirectDraw4_SetCooperativeLevel(dgl->lpDD4, dgl->hWnd, dwFlags);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Unable to set Exclusive Fullscreen mode", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ hResult = IDirectDraw4_SetDisplayMode(dgl->lpDD4,
+ dgl->dwModeWidth,
+ dgl->dwModeHeight,
+ dgl->dwBPP,
+ 0,
+ 0);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetDisplayMode failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // ** The display mode has changed, so dont use MessageBox! **
+
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+
+ if (dgl->bDoubleBuffer) {
+ // Double buffered
+ // Primary surface
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
+ DDSCAPS_FLIP |
+ DDSCAPS_COMPLEX |
+ DDSCAPS_3DDEVICE |
+ dwMemoryType;
+ ddsd2.dwBackBufferCount = 1;
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ // Render target surface
+ ZeroMemory(&ddscaps2, sizeof(ddscaps2)); // Clear the entire struct.
+ ddscaps2.dwCaps = DDSCAPS_BACKBUFFER;
+ hResult = IDirectDrawSurface4_GetAttachedSurface(dgl->lpFront4, &ddscaps2, &dgl->lpBack4);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: GetAttachedSurface failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ } else {
+ // Single buffered
+ // Primary surface
+ ddsd2.dwFlags = DDSD_CAPS;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
+ //DDSCAPS_3DDEVICE |
+ dwMemoryType;
+
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ dgl->lpBack4 = NULL;
+ }
+ } else {
+ // WINDOWED
+
+ // OK to enable warning popups in windowed mode
+ ddlogWarnOption(glb.bMessageBoxWarnings);
+
+ // Ditto if persistant DirectDraw primary
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
+ goto DoClipperOnly;
+
+ // WINDOWED
+ dwFlags = DDSCL_NORMAL;
+ if (glb.bMultiThreaded)
+ dwFlags |= DDSCL_MULTITHREADED;
+ if (glb.bFastFPU)
+ dwFlags |= DDSCL_FPUSETUP; // optional
+ hResult = IDirectDraw4_SetCooperativeLevel(dgl->lpDD4,
+ dgl->hWnd,
+ dwFlags);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Unable to set Normal coop level", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ // Primary surface
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // Cache the primary surface for persistant DirectDraw state
+ if (glb.bDirectDrawPersistant && !glb.bDirectDrawPrimary) {
+ glb.lpPrimary4 = dgl->lpFront4;
+ IDirectDrawSurface4_AddRef(glb.lpPrimary4);
+ glb.bDirectDrawPrimary = TRUE;
+ }
+
+ // Clipper object
+ hResult = DirectDrawCreateClipper(0, &lpddClipper, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateClipper failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ hResult = IDirectDrawClipper_SetHWnd(lpddClipper, 0, dgl->hWnd);
+ if (FAILED(hResult)) {
+ RELEASE(lpddClipper);
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetHWnd failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+ hResult = IDirectDrawSurface4_SetClipper(dgl->lpFront4, lpddClipper);
+ RELEASE(lpddClipper); // We have finished with it.
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetClipper failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+DoClipperOnly:
+ // Update the window for the original clipper
+ if ((glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) || bSaveDesktop) {
+ IDirectDrawSurface4_GetClipper(dgl->lpFront4, &lpddClipper);
+ IDirectDrawClipper_SetHWnd(lpddClipper, 0, dgl->hWnd);
+ RELEASE(lpddClipper);
+ }
+
+ if (dgl->bDoubleBuffer) {
+ // Render target surface
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
+ ddsd2.dwWidth = dgl->dwWidth;
+ ddsd2.dwHeight = dgl->dwHeight;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE |
+ DDSCAPS_OFFSCREENPLAIN |
+ dwMemoryType;
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpBack4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Create Backbuffer failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ } else {
+ dgl->lpBack4 = NULL;
+ }
+ }
+
+ //
+ // Now create the Zbuffer
+ //
+ if (dgl->bDepthBuffer) {
+ // Get z-buffer dimensions from the render target
+ // Setup the surface desc for the z-buffer.
+ ZeroMemory(&ddsd2, sizeof(ddsd2));
+ ddsd2.dwSize = sizeof(ddsd2);
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | dwMemoryType;
+ ddsd2.dwWidth = dgl->dwWidth;
+ ddsd2.dwHeight = dgl->dwHeight;
+ memcpy(&ddsd2.ddpfPixelFormat,
+ &glb.lpZBufferPF[dgl->iZBufferPF],
+ sizeof(DDPIXELFORMAT) );
+
+ // Create a z-buffer
+ hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpDepth4, NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (ZBuffer) failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // Attach Zbuffer to render target
+ TRY(IDirectDrawSurface4_AddAttachedSurface(
+ dgl->bDoubleBuffer ? dgl->lpBack4 : dgl->lpFront4,
+ dgl->lpDepth4),
+ "dglResize: Attach Zbuffer");
+
+ }
+
+ // Clear the newly resized back buffers for the window client area.
+ ZeroMemory(&ddbltfx, sizeof(ddbltfx));
+ ddbltfx.dwSize = sizeof(ddbltfx);
+ ddbltfx.dwFillColor = dgl->dwClearColorPF;
+ IDirectDrawSurface4_Blt(dgl->lpBack4, &rcScreenRect, NULL, NULL,
+ DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);
+
+ //
+ // Now that we have a zbuffer we can create the 3D device
+ //
+ hResult = IDirect3D3_CreateDevice(dgl->lpD3D3,
+ bDefaultDriver ? &glb.d3dGuid : &IID_IDirect3DRGBDevice,
+ dgl->bDoubleBuffer ? dgl->lpBack4 : dgl->lpFront4,
+ &dgl->lpDev3,
+ NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Could not create Direct3D device", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // We must do this as soon as the device is created
+ dglInitStateCaches(dgl);
+
+ //
+ // Viewport
+ //
+ hResult = IDirect3DDevice3_AddViewport(dgl->lpDev3, dgl->lpViewport3);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: AddViewport failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // Initialise the viewport
+ dgl->d3dViewport.dwSize = sizeof(dgl->d3dViewport);
+ dgl->d3dViewport.dwX = 0;
+ dgl->d3dViewport.dwY = 0;
+ dgl->d3dViewport.dwWidth = dgl->dwWidth;
+ dgl->d3dViewport.dwHeight = dgl->dwHeight;
+ dgl->d3dViewport.dvClipX = 0;
+ dgl->d3dViewport.dvClipY = 0;
+ dgl->d3dViewport.dvClipWidth = dgl->dwWidth;
+ dgl->d3dViewport.dvClipHeight = dgl->dwHeight;
+// dgl->d3dViewport.dvMinZ = 0.0f;
+// dgl->d3dViewport.dvMaxZ = 1.0f;
+ TRY(IDirect3DViewport3_SetViewport2(dgl->lpViewport3, &dgl->d3dViewport),
+ "dglResize: SetViewport2");
+
+ hResult = IDirect3DDevice3_SetCurrentViewport(dgl->lpDev3, dgl->lpViewport3);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetCurrentViewport failed", hResult);
+ goto cleanup_and_return_with_error;
+ }
+
+ // (Re)Initialise all the Direct3D renderstates
+ dglInitStateD3D(ctx);
+
+ // Now we have to recreate all of our textures (+ mipmaps).
+ // Luckily, Mesa has a list of them.
+ tObj = ctx->Shared->TexObjectList;
+ while (tObj != NULL) {
+ if (tObj->DriverData) {
+ // We could call our TexImage function directly, but it's
+ // safer to use the driver pointer.
+ for (i=0; i<MAX_TEXTURE_LEVELS; i++) {
+ image = tObj->Image[i];
+ if (image) {
+ switch (tObj->Dimensions){
+ case 1:
+ if (ctx->Driver.TexImage)
+ (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_1D, tObj, i, image->Format, image);
+ break;
+ case 2:
+ if (ctx->Driver.TexImage)
+ (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, tObj, i, image->Format, image);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ tObj = tObj->Next;
+ }
+
+ // Re-Bind each texture Unit
+ for (i=0; i<glb.wMaxSimultaneousTextures; i++) {
+ tObj = ctx->Texture.Unit[i].Current;
+ if (tObj) {
+ DGL_texture *lpTex = (DGL_texture *)tObj->DriverData;
+ hResult = dglSetTexture(dgl, i, lpTex ? lpTex->lpTexture : NULL);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_ERROR, "dglResize: SetTexture failed", hResult);
+ }
+ }
+ }
+#endif // _USE_GLD3_WGL
+
+ dgl->bCanRender = TRUE;
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ // SUCCESS.
+ return TRUE;
+
+cleanup_and_return_with_error:
+ // Relase all interfaces before returning.
+#ifdef _USE_GLD3_WGL
+ _gldDriver.DestroyDrawable(dgl);
+#else // _USE_GLD3_WGL
+ RELEASE(dgl->lpDev3);
+ RELEASE(dgl->lpDepth4);
+ RELEASE(dgl->lpBack4);
+ if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
+ ;
+ else
+ RELEASE(dgl->lpFront4);
+
+#undef DDLOG_CRITICAL_OR_WARN
+#endif // _USE_GLD3_WGL
+
+ // Mark context as not being able to render
+ dgl->bCanRender = FALSE;
+
+#ifdef GLD_THREADS
+ // Release serialized access
+ if (glb.bMultiThreaded)
+ LeaveCriticalSection(&CriticalSection);
+#endif
+
+ return FALSE;
+}
+
+// ***********************************************************************
+// ***********************************************************************
+// Support for bitmap fonts.
+// ***********************************************************************
+// ***********************************************************************
+
+/*****************************************************************************
+**
+** InvertGlyphBitmap.
+**
+** Invert the bitmap so that it suits OpenGL's representation.
+** Each row starts on a double word boundary.
+**
+*****************************************************************************/
+
+static void InvertGlyphBitmap(
+ int w,
+ int h,
+ DWORD *fptr,
+ DWORD *tptr)
+{
+ int dWordsInRow = (w+31)/32;
+ int i, j;
+ DWORD *tmp = tptr;
+
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
+ tptr += ((h-1)*dWordsInRow);
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < dWordsInRow; j++) {
+ *(tptr + j) = *(fptr + j);
+ }
+ tptr -= dWordsInRow;
+ fptr += dWordsInRow;
+ }
+}
+
+// ***********************************************************************
+
+/*****************************************************************************
+ * wglUseFontBitmaps
+ *
+ * Converts a subrange of the glyphs in a GDI font to OpenGL display
+ * lists.
+ *
+ * Extended to support any GDI font, not just TrueType fonts. (DaveM)
+ *
+ *****************************************************************************/
+
+BOOL APIENTRY _GLD_WGL_EXPORT(UseFontBitmapsA)(
+ HDC hDC,
+ DWORD first,
+ DWORD count,
+ DWORD listBase)
+{
+ int i, ox, oy, ix, iy;
+ int w, h;
+ int iBufSize, iCurBufSize = 0;
+ DWORD *bitmapBuffer = NULL;
+ DWORD *invertedBitmapBuffer = NULL;
+ BOOL bSuccessOrFail = TRUE;
+ BOOL bTrueType = FALSE;
+ TEXTMETRIC tm;
+ GLYPHMETRICS gm;
+ RASTERIZER_STATUS rs;
+ MAT2 mat;
+ SIZE size;
+ RECT rect;
+ HDC hDCMem;
+ HBITMAP hBitmap;
+ BITMAPINFO bmi;
+ HFONT hFont;
+
+ // Validate SciTech DirectGL license
+ if (!dglValidate())
+ return FALSE;
+
+ // Set up a unity matrix.
+ ZeroMemory(&mat, sizeof(mat));
+ mat.eM11.value = 1;
+ mat.eM22.value = 1;
+
+ // Test to see if selected font is TrueType or not
+ ZeroMemory(&tm, sizeof(tm));
+ if (!GetTextMetrics(hDC, &tm)) {
+ ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Font metrics error\n");
+ return (FALSE);
+ }
+ bTrueType = (tm.tmPitchAndFamily & TMPF_TRUETYPE) ? TRUE : FALSE;
+
+ // Test to see if TRUE-TYPE capabilities are installed
+ // (only necessary if TrueType font selected)
+ ZeroMemory(&rs, sizeof(rs));
+ if (bTrueType) {
+ if (!GetRasterizerCaps (&rs, sizeof (RASTERIZER_STATUS))) {
+ ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Raster caps error\n");
+ return (FALSE);
+ }
+ if (!(rs.wFlags & TT_ENABLED)) {
+ ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: No TrueType caps\n");
+ return (FALSE);
+ }
+ }
+
+ // Trick to get the current font handle
+ hFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
+ SelectObject(hDC, hFont);
+
+ // Have memory device context available for holding bitmaps of font glyphs
+ hDCMem = CreateCompatibleDC(hDC);
+ SelectObject(hDCMem, hFont);
+ SetTextColor(hDCMem, RGB(0xFF, 0xFF, 0xFF));
+ SetBkColor(hDCMem, 0);
+
+ for (i = first; (DWORD) i < (first + count); i++) {
+ // Find out how much space is needed for the bitmap so we can
+ // Set the buffer size correctly.
+ if (bTrueType) {
+ // Use TrueType support to get bitmap size of glyph
+ iBufSize = GetGlyphOutline(hDC, i, GGO_BITMAP, &gm,
+ 0, NULL, &mat);
+ if (iBufSize == GDI_ERROR) {
+ bSuccessOrFail = FALSE;
+ break;
+ }
+ }
+ else {
+ // Use generic GDI support to compute bitmap size of glyph
+ w = tm.tmMaxCharWidth;
+ h = tm.tmHeight;
+ if (GetTextExtentPoint32(hDC, (LPCTSTR)&i, 1, &size)) {
+ w = size.cx;
+ h = size.cy;
+ }
+ iBufSize = w * h;
+ // Use DWORD multiple for compatibility
+ iBufSize += 3;
+ iBufSize /= 4;
+ iBufSize *= 4;
+ }
+
+ // If we need to allocate Larger Buffers, then do so - but allocate
+ // An extra 50 % so that we don't do too many mallocs !
+ if (iBufSize > iCurBufSize) {
+ if (bitmapBuffer) {
+ __wglFree(bitmapBuffer);
+ }
+ if (invertedBitmapBuffer) {
+ __wglFree(invertedBitmapBuffer);
+ }
+
+ iCurBufSize = iBufSize * 2;
+ bitmapBuffer = (DWORD *) __wglMalloc(iCurBufSize);
+ invertedBitmapBuffer = (DWORD *) __wglMalloc(iCurBufSize);
+
+ if (bitmapBuffer == NULL || invertedBitmapBuffer == NULL) {
+ bSuccessOrFail = FALSE;
+ break;
+ }
+ }
+
+ // If we fail to get the Glyph data, delete the display lists
+ // Created so far and return FALSE.
+ if (bTrueType) {
+ // Use TrueType support to get bitmap of glyph
+ if (GetGlyphOutline(hDC, i, GGO_BITMAP, &gm,
+ iBufSize, bitmapBuffer, &mat) == GDI_ERROR) {
+ bSuccessOrFail = FALSE;
+ break;
+ }
+
+ // Setup glBitmap parameters for current font glyph
+ w = gm.gmBlackBoxX;
+ h = gm.gmBlackBoxY;
+ ox = gm.gmptGlyphOrigin.x;
+ oy = gm.gmptGlyphOrigin.y;
+ ix = gm.gmCellIncX;
+ iy = gm.gmCellIncY;
+ }
+ else {
+ // Use generic GDI support to create bitmap of glyph
+ ZeroMemory(bitmapBuffer, iBufSize);
+
+ if (i >= tm.tmFirstChar && i <= tm.tmLastChar) {
+ // Only create bitmaps for actual font glyphs
+ hBitmap = CreateBitmap(w, h, 1, 1, NULL);
+ SelectObject(hDCMem, hBitmap);
+ // Make bitmap of current font glyph
+ SetRect(&rect, 0, 0, w, h);
+ DrawText(hDCMem, (LPCTSTR)&i, 1, &rect,
+ DT_LEFT | DT_BOTTOM | DT_SINGLELINE | DT_NOCLIP);
+ // Make copy of bitmap in our local buffer
+ ZeroMemory(&bmi, sizeof(bmi));
+ bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi.bmiHeader.biWidth = w;
+ bmi.bmiHeader.biHeight = -h;
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biBitCount = 1;
+ bmi.bmiHeader.biCompression = BI_RGB;
+ GetDIBits(hDCMem, hBitmap, 0, h, bitmapBuffer, &bmi, 0);
+ DeleteObject(hBitmap);
+ }
+ else {
+ // Otherwise use empty display list for non-existing glyph
+ iBufSize = 0;
+ }
+
+ // Setup glBitmap parameters for current font glyph
+ ox = 0;
+ oy = tm.tmDescent;
+ ix = w;
+ iy = 0;
+ }
+
+ // Create an OpenGL display list.
+ _GLD_glNewList((listBase + i), GL_COMPILE);
+
+ // Some fonts have no data for the space character, yet advertise
+ // a non-zero size.
+ if (0 == iBufSize) {
+ _GLD_glBitmap(0, 0, 0.0f, 0.0f, (GLfloat) ix, (GLfloat) iy, NULL);
+ } else {
+ // Invert the Glyph data.
+ InvertGlyphBitmap(w, h, bitmapBuffer, invertedBitmapBuffer);
+
+ // Render an OpenGL bitmap and invert the origin.
+ _GLD_glBitmap(w, h,
+ (GLfloat) ox, (GLfloat) (h-oy),
+ (GLfloat) ix, (GLfloat) iy,
+ (GLubyte *) invertedBitmapBuffer);
+ }
+
+ // Close this display list.
+ _GLD_glEndList();
+ }
+
+ if (bSuccessOrFail == FALSE) {
+ ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Get glyph failed\n");
+ _GLD_glDeleteLists((i+listBase), (i-first));
+ }
+
+ // Release resources used
+ DeleteObject(hFont);
+ DeleteDC(hDCMem);
+
+ if (bitmapBuffer)
+ __wglFree(bitmapBuffer);
+ if (invertedBitmapBuffer)
+ __wglFree(invertedBitmapBuffer);
+
+ return(bSuccessOrFail);
+}
+
+// ***********************************************************************
+
+BOOL APIENTRY _GLD_WGL_EXPORT(UseFontBitmapsW)(
+ HDC a,
+ DWORD b,
+ DWORD c,
+ DWORD d)
+{
+ // Validate license
+ if (!dglValidate())
+ return FALSE;
+
+ return _GLD_WGL_EXPORT(UseFontBitmapsA)(a, b, c, d);
+}
+
+// ***********************************************************************
+// ***********************************************************************
+// Support for outline TrueType fonts.
+// ***********************************************************************
+// ***********************************************************************
+
+void * __wglRealloc(
+ void *oldPtr,
+ size_t newSize)
+{
+ void *newPtr = NULL;
+
+ if (newSize != 0) {
+ newPtr = (void *) GlobalAlloc(GPTR, newSize);
+ if (oldPtr && newPtr) {
+ DWORD oldSize = GlobalSize(oldPtr);
+
+ memcpy(newPtr, oldPtr, (oldSize <= newSize ? oldSize : newSize));
+ GlobalFree(oldPtr);
+ }
+ } else if (oldPtr) {
+ GlobalFree(oldPtr);
+ }
+ if (newPtr == NULL) {
+ return NULL; /* XXX out of memory error */
+ }
+ return newPtr;
+}
+
+// ***********************************************************************
+
+
+/*****************************************************************************
+ * wglUseFontOutlinesW
+ *
+ * Converts a subrange of the glyphs in a TrueType font to OpenGL display
+ * lists.
+ *****************************************************************************/
+
+BOOL APIENTRY _GLD_WGL_EXPORT(UseFontOutlinesW)(
+ IN HDC hDC,
+ IN DWORD first,
+ IN DWORD count,
+ IN DWORD listBase,
+ IN FLOAT chordalDeviation,
+ IN FLOAT extrusion,
+ IN INT format,
+ OUT LPGLYPHMETRICSFLOAT lpgmf)
+{
+ return _GLD_WGL_EXPORT(UseFontOutlinesA)(hDC, first, count, listBase,
+ chordalDeviation, extrusion, format, lpgmf);
+}
+
+/*****************************************************************************
+ * wglUseFontOutlinesA
+ *
+ * Converts a subrange of the glyphs in a TrueType font to OpenGL display
+ * lists.
+ *****************************************************************************/
+
+BOOL APIENTRY _GLD_WGL_EXPORT(UseFontOutlinesA)(
+ IN HDC hDC,
+ IN DWORD first,
+ IN DWORD count,
+ IN DWORD listBase,
+ IN FLOAT chordalDeviation,
+ IN FLOAT extrusion,
+ IN INT format,
+ OUT LPGLYPHMETRICSFLOAT glyphMetricsFloatArray)
+ {
+ DWORD glyphIndex;
+ UCHAR* glyphBuf;
+ DWORD glyphBufSize;
+
+
+ /*
+ * Flush any previous OpenGL errors. This allows us to check for
+ * new errors so they can be reported via the function return value.
+ */
+ while (_GLD_glGetError() != GL_NO_ERROR)
+ ;
+
+ /*
+ * Make sure that the current font can be sampled accurately.
+ */
+ hNewFont = CreateHighResolutionFont(hDC);
+ if (!hNewFont)
+ return FALSE;
+
+ hOldFont = SelectObject(hDC, hNewFont);
+ if (!hOldFont)
+ return FALSE;
+
+ /*
+ * Preallocate a buffer for the outline data, and track its size:
+ */
+ glyphBuf = (UCHAR*) __wglMalloc(glyphBufSize = 10240);
+ if (!glyphBuf)
+ return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
+
+ /*
+ * Process each glyph in the given range:
+ */
+ for (glyphIndex = first; glyphIndex - first < count; ++glyphIndex)
+ {
+ GLYPHMETRICS glyphMetrics;
+ DWORD glyphSize;
+ static MAT2 matrix =
+ {
+ {0, 1}, {0, 0},
+ {0, 0}, {0, 1}
+ };
+ LPGLYPHMETRICSFLOAT glyphMetricsFloat =
+ &glyphMetricsFloatArray[glyphIndex - first];
+
+
+ /*
+ * Determine how much space is needed to store the glyph's
+ * outlines. If our glyph buffer isn't large enough,
+ * resize it.
+ */
+ glyphSize = GetGlyphOutline( hDC,
+ glyphIndex,
+ GGO_NATIVE,
+ &glyphMetrics,
+ 0,
+ NULL,
+ &matrix
+ );
+ if (glyphSize < 0)
+ return FALSE; /*WGL_STATUS_FAILURE*/
+ if (glyphSize > glyphBufSize)
+ {
+ __wglFree(glyphBuf);
+ glyphBuf = (UCHAR*) __wglMalloc(glyphBufSize = glyphSize);
+ if (!glyphBuf)
+ return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
+ }
+
+
+ /*
+ * Get the glyph's outlines.
+ */
+ if (GetGlyphOutline( hDC,
+ glyphIndex,
+ GGO_NATIVE,
+ &glyphMetrics,
+ glyphBufSize,
+ glyphBuf,
+ &matrix
+ ) < 0)
+ {
+ __wglFree(glyphBuf);
+ return FALSE; /*WGL_STATUS_FAILURE*/
+ }
+
+ glyphMetricsFloat->gmfBlackBoxX =
+ (FLOAT) glyphMetrics.gmBlackBoxX * ScaleFactor;
+ glyphMetricsFloat->gmfBlackBoxY =
+ (FLOAT) glyphMetrics.gmBlackBoxY * ScaleFactor;
+ glyphMetricsFloat->gmfptGlyphOrigin.x =
+ (FLOAT) glyphMetrics.gmptGlyphOrigin.x * ScaleFactor;
+ glyphMetricsFloat->gmfptGlyphOrigin.y =
+ (FLOAT) glyphMetrics.gmptGlyphOrigin.y * ScaleFactor;
+ glyphMetricsFloat->gmfCellIncX =
+ (FLOAT) glyphMetrics.gmCellIncX * ScaleFactor;
+ glyphMetricsFloat->gmfCellIncY =
+ (FLOAT) glyphMetrics.gmCellIncY * ScaleFactor;
+
+ /*
+ * Turn the glyph into a display list:
+ */
+ if (!MakeDisplayListFromGlyph( (glyphIndex - first) + listBase,
+ glyphBuf,
+ glyphSize,
+ glyphMetricsFloat,
+ chordalDeviation + ScaleFactor,
+ extrusion,
+ format))
+ {
+ __wglFree(glyphBuf);
+ return FALSE; /*WGL_STATUS_FAILURE*/
+ }
+ }
+
+
+ /*
+ * Clean up temporary storage and return. If an error occurred,
+ * clear all OpenGL error flags and return FAILURE status;
+ * otherwise just return SUCCESS.
+ */
+ __wglFree(glyphBuf);
+
+ SelectObject(hDC, hOldFont);
+
+ if (_GLD_glGetError() == GL_NO_ERROR)
+ return TRUE; /*WGL_STATUS_SUCCESS*/
+ else
+ {
+ while (_GLD_glGetError() != GL_NO_ERROR)
+ ;
+ return FALSE; /*WGL_STATUS_FAILURE*/
+ }
+ }
+
+
+
+/*****************************************************************************
+ * CreateHighResolutionFont
+ *
+ * Gets metrics for the current font and creates an equivalent font
+ * scaled to the design units of the font.
+ *
+ *****************************************************************************/
+
+static HFONT
+CreateHighResolutionFont(HDC hDC)
+ {
+ UINT otmSize;
+ OUTLINETEXTMETRIC *otm;
+ LONG fontHeight, fontWidth, fontUnits;
+ LOGFONT logFont;
+
+ otmSize = GetOutlineTextMetrics(hDC, 0, NULL);
+ if (otmSize == 0)
+ return NULL;
+
+ otm = (OUTLINETEXTMETRIC *) __wglMalloc(otmSize);
+ if (otm == NULL)
+ return NULL;
+
+ otm->otmSize = otmSize;
+ if (GetOutlineTextMetrics(hDC, otmSize, otm) == 0)
+ return NULL;
+
+ fontHeight = otm->otmTextMetrics.tmHeight -
+ otm->otmTextMetrics.tmInternalLeading;
+ fontWidth = otm->otmTextMetrics.tmAveCharWidth;
+ fontUnits = (LONG) otm->otmEMSquare;
+
+ ScaleFactor = 1.0F / (FLOAT) fontUnits;
+
+ logFont.lfHeight = - ((LONG) fontUnits);
+ logFont.lfWidth = (LONG)
+ ((FLOAT) (fontWidth * fontUnits) / (FLOAT) fontHeight);
+ logFont.lfEscapement = 0;
+ logFont.lfOrientation = 0;
+ logFont.lfWeight = otm->otmTextMetrics.tmWeight;
+ logFont.lfItalic = otm->otmTextMetrics.tmItalic;
+ logFont.lfUnderline = otm->otmTextMetrics.tmUnderlined;
+ logFont.lfStrikeOut = otm->otmTextMetrics.tmStruckOut;
+ logFont.lfCharSet = otm->otmTextMetrics.tmCharSet;
+ logFont.lfOutPrecision = OUT_OUTLINE_PRECIS;
+ logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ logFont.lfQuality = DEFAULT_QUALITY;
+ logFont.lfPitchAndFamily =
+ otm->otmTextMetrics.tmPitchAndFamily & 0xf0;
+ strcpy(logFont.lfFaceName,
+ (char *)otm + (int)otm->otmpFaceName);
+
+ hNewFont = CreateFontIndirect(&logFont);
+ if (hNewFont == NULL)
+ return NULL;
+
+ __wglFree(otm);
+
+ return hNewFont;
+ }
+
+
+
+/*****************************************************************************
+ * MakeDisplayListFromGlyph
+ *
+ * Converts the outline of a glyph to an OpenGL display list.
+ *
+ * Return value is nonzero for success, zero for failure.
+ *
+ * Does not check for OpenGL errors, so if the caller needs to know about them,
+ * it should call glGetError().
+ *****************************************************************************/
+
+static int
+MakeDisplayListFromGlyph( IN DWORD listName,
+ IN UCHAR* glyphBuf,
+ IN DWORD glyphSize,
+ IN LPGLYPHMETRICSFLOAT glyphMetricsFloat,
+ IN FLOAT chordalDeviation,
+ IN FLOAT extrusion,
+ IN INT format)
+ {
+ int status;
+
+ _GLD_glNewList(listName, GL_COMPILE);
+ status = DrawGlyph( glyphBuf,
+ glyphSize,
+ chordalDeviation,
+ extrusion,
+ format);
+
+ _GLD_glTranslatef(glyphMetricsFloat->gmfCellIncX,
+ glyphMetricsFloat->gmfCellIncY,
+ 0.0F);
+ _GLD_glEndList();
+
+ return status;
+ }
+
+
+
+/*****************************************************************************
+ * DrawGlyph
+ *
+ * Converts the outline of a glyph to OpenGL drawing primitives, tessellating
+ * as needed, and then draws the glyph. Tessellation of the quadratic splines
+ * in the outline is controlled by "chordalDeviation", and the drawing
+ * primitives (lines or polygons) are selected by "format".
+ *
+ * Return value is nonzero for success, zero for failure.
+ *
+ * Does not check for OpenGL errors, so if the caller needs to know about them,
+ * it should call glGetError().
+ *****************************************************************************/
+
+static int
+DrawGlyph( IN UCHAR* glyphBuf,
+ IN DWORD glyphSize,
+ IN FLOAT chordalDeviation,
+ IN FLOAT extrusion,
+ IN INT format)
+ {
+ INT status = 0;
+ FLOAT* p;
+ DWORD loop;
+ DWORD point;
+ GLUtesselator* tess = NULL;
+
+
+ /*
+ * Initialize the global buffer into which we place the outlines:
+ */
+ if (!InitLineBuf())
+ goto exit;
+
+
+ /*
+ * Convert the glyph outlines to a set of polyline loops.
+ * (See MakeLinesFromGlyph() for the format of the loop data
+ * structure.)
+ */
+ if (!MakeLinesFromGlyph(glyphBuf, glyphSize, chordalDeviation))
+ goto exit;
+ p = LineBuf;
+
+
+ /*
+ * Now draw the loops in the appropriate format:
+ */
+ if (format == WGL_FONT_LINES)
+ {
+ /*
+ * This is the easy case. Just draw the outlines.
+ */
+ for (loop = (DWORD) *p++; loop; --loop)
+ {
+ _GLD_glBegin(GL_LINE_LOOP);
+ for (point = (DWORD) *p++; point; --point)
+ {
+ _GLD_glVertex2fv(p);
+ p += 2;
+ }
+ _GLD_glEnd();
+ }
+ status = 1;
+ }
+
+ else if (format == WGL_FONT_POLYGONS)
+ {
+ double v[3];
+ FLOAT *save_p = p;
+ GLfloat z_value;
+
+ /*
+ * This is the hard case. We have to set up a tessellator
+ * to convert the outlines into a set of polygonal
+ * primitives, which the tessellator passes to some
+ * auxiliary routines for drawing.
+ */
+ if (!LoadGLUTesselator())
+ goto exit;
+ if (!InitVertBuf())
+ goto exit;
+ if (!(tess = gluNewTessProc()))
+ goto exit;
+ gluTessCallbackProc(tess, GLU_BEGIN, (void(CALLBACK *)()) _GLD_glBegin);
+ gluTessCallbackProc(tess, GLU_TESS_VERTEX_DATA,
+ (void(CALLBACK *)()) TessVertexOutData);
+ gluTessCallbackProc(tess, GLU_END, (void(CALLBACK *)()) _GLD_glEnd);
+ gluTessCallbackProc(tess, GLU_ERROR, (void(CALLBACK *)()) TessError);
+ gluTessCallbackProc(tess, GLU_TESS_COMBINE, (void(CALLBACK *)()) TessCombine);
+ gluTessNormalProc(tess, 0.0F, 0.0F, 1.0F);
+
+ TessErrorOccurred = 0;
+ _GLD_glNormal3f(0.0f, 0.0f, 1.0f);
+ v[2] = 0.0;
+ z_value = 0.0f;
+
+ gluTessBeginPolygonProc(tess, (void *)*(int *)&z_value);
+ for (loop = (DWORD) *p++; loop; --loop)
+ {
+ gluTessBeginContourProc(tess);
+
+ for (point = (DWORD) *p++; point; --point)
+ {
+ v[0] = p[0];
+ v[1] = p[1];
+ gluTessVertexProc(tess, v, p);
+ p += 2;
+ }
+
+ gluTessEndContourProc(tess);
+ }
+ gluTessEndPolygonProc(tess);
+
+ status = !TessErrorOccurred;
+
+ /* Extrusion code */
+ if (extrusion) {
+ DWORD loops;
+ GLfloat thickness = (GLfloat) -extrusion;
+ FLOAT *vert, *vert2;
+ DWORD count;
+
+ p = save_p;
+ loops = (DWORD) *p++;
+
+ for (loop = 0; loop < loops; loop++) {
+ GLfloat dx, dy, len;
+ DWORD last;
+
+ count = (DWORD) *p++;
+ _GLD_glBegin(GL_QUAD_STRIP);
+
+ /* Check if the first and last vertex are identical
+ * so we don't draw the same quad twice.
+ */
+ vert = p + (count-1)*2;
+ last = (p[0] == vert[0] && p[1] == vert[1]) ? count-1 : count;
+
+ for (point = 0; point <= last; point++) {
+ vert = p + 2 * (point % last);
+ vert2 = p + 2 * ((point+1) % last);
+
+ dx = vert[0] - vert2[0];
+ dy = vert[1] - vert2[1];
+ len = (GLfloat)sqrt(dx * dx + dy * dy);
+
+ _GLD_glNormal3f(dy / len, -dx / len, 0.0f);
+ _GLD_glVertex3f((GLfloat) vert[0],
+ (GLfloat) vert[1], thickness);
+ _GLD_glVertex3f((GLfloat) vert[0],
+ (GLfloat) vert[1], 0.0f);
+ }
+
+ _GLD_glEnd();
+ p += count*2;
+ }
+
+ /* Draw the back face */
+ p = save_p;
+ v[2] = thickness;
+ _GLD_glNormal3f(0.0f, 0.0f, -1.0f);
+ gluTessNormalProc(tess, 0.0F, 0.0F, -1.0F);
+
+ gluTessBeginPolygonProc(tess, (void *)*(int *)&thickness);
+
+ for (loop = (DWORD) *p++; loop; --loop)
+ {
+ count = (DWORD) *p++;
+
+ gluTessBeginContourProc(tess);
+
+ for (point = 0; point < count; point++)
+ {
+ vert = p + ((count-point-1)<<1);
+ v[0] = vert[0];
+ v[1] = vert[1];
+ gluTessVertexProc(tess, v, vert);
+ }
+ p += count*2;
+
+ gluTessEndContourProc(tess);
+ }
+ gluTessEndPolygonProc(tess);
+ }
+
+#if DEBUG
+ if (TessErrorOccurred)
+ printf("Tessellation error %s\n",
+ gluErrorString(TessErrorOccurred));
+#endif
+ }
+
+
+exit:
+ FreeLineBuf();
+ if (tess)
+ gluDeleteTessProc(tess);
+ // UnloadGLUTesselator();
+ FreeVertBuf();
+ return status;
+ }
+
+
+
+/*****************************************************************************
+ * LoadGLUTesselator
+ *
+ * Maps the glu32.dll module and gets function pointers for the
+ * tesselator functions.
+ *****************************************************************************/
+
+static BOOL
+LoadGLUTesselator(void)
+ {
+ if (gluModuleHandle != NULL)
+ return TRUE;
+
+ {
+ extern HINSTANCE hInstanceOpenGL;
+ char *gluName = "GLU32.DLL";
+// char name[256];
+// char *ptr;
+// int len;
+
+/*
+ len = GetModuleFileName(hInstanceOpenGL, name, 255);
+ if (len != 0)
+ {
+ ptr = name+len-1;
+ while (ptr > name && *ptr != '\\')
+ ptr--;
+ if (*ptr == '\\')
+ ptr++;
+ if (!stricmp(ptr, "cosmogl.dll"))
+ {
+ gluName = "COSMOGLU.DLL";
+ }
+ else if (!stricmp(ptr, "opengl32.dll"))
+ {
+ gluName = "GLU32.DLL";
+ }
+ }
+*/
+ if ((gluModuleHandle = LoadLibrary(gluName)) == NULL)
+ return FALSE;
+ }
+
+ if ((gluNewTessProc = (gluNewTessProto)
+ GetProcAddress(gluModuleHandle, "gluNewTess")) == NULL)
+ return FALSE;
+
+ if ((gluDeleteTessProc = (gluDeleteTessProto)
+ GetProcAddress(gluModuleHandle, "gluDeleteTess")) == NULL)
+ return FALSE;
+
+ if ((gluTessBeginPolygonProc = (gluTessBeginPolygonProto)
+ GetProcAddress(gluModuleHandle, "gluTessBeginPolygon")) == NULL)
+ return FALSE;
+
+ if ((gluTessBeginContourProc = (gluTessBeginContourProto)
+ GetProcAddress(gluModuleHandle, "gluTessBeginContour")) == NULL)
+ return FALSE;
+
+ if ((gluTessVertexProc = (gluTessVertexProto)
+ GetProcAddress(gluModuleHandle, "gluTessVertex")) == NULL)
+ return FALSE;
+
+ if ((gluTessEndContourProc = (gluTessEndContourProto)
+ GetProcAddress(gluModuleHandle, "gluTessEndContour")) == NULL)
+ return FALSE;
+
+ if ((gluTessEndPolygonProc = (gluTessEndPolygonProto)
+ GetProcAddress(gluModuleHandle, "gluTessEndPolygon")) == NULL)
+ return FALSE;
+
+ if ((gluTessPropertyProc = (gluTessPropertyProto)
+ GetProcAddress(gluModuleHandle, "gluTessProperty")) == NULL)
+ return FALSE;
+
+ if ((gluTessNormalProc = (gluTessNormalProto)
+ GetProcAddress(gluModuleHandle, "gluTessNormal")) == NULL)
+ return FALSE;
+
+ if ((gluTessCallbackProc = (gluTessCallbackProto)
+ GetProcAddress(gluModuleHandle, "gluTessCallback")) == NULL)
+ return FALSE;
+
+ return TRUE;
+ }
+
+
+
+/*****************************************************************************
+ * UnloadGLUTesselator
+ *
+ * Unmaps the glu32.dll module.
+ *****************************************************************************/
+
+static BOOL
+UnloadGLUTesselator(void)
+ {
+ if (gluModuleHandle != NULL)
+ if (FreeLibrary(gluModuleHandle) == FALSE)
+ return FALSE;
+ gluModuleHandle = NULL;
+ }
+
+
+
+/*****************************************************************************
+ * TessVertexOut
+ *
+ * Used by tessellator to handle output vertexes.
+ *****************************************************************************/
+
+static void CALLBACK
+TessVertexOut(FLOAT p[3])
+ {
+ GLfloat v[2];
+
+ v[0] = p[0] * ScaleFactor;
+ v[1] = p[1] * ScaleFactor;
+ _GLD_glVertex2fv(v);
+ }
+
+static void CALLBACK
+TessVertexOutData(FLOAT p[3], GLfloat z)
+{
+ GLfloat v[3];
+
+ v[0] = (GLfloat) p[0];
+ v[1] = (GLfloat) p[1];
+ v[2] = z;
+ _GLD_glVertex3fv(v);
+}
+
+
+/*****************************************************************************
+ * TessCombine
+ *
+ * Used by tessellator to handle self-intersecting contours and degenerate
+ * geometry.
+ *****************************************************************************/
+
+static void CALLBACK
+TessCombine(double coords[3],
+ void* vertex_data[4],
+ FLOAT weight[4],
+ void** outData)
+ {
+ if (!AppendToVertBuf((FLOAT) coords[0])
+ || !AppendToVertBuf((FLOAT) coords[1])
+ || !AppendToVertBuf((FLOAT) coords[2]))
+ TessErrorOccurred = GL_OUT_OF_MEMORY;
+ *outData = VertBuf + (VertBufIndex - 3);
+ }
+
+
+
+/*****************************************************************************
+ * TessError
+ *
+ * Saves the last tessellator error code in the global TessErrorOccurred.
+ *****************************************************************************/
+
+static void CALLBACK
+TessError(GLenum error)
+ {
+ TessErrorOccurred = error;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromGlyph
+ *
+ * Converts the outline of a glyph from the TTPOLYGON format to a simple
+ * array of floating-point values containing one or more loops.
+ *
+ * The first element of the output array is a count of the number of loops.
+ * The loop data follows this count. Each loop consists of a count of the
+ * number of vertices it contains, followed by the vertices. Each vertex
+ * is an X and Y coordinate. For example, a single triangle might be
+ * described by this array:
+ *
+ * 1., 3., 0., 0., 1., 0., 0., 1.
+ * ^ ^ ^ ^ ^ ^ ^ ^
+ * #loops #verts x1 y1 x2 y2 x3 y3
+ *
+ * A two-loop glyph would look like this:
+ *
+ * 2., 3., 0.,0., 1.,0., 0.,1., 3., .2,.2, .4,.2, .2,.4
+ *
+ * Line segments from the TTPOLYGON are transferred to the output array in
+ * the obvious way. Quadratic splines in the TTPOLYGON are converted to
+ * collections of line segments
+ *****************************************************************************/
+
+static int
+MakeLinesFromGlyph(IN UCHAR* glyphBuf,
+ IN DWORD glyphSize,
+ IN FLOAT chordalDeviation)
+ {
+ UCHAR* p;
+ int status = 0;
+
+
+ /*
+ * Pick up all the polygons (aka loops) that make up the glyph:
+ */
+ if (!AppendToLineBuf(0.0F)) /* loop count at LineBuf[0] */
+ goto exit;
+
+ p = glyphBuf;
+ while (p < glyphBuf + glyphSize)
+ {
+ if (!MakeLinesFromTTPolygon(&p, chordalDeviation))
+ goto exit;
+ LineBuf[0] += 1.0F; /* increment loop count */
+ }
+
+ status = 1;
+
+exit:
+ return status;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromTTPolygon
+ *
+ * Converts a TTPOLYGONHEADER and its associated curve structures into a
+ * single polyline loop in the global LineBuf.
+ *****************************************************************************/
+
+static int
+MakeLinesFromTTPolygon( IN OUT UCHAR** pp,
+ IN FLOAT chordalDeviation)
+ {
+ DWORD polySize;
+ UCHAR* polyStart;
+ DWORD vertexCountIndex;
+
+ /*
+ * Record where the polygon data begins, and where the loop's
+ * vertex count resides:
+ */
+ polyStart = *pp;
+ vertexCountIndex = LineBufIndex;
+ if (!AppendToLineBuf(0.0F))
+ return 0;
+
+ /*
+ * Extract relevant data from the TTPOLYGONHEADER:
+ */
+ polySize = GetDWord(pp);
+ if (GetDWord(pp) != TT_POLYGON_TYPE) /* polygon type */
+ return 0;
+ if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first X coord */
+ return 0;
+ if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first Y coord */
+ return 0;
+ LineBuf[vertexCountIndex] += 1.0F;
+
+ /*
+ * Process each of the TTPOLYCURVE structures in the polygon:
+ */
+ while (*pp < polyStart + polySize)
+ if (!MakeLinesFromTTPolycurve( pp,
+ vertexCountIndex,
+ chordalDeviation))
+ return 0;
+
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromTTPolyCurve
+ *
+ * Converts the lines and splines in a single TTPOLYCURVE structure to points
+ * in the global LineBuf.
+ *****************************************************************************/
+
+static int
+MakeLinesFromTTPolycurve( IN OUT UCHAR** pp,
+ IN DWORD vertexCountIndex,
+ IN FLOAT chordalDeviation)
+ {
+ WORD type;
+ WORD pointCount;
+
+
+ /*
+ * Pick up the relevant fields of the TTPOLYCURVE structure:
+ */
+ type = (WORD) GetWord(pp);
+ pointCount = (WORD) GetWord(pp);
+
+ /*
+ * Convert the "curve" to line segments:
+ */
+ if (type == TT_PRIM_LINE)
+ return MakeLinesFromTTLine( pp,
+ vertexCountIndex,
+ pointCount);
+ else if (type == TT_PRIM_QSPLINE)
+ return MakeLinesFromTTQSpline( pp,
+ vertexCountIndex,
+ pointCount,
+ chordalDeviation);
+ else
+ return 0;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromTTLine
+ *
+ * Converts points from the polyline in a TT_PRIM_LINE structure to
+ * equivalent points in the global LineBuf.
+ *****************************************************************************/
+static int
+MakeLinesFromTTLine( IN OUT UCHAR** pp,
+ IN DWORD vertexCountIndex,
+ IN WORD pointCount)
+ {
+ /*
+ * Just copy the line segments into the line buffer (converting
+ * type as we go):
+ */
+ LineBuf[vertexCountIndex] += pointCount;
+ while (pointCount--)
+ {
+ if (!AppendToLineBuf((FLOAT) GetFixed(pp)) /* X coord */
+ || !AppendToLineBuf((FLOAT) GetFixed(pp))) /* Y coord */
+ return 0;
+ }
+
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromTTQSpline
+ *
+ * Converts points from the poly quadratic spline in a TT_PRIM_QSPLINE
+ * structure to polyline points in the global LineBuf.
+ *****************************************************************************/
+
+static int
+MakeLinesFromTTQSpline( IN OUT UCHAR** pp,
+ IN DWORD vertexCountIndex,
+ IN WORD pointCount,
+ IN FLOAT chordalDeviation)
+ {
+ FLOAT x0, y0, x1, y1, x2, y2;
+ WORD point;
+
+ /*
+ * Process each of the non-interpolated points in the outline.
+ * To do this, we need to generate two interpolated points (the
+ * start and end of the arc) for each non-interpolated point.
+ * The first interpolated point is always the one most recently
+ * stored in LineBuf, so we just extract it from there. The
+ * second interpolated point is either the average of the next
+ * two points in the QSpline, or the last point in the QSpline
+ * if only one remains.
+ */
+ for (point = 0; point < pointCount - 1; ++point)
+ {
+ x0 = LineBuf[LineBufIndex - 2];
+ y0 = LineBuf[LineBufIndex - 1];
+
+ x1 = (FLOAT) GetFixed(pp);
+ y1 = (FLOAT) GetFixed(pp);
+
+ if (point == pointCount - 2)
+ {
+ /*
+ * This is the last arc in the QSpline. The final
+ * point is the end of the arc.
+ */
+ x2 = (FLOAT) GetFixed(pp);
+ y2 = (FLOAT) GetFixed(pp);
+ }
+ else
+ {
+ /*
+ * Peek at the next point in the input to compute
+ * the end of the arc:
+ */
+ x2 = 0.5F * (x1 + (FLOAT) GetFixed(pp));
+ y2 = 0.5F * (y1 + (FLOAT) GetFixed(pp));
+ /*
+ * Push the point back onto the input so it will
+ * be reused as the next off-curve point:
+ */
+ *pp -= 8;
+ }
+
+ if (!MakeLinesFromArc( x0, y0,
+ x1, y1,
+ x2, y2,
+ vertexCountIndex,
+ chordalDeviation * chordalDeviation))
+ return 0;
+ }
+
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * MakeLinesFromArc
+ *
+ * Subdivides one arc of a quadratic spline until the chordal deviation
+ * tolerance requirement is met, then places the resulting set of line
+ * segments in the global LineBuf.
+ *****************************************************************************/
+
+static int
+MakeLinesFromArc( IN FLOAT x0,
+ IN FLOAT y0,
+ IN FLOAT x1,
+ IN FLOAT y1,
+ IN FLOAT x2,
+ IN FLOAT y2,
+ IN DWORD vertexCountIndex,
+ IN FLOAT chordalDeviationSquared)
+ {
+ FLOAT x01;
+ FLOAT y01;
+ FLOAT x12;
+ FLOAT y12;
+ FLOAT midPointX;
+ FLOAT midPointY;
+ FLOAT deltaX;
+ FLOAT deltaY;
+
+ /*
+ * Calculate midpoint of the curve by de Casteljau:
+ */
+ x01 = 0.5F * (x0 + x1);
+ y01 = 0.5F * (y0 + y1);
+ x12 = 0.5F * (x1 + x2);
+ y12 = 0.5F * (y1 + y2);
+ midPointX = 0.5F * (x01 + x12);
+ midPointY = 0.5F * (y01 + y12);
+
+
+ /*
+ * Estimate chordal deviation by the distance from the midpoint
+ * of the curve to its non-interpolated control point. If this
+ * distance is greater than the specified chordal deviation
+ * constraint, then subdivide. Otherwise, generate polylines
+ * from the three control points.
+ */
+ deltaX = midPointX - x1;
+ deltaY = midPointY - y1;
+ if (deltaX * deltaX + deltaY * deltaY > chordalDeviationSquared)
+ {
+ MakeLinesFromArc( x0, y0,
+ x01, y01,
+ midPointX, midPointY,
+ vertexCountIndex,
+ chordalDeviationSquared);
+
+ MakeLinesFromArc( midPointX, midPointY,
+ x12, y12,
+ x2, y2,
+ vertexCountIndex,
+ chordalDeviationSquared);
+ }
+ else
+ {
+ /*
+ * The "pen" is already at (x0, y0), so we don't need to
+ * add that point to the LineBuf.
+ */
+ if (!AppendToLineBuf(x1)
+ || !AppendToLineBuf(y1)
+ || !AppendToLineBuf(x2)
+ || !AppendToLineBuf(y2))
+ return 0;
+ LineBuf[vertexCountIndex] += 2.0F;
+ }
+
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * InitLineBuf
+ *
+ * Initializes the global LineBuf and its associated size and current-element
+ * counters.
+ *****************************************************************************/
+
+static int
+InitLineBuf(void)
+ {
+ if (!(LineBuf = (FLOAT*)
+ __wglMalloc((LineBufSize = LINE_BUF_QUANT) * sizeof(FLOAT))))
+ return 0;
+ LineBufIndex = 0;
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * InitVertBuf
+ *
+ * Initializes the global VertBuf and its associated size and current-element
+ * counters.
+ *****************************************************************************/
+
+static int
+InitVertBuf(void)
+ {
+ if (!(VertBuf = (FLOAT*)
+ __wglMalloc((VertBufSize = VERT_BUF_QUANT) * sizeof(FLOAT))))
+ return 0;
+ VertBufIndex = 0;
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * AppendToLineBuf
+ *
+ * Appends one floating-point value to the global LineBuf array. Return value
+ * is non-zero for success, zero for failure.
+ *****************************************************************************/
+
+static int
+AppendToLineBuf(FLOAT value)
+ {
+ if (LineBufIndex >= LineBufSize)
+ {
+ FLOAT* f;
+
+ f = (FLOAT*) __wglRealloc(LineBuf,
+ (LineBufSize += LINE_BUF_QUANT) * sizeof(FLOAT));
+ if (!f)
+ return 0;
+ LineBuf = f;
+ }
+ LineBuf[LineBufIndex++] = value;
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * AppendToVertBuf
+ *
+ * Appends one floating-point value to the global VertBuf array. Return value
+ * is non-zero for success, zero for failure.
+ *
+ * Note that we can't realloc this one, because the tessellator is using
+ * pointers into it.
+ *****************************************************************************/
+
+static int
+AppendToVertBuf(FLOAT value)
+ {
+ if (VertBufIndex >= VertBufSize)
+ return 0;
+ VertBuf[VertBufIndex++] = value;
+ return 1;
+ }
+
+
+
+/*****************************************************************************
+ * FreeLineBuf
+ *
+ * Cleans up vertex buffer structure.
+ *****************************************************************************/
+
+static void
+FreeLineBuf(void)
+ {
+ if (LineBuf)
+ {
+ __wglFree(LineBuf);
+ LineBuf = NULL;
+ }
+ }
+
+
+
+/*****************************************************************************
+ * FreeVertBuf
+ *
+ * Cleans up vertex buffer structure.
+ *****************************************************************************/
+
+static void
+FreeVertBuf(void)
+ {
+ if (VertBuf)
+ {
+ __wglFree(VertBuf);
+ VertBuf = NULL;
+ }
+ }
+
+
+
+/*****************************************************************************
+ * GetWord
+ *
+ * Fetch the next 16-bit word from a little-endian byte stream, and increment
+ * the stream pointer to the next unscanned byte.
+ *****************************************************************************/
+
+static long GetWord(UCHAR** p)
+ {
+ long value;
+
+ value = ((*p)[1] << 8) + (*p)[0];
+ *p += 2;
+ return value;
+ }
+
+
+
+/*****************************************************************************
+ * GetDWord
+ *
+ * Fetch the next 32-bit word from a little-endian byte stream, and increment
+ * the stream pointer to the next unscanned byte.
+ *****************************************************************************/
+
+static long GetDWord(UCHAR** p)
+ {
+ long value;
+
+ value = ((*p)[3] << 24) + ((*p)[2] << 16) + ((*p)[1] << 8) + (*p)[0];
+ *p += 4;
+ return value;
+ }
+
+
+
+
+/*****************************************************************************
+ * GetFixed
+ *
+ * Fetch the next 32-bit fixed-point value from a little-endian byte stream,
+ * convert it to floating-point, and increment the stream pointer to the next
+ * unscanned byte.
+ *****************************************************************************/
+
+static double GetFixed(
+ UCHAR** p)
+{
+ long hiBits, loBits;
+ double value;
+
+ loBits = GetWord(p);
+ hiBits = GetWord(p);
+ value = (double) ((hiBits << 16) | loBits) / 65536.0;
+
+ return value * ScaleFactor;
+}
+
+// ***********************************************************************
+
diff --git a/src/mesa/drivers/windows/gldirect/dglwgl.h b/src/mesa/drivers/windows/gldirect/dglwgl.h
new file mode 100644
index 0000000000..c488ff9e65
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dglwgl.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: OpenGL window functions (wgl*).
+*
+****************************************************************************/
+
+#ifndef __DGLWGL_H
+#define __DGLWGL_H
+
+// Disable compiler complaints about DLL linkage
+#pragma warning (disable:4273)
+
+// Macros to control compilation
+#define STRICT
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+#include <GL\gl.h>
+
+#include "dglcontext.h"
+#include "dglglobals.h"
+#include "dglmacros.h"
+#include "ddlog.h"
+#include "dglpf.h"
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+typedef struct {
+ PROC proc;
+ char *name;
+} DGL_extension;
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _USE_GLD3_WGL
+int APIENTRY DGL_ChoosePixelFormat(HDC a, CONST PIXELFORMATDESCRIPTOR *ppfd);
+BOOL APIENTRY DGL_CopyContext(HGLRC a, HGLRC b, UINT c);
+HGLRC APIENTRY DGL_CreateContext(HDC a);
+HGLRC APIENTRY DGL_CreateLayerContext(HDC a, int b);
+BOOL APIENTRY DGL_DeleteContext(HGLRC a);
+BOOL APIENTRY DGL_DescribeLayerPlane(HDC a, int b, int c, UINT d, LPLAYERPLANEDESCRIPTOR e);
+int APIENTRY DGL_DescribePixelFormat(HDC a, int b, UINT c, LPPIXELFORMATDESCRIPTOR d);
+HGLRC APIENTRY DGL_GetCurrentContext(void);
+HDC APIENTRY DGL_GetCurrentDC(void);
+PROC APIENTRY DGL_GetDefaultProcAddress(LPCSTR a);
+int APIENTRY DGL_GetLayerPaletteEntries(HDC a, int b, int c, int d, COLORREF *e);
+int APIENTRY DGL_GetPixelFormat(HDC a);
+PROC APIENTRY DGL_GetProcAddress(LPCSTR a);
+BOOL APIENTRY DGL_MakeCurrent(HDC a, HGLRC b);
+BOOL APIENTRY DGL_RealizeLayerPalette(HDC a, int b, BOOL c);
+int APIENTRY DGL_SetLayerPaletteEntries(HDC a, int b, int c, int d, CONST COLORREF *e);
+BOOL APIENTRY DGL_SetPixelFormat(HDC a, int b, CONST PIXELFORMATDESCRIPTOR *c);
+BOOL APIENTRY DGL_ShareLists(HGLRC a, HGLRC b);
+BOOL APIENTRY DGL_SwapBuffers(HDC a);
+BOOL APIENTRY DGL_SwapLayerBuffers(HDC a, UINT b);
+BOOL APIENTRY DGL_UseFontBitmapsA(HDC a, DWORD b, DWORD c, DWORD d);
+BOOL APIENTRY DGL_UseFontBitmapsW(HDC a, DWORD b, DWORD c, DWORD d);
+BOOL APIENTRY DGL_UseFontOutlinesA(HDC a, DWORD b, DWORD c, DWORD d, FLOAT e, FLOAT f, int g, LPGLYPHMETRICSFLOAT h);
+BOOL APIENTRY DGL_UseFontOutlinesW(HDC a, DWORD b, DWORD c, DWORD d, FLOAT e, FLOAT f, int g, LPGLYPHMETRICSFLOAT h);
+#endif //_USE_GLD3_WGL
+
+BOOL dglWglResizeBuffers(GLcontext *ctx, BOOL bDefaultDriver);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/mesa/drivers/windows/gldirect/dll_main.c b/src/mesa/drivers/windows/gldirect/dll_main.c
new file mode 100644
index 0000000000..04f6466d12
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dll_main.c
@@ -0,0 +1,816 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Win32 DllMain functions.
+*
+****************************************************************************/
+
+// INITGUID must only be defined once.
+// Don't put it in a shared header file!
+// GLD3 uses dxguid.lib, so INITGUID must *not* be used!
+#ifndef _USE_GLD3_WGL
+#define INITGUID
+#endif // _USE_GLD3_WGL
+
+#include "dllmain.h"
+
+#include "snap/graphics.h"
+#include "drvlib/os/os.h"
+
+#ifdef _USE_GLD3_WGL
+typedef void (APIENTRY *LPDGLSPLASHSCREEN)(int, int, char*);
+#include "gld_driver.h"
+#endif
+
+// ***********************************************************************
+
+BOOL bInitialized = FALSE; // callback driver initialized?
+BOOL bExited = FALSE; // callback driver exited this instance?
+HINSTANCE hInstanceDll = NULL; // DLL instance handle
+
+static BOOL bDriverValidated = FALSE; // prior validation status
+static BOOL bSplashScreen = TRUE; // Splash Screen ?
+static BOOL bValidINIFound = FALSE; // Have we found a valid INI file?
+
+HHOOK hKeyHook = NULL; // global keyboard handler hook
+
+// Multi-threaded support needs to be reflected in Mesa code. (DaveM)
+int _gld_bMultiThreaded = FALSE;
+
+// ***********************************************************************
+
+DWORD dwLogging = 0; // Logging flag
+DWORD dwDebugLevel = 0; // Log debug level
+
+char szLogPath[_MAX_PATH] = {"\0"}; // Log file path
+char szSNAPPath[_MAX_PATH] = {"\0"}; // SNAP driver path
+
+#ifndef _USE_GLD3_WGL
+DGL_wglFuncs wglFuncs = {
+ sizeof(DGL_wglFuncs),
+ DGL_ChoosePixelFormat,
+ DGL_CopyContext,
+ DGL_CreateContext,
+ DGL_CreateLayerContext,
+ DGL_DeleteContext,
+ DGL_DescribeLayerPlane,
+ DGL_DescribePixelFormat,
+ DGL_GetCurrentContext,
+ DGL_GetCurrentDC,
+ DGL_GetDefaultProcAddress,
+ DGL_GetLayerPaletteEntries,
+ DGL_GetPixelFormat,
+ DGL_GetProcAddress,
+ DGL_MakeCurrent,
+ DGL_RealizeLayerPalette,
+ DGL_SetLayerPaletteEntries,
+ DGL_SetPixelFormat,
+ DGL_ShareLists,
+ DGL_SwapBuffers,
+ DGL_SwapLayerBuffers,
+ DGL_UseFontBitmapsA,
+ DGL_UseFontBitmapsW,
+ DGL_UseFontOutlinesA,
+ DGL_UseFontOutlinesW,
+};
+
+DGL_mesaFuncs mesaFuncs = {
+ sizeof(DGL_mesaFuncs),
+};
+#endif // _USE_GLD3_WGL
+
+// ***********************************************************************
+
+typedef struct {
+ DWORD dwDriver; // 0=SciTech SW, 1=Direct3D SW, 2=Direct3D HW
+ BOOL bMipmapping; // 0=off, 1=on
+ BOOL bMultitexture; // 0=off, 1=on
+ BOOL bWaitForRetrace; // 0=off, 1=on
+ BOOL bFullscreenBlit; // 0=off, 1=on
+ BOOL bFastFPU; // 0=off, 1=on
+ BOOL bDirectDrawPersistant;// 0=off, 1=on
+ BOOL bPersistantBuffers; // 0=off, 1=on
+ DWORD dwLogging; // 0=off, 1=normal, 2=crash-proof
+ DWORD dwLoggingSeverity; // 0=all, 1=warnings+errors, 2=errors only
+ BOOL bMessageBoxWarnings;// 0=off, 1=on
+ BOOL bMultiThreaded; // 0=off, 1=on
+ BOOL bAppCustomizations; // 0=off, 1=on
+ BOOL bHotKeySupport; // 0=off, 1=on
+ BOOL bSplashScreen; // 0=off, 1=on
+
+#ifdef _USE_GLD3_WGL
+ //
+ // New for GLDirect 3.0
+ //
+ DWORD dwAdapter; // DX8 adpater ordinal
+ DWORD dwTnL; // Transform & Lighting type
+ DWORD dwMultisample; // DX8 multisample type
+#endif // _USE_GLD3_WGL
+} INI_settings;
+
+static INI_settings ini;
+
+// ***********************************************************************
+
+BOOL APIENTRY DGL_initDriver(
+#ifdef _USE_GLD3_WGL
+ void)
+{
+#else
+ DGL_wglFuncs *lpWglFuncs,
+ DGL_mesaFuncs *lpMesaFuncs)
+{
+ // Check for valid pointers
+ if ((lpWglFuncs == NULL) || (lpMesaFuncs == NULL))
+ return FALSE;
+
+ // Check for valid structs
+ if (lpWglFuncs->dwSize != sizeof(DGL_wglFuncs)) {
+ return FALSE;
+ }
+
+ // Check for valid structs
+ if (lpMesaFuncs->dwSize != sizeof(DGL_mesaFuncs)) {
+ return FALSE;
+ }
+
+ // Copy the Mesa functions
+ memcpy(&mesaFuncs, lpMesaFuncs, sizeof(DGL_mesaFuncs));
+
+ // Pass back the wgl functions
+ memcpy(lpWglFuncs, &wglFuncs, sizeof(DGL_wglFuncs));
+#endif // _USE_GLD3_WGL
+
+ // Finally initialize the callback driver
+ if (!dglInitDriver())
+ return FALSE;
+
+ return TRUE;
+};
+
+// ***********************************************************************
+
+BOOL ReadINIFile(
+ HINSTANCE hInstance)
+{
+ char szModuleFilename[MAX_PATH];
+ char szSystemDirectory[MAX_PATH];
+ const char szSectionName[] = "Config";
+ char szINIFile[MAX_PATH];
+ int pos;
+
+ // Now using the DLL module handle. KeithH, 24/May/2000.
+ // Addendum: GetModuleFileName(NULL, ... returns process filename,
+ // GetModuleFileName(hModule, ... returns DLL filename,
+
+ // Get the dll path and filename.
+ GetModuleFileName(hInstance, &szModuleFilename[0], MAX_PATH); // NULL for current process
+ // Get the System directory.
+ GetSystemDirectory(&szSystemDirectory[0], MAX_PATH);
+
+ // Test to see if DLL is in system directory.
+ if (strnicmp(szModuleFilename, szSystemDirectory, strlen(szSystemDirectory))==0) {
+ // DLL *is* in system directory.
+ // Return FALSE to indicate that registry keys should be read.
+ return FALSE;
+ }
+
+ // Compose filename of INI file
+ strcpy(szINIFile, szModuleFilename);
+ pos = strlen(szINIFile);
+ while (szINIFile[pos] != '\\') {
+ pos--;
+ }
+ szINIFile[pos+1] = '\0';
+ // Use run-time DLL path for log file too
+ strcpy(szLogPath, szINIFile);
+ szLogPath[pos] = '\0';
+ // Complete full INI file path
+ strcat(szINIFile, "gldirect.ini");
+
+ // Read settings from private INI file.
+ // Note that defaults are contained in the calls.
+ ini.dwDriver = GetPrivateProfileInt(szSectionName, "dwDriver", 2, szINIFile);
+ ini.bMipmapping = GetPrivateProfileInt(szSectionName, "bMipmapping", 1, szINIFile);
+ ini.bMultitexture = GetPrivateProfileInt(szSectionName, "bMultitexture", 1, szINIFile);
+ ini.bWaitForRetrace = GetPrivateProfileInt(szSectionName, "bWaitForRetrace", 0, szINIFile);
+ ini.bFullscreenBlit = GetPrivateProfileInt(szSectionName, "bFullscreenBlit", 0, szINIFile);
+ ini.bFastFPU = GetPrivateProfileInt(szSectionName, "bFastFPU", 1, szINIFile);
+ ini.bDirectDrawPersistant = GetPrivateProfileInt(szSectionName, "bPersistantDisplay", 0, szINIFile);
+ ini.bPersistantBuffers = GetPrivateProfileInt(szSectionName, "bPersistantResources", 0, szINIFile);
+ ini.dwLogging = GetPrivateProfileInt(szSectionName, "dwLogging", 0, szINIFile);
+ ini.dwLoggingSeverity = GetPrivateProfileInt(szSectionName, "dwLoggingSeverity", 0, szINIFile);
+ ini.bMessageBoxWarnings = GetPrivateProfileInt(szSectionName, "bMessageBoxWarnings", 0, szINIFile);
+ ini.bMultiThreaded = GetPrivateProfileInt(szSectionName, "bMultiThreaded", 0, szINIFile);
+ ini.bAppCustomizations = GetPrivateProfileInt(szSectionName, "bAppCustomizations", 1, szINIFile);
+ ini.bHotKeySupport = GetPrivateProfileInt(szSectionName, "bHotKeySupport", 0, szINIFile);
+ ini.bSplashScreen = GetPrivateProfileInt(szSectionName, "bSplashScreen", 1, szINIFile);
+
+#ifdef _USE_GLD3_WGL
+ // New for GLDirect 3.x
+ ini.dwAdapter = GetPrivateProfileInt(szSectionName, "dwAdapter", 0, szINIFile);
+ // dwTnL now defaults to zero (chooses TnL at runtime). KeithH
+ ini.dwTnL = GetPrivateProfileInt(szSectionName, "dwTnL", 0, szINIFile);
+ ini.dwMultisample = GetPrivateProfileInt(szSectionName, "dwMultisample", 0, szINIFile);
+#endif
+
+ return TRUE;
+}
+
+// ***********************************************************************
+
+BOOL dllReadRegistry(
+ HINSTANCE hInstance)
+{
+ // Read settings from INI file, if available
+ bValidINIFound = FALSE;
+ if (ReadINIFile(hInstance)) {
+ const char *szRendering[3] = {
+ "SciTech Software Renderer",
+ "Direct3D MMX Software Renderer",
+ "Direct3D Hardware Renderer"
+ };
+ // Set globals
+ glb.bPrimary = 1;
+ glb.bHardware = (ini.dwDriver == 2) ? 1 : 0;
+#ifndef _USE_GLD3_WGL
+ memset(&glb.ddGuid, 0, sizeof(glb.ddGuid));
+ glb.d3dGuid = (ini.dwDriver == 2) ? IID_IDirect3DHALDevice : IID_IDirect3DRGBDevice;
+#endif // _USE_GLD3_WGL
+ strcpy(glb.szDDName, "Primary");
+ strcpy(glb.szD3DName, szRendering[ini.dwDriver]);
+ glb.dwRendering = ini.dwDriver;
+ glb.bUseMipmaps = ini.bMipmapping;
+ glb.bMultitexture = ini.bMultitexture;
+ glb.bWaitForRetrace = ini.bWaitForRetrace;
+ glb.bFullscreenBlit = ini.bFullscreenBlit;
+ glb.bFastFPU = ini.bFastFPU;
+ glb.bDirectDrawPersistant = ini.bDirectDrawPersistant;
+ glb.bPersistantBuffers = ini.bPersistantBuffers;
+ dwLogging = ini.dwLogging;
+ dwDebugLevel = ini.dwLoggingSeverity;
+ glb.bMessageBoxWarnings = ini.bMessageBoxWarnings;
+ glb.bMultiThreaded = ini.bMultiThreaded;
+ glb.bAppCustomizations = ini.bAppCustomizations;
+ glb.bHotKeySupport = ini.bHotKeySupport;
+ bSplashScreen = ini.bSplashScreen;
+#ifdef _USE_GLD3_WGL
+ // New for GLDirect 3.x
+ glb.dwAdapter = ini.dwAdapter;
+ glb.dwDriver = ini.dwDriver;
+ glb.dwTnL = ini.dwTnL;
+ glb.dwMultisample = ini.dwMultisample;
+#endif
+ bValidINIFound = TRUE;
+ return TRUE;
+ }
+ // Read settings from registry
+ else {
+ HKEY hReg;
+ DWORD cbValSize;
+ DWORD dwType = REG_SZ; // Registry data type for strings
+ BOOL bRegistryError;
+ BOOL bSuccess;
+
+#define REG_READ_DWORD(a, b) \
+ cbValSize = sizeof(b); \
+ if (ERROR_SUCCESS != RegQueryValueEx( hReg, (a), \
+ NULL, NULL, (LPBYTE)&(b), &cbValSize )) \
+ bRegistryError = TRUE;
+
+#define REG_READ_DEVICEID(a, b) \
+ cbValSize = MAX_DDDEVICEID_STRING; \
+ if(ERROR_SUCCESS != RegQueryValueEx(hReg, (a), 0, &dwType, \
+ (LPBYTE)&(b), &cbValSize)) \
+ bRegistryError = TRUE;
+
+#define REG_READ_STRING(a, b) \
+ cbValSize = sizeof((b)); \
+ if(ERROR_SUCCESS != RegQueryValueEx(hReg, (a), 0, &dwType, \
+ (LPBYTE)&(b), &cbValSize)) \
+ bRegistryError = TRUE;
+
+ // Read settings from the registry.
+
+ // Open the registry key for the current user if it exists.
+ bSuccess = (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER,
+ DIRECTGL_REG_SETTINGS_KEY,
+ 0,
+ KEY_READ,
+ &hReg));
+ // Otherwise open the registry key for the local machine.
+ if (!bSuccess)
+ bSuccess = (ERROR_SUCCESS == RegOpenKeyEx(DIRECTGL_REG_KEY_ROOT,
+ DIRECTGL_REG_SETTINGS_KEY,
+ 0,
+ KEY_READ,
+ &hReg));
+ if (!bSuccess)
+ return FALSE;
+
+ bRegistryError = FALSE;
+
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_PRIMARY, glb.bPrimary);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_D3D_HW, glb.bHardware);
+#ifndef _USE_GLD3_WGL
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_DD_GUID, glb.ddGuid);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_D3D_GUID, glb.d3dGuid);
+#endif // _USE_GLD3_WGL
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_LOGGING, dwLogging);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_DEBUGLEVEL, dwDebugLevel);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_RENDERING, glb.dwRendering);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_MULTITEXTURE, glb.bMultitexture);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_WAITFORRETRACE, glb.bWaitForRetrace);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_FULLSCREENBLIT, glb.bFullscreenBlit);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_USEMIPMAPS, glb.bUseMipmaps);
+
+ REG_READ_DEVICEID(DIRECTGL_REG_SETTING_DD_NAME, glb.szDDName);
+ REG_READ_DEVICEID(DIRECTGL_REG_SETTING_D3D_NAME, glb.szD3DName);
+
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_MSGBOXWARNINGS, glb.bMessageBoxWarnings);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_PERSISTDISPLAY, glb.bDirectDrawPersistant);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_PERSISTBUFFERS, glb.bPersistantBuffers);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_FASTFPU, glb.bFastFPU);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_HOTKEYS, glb.bHotKeySupport);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_MULTITHREAD, glb.bMultiThreaded);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_APPCUSTOM, glb.bAppCustomizations);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_SPLASHSCREEN, bSplashScreen);
+
+#ifdef _USE_GLD3_WGL
+ // New for GLDirect 3.x
+ glb.dwDriver = glb.dwRendering;
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_ADAPTER, glb.dwAdapter);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_TNL, glb.dwTnL);
+ REG_READ_DWORD(DIRECTGL_REG_SETTING_MULTISAMPLE, glb.dwMultisample);
+#endif
+
+ RegCloseKey(hReg);
+
+ // Open the global registry key for GLDirect
+ bSuccess = (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ DIRECTGL_REG_SETTINGS_KEY,
+ 0,
+ KEY_READ,
+ &hReg));
+ if (bSuccess) {
+ // Read the installation path for GLDirect
+ REG_READ_STRING("InstallLocation",szLogPath);
+ RegCloseKey(hReg);
+ }
+
+ if (bRegistryError || !bSuccess)
+ return FALSE;
+ else
+ return TRUE;
+
+#undef REG_READ_DWORD
+#undef REG_READ_DEVICEID
+#undef REG_READ_STRING
+ }
+}
+
+// ***********************************************************************
+
+BOOL dllWriteRegistry(
+ void )
+{
+ HKEY hReg;
+ DWORD dwCreateDisposition, cbValSize;
+ BOOL bRegistryError = FALSE;
+
+#define REG_WRITE_DWORD(a, b) \
+ cbValSize = sizeof(b); \
+ if (ERROR_SUCCESS != RegSetValueEx( hReg, (a), \
+ 0, REG_DWORD, (LPBYTE)&(b), cbValSize )) \
+ bRegistryError = TRUE;
+
+ if (ERROR_SUCCESS == RegCreateKeyEx( DIRECTGL_REG_KEY_ROOT, DIRECTGL_REG_SETTINGS_KEY,
+ 0, NULL, 0, KEY_WRITE, NULL, &hReg,
+ &dwCreateDisposition )) {
+ RegFlushKey(hReg); // Make sure keys are written to disk
+ RegCloseKey(hReg);
+ hReg = NULL;
+ }
+
+ if (bRegistryError)
+ return FALSE;
+ else
+ return TRUE;
+
+#undef REG_WRITE_DWORD
+}
+
+// ***********************************************************************
+
+void dglInitHotKeys(HINSTANCE hInstance)
+{
+ // Hot-Key support at all?
+ if (!glb.bHotKeySupport)
+ return;
+
+ // Install global keyboard interceptor
+ hKeyHook = SetWindowsHookEx(WH_KEYBOARD, dglKeyProc, hInstance, 0);
+}
+
+// ***********************************************************************
+
+void dglExitHotKeys(void)
+{
+ // Hot-Key support at all?
+ if (!glb.bHotKeySupport)
+ return;
+
+ // Remove global keyboard interceptor
+ if (hKeyHook)
+ UnhookWindowsHookEx(hKeyHook);
+ hKeyHook = NULL;
+}
+
+// ***********************************************************************
+
+// Note: This app-customization step must be performed in both the main
+// OpenGL32 driver and the callback driver DLLs for multithreading option.
+void dglSetAppCustomizations(void)
+{
+ char szModuleFileName[MAX_PATH];
+ int iSize = MAX_PATH;
+
+ // Get the currently loaded EXE filename.
+ GetModuleFileName(NULL, &szModuleFileName[0], MAX_PATH); // NULL for current process
+ strupr(szModuleFileName);
+ iSize = strlen(szModuleFileName);
+
+ // Check for specific EXEs and adjust global settings accordingly
+
+ // NOTE: In GLD3.x "bDirectDrawPersistant" corresponds to IDirect3D8 and
+ // "bPersistantBuffers" corresponds to IDirect3DDevice8. KeithH
+
+ // Case 1: 3DStudio must be multi-threaded
+ // Added: Discreet GMAX (3DStudio MAX 4 for gamers. KeithH)
+ if (strstr(szModuleFileName, "3DSMAX.EXE")
+ || strstr(szModuleFileName, "3DSVIZ.EXE")
+ || strstr(szModuleFileName, "GMAX.EXE")) {
+ glb.bMultiThreaded = TRUE;
+ glb.bDirectDrawPersistant = FALSE;
+ glb.bPersistantBuffers = FALSE;
+ return;
+ }
+
+ // Case 2: Solid Edge must use pre-allocated resources for all GLRCs
+ if (strstr(szModuleFileName, "PART.EXE")
+ || strstr(szModuleFileName, "ASSEMBL.EXE")
+ || strstr(szModuleFileName, "DRAFT.EXE")
+ || strstr(szModuleFileName, "SMARTVW.EXE")
+ || strstr(szModuleFileName, "SMETAL.EXE")) {
+ glb.bMultiThreaded = FALSE;
+ glb.bDirectDrawPersistant = TRUE;
+ glb.bPersistantBuffers = FALSE;
+ return;
+ }
+
+ // Case 3: Sudden Depth creates and destroys GLRCs on paint commands
+ if (strstr(szModuleFileName, "SUDDEPTH.EXE")
+ || strstr(szModuleFileName, "SUDDEMO.EXE")) {
+ glb.bMultiThreaded = FALSE;
+ glb.bDirectDrawPersistant = TRUE;
+ glb.bPersistantBuffers = TRUE;
+ glb.bFullscreenBlit = TRUE;
+ return;
+ }
+
+ // Case 4: StereoGraphics test apps create and destroy GLRCs on paint commands
+ if (strstr(szModuleFileName, "REDBLUE.EXE")
+ || strstr(szModuleFileName, "DIAGNOSE.EXE")) {
+ glb.bMultiThreaded = FALSE;
+ glb.bDirectDrawPersistant = TRUE;
+ glb.bPersistantBuffers = TRUE;
+ return;
+ }
+
+ // Case 5: Pipes screen savers share multiple GLRCs for same window
+ if (strstr(szModuleFileName, "PIPES.SCR")
+ || (strstr(szModuleFileName, "PIPES") && strstr(szModuleFileName, ".SCR"))) {
+ glb.bMultiThreaded = FALSE;
+ glb.bDirectDrawPersistant = TRUE;
+ glb.bPersistantBuffers = TRUE;
+ return;
+ }
+
+ // Case 6: AutoVue uses sub-viewport ops which are temporarily broken in stereo window
+ if (strstr(szModuleFileName, "AVWIN.EXE")) {
+ glb.bMultiThreaded = FALSE;
+ glb.bDirectDrawPersistant = TRUE;
+ glb.bPersistantBuffers = TRUE;
+ return;
+ }
+ // Case 7: Quake3 is waiting for DDraw objects to be released at exit
+ if (strstr(szModuleFileName, "QUAKE")) {
+ glb.bMultiThreaded = FALSE;
+ glb.bDirectDrawPersistant = FALSE;
+ glb.bPersistantBuffers = FALSE;
+ glb.bFullscreenBlit = FALSE;
+ return;
+ }
+ // Case 8: Reflection GLX server is unable to switch contexts at run-time
+ if (strstr(szModuleFileName, "RX.EXE")) {
+ glb.bMultiThreaded = FALSE;
+ glb.bMessageBoxWarnings = FALSE;
+ return;
+ }
+ // Case 9: Original AutoCAD 2000 must share DDraw objects across GLRCs
+ if (strstr(szModuleFileName, "ACAD.EXE")) {
+ glb.bFastFPU = FALSE;
+ if (GetModuleHandle("wopengl6.hdi") != NULL) {
+ glb.bMultiThreaded = FALSE;
+ glb.bDirectDrawPersistant = TRUE;
+ glb.bPersistantBuffers = FALSE;
+ }
+ return;
+ }
+}
+
+// ***********************************************************************
+
+BOOL dglInitDriver(void)
+{
+ UCHAR szExeName[MAX_PATH];
+ const char *szRendering[] = {
+ "Mesa Software",
+ "Direct3D RGB SW",
+ "Direct3D HW",
+ };
+ static ibool bWarnOnce = false;
+
+ // Already initialized?
+ if (bInitialized)
+ return TRUE;
+
+ // Moved from DllMain DLL_PROCESS_ATTACH:
+
+ // (Re-)Init defaults
+ dglInitGlobals();
+
+ // Read registry or INI file settings
+ if (!dllReadRegistry(hInstanceDll)) {
+ if (!bWarnOnce)
+ MessageBox( NULL, "GLDirect has not been configured.\n\n"
+ "Please run the configuration program\n"
+ "before using GLDirect with applications.\n",
+ "GLDirect", MB_OK | MB_ICONWARNING);
+ bWarnOnce = true;
+ return FALSE;
+ }
+
+#ifdef _USE_GLD3_WGL
+ // Must do this as early as possible.
+ // Need to read regkeys/ini-file first though.
+ gldInitDriverPointers(glb.dwDriver);
+
+ // Create private driver globals
+ _gldDriver.CreatePrivateGlobals();
+#endif
+ // Overide settings with application customizations
+ if (glb.bAppCustomizations)
+ dglSetAppCustomizations();
+
+//#ifndef _USE_GLD3_WGL
+ // Set the global memory type to either sysmem or vidmem
+ glb.dwMemoryType = glb.bHardware ? DDSCAPS_VIDEOMEMORY : DDSCAPS_SYSTEMMEMORY;
+//#endif
+
+ // Multi-threaded support overides persistant display support
+ if (glb.bMultiThreaded)
+ glb.bDirectDrawPersistant = glb.bPersistantBuffers = FALSE;
+
+ // Multi-threaded support needs to be reflected in Mesa code. (DaveM)
+ _gld_bMultiThreaded = glb.bMultiThreaded;
+
+ // Start logging
+ ddlogPathOption(szLogPath);
+ ddlogWarnOption(glb.bMessageBoxWarnings);
+ ddlogOpen((DDLOG_loggingMethodType)dwLogging,
+ (DDLOG_severityType)dwDebugLevel);
+
+ // Obtain the name of the calling app
+ ddlogMessage(DDLOG_SYSTEM, "Driver : SciTech GLDirect 4.0\n");
+ GetModuleFileName(NULL, szExeName, sizeof(szExeName));
+ ddlogPrintf(DDLOG_SYSTEM, "Executable : %s", szExeName);
+
+ ddlogPrintf(DDLOG_SYSTEM, "DirectDraw device: %s", glb.szDDName);
+ ddlogPrintf(DDLOG_SYSTEM, "Direct3D driver : %s", glb.szD3DName);
+
+ ddlogPrintf(DDLOG_SYSTEM, "Rendering type : %s", szRendering[glb.dwRendering]);
+
+ ddlogPrintf(DDLOG_SYSTEM, "Multithreaded : %s", glb.bMultiThreaded ? "Enabled" : "Disabled");
+ ddlogPrintf(DDLOG_SYSTEM, "Display resources: %s", glb.bDirectDrawPersistant ? "Persistant" : "Instanced");
+ ddlogPrintf(DDLOG_SYSTEM, "Buffer resources : %s", glb.bPersistantBuffers ? "Persistant" : "Instanced");
+
+ dglInitContextState();
+ dglBuildPixelFormatList();
+ //dglBuildTextureFormatList();
+
+ // D3D callback driver is now successfully initialized
+ bInitialized = TRUE;
+ // D3D callback driver is now ready to be exited
+ bExited = FALSE;
+
+ return TRUE;
+}
+
+// ***********************************************************************
+
+void dglExitDriver(void)
+{
+
+ // Only need to clean up once per instance:
+ // May be called implicitly from DLL_PROCESS_DETACH,
+ // or explicitly from DGL_exitDriver().
+ if (bExited)
+ return;
+ bExited = TRUE;
+
+ // DDraw objects may be invalid when DLL unloads.
+__try {
+
+ // Clean-up sequence (moved from DLL_PROCESS_DETACH)
+#ifndef _USE_GLD3_WGL
+ dglReleaseTextureFormatList();
+#endif
+ dglReleasePixelFormatList();
+ dglDeleteContextState();
+
+#ifdef _USE_GLD3_WGL
+ _gldDriver.DestroyPrivateGlobals();
+#endif
+
+}
+__except(EXCEPTION_EXECUTE_HANDLER) {
+ ddlogPrintf(DDLOG_WARN, "Exception raised in dglExitDriver.");
+}
+
+ // Close the log file
+ ddlogClose();
+}
+
+// ***********************************************************************
+
+int WINAPI DllMain(
+ HINSTANCE hInstance,
+ DWORD fdwReason,
+ PVOID pvReserved)
+{
+ switch (fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ // Cache DLL instance handle
+ hInstanceDll = hInstance;
+
+ // Flag that callback driver has yet to be initialized
+ bInitialized = bExited = FALSE;
+
+#ifndef _USE_GLD3_WGL
+ // Init internal Mesa function pointers
+ memset(&mesaFuncs, 0, sizeof(DGL_mesaFuncs));
+#endif // _USE_GLD3_WGL
+
+ // Init defaults
+ dglInitGlobals();
+
+ // Defer rest of DLL initialization to 1st WGL function call
+ break;
+
+ case DLL_PROCESS_DETACH:
+ // Call exit clean-up sequence
+ dglExitDriver();
+ break;
+ }
+
+ return TRUE;
+}
+
+// ***********************************************************************
+
+void APIENTRY DGL_exitDriver(void)
+{
+ // Call exit clean-up sequence
+ dglExitDriver();
+}
+
+// ***********************************************************************
+
+void APIENTRY DGL_reinitDriver(void)
+{
+ // Force init sequence again
+ bInitialized = bExited = FALSE;
+ dglInitDriver();
+}
+
+// ***********************************************************************
+
+int WINAPI DllInitialize(
+ HINSTANCE hInstance,
+ DWORD fdwReason,
+ PVOID pvReserved)
+{
+ // Some Watcom compiled executables require this.
+ return DllMain(hInstance, fdwReason, pvReserved);
+}
+
+// ***********************************************************************
+
+void DGL_LoadSplashScreen(int piReg, char* pszUser)
+{
+ HINSTANCE hSplashDll = NULL;
+ LPDGLSPLASHSCREEN dglSplashScreen = NULL;
+ static BOOL bOnce = FALSE;
+ static int iReg = 0;
+ static char szUser[255] = {"\0"};
+
+ // Display splash screen at all?
+ if (!bSplashScreen)
+ return;
+
+ // Only display splash screen once
+ if (bOnce)
+ return;
+ bOnce = TRUE;
+
+ // Make local copy of string for passing to DLL
+ if (pszUser)
+ strcpy(szUser, pszUser);
+ iReg = piReg;
+
+ // Load Splash Screen DLL
+ // (If it fails to load for any reason, we don't care...)
+ hSplashDll = LoadLibrary("gldsplash.dll");
+ if (hSplashDll) {
+ // Execute the Splash Screen function
+ dglSplashScreen = (LPDGLSPLASHSCREEN)GetProcAddress(hSplashDll, "GLDSplashScreen");
+ if (dglSplashScreen)
+ (*dglSplashScreen)(1, iReg, szUser);
+ // Don't unload the DLL since splash screen dialog is modeless now
+ }
+}
+
+// ***********************************************************************
+
+BOOL dglValidate()
+{
+ char *szCaption = "SciTech GLDirect Driver";
+ UINT uType = MB_OK | MB_ICONEXCLAMATION;
+
+#ifdef _USE_GLD3_WGL
+ // (Re)build pixelformat list
+ if (glb.bPixelformatsDirty)
+ _gldDriver.BuildPixelformatList();
+#endif
+
+ // Check to see if we have already validated
+ if (bDriverValidated && bInitialized)
+ return TRUE;
+
+ // Since all (most) the WGL functions must be validated at this point,
+ // this also insure that the callback driver is completely initialized.
+ if (!bInitialized)
+ if (!dglInitDriver()) {
+ MessageBox(NULL,
+ "The GLDirect driver could not initialize.\n\n"
+ "Please run the configuration program to\n"
+ "properly configure the driver, or else\n"
+ "re-run the installation program.", szCaption, uType);
+ _exit(1); // Bail
+ }
+
+ return TRUE;
+}
+
+// ***********************************************************************
+
diff --git a/src/mesa/drivers/windows/gldirect/dllmain.h b/src/mesa/drivers/windows/gldirect/dllmain.h
new file mode 100644
index 0000000000..d898c31067
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dllmain.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Win32 DllMain functions.
+*
+****************************************************************************/
+
+#ifndef __DLLMAIN_H
+#define __DLLMAIN_H
+
+// Macros to control compilation
+#define STRICT
+#define WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+
+#ifndef _USE_GLD3_WGL
+#include "DirectGL.h"
+#endif // _USE_GLD3_WGL
+
+#include "gldirect/regkeys.h"
+#include "dglglobals.h"
+#include "ddlog.h"
+#ifndef _USE_GLD3_WGL
+#include "d3dtexture.h"
+#endif // _USE_GLD3_WGL
+
+#include "dglwgl.h"
+
+extern BOOL bInitialized;
+
+BOOL dglInitDriver(void);
+void dglExitDriver(void);
+
+#endif
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c
new file mode 100644
index 0000000000..5ce14c50bc
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_driver_dx7.c
@@ -0,0 +1,1195 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Driver interface code to Mesa
+*
+****************************************************************************/
+
+//#include <windows.h>
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx7.h"
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "array_cache/acache.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast_setup/ss_context.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+extern BOOL dglSwapBuffers(HDC hDC);
+
+// HACK: Hack the _33 member of the OpenGL perspective projection matrix
+const float _fPersp_33 = 1.6f;
+
+//---------------------------------------------------------------------------
+// Internal functions
+//---------------------------------------------------------------------------
+
+void _gld_mesa_warning(
+ __GLcontext *gc,
+ char *str)
+{
+ // Intercept Mesa's internal warning mechanism
+ gldLogPrintf(GLDLOG_WARN, "Mesa warning: %s", str);
+}
+
+//---------------------------------------------------------------------------
+
+void _gld_mesa_fatal(
+ __GLcontext *gc,
+ char *str)
+{
+ // Intercept Mesa's internal fatal-message mechanism
+ gldLogPrintf(GLDLOG_CRITICAL, "Mesa FATAL: %s", str);
+
+ // Mesa calls abort(0) here.
+ ddlogClose();
+ exit(0);
+}
+
+//---------------------------------------------------------------------------
+
+D3DSTENCILOP _gldConvertStencilOp(
+ GLenum StencilOp)
+{
+ // Used by Stencil: pass, fail and zfail
+
+ switch (StencilOp) {
+ case GL_KEEP:
+ return D3DSTENCILOP_KEEP;
+ case GL_ZERO:
+ return D3DSTENCILOP_ZERO;
+ case GL_REPLACE:
+ return D3DSTENCILOP_REPLACE;
+ case GL_INCR:
+ return D3DSTENCILOP_INCRSAT;
+ case GL_DECR:
+ return D3DSTENCILOP_DECRSAT;
+ case GL_INVERT:
+ return D3DSTENCILOP_INVERT;
+ case GL_INCR_WRAP_EXT: // GL_EXT_stencil_wrap
+ return D3DSTENCILOP_INCR;
+ case GL_DECR_WRAP_EXT: // GL_EXT_stencil_wrap
+ return D3DSTENCILOP_DECR;
+ }
+
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "_gldConvertStencilOp: Unknown StencilOp\n");
+#endif
+
+ return D3DSTENCILOP_KEEP;
+}
+
+//---------------------------------------------------------------------------
+
+D3DCMPFUNC _gldConvertCompareFunc(
+ GLenum CmpFunc)
+{
+ // Used for Alpha func, depth func and stencil func.
+
+ switch (CmpFunc) {
+ case GL_NEVER:
+ return D3DCMP_NEVER;
+ case GL_LESS:
+ return D3DCMP_LESS;
+ case GL_EQUAL:
+ return D3DCMP_EQUAL;
+ case GL_LEQUAL:
+ return D3DCMP_LESSEQUAL;
+ case GL_GREATER:
+ return D3DCMP_GREATER;
+ case GL_NOTEQUAL:
+ return D3DCMP_NOTEQUAL;
+ case GL_GEQUAL:
+ return D3DCMP_GREATEREQUAL;
+ case GL_ALWAYS:
+ return D3DCMP_ALWAYS;
+ };
+
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "_gldConvertCompareFunc: Unknown CompareFunc\n");
+#endif
+
+ return D3DCMP_ALWAYS;
+}
+
+//---------------------------------------------------------------------------
+
+D3DBLEND _gldConvertBlendFunc(
+ GLenum blend,
+ GLenum DefaultBlend)
+{
+ switch (blend) {
+ case GL_ZERO:
+ return D3DBLEND_ZERO;
+ case GL_ONE:
+ return D3DBLEND_ONE;
+ case GL_DST_COLOR:
+ return D3DBLEND_DESTCOLOR;
+ case GL_SRC_COLOR:
+ return D3DBLEND_SRCCOLOR;
+ case GL_ONE_MINUS_DST_COLOR:
+ return D3DBLEND_INVDESTCOLOR;
+ case GL_ONE_MINUS_SRC_COLOR:
+ return D3DBLEND_INVSRCCOLOR;
+ case GL_SRC_ALPHA:
+ return D3DBLEND_SRCALPHA;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ return D3DBLEND_INVSRCALPHA;
+ case GL_DST_ALPHA:
+ return D3DBLEND_DESTALPHA;
+ case GL_ONE_MINUS_DST_ALPHA:
+ return D3DBLEND_INVDESTALPHA;
+ case GL_SRC_ALPHA_SATURATE:
+ return D3DBLEND_SRCALPHASAT;
+ }
+
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "_gldConvertBlendFunc: Unknown BlendFunc\n");
+#endif
+
+ return DefaultBlend;
+}
+
+//---------------------------------------------------------------------------
+// Misc. functions
+//---------------------------------------------------------------------------
+
+void gld_Noop_DX7(
+ GLcontext *ctx)
+{
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "gld_Noop called!\n");
+#endif
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Error_DX7(
+ GLcontext *ctx)
+{
+#ifdef _DEBUG
+ // Quite useless.
+// gldLogMessage(GLDLOG_ERROR, "ctx->Driver.Error called!\n");
+#endif
+}
+
+//---------------------------------------------------------------------------
+// Required Mesa functions
+//---------------------------------------------------------------------------
+
+static GLboolean gld_set_draw_buffer_DX7(
+ GLcontext *ctx,
+ GLenum mode)
+{
+ (void) ctx;
+ if ((mode==GL_FRONT_LEFT) || (mode == GL_BACK_LEFT)) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_set_read_buffer_DX7(
+ GLcontext *ctx,
+ GLframebuffer *buffer,
+ GLenum mode)
+{
+ /* separate read buffer not supported */
+/*
+ ASSERT(buffer == ctx->DrawBuffer);
+ ASSERT(mode == GL_FRONT_LEFT);
+*/
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Clear_DX7(
+ GLcontext *ctx,
+ GLbitfield mask,
+ GLboolean all,
+ GLint x,
+ GLint y,
+ GLint width,
+ GLint height)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ DWORD dwFlags = 0;
+ D3DCOLOR Color = 0;
+ float Z = 0.0f;
+ DWORD Stencil = 0;
+ D3DRECT d3dClearRect;
+
+ // TODO: Colourmask
+ const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
+
+ if (!gld->pDev)
+ return;
+
+ if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) {
+ GLubyte col[4];
+ CLAMPED_FLOAT_TO_UBYTE(col[0], ctx->Color.ClearColor[0]);
+ CLAMPED_FLOAT_TO_UBYTE(col[1], ctx->Color.ClearColor[1]);
+ CLAMPED_FLOAT_TO_UBYTE(col[2], ctx->Color.ClearColor[2]);
+ CLAMPED_FLOAT_TO_UBYTE(col[3], ctx->Color.ClearColor[3]);
+ dwFlags |= D3DCLEAR_TARGET;
+ Color = D3DCOLOR_RGBA(col[0], col[1], col[2], col[3]);
+// ctx->Color.ClearColor[1],
+// ctx->Color.ClearColor[2],
+// ctx->Color.ClearColor[3]);
+ }
+
+ if (mask & DD_DEPTH_BIT) {
+ // D3D7 will fail the Clear call if we try and clear a
+ // depth buffer and we haven't created one.
+ // Also, some apps try and clear a depth buffer,
+ // when a depth buffer hasn't been requested by the app.
+ if (ctx->Visual.depthBits == 0) {
+ mask &= ~DD_DEPTH_BIT; // Remove depth bit from mask
+ } else {
+ dwFlags |= D3DCLEAR_ZBUFFER;
+ Z = ctx->Depth.Clear;
+ }
+ }
+
+ if (mask & DD_STENCIL_BIT) {
+ if (ctx->Visual.stencilBits == 0) {
+ // No stencil bits in depth buffer
+ mask &= ~DD_STENCIL_BIT; // Remove stencil bit from mask
+ } else {
+ dwFlags |= D3DCLEAR_STENCIL;
+ Stencil = ctx->Stencil.Clear;
+ }
+ }
+
+ // Some apps do really weird things with the rect, such as Quake3.
+ if ((x < 0) || (y < 0) || (width <= 0) || (height <= 0)) {
+ all = GL_TRUE;
+ }
+
+ if (!all) {
+ // Calculate clear subrect
+ d3dClearRect.x1 = x;
+ d3dClearRect.y1 = gldCtx->dwHeight - (y + height);
+ d3dClearRect.x2 = x + width;
+ d3dClearRect.y2 = d3dClearRect.y1 + height;
+ }
+
+ // dwFlags will be zero if there's nothing to clear
+ if (dwFlags) {
+ _GLD_DX7_DEV(Clear(
+ gld->pDev,
+ all ? 0 : 1,
+ all ? NULL : &d3dClearRect,
+ dwFlags,
+ Color, Z, Stencil));
+ }
+
+ if (mask & DD_ACCUM_BIT) {
+ // Clear accumulation buffer
+ }
+}
+
+//---------------------------------------------------------------------------
+
+// Mesa 5: Parameter change
+static void gld_buffer_size_DX7(
+// GLcontext *ctx,
+ GLframebuffer *fb,
+ GLuint *width,
+ GLuint *height)
+{
+// GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+
+ *width = fb->Width; // gldCtx->dwWidth;
+ *height = fb->Height; // gldCtx->dwHeight;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_Finish_DX7(
+ GLcontext *ctx)
+{
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_Flush_DX7(
+ GLcontext *ctx)
+{
+ GLD_context *gld = GLD_GET_CONTEXT(ctx);
+
+ // TODO: Detect apps that glFlush() then SwapBuffers() ?
+
+ if (gld->EmulateSingle) {
+ // Emulating a single-buffered context.
+ // [Direct3D doesn't allow rendering to front buffer]
+ dglSwapBuffers(gld->hDC);
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_STENCIL(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ // Two-sided stencil. New for Mesa 5
+ const GLuint uiFace = 0UL;
+
+ struct gl_stencil_attrib *pStencil = &ctx->Stencil;
+
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILENABLE, pStencil->Enabled ? TRUE : FALSE));
+ if (pStencil->Enabled) {
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILFUNC, _gldConvertCompareFunc(pStencil->Function[uiFace])));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILREF, pStencil->Ref[uiFace]));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILMASK, pStencil->ValueMask[uiFace]));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILWRITEMASK, pStencil->WriteMask[uiFace]));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILFAIL, _gldConvertStencilOp(pStencil->FailFunc[uiFace])));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILZFAIL, _gldConvertStencilOp(pStencil->ZFailFunc[uiFace])));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_STENCILPASS, _gldConvertStencilOp(pStencil->ZPassFunc[uiFace])));
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_COLOR(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ DWORD dwFlags = 0;
+ D3DBLEND src;
+ D3DBLEND dest;
+
+ // Alpha func
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ALPHAFUNC, _gldConvertCompareFunc(ctx->Color.AlphaFunc)));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ALPHAREF, (DWORD)ctx->Color.AlphaRef));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ALPHATESTENABLE, ctx->Color.AlphaEnabled));
+
+ // Blend func
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ALPHABLENDENABLE, ctx->Color.BlendEnabled));
+ src = _gldConvertBlendFunc(ctx->Color.BlendSrcRGB, GL_ONE);
+ dest = _gldConvertBlendFunc(ctx->Color.BlendDstRGB, GL_ZERO);
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_SRCBLEND, src));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_DESTBLEND, dest));
+
+/*
+ // Color mask - unsupported by DX7
+ if (ctx->Color.ColorMask[0]) dwFlags |= D3DCOLORWRITEENABLE_RED;
+ if (ctx->Color.ColorMask[1]) dwFlags |= D3DCOLORWRITEENABLE_GREEN;
+ if (ctx->Color.ColorMask[2]) dwFlags |= D3DCOLORWRITEENABLE_BLUE;
+ if (ctx->Color.ColorMask[3]) dwFlags |= D3DCOLORWRITEENABLE_ALPHA;
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_COLORWRITEENABLE, dwFlags));
+*/
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_DEPTH(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ZENABLE, ctx->Depth.Test ? D3DZB_TRUE : D3DZB_FALSE));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ZFUNC, _gldConvertCompareFunc(ctx->Depth.Func)));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ZWRITEENABLE, ctx->Depth.Mask ? TRUE : FALSE));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_POLYGON(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ D3DFILLMODE d3dFillMode = D3DFILL_SOLID;
+ D3DCULL d3dCullMode = D3DCULL_NONE;
+ int iOffset = 0;
+
+ // Fillmode
+ switch (ctx->Polygon.FrontMode) {
+ case GL_POINT:
+ d3dFillMode = D3DFILL_POINT;
+ break;
+ case GL_LINE:
+ d3dFillMode = D3DFILL_WIREFRAME;
+ break;
+ case GL_FILL:
+ d3dFillMode = D3DFILL_SOLID;
+ break;
+ }
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FILLMODE, d3dFillMode));
+
+ if (ctx->Polygon.CullFlag) {
+ switch (ctx->Polygon.CullFaceMode) {
+ case GL_BACK:
+ if (ctx->Polygon.FrontFace == GL_CCW)
+ d3dCullMode = D3DCULL_CW;
+ else
+ d3dCullMode = D3DCULL_CCW;
+ break;
+ case GL_FRONT:
+ if (ctx->Polygon.FrontFace == GL_CCW)
+ d3dCullMode = D3DCULL_CCW;
+ else
+ d3dCullMode = D3DCULL_CW;
+ break;
+ case GL_FRONT_AND_BACK:
+ d3dCullMode = D3DCULL_NONE;
+ break;
+ default:
+ break;
+ }
+ } else {
+ d3dCullMode = D3DCULL_NONE;
+ }
+// d3dCullMode = D3DCULL_NONE; // TODO: DEBUGGING
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_CULLMODE, d3dCullMode));
+
+ // Polygon offset
+ // ZBIAS ranges from 0 to 16 and can only move towards the viewer
+ // Mesa5: ctx->Polygon._OffsetAny removed
+ if (ctx->Polygon.OffsetFill) {
+ iOffset = (int)ctx->Polygon.OffsetUnits;
+ if (iOffset < 0)
+ iOffset = -iOffset;
+ else
+ iOffset = 0; // D3D can't push away
+ }
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_ZBIAS, iOffset));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_FOG(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ D3DCOLOR d3dFogColour;
+ D3DFOGMODE d3dFogMode = D3DFOG_LINEAR;
+
+ // TODO: Fog is calculated seperately in the Mesa pipeline
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGENABLE, FALSE));
+ return;
+
+ // Fog enable
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGENABLE, ctx->Fog.Enabled));
+ if (!ctx->Fog.Enabled) {
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_NONE));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_NONE));
+ return; // If disabled, don't bother setting any fog state
+ }
+
+ // Fog colour
+ d3dFogColour = D3DCOLOR_COLORVALUE( ctx->Fog.Color[0],
+ ctx->Fog.Color[1],
+ ctx->Fog.Color[2],
+ ctx->Fog.Color[3]);
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGCOLOR, d3dFogColour));
+
+ // Fog density
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGDENSITY, *((DWORD*) (&ctx->Fog.Density))));
+
+ // Fog start
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGSTART, *((DWORD*) (&ctx->Fog.Start))));
+
+ // Fog end
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGEND, *((DWORD*) (&ctx->Fog.End))));
+
+ // Fog mode
+ switch (ctx->Fog.Mode) {
+ case GL_LINEAR:
+ d3dFogMode = D3DFOG_LINEAR;
+ break;
+ case GL_EXP:
+ d3dFogMode = D3DFOG_EXP;
+ break;
+ case GL_EXP2:
+ d3dFogMode = D3DFOG_EXP2;
+ break;
+ }
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGTABLEMODE, d3dFogMode));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_NONE));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_LIGHT(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+ DWORD dwSpecularEnable;
+
+ // Shademode
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_SHADEMODE, (ctx->Light.ShadeModel == GL_SMOOTH) ? D3DSHADE_GOURAUD : D3DSHADE_FLAT));
+
+ // Separate specular colour
+ if (ctx->Light.Enabled)
+ dwSpecularEnable = (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) ? TRUE: FALSE;
+ else
+ dwSpecularEnable = FALSE;
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_SPECULARENABLE, dwSpecularEnable));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_MODELVIEW(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ D3DMATRIX m;
+ //GLfloat *pM = ctx->ModelView.m;
+ // Mesa5: Model-view is now a stack
+ GLfloat *pM = ctx->ModelviewMatrixStack.Top->m;
+ m._11 = pM[0];
+ m._12 = pM[1];
+ m._13 = pM[2];
+ m._14 = pM[3];
+ m._21 = pM[4];
+ m._22 = pM[5];
+ m._23 = pM[6];
+ m._24 = pM[7];
+ m._31 = pM[8];
+ m._32 = pM[9];
+ m._33 = pM[10];
+ m._34 = pM[11];
+ m._41 = pM[12];
+ m._42 = pM[13];
+ m._43 = pM[14];
+ m._44 = pM[15];
+/* m[0][0] = pM[0];
+ m[0][1] = pM[1];
+ m[0][2] = pM[2];
+ m[0][3] = pM[3];
+ m[1][0] = pM[4];
+ m[1][1] = pM[5];
+ m[1][2] = pM[6];
+ m[1][3] = pM[7];
+ m[2][0] = pM[8];
+ m[2][1] = pM[9];
+ m[2][2] = pM[10];
+ m[2][3] = pM[11];
+ m[3][0] = pM[12];
+ m[3][1] = pM[13];
+ m[3][2] = pM[14];
+ m[3][3] = pM[15];*/
+
+ gld->matModelView = m;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_PROJECTION(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ D3DMATRIX m;
+ //GLfloat *pM = ctx->ProjectionMatrix.m;
+ // Mesa 5: Now a stack
+ GLfloat *pM = ctx->ProjectionMatrixStack.Top->m;
+ m._11 = pM[0];
+ m._12 = pM[1];
+ m._13 = pM[2];
+ m._14 = pM[3];
+
+ m._21 = pM[4];
+ m._22 = pM[5];
+ m._23 = pM[6];
+ m._24 = pM[7];
+
+ m._31 = pM[8];
+ m._32 = pM[9];
+ m._33 = pM[10] / _fPersp_33; // / 1.6f;
+ m._34 = pM[11];
+
+ m._41 = pM[12];
+ m._42 = pM[13];
+ m._43 = pM[14] / 2.0f;
+ m._44 = pM[15];
+
+ gld->matProjection = m;
+}
+
+//---------------------------------------------------------------------------
+/*
+void gldFrustumHook_DX7(
+ GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top,
+ GLdouble nearval,
+ GLdouble farval)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ // Pass values on to Mesa first (in case we mess with them)
+ _mesa_Frustum(left, right, bottom, top, nearval, farval);
+
+ _fPersp_33 = farval / (nearval - farval);
+
+// ddlogPrintf(GLDLOG_SYSTEM, "Frustum: %f", farval/nearval);
+}
+
+//---------------------------------------------------------------------------
+
+void gldOrthoHook_DX7(
+ GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top,
+ GLdouble nearval,
+ GLdouble farval)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ // Pass values on to Mesa first (in case we mess with them)
+ _mesa_Ortho(left, right, bottom, top, nearval, farval);
+
+ _fPersp_33 = 1.6f;
+
+// ddlogPrintf(GLDLOG_SYSTEM, "Ortho: %f", farval/nearval);
+}
+*/
+//---------------------------------------------------------------------------
+
+void gld_NEW_VIEWPORT(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ D3DVIEWPORT7 d3dvp;
+// GLint x, y;
+// GLsizei w, h;
+
+ // Set depth range
+ _GLD_DX7_DEV(GetViewport(gld->pDev, &d3dvp));
+ // D3D can't do Quake1/Quake2 z-trick
+ if (ctx->Viewport.Near <= ctx->Viewport.Far) {
+ d3dvp.dvMinZ = ctx->Viewport.Near;
+ d3dvp.dvMaxZ = ctx->Viewport.Far;
+ } else {
+ d3dvp.dvMinZ = ctx->Viewport.Far;
+ d3dvp.dvMaxZ = ctx->Viewport.Near;
+ }
+/* x = ctx->Viewport.X;
+ y = ctx->Viewport.Y;
+ w = ctx->Viewport.Width;
+ h = ctx->Viewport.Height;
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (w > gldCtx->dwWidth) w = gldCtx->dwWidth;
+ if (h > gldCtx->dwHeight) h = gldCtx->dwHeight;
+ // Ditto for D3D viewport dimensions
+ if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x;
+ if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y;
+ d3dvp.X = x;
+ d3dvp.Y = gldCtx->dwHeight - (y + h);
+ d3dvp.Width = w;
+ d3dvp.Height = h;*/
+ _GLD_DX7_DEV(SetViewport(gld->pDev, &d3dvp));
+
+// gld->fFlipWindowY = (float)gldCtx->dwHeight;
+}
+
+//---------------------------------------------------------------------------
+
+__inline BOOL _gldAnyEvalEnabled(
+ GLcontext *ctx)
+{
+ struct gl_eval_attrib *eval = &ctx->Eval;
+
+ if ((eval->AutoNormal) ||
+ (eval->Map1Color4) ||
+ (eval->Map1Index) ||
+ (eval->Map1Normal) ||
+ (eval->Map1TextureCoord1) ||
+ (eval->Map1TextureCoord2) ||
+ (eval->Map1TextureCoord3) ||
+ (eval->Map1TextureCoord4) ||
+ (eval->Map1Vertex3) ||
+ (eval->Map1Vertex4) ||
+ (eval->Map2Color4) ||
+ (eval->Map2Index) ||
+ (eval->Map2Normal) ||
+ (eval->Map2TextureCoord1) ||
+ (eval->Map2TextureCoord2) ||
+ (eval->Map2TextureCoord3) ||
+ (eval->Map2TextureCoord4) ||
+ (eval->Map2Vertex3) ||
+ (eval->Map2Vertex4)
+ )
+ return TRUE;
+
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL _gldChooseInternalPipeline(
+ GLcontext *ctx,
+ GLD_driver_dx7 *gld)
+{
+// return TRUE; // DEBUGGING: ALWAYS USE MESA
+// return FALSE; // DEBUGGING: ALWAYS USE D3D
+
+ if ((glb.dwTnL == GLDS_TNL_MESA) || (gld->bHasHWTnL == FALSE))
+ {
+ gld->PipelineUsage.qwMesa.QuadPart++;
+ return TRUE; // Force Mesa TnL
+ }
+
+ if ((ctx->Light.Enabled) ||
+ (1) ||
+ (ctx->Texture._TexGenEnabled) ||
+ (ctx->Texture._TexMatEnabled) ||
+// (ctx->Transform._AnyClip) ||
+ (ctx->Scissor.Enabled) ||
+ _gldAnyEvalEnabled(ctx) // Put this last so we can early-out
+ )
+ {
+ gld->PipelineUsage.qwMesa.QuadPart++;
+ return TRUE;
+ }
+
+ gld->PipelineUsage.qwD3DFVF.QuadPart++;
+ return FALSE;
+
+/* // Force Mesa pipeline?
+ if (glb.dwTnL == GLDS_TNL_MESA) {
+ gld->PipelineUsage.dwMesa.QuadPart++;
+ return GLD_PIPELINE_MESA;
+ }
+
+ // Test for functionality not exposed in the D3D pathways
+ if ((ctx->Texture._GenFlags)) {
+ gld->PipelineUsage.dwMesa.QuadPart++;
+ return GLD_PIPELINE_MESA;
+ }
+
+ // Now decide if vertex shader can be used.
+ // If two sided lighting is enabled then we must either
+ // use Mesa TnL or the vertex shader
+ if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
+ if (gld->VStwosidelight.hShader && !ctx->Fog.Enabled) {
+ // Use Vertex Shader
+ gld->PipelineUsage.dwD3D2SVS.QuadPart++;
+ return GLD_PIPELINE_D3D_VS_TWOSIDE;
+ } else {
+ // Use Mesa TnL
+ gld->PipelineUsage.dwMesa.QuadPart++;
+ return GLD_PIPELINE_MESA;
+ }
+ }
+
+ // Must be D3D fixed-function pipeline
+ gld->PipelineUsage.dwD3DFVF.QuadPart++;
+ return GLD_PIPELINE_D3D_FVF;
+*/
+}
+
+//---------------------------------------------------------------------------
+
+void gld_update_state_DX7(
+ GLcontext *ctx,
+ GLuint new_state)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLD_pb_dx7 *gldPB;
+
+ if (!gld || !gld->pDev)
+ return;
+
+ _swsetup_InvalidateState( ctx, new_state );
+ _ac_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+
+ // SetupIndex will be used in the pipelines for choosing setup function
+ if ((ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE | DD_SEPARATE_SPECULAR)) ||
+ (ctx->Fog.Enabled))
+ {
+ if (ctx->_TriangleCaps & DD_FLATSHADE)
+ gld->iSetupFunc = GLD_SI_FLAT_EXTRAS;
+ else
+ gld->iSetupFunc = GLD_SI_SMOOTH_EXTRAS;
+ } else {
+ if (ctx->_TriangleCaps & DD_FLATSHADE)
+ gld->iSetupFunc = GLD_SI_FLAT; // Setup flat shade + texture
+ else
+ gld->iSetupFunc = GLD_SI_SMOOTH; // Setup smooth shade + texture
+ }
+
+ gld->bUseMesaTnL = _gldChooseInternalPipeline(ctx, gld);
+ if (gld->bUseMesaTnL) {
+ gldPB = &gld->PB2d;
+ // DX7 Does not implement D3DRS_SOFTWAREVERTEXPROCESSING
+// _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_SOFTWAREVERTEXPROCESSING, TRUE));
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_CLIPPING, FALSE));
+// _GLD_DX7_DEV(SetVertexShader(gld->pDev, gldPB->dwFVF));
+ } else {
+ gldPB = &gld->PB3d;
+ _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_CLIPPING, TRUE));
+// if (gld->TnLPipeline == GLD_PIPELINE_D3D_VS_TWOSIDE) {
+// _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_SOFTWAREVERTEXPROCESSING, !gld->VStwosidelight.bHardware));
+// _GLD_DX7_DEV(SetVertexShader(gld->pDev, gld->VStwosidelight.hShader));
+// } else {
+ // DX7 Does not implement D3DRS_SOFTWAREVERTEXPROCESSING
+// _GLD_DX7_DEV(SetRenderState(gld->pDev, D3DRENDERSTATE_SOFTWAREVERTEXPROCESSING, !gld->bHasHWTnL));
+// _GLD_DX7_DEV(SetVertexShader(gld->pDev, gldPB->dwFVF));
+// }
+ }
+
+#define _GLD_TEST_STATE(a) \
+ if (new_state & (a)) { \
+ gld##a(ctx); \
+ new_state &= ~(a); \
+ }
+
+#define _GLD_TEST_STATE_DX7(a) \
+ if (new_state & (a)) { \
+ gld##a##_DX7(ctx); \
+ new_state &= ~(a); \
+ }
+
+#define _GLD_IGNORE_STATE(a) new_state &= ~(a);
+
+// if (!gld->bUseMesaTnL) {
+ // Not required if Mesa is doing the TnL.
+ // Problem: If gld->bUseMesaTnL is TRUE when these are signaled,
+ // then we'll miss updating the D3D TnL pipeline.
+ // Therefore, don't test for gld->bUseMesaTnL
+ _GLD_TEST_STATE(_NEW_MODELVIEW);
+ _GLD_TEST_STATE(_NEW_PROJECTION);
+// }
+
+ _GLD_TEST_STATE_DX7(_NEW_TEXTURE); // extern, so guard with _DX7
+ _GLD_TEST_STATE(_NEW_COLOR);
+ _GLD_TEST_STATE(_NEW_DEPTH);
+ _GLD_TEST_STATE(_NEW_POLYGON);
+ _GLD_TEST_STATE(_NEW_STENCIL);
+ _GLD_TEST_STATE(_NEW_FOG);
+ _GLD_TEST_STATE(_NEW_LIGHT);
+ _GLD_TEST_STATE(_NEW_VIEWPORT);
+
+ _GLD_IGNORE_STATE(_NEW_TRANSFORM);
+
+
+// Stubs for future use.
+/* _GLD_TEST_STATE(_NEW_TEXTURE_MATRIX);
+ _GLD_TEST_STATE(_NEW_COLOR_MATRIX);
+ _GLD_TEST_STATE(_NEW_ACCUM);
+ _GLD_TEST_STATE(_NEW_EVAL);
+ _GLD_TEST_STATE(_NEW_HINT);
+ _GLD_TEST_STATE(_NEW_LINE);
+ _GLD_TEST_STATE(_NEW_PIXEL);
+ _GLD_TEST_STATE(_NEW_POINT);
+ _GLD_TEST_STATE(_NEW_POLYGONSTIPPLE);
+ _GLD_TEST_STATE(_NEW_SCISSOR);
+ _GLD_TEST_STATE(_NEW_PACKUNPACK);
+ _GLD_TEST_STATE(_NEW_ARRAY);
+ _GLD_TEST_STATE(_NEW_RENDERMODE);
+ _GLD_TEST_STATE(_NEW_BUFFERS);
+ _GLD_TEST_STATE(_NEW_MULTISAMPLE);
+*/
+
+// For debugging.
+#if 0
+#define _GLD_TEST_UNHANDLED_STATE(a) \
+ if (new_state & (a)) { \
+ gldLogMessage(GLDLOG_ERROR, "Unhandled " #a "\n"); \
+ }
+ _GLD_TEST_UNHANDLED_STATE(_NEW_TEXTURE_MATRIX);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_COLOR_MATRIX);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_ACCUM);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_EVAL);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_HINT);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_LINE);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_PIXEL);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_POINT);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_POLYGONSTIPPLE);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_SCISSOR);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_PACKUNPACK);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_ARRAY);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_RENDERMODE);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_BUFFERS);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_MULTISAMPLE);
+#undef _GLD_UNHANDLED_STATE
+#endif
+
+#undef _GLD_TEST_STATE
+}
+
+//---------------------------------------------------------------------------
+// Viewport
+//---------------------------------------------------------------------------
+
+void gld_Viewport_DX7(
+ GLcontext *ctx,
+ GLint x,
+ GLint y,
+ GLsizei w,
+ GLsizei h)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ D3DVIEWPORT7 d3dvp;
+
+ if (!gld || !gld->pDev)
+ return;
+
+ // This is a hack. When the app is minimized, Mesa passes
+ // w=1 and h=1 for viewport dimensions. Without this test
+ // we get a GPF in gld_wgl_resize_buffers().
+ if ((w==1) && (h==1))
+ return;
+
+ // Call ResizeBuffersMESA. This function will early-out
+ // if no resize is needed.
+ //ctx->Driver.ResizeBuffersMESA(ctx);
+ // Mesa 5: Changed parameters
+ ctx->Driver.ResizeBuffers(gldCtx->glBuffer);
+
+#if 0
+ ddlogPrintf(GLDLOG_SYSTEM, ">> Viewport x=%d y=%d w=%d h=%d", x,y,w,h);
+#endif
+
+ // ** D3D viewport must not be outside the render target surface **
+ // Sanity check the GL viewport dimensions
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (w > gldCtx->dwWidth) w = gldCtx->dwWidth;
+ if (h > gldCtx->dwHeight) h = gldCtx->dwHeight;
+ // Ditto for D3D viewport dimensions
+ if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x;
+ if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y;
+
+ d3dvp.dwX = x;
+ d3dvp.dwY = gldCtx->dwHeight - (y + h);
+ d3dvp.dwWidth = w;
+ d3dvp.dwHeight = h;
+ if (ctx->Viewport.Near <= ctx->Viewport.Far) {
+ d3dvp.dvMinZ = ctx->Viewport.Near;
+ d3dvp.dvMaxZ = ctx->Viewport.Far;
+ } else {
+ d3dvp.dvMinZ = ctx->Viewport.Far;
+ d3dvp.dvMaxZ = ctx->Viewport.Near;
+ }
+
+ // TODO: DEBUGGING
+// d3dvp.MinZ = 0.0f;
+// d3dvp.MaxZ = 1.0f;
+
+ _GLD_DX7_DEV(SetViewport(gld->pDev, &d3dvp));
+
+}
+
+//---------------------------------------------------------------------------
+
+extern BOOL dglWglResizeBuffers(GLcontext *ctx, BOOL bDefaultDriver);
+
+// Mesa 5: Parameter change
+void gldResizeBuffers_DX7(
+// GLcontext *ctx)
+ GLframebuffer *fb)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ dglWglResizeBuffers(ctx, TRUE);
+}
+
+//---------------------------------------------------------------------------
+#ifdef _DEBUG
+// This is only for debugging.
+// To use, plug into ctx->Driver.Enable pointer below.
+void gld_Enable(
+ GLcontext *ctx,
+ GLenum e,
+ GLboolean b)
+{
+ char buf[1024];
+ sprintf(buf, "Enable: %s (%s)\n", _mesa_lookup_enum_by_nr(e), b?"TRUE":"FALSE");
+ ddlogMessage(DDLOG_SYSTEM, buf);
+}
+#endif
+//---------------------------------------------------------------------------
+// Driver pointer setup
+//---------------------------------------------------------------------------
+
+extern const GLubyte* _gldGetStringGeneric(GLcontext*, GLenum);
+
+void gldSetupDriverPointers_DX7(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ // Mandatory functions
+ ctx->Driver.GetString = _gldGetStringGeneric;
+ ctx->Driver.UpdateState = gld_update_state_DX7;
+ ctx->Driver.Clear = gld_Clear_DX7;
+ ctx->Driver.DrawBuffer = gld_set_draw_buffer_DX7;
+ ctx->Driver.GetBufferSize = gld_buffer_size_DX7;
+ ctx->Driver.Finish = gld_Finish_DX7;
+ ctx->Driver.Flush = gld_Flush_DX7;
+ ctx->Driver.Error = gld_Error_DX7;
+
+ // Hardware accumulation buffer
+ ctx->Driver.Accum = NULL; // TODO: gld_Accum;
+
+ // Bitmap functions
+ ctx->Driver.CopyPixels = gld_CopyPixels_DX7;
+ ctx->Driver.DrawPixels = gld_DrawPixels_DX7;
+ ctx->Driver.ReadPixels = gld_ReadPixels_DX7;
+ ctx->Driver.Bitmap = gld_Bitmap_DX7;
+
+ // Buffer resize
+ ctx->Driver.ResizeBuffers = gldResizeBuffers_DX7;
+
+ // Texture image functions
+ ctx->Driver.ChooseTextureFormat = gld_ChooseTextureFormat_DX7;
+ ctx->Driver.TexImage1D = gld_TexImage1D_DX7;
+ ctx->Driver.TexImage2D = gld_TexImage2D_DX7;
+ ctx->Driver.TexImage3D = _mesa_store_teximage3d;
+ ctx->Driver.TexSubImage1D = gld_TexSubImage1D_DX7;
+ ctx->Driver.TexSubImage2D = gld_TexSubImage2D_DX7;
+ ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
+
+ ctx->Driver.CopyTexImage1D = gldCopyTexImage1D_DX7; //NULL;
+ ctx->Driver.CopyTexImage2D = gldCopyTexImage2D_DX7; //NULL;
+ ctx->Driver.CopyTexSubImage1D = gldCopyTexSubImage1D_DX7; //NULL;
+ ctx->Driver.CopyTexSubImage2D = gldCopyTexSubImage2D_DX7; //NULL;
+ ctx->Driver.CopyTexSubImage3D = gldCopyTexSubImage3D_DX7;
+ ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
+
+ // Texture object functions
+ ctx->Driver.BindTexture = NULL;
+ ctx->Driver.CreateTexture = NULL; // Not yet implemented by Mesa!;
+ ctx->Driver.DeleteTexture = gld_DeleteTexture_DX7;
+ ctx->Driver.PrioritizeTexture = NULL;
+
+ // Imaging functionality
+ ctx->Driver.CopyColorTable = NULL;
+ ctx->Driver.CopyColorSubTable = NULL;
+ ctx->Driver.CopyConvolutionFilter1D = NULL;
+ ctx->Driver.CopyConvolutionFilter2D = NULL;
+
+ // State changing functions
+ ctx->Driver.AlphaFunc = NULL; //gld_AlphaFunc;
+ ctx->Driver.BlendFunc = NULL; //gld_BlendFunc;
+ ctx->Driver.ClearColor = NULL; //gld_ClearColor;
+ ctx->Driver.ClearDepth = NULL; //gld_ClearDepth;
+ ctx->Driver.ClearStencil = NULL; //gld_ClearStencil;
+ ctx->Driver.ColorMask = NULL; //gld_ColorMask;
+ ctx->Driver.CullFace = NULL; //gld_CullFace;
+ ctx->Driver.ClipPlane = NULL; //gld_ClipPlane;
+ ctx->Driver.FrontFace = NULL; //gld_FrontFace;
+ ctx->Driver.DepthFunc = NULL; //gld_DepthFunc;
+ ctx->Driver.DepthMask = NULL; //gld_DepthMask;
+ ctx->Driver.DepthRange = NULL;
+ ctx->Driver.Enable = NULL; //gld_Enable;
+ ctx->Driver.Fogfv = NULL; //gld_Fogfv;
+ ctx->Driver.Hint = NULL; //gld_Hint;
+ ctx->Driver.Lightfv = NULL; //gld_Lightfv;
+ ctx->Driver.LightModelfv = NULL; //gld_LightModelfv;
+ ctx->Driver.LineStipple = NULL; //gld_LineStipple;
+ ctx->Driver.LineWidth = NULL; //gld_LineWidth;
+ ctx->Driver.LogicOpcode = NULL; //gld_LogicOpcode;
+ ctx->Driver.PointParameterfv = NULL; //gld_PointParameterfv;
+ ctx->Driver.PointSize = NULL; //gld_PointSize;
+ ctx->Driver.PolygonMode = NULL; //gld_PolygonMode;
+ ctx->Driver.PolygonOffset = NULL; //gld_PolygonOffset;
+ ctx->Driver.PolygonStipple = NULL; //gld_PolygonStipple;
+ ctx->Driver.RenderMode = NULL; //gld_RenderMode;
+ ctx->Driver.Scissor = NULL; //gld_Scissor;
+ ctx->Driver.ShadeModel = NULL; //gld_ShadeModel;
+ ctx->Driver.StencilFunc = NULL; //gld_StencilFunc;
+ ctx->Driver.StencilMask = NULL; //gld_StencilMask;
+ ctx->Driver.StencilOp = NULL; //gld_StencilOp;
+ ctx->Driver.TexGen = NULL; //gld_TexGen;
+ ctx->Driver.TexEnv = NULL;
+ ctx->Driver.TexParameter = NULL;
+ ctx->Driver.TextureMatrix = NULL; //gld_TextureMatrix;
+ ctx->Driver.Viewport = gld_Viewport_DX7;
+
+ _swsetup_Wakeup(ctx);
+
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+ tnl->Driver.Render.ResetLineStipple = gld_ResetLineStipple_DX7;
+ tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
+ tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine;
+
+ // Hook into glFrustum() and glOrtho()
+// ctx->Exec->Frustum = gldFrustumHook_DX7;
+// ctx->Exec->Ortho = gldOrthoHook_DX7;
+
+}
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_dx7.h b/src/mesa/drivers/windows/gldirect/dx7/gld_dx7.h
new file mode 100644
index 0000000000..b5a491e41b
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_dx7.h
@@ -0,0 +1,292 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GLDirect Direct3D 7.0a header file
+*
+****************************************************************************/
+
+#ifndef _GLD_DX7_H
+#define _GLD_DX7_H
+
+//---------------------------------------------------------------------------
+// Windows includes
+//---------------------------------------------------------------------------
+
+#define DIRECTDRAW_VERSION 0x0700
+#define DIRECT3D_VERSION 0x0700
+#include <d3d.h>
+#include <d3dx.h>
+
+// Typedef for obtaining function from d3d7.dll
+//typedef IDirect3D7* (WINAPI *FNDIRECT3DCREATE7) (UINT);
+
+
+//---------------------------------------------------------------------------
+// Defines
+//---------------------------------------------------------------------------
+
+#ifdef _DEBUG
+// Debug build tests the return value of D3D calls
+#define _GLD_TEST_HRESULT(h) \
+{ \
+ HRESULT _hr = (h); \
+ if (FAILED(_hr)) { \
+ gldLogError(GLDLOG_ERROR, #h, _hr); \
+ } \
+}
+#define _GLD_DX7(func) _GLD_TEST_HRESULT(IDirect3D7_##func##)
+#define _GLD_DX7_DEV(func) _GLD_TEST_HRESULT(IDirect3DDevice7_##func##)
+#define _GLD_DX7_VB(func) _GLD_TEST_HRESULT(IDirect3DVertexBuffer7_##func##)
+#define _GLD_DX7_TEX(func) _GLD_TEST_HRESULT(IDirectDrawSurface7_##func##)
+#else
+#define _GLD_DX7(func) IDirect3D7_##func
+#define _GLD_DX7_DEV(func) IDirect3DDevice7_##func
+#define _GLD_DX7_VB(func) IDirect3DVertexBuffer7_##func
+#define _GLD_DX7_TEX(func) IDirectDrawSurface7_##func
+#endif
+
+#define SAFE_RELEASE(p) \
+{ \
+ if (p) { \
+ (p)->lpVtbl->Release(p); \
+ (p) = NULL; \
+ } \
+}
+
+#define SAFE_RELEASE_VB7(p) \
+{ \
+ if (p) { \
+ IDirect3DVertexBuffer7_Release((p)); \
+ (p) = NULL; \
+ } \
+}
+
+#define SAFE_RELEASE_SURFACE7(p) \
+{ \
+ if (p) { \
+ IDirectDrawSurface7_Release((p)); \
+ (p) = NULL; \
+ } \
+}
+
+// Emulate some DX8 defines
+#define D3DCOLOR_ARGB(a,r,g,b) ((D3DCOLOR)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff)))
+#define D3DCOLOR_RGBA(r,g,b,a) D3DCOLOR_ARGB(a,r,g,b)
+#define D3DCOLOR_COLORVALUE(r,g,b,a) D3DCOLOR_RGBA((DWORD)((r)*255.f),(DWORD)((g)*255.f),(DWORD)((b)*255.f),(DWORD)((a)*255.f))
+
+
+// Setup index.
+enum {
+ GLD_SI_FLAT = 0,
+ GLD_SI_SMOOTH = 1,
+ GLD_SI_FLAT_EXTRAS = 2,
+ GLD_SI_SMOOTH_EXTRAS = 3,
+};
+
+//---------------------------------------------------------------------------
+// Vertex definitions for Fixed-Function pipeline
+//---------------------------------------------------------------------------
+
+//
+// NOTE: If the number of texture units is altered then most of
+// the texture code will need to be revised.
+//
+
+#define GLD_MAX_TEXTURE_UNITS_DX7 2
+
+//
+// 2D vertex transformed by Mesa
+//
+#define GLD_FVF_2D_VERTEX ( D3DFVF_XYZRHW | \
+ D3DFVF_DIFFUSE | \
+ D3DFVF_SPECULAR | \
+ D3DFVF_TEX2)
+typedef struct {
+ FLOAT x, y; // 2D raster coords
+ FLOAT sz; // Screen Z (depth)
+ FLOAT rhw; // Reciprocal homogenous W
+ DWORD diffuse; // Diffuse colour
+ DWORD specular; // For separate-specular support
+ FLOAT t0_u, t0_v; // 1st set of texture coords
+ FLOAT t1_u, t1_v; // 2nd set of texture coords
+} GLD_2D_VERTEX;
+
+
+//
+// 3D vertex transformed by Direct3D
+//
+#define GLD_FVF_3D_VERTEX ( D3DFVF_XYZ | \
+ D3DFVF_DIFFUSE | \
+ D3DFVF_TEX2)
+
+typedef struct {
+ D3DXVECTOR3 Position; // XYZ Vector in object space
+ D3DCOLOR Diffuse; // Diffuse colour
+ D3DXVECTOR2 TexUnit0; // Texture unit 0
+ D3DXVECTOR2 TexUnit1; // Texture unit 1
+} GLD_3D_VERTEX;
+
+//---------------------------------------------------------------------------
+// Structs
+//---------------------------------------------------------------------------
+
+// This keeps a count of how many times we choose each individual internal
+// pathway. Useful for seeing if a certain pathway was ever used by an app, and
+// how much each pathway is biased.
+// Zero the members at context creation and dump stats at context deletion.
+typedef struct {
+ // Note: DWORD is probably too small
+ ULARGE_INTEGER qwMesa; // Mesa TnL pipeline
+ ULARGE_INTEGER qwD3DFVF; // Direct3D Fixed-Function pipeline
+} GLD_pipeline_usage;
+
+// GLDirect Primitive Buffer (points, lines, triangles and quads)
+typedef struct {
+ // Data for IDirect3D7::CreateVertexBuffer()
+ DWORD dwStride; // Stride of vertex
+ DWORD dwCreateFlags; // Create flags
+ DWORD dwFVF; // Direct3D Flexible Vertex Format
+
+ IDirect3DVertexBuffer7 *pVB; // Holds points, lines, tris and quads.
+
+ // Point list is assumed to be at start of buffer
+ DWORD iFirstLine; // Index of start of line list
+ DWORD iFirstTriangle; // Index of start of triangle list
+
+ BYTE *pPoints; // Pointer to next free point
+ BYTE *pLines; // Pointer to next free line
+ BYTE *pTriangles; // Pointer to next free triangle
+
+ DWORD nPoints; // Number of points ready to render
+ DWORD nLines; // Number of lines ready to render
+ DWORD nTriangles; // Number of triangles ready to render
+} GLD_pb_dx7;
+
+// GLDirect DX7 driver data
+typedef struct {
+ // GLDirect vars
+ BOOL bDoublebuffer; // Doublebuffer (otherwise single-buffered)
+ BOOL bDepthStencil; // Depth buffer needed (stencil optional)
+ D3DX_SURFACEFORMAT RenderFormat; // Format of back/front buffer
+ D3DX_SURFACEFORMAT DepthFormat; // Format of depth/stencil
+
+ // Direct3D vars
+ DDCAPS ddCaps;
+ D3DDEVICEDESC7 d3dCaps;
+ BOOL bHasHWTnL; // Device has Hardware Transform/Light?
+ ID3DXContext *pD3DXContext; // Base D3DX context
+ IDirectDraw7 *pDD; // DirectDraw7 interface
+ IDirect3D7 *pD3D; // Base Direct3D7 interface
+ IDirect3DDevice7 *pDev; // Direct3D7 Device interface
+ GLD_pb_dx7 PB2d; // Vertices transformed by Mesa
+ GLD_pb_dx7 PB3d; // Vertices transformed by Direct3D
+ D3DPRIMITIVETYPE d3dpt; // Current Direct3D primitive type
+ D3DMATRIX matProjection; // Projection matrix for D3D TnL
+ D3DMATRIX matModelView; // Model/View matrix for D3D TnL
+ int iSetupFunc; // Which setup functions to use
+ BOOL bUseMesaTnL; // Whether to use Mesa or D3D for TnL
+
+ GLD_pipeline_usage PipelineUsage;
+} GLD_driver_dx7;
+
+#define GLD_GET_DX7_DRIVER(c) (GLD_driver_dx7*)(c)->glPriv
+
+//---------------------------------------------------------------------------
+// Function prototypes
+//---------------------------------------------------------------------------
+
+PROC gldGetProcAddress_DX7(LPCSTR a);
+void gldEnableExtensions_DX7(GLcontext *ctx);
+void gldInstallPipeline_DX7(GLcontext *ctx);
+void gldSetupDriverPointers_DX7(GLcontext *ctx);
+void gldResizeBuffers_DX7(GLframebuffer *fb);
+
+
+// Texture functions
+
+void gldCopyTexImage1D_DX7(GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
+void gldCopyTexImage2D_DX7(GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+void gldCopyTexSubImage1D_DX7(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width );
+void gldCopyTexSubImage2D_DX7(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height );
+void gldCopyTexSubImage3D_DX7(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height );
+
+void gld_NEW_TEXTURE_DX7(GLcontext *ctx);
+void gld_DrawPixels_DX7(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels);
+void gld_ReadPixels_DX7(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, GLvoid *dest);
+void gld_CopyPixels_DX7(GLcontext *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLint dstx, GLint dsty, GLenum type);
+void gld_Bitmap_DX7(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap);
+const struct gl_texture_format* gld_ChooseTextureFormat_DX7(GLcontext *ctx, GLint internalFormat, GLenum srcFormat, GLenum srcType);
+void gld_TexImage2D_DX7(GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint height, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *tObj, struct gl_texture_image *texImage);
+void gld_TexImage1D_DX7(GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage );
+void gld_TexSubImage2D_DX7( GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage );
+void gld_TexSubImage1D_DX7(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage);
+void gld_DeleteTexture_DX7(GLcontext *ctx, struct gl_texture_object *tObj);
+void gld_ResetLineStipple_DX7(GLcontext *ctx);
+
+// 2D primitive functions
+
+void gld_Points2D_DX7(GLcontext *ctx, GLuint first, GLuint last);
+
+void gld_Line2DFlat_DX7(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Line2DSmooth_DX7(GLcontext *ctx, GLuint v0, GLuint v1);
+
+void gld_Triangle2DFlat_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DSmooth_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DFlatExtras_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DSmoothExtras_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+
+void gld_Quad2DFlat_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DSmooth_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DFlatExtras_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DSmoothExtras_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+
+// 3D primitive functions
+
+void gld_Points3D_DX7(GLcontext *ctx, GLuint first, GLuint last);
+void gld_Line3DFlat_DX7(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Triangle3DFlat_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Quad3DFlat_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Line3DSmooth_DX7(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Triangle3DSmooth_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Quad3DSmooth_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+
+// Primitive functions for Two-sided-lighting Vertex Shader
+
+void gld_Points2DTwoside_DX7(GLcontext *ctx, GLuint first, GLuint last);
+void gld_Line2DFlatTwoside_DX7(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Line2DSmoothTwoside_DX7(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Triangle2DFlatTwoside_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DSmoothTwoside_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Quad2DFlatTwoside_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DSmoothTwoside_DX7(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+
+#endif
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_dxerr7.h b/src/mesa/drivers/windows/gldirect/dx7/gld_dxerr7.h
new file mode 100644
index 0000000000..df6fceb43e
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_dxerr7.h
@@ -0,0 +1,77 @@
+/*==========================================================================;
+ *
+ *
+ * File: dxerr8.h
+ * Content: DirectX Error Library Include File
+ *
+ ****************************************************************************/
+
+#ifndef _GLD_DXERR7_H_
+#define _GLD_DXERR7_H_
+
+
+#include <d3d.h>
+
+//
+// DXGetErrorString8
+//
+// Desc: Converts an DirectX HRESULT to a string
+//
+// Args: HRESULT hr Can be any error code from
+// DPLAY D3D8 D3DX8 DMUSIC DSOUND
+//
+// Return: Converted string
+//
+const char* __stdcall DXGetErrorString8A(HRESULT hr);
+const WCHAR* __stdcall DXGetErrorString8W(HRESULT hr);
+
+#ifdef UNICODE
+ #define DXGetErrorString8 DXGetErrorString8W
+#else
+ #define DXGetErrorString8 DXGetErrorString8A
+#endif
+
+
+//
+// DXTrace
+//
+// Desc: Outputs a formatted error message to the debug stream
+//
+// Args: CHAR* strFile The current file, typically passed in using the
+// __FILE__ macro.
+// DWORD dwLine The current line number, typically passed in using the
+// __LINE__ macro.
+// HRESULT hr An HRESULT that will be traced to the debug stream.
+// CHAR* strMsg A string that will be traced to the debug stream (may be NULL)
+// BOOL bPopMsgBox If TRUE, then a message box will popup also containing the passed info.
+//
+// Return: The hr that was passed in.
+//
+//HRESULT __stdcall DXTraceA( char* strFile, DWORD dwLine, HRESULT hr, char* strMsg, BOOL bPopMsgBox = FALSE );
+//HRESULT __stdcall DXTraceW( char* strFile, DWORD dwLine, HRESULT hr, WCHAR* strMsg, BOOL bPopMsgBox = FALSE );
+HRESULT __stdcall DXTraceA( char* strFile, DWORD dwLine, HRESULT hr, char* strMsg, BOOL bPopMsgBox);
+HRESULT __stdcall DXTraceW( char* strFile, DWORD dwLine, HRESULT hr, WCHAR* strMsg, BOOL bPopMsgBox);
+
+#ifdef UNICODE
+ #define DXTrace DXTraceW
+#else
+ #define DXTrace DXTraceA
+#endif
+
+
+//
+// Helper macros
+//
+#if defined(DEBUG) | defined(_DEBUG)
+ #define DXTRACE_MSG(str) DXTrace( __FILE__, (DWORD)__LINE__, 0, str, FALSE )
+ #define DXTRACE_ERR(str,hr) DXTrace( __FILE__, (DWORD)__LINE__, hr, str, TRUE )
+ #define DXTRACE_ERR_NOMSGBOX(str,hr) DXTrace( __FILE__, (DWORD)__LINE__, hr, str, FALSE )
+#else
+ #define DXTRACE_MSG(str) (0L)
+ #define DXTRACE_ERR(str,hr) (hr)
+ #define DXTRACE_ERR_NOMSGBOX(str,hr) (hr)
+#endif
+
+
+#endif
+
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_ext_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_ext_dx7.c
new file mode 100644
index 0000000000..ac99211089
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_ext_dx7.c
@@ -0,0 +1,346 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GL extensions
+*
+****************************************************************************/
+
+//#include "../GLDirect.h"
+//#include "../gld_log.h"
+//#include "../gld_settings.h"
+
+#include <windows.h>
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glext.h>
+
+//#include "ddlog.h"
+//#include "gld_dx8.h"
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "array_cache/acache.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast_setup/ss_context.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+#include "dglcontext.h"
+#include "extensions.h"
+
+// For some reason this is not defined in an above header...
+extern void _mesa_enable_imaging_extensions(GLcontext *ctx);
+
+//---------------------------------------------------------------------------
+// Hack for the SGIS_multitexture extension that was removed from Mesa
+// NOTE: SGIS_multitexture enums also clash with GL_SGIX_async_pixel
+
+ // NOTE: Quake2 ran *slower* with this enabled, so I've
+ // disabled it for now.
+ // To enable, uncomment:
+ // _mesa_add_extension(ctx, GL_TRUE, szGL_SGIS_multitexture, 0);
+
+//---------------------------------------------------------------------------
+
+enum {
+ /* Quake2 GL_SGIS_multitexture */
+ GL_SELECTED_TEXTURE_SGIS = 0x835B,
+ GL_SELECTED_TEXTURE_COORD_SET_SGIS = 0x835C,
+ GL_MAX_TEXTURES_SGIS = 0x835D,
+ GL_TEXTURE0_SGIS = 0x835E,
+ GL_TEXTURE1_SGIS = 0x835F,
+ GL_TEXTURE2_SGIS = 0x8360,
+ GL_TEXTURE3_SGIS = 0x8361,
+ GL_TEXTURE_COORD_SET_SOURCE_SGIS = 0x8363,
+};
+
+//---------------------------------------------------------------------------
+
+void APIENTRY gldSelectTextureSGIS(
+ GLenum target)
+{
+ GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS);
+ glActiveTextureARB(ARB_target);
+}
+
+//---------------------------------------------------------------------------
+
+void APIENTRY gldMTexCoord2fSGIS(
+ GLenum target,
+ GLfloat s,
+ GLfloat t)
+{
+ GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS);
+ glMultiTexCoord2fARB(ARB_target, s, t);
+}
+
+//---------------------------------------------------------------------------
+
+void APIENTRY gldMTexCoord2fvSGIS(
+ GLenum target,
+ const GLfloat *v)
+{
+ GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS);
+ glMultiTexCoord2fvARB(ARB_target, v);
+}
+
+//---------------------------------------------------------------------------
+// Extensions
+//---------------------------------------------------------------------------
+
+typedef struct {
+ PROC proc;
+ char *name;
+} GLD_extension;
+
+GLD_extension GLD_extList[] = {
+#ifdef GL_EXT_polygon_offset
+ { (PROC)glPolygonOffsetEXT, "glPolygonOffsetEXT" },
+#endif
+ { (PROC)glBlendEquationEXT, "glBlendEquationEXT" },
+ { (PROC)glBlendColorEXT, "glBlendColorExt" },
+ { (PROC)glVertexPointerEXT, "glVertexPointerEXT" },
+ { (PROC)glNormalPointerEXT, "glNormalPointerEXT" },
+ { (PROC)glColorPointerEXT, "glColorPointerEXT" },
+ { (PROC)glIndexPointerEXT, "glIndexPointerEXT" },
+ { (PROC)glTexCoordPointerEXT, "glTexCoordPointer" },
+ { (PROC)glEdgeFlagPointerEXT, "glEdgeFlagPointerEXT" },
+ { (PROC)glGetPointervEXT, "glGetPointervEXT" },
+ { (PROC)glArrayElementEXT, "glArrayElementEXT" },
+ { (PROC)glDrawArraysEXT, "glDrawArrayEXT" },
+ { (PROC)glAreTexturesResidentEXT, "glAreTexturesResidentEXT" },
+ { (PROC)glBindTextureEXT, "glBindTextureEXT" },
+ { (PROC)glDeleteTexturesEXT, "glDeleteTexturesEXT" },
+ { (PROC)glGenTexturesEXT, "glGenTexturesEXT" },
+ { (PROC)glIsTextureEXT, "glIsTextureEXT" },
+ { (PROC)glPrioritizeTexturesEXT, "glPrioritizeTexturesEXT" },
+ { (PROC)glCopyTexSubImage3DEXT, "glCopyTexSubImage3DEXT" },
+ { (PROC)glTexImage3DEXT, "glTexImage3DEXT" },
+ { (PROC)glTexSubImage3DEXT, "glTexSubImage3DEXT" },
+ { (PROC)glPointParameterfEXT, "glPointParameterfEXT" },
+ { (PROC)glPointParameterfvEXT, "glPointParameterfvEXT" },
+
+ { (PROC)glLockArraysEXT, "glLockArraysEXT" },
+ { (PROC)glUnlockArraysEXT, "glUnlockArraysEXT" },
+ { NULL, "\0" }
+};
+
+GLD_extension GLD_multitexList[] = {
+/*
+ { (PROC)glMultiTexCoord1dSGIS, "glMTexCoord1dSGIS" },
+ { (PROC)glMultiTexCoord1dvSGIS, "glMTexCoord1dvSGIS" },
+ { (PROC)glMultiTexCoord1fSGIS, "glMTexCoord1fSGIS" },
+ { (PROC)glMultiTexCoord1fvSGIS, "glMTexCoord1fvSGIS" },
+ { (PROC)glMultiTexCoord1iSGIS, "glMTexCoord1iSGIS" },
+ { (PROC)glMultiTexCoord1ivSGIS, "glMTexCoord1ivSGIS" },
+ { (PROC)glMultiTexCoord1sSGIS, "glMTexCoord1sSGIS" },
+ { (PROC)glMultiTexCoord1svSGIS, "glMTexCoord1svSGIS" },
+ { (PROC)glMultiTexCoord2dSGIS, "glMTexCoord2dSGIS" },
+ { (PROC)glMultiTexCoord2dvSGIS, "glMTexCoord2dvSGIS" },
+ { (PROC)glMultiTexCoord2fSGIS, "glMTexCoord2fSGIS" },
+ { (PROC)glMultiTexCoord2fvSGIS, "glMTexCoord2fvSGIS" },
+ { (PROC)glMultiTexCoord2iSGIS, "glMTexCoord2iSGIS" },
+ { (PROC)glMultiTexCoord2ivSGIS, "glMTexCoord2ivSGIS" },
+ { (PROC)glMultiTexCoord2sSGIS, "glMTexCoord2sSGIS" },
+ { (PROC)glMultiTexCoord2svSGIS, "glMTexCoord2svSGIS" },
+ { (PROC)glMultiTexCoord3dSGIS, "glMTexCoord3dSGIS" },
+ { (PROC)glMultiTexCoord3dvSGIS, "glMTexCoord3dvSGIS" },
+ { (PROC)glMultiTexCoord3fSGIS, "glMTexCoord3fSGIS" },
+ { (PROC)glMultiTexCoord3fvSGIS, "glMTexCoord3fvSGIS" },
+ { (PROC)glMultiTexCoord3iSGIS, "glMTexCoord3iSGIS" },
+ { (PROC)glMultiTexCoord3ivSGIS, "glMTexCoord3ivSGIS" },
+ { (PROC)glMultiTexCoord3sSGIS, "glMTexCoord3sSGIS" },
+ { (PROC)glMultiTexCoord3svSGIS, "glMTexCoord3svSGIS" },
+ { (PROC)glMultiTexCoord4dSGIS, "glMTexCoord4dSGIS" },
+ { (PROC)glMultiTexCoord4dvSGIS, "glMTexCoord4dvSGIS" },
+ { (PROC)glMultiTexCoord4fSGIS, "glMTexCoord4fSGIS" },
+ { (PROC)glMultiTexCoord4fvSGIS, "glMTexCoord4fvSGIS" },
+ { (PROC)glMultiTexCoord4iSGIS, "glMTexCoord4iSGIS" },
+ { (PROC)glMultiTexCoord4ivSGIS, "glMTexCoord4ivSGIS" },
+ { (PROC)glMultiTexCoord4sSGIS, "glMTexCoord4sSGIS" },
+ { (PROC)glMultiTexCoord4svSGIS, "glMTexCoord4svSGIS" },
+ { (PROC)glMultiTexCoordPointerSGIS, "glMTexCoordPointerSGIS" },
+ { (PROC)glSelectTextureSGIS, "glSelectTextureSGIS" },
+ { (PROC)glSelectTextureCoordSetSGIS, "glSelectTextureCoordSetSGIS" },
+*/
+ { (PROC)glActiveTextureARB, "glActiveTextureARB" },
+ { (PROC)glClientActiveTextureARB, "glClientActiveTextureARB" },
+ { (PROC)glMultiTexCoord1dARB, "glMultiTexCoord1dARB" },
+ { (PROC)glMultiTexCoord1dvARB, "glMultiTexCoord1dvARB" },
+ { (PROC)glMultiTexCoord1fARB, "glMultiTexCoord1fARB" },
+ { (PROC)glMultiTexCoord1fvARB, "glMultiTexCoord1fvARB" },
+ { (PROC)glMultiTexCoord1iARB, "glMultiTexCoord1iARB" },
+ { (PROC)glMultiTexCoord1ivARB, "glMultiTexCoord1ivARB" },
+ { (PROC)glMultiTexCoord1sARB, "glMultiTexCoord1sARB" },
+ { (PROC)glMultiTexCoord1svARB, "glMultiTexCoord1svARB" },
+ { (PROC)glMultiTexCoord2dARB, "glMultiTexCoord2dARB" },
+ { (PROC)glMultiTexCoord2dvARB, "glMultiTexCoord2dvARB" },
+ { (PROC)glMultiTexCoord2fARB, "glMultiTexCoord2fARB" },
+ { (PROC)glMultiTexCoord2fvARB, "glMultiTexCoord2fvARB" },
+ { (PROC)glMultiTexCoord2iARB, "glMultiTexCoord2iARB" },
+ { (PROC)glMultiTexCoord2ivARB, "glMultiTexCoord2ivARB" },
+ { (PROC)glMultiTexCoord2sARB, "glMultiTexCoord2sARB" },
+ { (PROC)glMultiTexCoord2svARB, "glMultiTexCoord2svARB" },
+ { (PROC)glMultiTexCoord3dARB, "glMultiTexCoord3dARB" },
+ { (PROC)glMultiTexCoord3dvARB, "glMultiTexCoord3dvARB" },
+ { (PROC)glMultiTexCoord3fARB, "glMultiTexCoord3fARB" },
+ { (PROC)glMultiTexCoord3fvARB, "glMultiTexCoord3fvARB" },
+ { (PROC)glMultiTexCoord3iARB, "glMultiTexCoord3iARB" },
+ { (PROC)glMultiTexCoord3ivARB, "glMultiTexCoord3ivARB" },
+ { (PROC)glMultiTexCoord3sARB, "glMultiTexCoord3sARB" },
+ { (PROC)glMultiTexCoord3svARB, "glMultiTexCoord3svARB" },
+ { (PROC)glMultiTexCoord4dARB, "glMultiTexCoord4dARB" },
+ { (PROC)glMultiTexCoord4dvARB, "glMultiTexCoord4dvARB" },
+ { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4fARB" },
+ { (PROC)glMultiTexCoord4fvARB, "glMultiTexCoord4fvARB" },
+ { (PROC)glMultiTexCoord4iARB, "glMultiTexCoord4iARB" },
+ { (PROC)glMultiTexCoord4ivARB, "glMultiTexCoord4ivARB" },
+ { (PROC)glMultiTexCoord4sARB, "glMultiTexCoord4sARB" },
+ { (PROC)glMultiTexCoord4svARB, "glMultiTexCoord4svARB" },
+
+ // Descent3 doesn't use correct string, hence this hack
+ { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4f" },
+
+ // Quake2 SGIS multitexture
+ { (PROC)gldSelectTextureSGIS, "glSelectTextureSGIS" },
+ { (PROC)gldMTexCoord2fSGIS, "glMTexCoord2fSGIS" },
+ { (PROC)gldMTexCoord2fvSGIS, "glMTexCoord2fvSGIS" },
+
+ { NULL, "\0" }
+};
+
+//---------------------------------------------------------------------------
+
+PROC gldGetProcAddress_DX(
+ LPCSTR a)
+{
+ int i;
+ PROC proc = NULL;
+
+ for (i=0; GLD_extList[i].proc; i++) {
+ if (!strcmp(a, GLD_extList[i].name)) {
+ proc = GLD_extList[i].proc;
+ break;
+ }
+ }
+
+ if (glb.bMultitexture) {
+ for (i=0; GLD_multitexList[i].proc; i++) {
+ if (!strcmp(a, GLD_multitexList[i].name)) {
+ proc = GLD_multitexList[i].proc;
+ break;
+ }
+ }
+ }
+
+ gldLogPrintf(GLDLOG_INFO, "GetProcAddress: %s (%s)", a, proc ? "OK" : "Failed");
+
+ return proc;
+}
+
+//---------------------------------------------------------------------------
+
+void gldEnableExtensions_DX7(
+ GLcontext *ctx)
+{
+ GLuint i;
+
+ // Mesa enables some extensions by default.
+ // This table decides which ones we want to switch off again.
+
+ // NOTE: GL_EXT_compiled_vertex_array appears broken.
+
+ const char *gld_disable_extensions[] = {
+// "GL_ARB_transpose_matrix",
+// "GL_EXT_compiled_vertex_array",
+// "GL_EXT_polygon_offset",
+// "GL_EXT_rescale_normal",
+ "GL_EXT_texture3D",
+// "GL_NV_texgen_reflection",
+ "GL_EXT_abgr",
+ "GL_EXT_bgra",
+ NULL
+ };
+
+ const char *gld_multitex_extensions[] = {
+ "GL_ARB_multitexture", // Quake 3
+ NULL
+ };
+
+ // Quake 2 engines
+ const char *szGL_SGIS_multitexture = "GL_SGIS_multitexture";
+
+ const char *gld_enable_extensions[] = {
+ "GL_EXT_texture_env_add", // Quake 3
+ "GL_ARB_texture_env_add", // Quake 3
+ NULL
+ };
+
+ for (i=0; gld_disable_extensions[i]; i++) {
+ _mesa_disable_extension(ctx, gld_disable_extensions[i]);
+ }
+
+ for (i=0; gld_enable_extensions[i]; i++) {
+ _mesa_enable_extension(ctx, gld_enable_extensions[i]);
+ }
+
+ if (glb.bMultitexture) {
+ for (i=0; gld_multitex_extensions[i]; i++) {
+ _mesa_enable_extension(ctx, gld_multitex_extensions[i]);
+ }
+
+ // GL_SGIS_multitexture
+ // NOTE: Quake2 ran *slower* with this enabled, so I've
+ // disabled it for now.
+ // Fair bit slower on GeForce256,
+ // Much slower on 3dfx Voodoo5 5500.
+// _mesa_add_extension(ctx, GL_TRUE, szGL_SGIS_multitexture, 0);
+
+ }
+
+ _mesa_enable_imaging_extensions(ctx);
+ _mesa_enable_1_3_extensions(ctx);
+ _mesa_enable_1_4_extensions(ctx);
+}
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_pipeline_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_pipeline_dx7.c
new file mode 100644
index 0000000000..885fe7abba
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_pipeline_dx7.c
@@ -0,0 +1,77 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Mesa transformation pipeline with GLDirect fastpath
+*
+****************************************************************************/
+
+//#include "../GLDirect.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx7.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+//---------------------------------------------------------------------------
+
+extern struct gl_pipeline_stage _gld_d3d_render_stage;
+extern struct gl_pipeline_stage _gld_mesa_render_stage;
+
+static const struct gl_pipeline_stage *gld_pipeline[] = {
+ &_gld_d3d_render_stage, // Direct3D TnL
+ &_tnl_vertex_transform_stage,
+ &_tnl_normal_transform_stage,
+ &_tnl_lighting_stage,
+ &_tnl_fog_coordinate_stage, /* TODO: Omit fog stage. ??? */
+ &_tnl_texgen_stage,
+ &_tnl_texture_transform_stage,
+ &_tnl_point_attenuation_stage,
+ &_gld_mesa_render_stage, // Mesa TnL, D3D rendering
+ 0,
+};
+
+//---------------------------------------------------------------------------
+
+void gldInstallPipeline_DX7(
+ GLcontext *ctx)
+{
+ // Remove any existing pipeline stages,
+ // then install GLDirect pipeline stages.
+
+ _tnl_destroy_pipeline(ctx);
+ _tnl_install_pipeline(ctx, gld_pipeline);
+}
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c
new file mode 100644
index 0000000000..a0642b4bd1
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_primitive_dx7.c
@@ -0,0 +1,1448 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Primitive (points/lines/tris/quads) rendering
+*
+****************************************************************************/
+
+//#include "../GLDirect.h"
+
+//#include "gld_dx8.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx7.h"
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "array_cache/acache.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast_setup/ss_context.h"
+#include "swrast/s_context.h"
+#include "swrast/s_depth.h"
+#include "swrast/s_lines.h"
+#include "swrast/s_triangle.h"
+#include "swrast/s_trispan.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+// Disable compiler complaints about unreferenced local variables
+#pragma warning (disable:4101)
+
+//---------------------------------------------------------------------------
+// Helper defines for primitives
+//---------------------------------------------------------------------------
+
+//static const float ooZ = 1.0f / 65536.0f; // One over Z
+
+#define GLD_COLOUR (D3DCOLOR_RGBA(swv->color[0], swv->color[1], swv->color[2], swv->color[3]))
+#define GLD_SPECULAR (D3DCOLOR_RGBA(swv->specular[0], swv->specular[1], swv->specular[2], swv->specular[3]))
+#define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y))
+
+//---------------------------------------------------------------------------
+// 2D vertex setup
+//---------------------------------------------------------------------------
+
+#define GLD_SETUP_2D_VARS_POINTS \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); \
+ GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pPoints; \
+ SScontext *ss = SWSETUP_CONTEXT(ctx); \
+ SWvertex *swv; \
+ DWORD dwSpecularColour; \
+ DWORD dwFlatColour
+
+#define GLD_SETUP_2D_VARS_LINES \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); \
+ GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pLines; \
+ SScontext *ss = SWSETUP_CONTEXT(ctx); \
+ SWvertex *swv; \
+ DWORD dwSpecularColour; \
+ DWORD dwFlatColour
+
+#define GLD_SETUP_2D_VARS_TRIANGLES \
+ BOOL bFog = ctx->Fog.Enabled; \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); \
+ GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pTriangles; \
+ SScontext *ss = SWSETUP_CONTEXT(ctx); \
+ SWvertex *swv; \
+ DWORD dwSpecularColour; \
+ DWORD dwFlatColour; \
+ GLuint facing = 0; \
+ struct vertex_buffer *VB; \
+ GLchan (*vbcolor)[4]; \
+ GLchan (*vbspec)[4]
+
+#define GLD_SETUP_GET_SWVERT(s) \
+ swv = &ss->verts[##s]
+
+#define GLD_SETUP_2D_VERTEX \
+ pV->x = swv->win[0]; \
+ pV->y = GLD_FLIP_Y(swv->win[1]); \
+ pV->rhw = swv->win[3]
+
+#define GLD_SETUP_SMOOTH_COLOUR \
+ pV->diffuse = GLD_COLOUR
+
+#define GLD_SETUP_GET_FLAT_COLOUR \
+ dwFlatColour = GLD_COLOUR
+#define GLD_SETUP_GET_FLAT_FOG_COLOUR \
+ dwFlatColour = _gldComputeFog(ctx, swv)
+
+#define GLD_SETUP_USE_FLAT_COLOUR \
+ pV->diffuse = dwFlatColour
+
+#define GLD_SETUP_GET_FLAT_SPECULAR \
+ dwSpecularColour= GLD_SPECULAR
+
+#define GLD_SETUP_USE_FLAT_SPECULAR \
+ pV->specular = dwSpecularColour
+
+#define GLD_SETUP_DEPTH \
+ pV->sz = swv->win[2] / ctx->DepthMaxF
+// pV->z = swv->win[2] * ooZ;
+
+#define GLD_SETUP_SPECULAR \
+ pV->specular = GLD_SPECULAR
+
+#define GLD_SETUP_FOG \
+ pV->diffuse = _gldComputeFog(ctx, swv)
+
+#define GLD_SETUP_TEX0 \
+ pV->t0_u = swv->texcoord[0][0]; \
+ pV->t0_v = swv->texcoord[0][1]
+
+#define GLD_SETUP_TEX1 \
+ pV->t1_u = swv->texcoord[1][0]; \
+ pV->t1_v = swv->texcoord[1][1]
+
+#define GLD_SETUP_LIGHTING(v) \
+ if (facing == 1) { \
+ pV->diffuse = D3DCOLOR_RGBA(vbcolor[##v][0], vbcolor[##v][1], vbcolor[##v][2], vbcolor[##v][3]); \
+ if (vbspec) { \
+ pV->specular = D3DCOLOR_RGBA(vbspec[##v][0], vbspec[##v][1], vbspec[##v][2], vbspec[##v][3]); \
+ } \
+ } else { \
+ if (bFog) \
+ GLD_SETUP_FOG; \
+ else \
+ GLD_SETUP_SMOOTH_COLOUR; \
+ GLD_SETUP_SPECULAR; \
+ }
+
+#define GLD_SETUP_GET_FLAT_LIGHTING(v) \
+ if (facing == 1) { \
+ dwFlatColour = D3DCOLOR_RGBA(vbcolor[##v][0], vbcolor[##v][1], vbcolor[##v][2], vbcolor[##v][3]); \
+ if (vbspec) { \
+ dwSpecularColour = D3DCOLOR_RGBA(vbspec[##v][0], vbspec[##v][1], vbspec[##v][2], vbspec[##v][3]); \
+ } \
+ }
+
+#define GLD_SETUP_TWOSIDED_LIGHTING \
+ /* Two-sided lighting */ \
+ if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) { \
+ SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts; \
+ SWvertex *v[3]; \
+ GLfloat ex,ey,fx,fy,cc; \
+ /* Get vars for later */ \
+ VB = &TNL_CONTEXT(ctx)->vb; \
+ vbcolor = (GLchan (*)[4])VB->ColorPtr[1]->Ptr; \
+ if (VB->SecondaryColorPtr[1]) { \
+ vbspec = (GLchan (*)[4])VB->SecondaryColorPtr[1]->Ptr; \
+ } else { \
+ vbspec = NULL; \
+ } \
+ v[0] = &verts[v0]; \
+ v[1] = &verts[v1]; \
+ v[2] = &verts[v2]; \
+ ex = v[0]->win[0] - v[2]->win[0]; \
+ ey = v[0]->win[1] - v[2]->win[1]; \
+ fx = v[1]->win[0] - v[2]->win[0]; \
+ fy = v[1]->win[1] - v[2]->win[1]; \
+ cc = ex*fy - ey*fx; \
+ facing = (cc < 0.0) ^ ctx->Polygon._FrontBit; \
+ }
+
+//---------------------------------------------------------------------------
+// 3D vertex setup
+//---------------------------------------------------------------------------
+
+#define GLD_SETUP_3D_VARS_POINTS \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); \
+ GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pPoints; \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ GLfloat (*p4f)[4]; \
+ GLfloat (*tc)[4]; \
+ DWORD dwColor;
+
+#define GLD_SETUP_3D_VARS_LINES \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); \
+ GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pLines; \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ GLfloat (*p4f)[4]; \
+ GLfloat (*tc)[4]; \
+ DWORD dwColor;
+
+#define GLD_SETUP_3D_VARS_TRIANGLES \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx); \
+ GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pTriangles; \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ GLfloat (*p4f)[4]; \
+ GLfloat (*tc)[4]; \
+ DWORD dwColor;
+
+#define GLD_SETUP_3D_VERTEX(v) \
+ p4f = VB->ObjPtr->data; \
+ pV->Position.x = p4f[##v][0]; \
+ pV->Position.y = p4f[##v][1]; \
+ pV->Position.z = p4f[##v][2];
+
+#define GLD_SETUP_SMOOTH_COLOUR_3D(v) \
+ p4f = (GLfloat (*)[4])VB->ColorPtr[0]->Ptr; \
+ pV->Diffuse = D3DCOLOR_COLORVALUE(p4f[##v][0], p4f[##v][1], p4f[##v][2], p4f[##v][3]);
+
+
+#define GLD_SETUP_GET_FLAT_COLOUR_3D(v) \
+ p4f = (GLfloat (*)[4])VB->ColorPtr[0]->Ptr; \
+ dwColor = D3DCOLOR_COLORVALUE(p4f[##v][0], p4f[##v][1], p4f[##v][2], p4f[##v][3]);
+
+#define GLD_SETUP_USE_FLAT_COLOUR_3D \
+ pV->Diffuse = dwColor;
+
+#define GLD_SETUP_TEX0_3D(v) \
+ if (VB->TexCoordPtr[0]) { \
+ tc = VB->TexCoordPtr[0]->data; \
+ pV->TexUnit0.x = tc[##v][0]; \
+ pV->TexUnit0.y = tc[##v][1]; \
+ }
+
+#define GLD_SETUP_TEX1_3D(v) \
+ if (VB->TexCoordPtr[1]) { \
+ tc = VB->TexCoordPtr[1]->data; \
+ pV->TexUnit1.x = tc[##v][0]; \
+ pV->TexUnit1.y = tc[##v][1]; \
+ }
+
+//---------------------------------------------------------------------------
+// Helper functions
+//---------------------------------------------------------------------------
+
+__inline DWORD _gldComputeFog(
+ GLcontext *ctx,
+ SWvertex *swv)
+{
+ // Full fog calculation.
+ // Based on Mesa code.
+
+ GLchan rFog, gFog, bFog;
+ GLchan fR, fG, fB;
+ const GLfloat f = swv->fog;
+ const GLfloat g = 1.0 - f;
+
+ UNCLAMPED_FLOAT_TO_CHAN(rFog, ctx->Fog.Color[RCOMP]);
+ UNCLAMPED_FLOAT_TO_CHAN(gFog, ctx->Fog.Color[GCOMP]);
+ UNCLAMPED_FLOAT_TO_CHAN(bFog, ctx->Fog.Color[BCOMP]);
+ fR = f * swv->color[0] + g * rFog;
+ fG = f * swv->color[1] + g * gFog;
+ fB = f * swv->color[2] + g * bFog;
+ return D3DCOLOR_RGBA(fR, fG, fB, swv->color[3]);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_ResetLineStipple_DX7(
+ GLcontext *ctx)
+{
+ // TODO: Fake stipple with a 32x32 texture.
+}
+
+//---------------------------------------------------------------------------
+// 2D (post-transformed) primitives
+//---------------------------------------------------------------------------
+
+void gld_Points2D_DX7(
+ GLcontext *ctx,
+ GLuint first,
+ GLuint last)
+{
+ GLD_SETUP_2D_VARS_POINTS;
+
+ unsigned i;
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ // _Size is already clamped to MaxPointSize and MinPointSize
+ // Not supported by DX7
+// IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_POINTSIZE, *((DWORD*)&ctx->Point._Size));
+
+ if (VB->Elts) {
+ for (i=first; i<last; i++, pV++) {
+ if (VB->ClipMask[VB->Elts[i]] == 0) {
+// _swrast_Point( ctx, &verts[VB->Elts[i]] );
+ GLD_SETUP_GET_SWVERT(VB->Elts[i]);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ }
+ }
+ } else {
+ GLD_SETUP_GET_SWVERT(first);
+ for (i=first; i<last; i++, swv++, pV++) {
+ if (VB->ClipMask[i] == 0) {
+// _swrast_Point( ctx, &verts[i] );
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ }
+ }
+ }
+
+ gld->PB2d.pPoints = (BYTE*)pV;
+ gld->PB2d.nPoints += (last-first);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DFlat_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_2D_VARS_LINES;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_GET_FLAT_SPECULAR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ gld->PB2d.pLines = (BYTE*)pV;
+ gld->PB2d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DSmooth_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_2D_VARS_LINES;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ gld->PB2d.pLines = (BYTE*)pV;
+ gld->PB2d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DFlat_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DSmooth_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DFlatExtras_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v2);
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ if (bFog)
+ GLD_SETUP_GET_FLAT_FOG_COLOUR;
+ else
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_GET_FLAT_SPECULAR;
+ GLD_SETUP_GET_FLAT_LIGHTING(v2);
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DSmoothExtras_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v0);
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v0);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v1);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v2);
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DFlat_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DSmooth_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DFlatExtras_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v3);
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ if (bFog)
+ GLD_SETUP_GET_FLAT_FOG_COLOUR;
+ else
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_GET_FLAT_SPECULAR;
+ GLD_SETUP_GET_FLAT_LIGHTING(v3);
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DSmoothExtras_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v0);
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v0);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v1);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v2);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v2);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v3);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v0);
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+// 3D (pre-transformed) primitives
+//---------------------------------------------------------------------------
+
+void gld_Points3D_DX7(
+ GLcontext *ctx,
+ GLuint first,
+ GLuint last)
+{
+ GLD_SETUP_3D_VARS_POINTS
+
+ unsigned i;
+// struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ // _Size is already clamped to MaxPointSize and MinPointSize
+ // Not supported by DX7
+// IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_POINTSIZE, *((DWORD*)&ctx->Point._Size));
+
+ if (VB->Elts) {
+ for (i=first; i<last; i++, pV++) {
+ if (VB->ClipMask[VB->Elts[i]] == 0) {
+// _swrast_Point( ctx, &verts[VB->Elts[i]] );
+// GLD_SETUP_GET_SWVERT(VB->Elts[i]);
+ GLD_SETUP_3D_VERTEX(VB->Elts[i])
+ GLD_SETUP_SMOOTH_COLOUR_3D(i)
+ GLD_SETUP_TEX0_3D(i)
+ GLD_SETUP_TEX1_3D(i)
+ }
+ }
+ } else {
+// GLD_SETUP_GET_SWVERT(first);
+ for (i=first; i<last; i++, pV++) {
+ if (VB->ClipMask[i] == 0) {
+// _swrast_Point( ctx, &verts[i] );
+ GLD_SETUP_3D_VERTEX(i)
+ GLD_SETUP_SMOOTH_COLOUR_3D(i)
+ GLD_SETUP_TEX0_3D(i)
+ GLD_SETUP_TEX1_3D(i)
+ }
+ }
+ }
+/*
+ for (i=first; i<last; i++, pV++) {
+ GLD_SETUP_3D_VERTEX(i)
+ GLD_SETUP_SMOOTH_COLOUR_3D(i)
+ GLD_SETUP_TEX0_3D(i)
+ GLD_SETUP_TEX1_3D(i)
+ }
+*/
+ gld->PB3d.pPoints = (BYTE*)pV;
+ gld->PB3d.nPoints += (last-first);
+}
+
+//---------------------------------------------------------------------------
+// Line functions
+//---------------------------------------------------------------------------
+
+void gld_Line3DFlat_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_3D_VARS_LINES
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_GET_FLAT_COLOUR_3D(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ gld->PB3d.pLines = (BYTE*)pV;
+ gld->PB3d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line3DSmooth_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_3D_VARS_LINES
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ gld->PB3d.pLines = (BYTE*)pV;
+ gld->PB3d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+// Triangle functions
+//---------------------------------------------------------------------------
+
+void gld_Triangle3DFlat_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ GLD_SETUP_GET_FLAT_COLOUR_3D(v2)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle3DSmooth_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+// Quad functions
+//---------------------------------------------------------------------------
+
+void gld_Quad3DFlat_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v3)
+ GLD_SETUP_GET_FLAT_COLOUR_3D(v3)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v3)
+ GLD_SETUP_TEX1_3D(v3)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v3)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v3)
+ GLD_SETUP_TEX1_3D(v3)
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad3DSmooth_DX7(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v3)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v3)
+ GLD_SETUP_TEX0_3D(v3)
+ GLD_SETUP_TEX1_3D(v3)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+// Vertex setup for two-sided-lighting vertex shader
+//---------------------------------------------------------------------------
+
+/*
+
+void gld_Points2DTwoside_DX8(GLcontext *ctx, GLuint first, GLuint last)
+{
+ // NOTE: Two-sided lighting does not apply to Points
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1)
+{
+ // NOTE: Two-sided lighting does not apply to Lines
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1)
+{
+ // NOTE: Two-sided lighting does not apply to Lines
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2)
+{
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+ GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles;
+ SScontext *ss = SWSETUP_CONTEXT(ctx);
+ SWvertex *swv;
+ DWORD dwSpecularColour;
+ DWORD dwFlatColour;
+ GLuint facing = 0;
+ struct vertex_buffer *VB;
+ GLchan (*vbcolor)[4];
+ GLchan (*vbspec)[4];
+
+ // Reciprocal of DepthMax
+ const float ooDepthMax = 1.0f / ctx->DepthMaxF;
+
+ // 1st vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 2nd vert
+ swv = &ss->verts[v1];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 3rd vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ gld->PBtwosidelight.pTriangles = (BYTE*)pV;
+ gld->PBtwosidelight.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+ GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles;
+ SScontext *ss = SWSETUP_CONTEXT(ctx);
+ SWvertex *swv;
+ DWORD dwSpecularColour;
+ DWORD dwFlatColour;
+ GLuint facing = 0;
+ struct vertex_buffer *VB;
+ GLchan (*vbcolor)[4];
+ GLchan (*vbspec)[4];
+
+ // Reciprocal of DepthMax
+ const float ooDepthMax = 1.0f / ctx->DepthMaxF;
+
+ // 1st vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 2nd vert
+ swv = &ss->verts[v1];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 3rd vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 4th vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 5th vert
+ swv = &ss->verts[v3];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 6th vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ gld->PBtwosidelight.pTriangles = (BYTE*)pV;
+ gld->PBtwosidelight.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+ GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles;
+ SScontext *ss = SWSETUP_CONTEXT(ctx);
+ SWvertex *swv;
+ DWORD dwSpecularColour;
+ DWORD dwFlatColour;
+ GLuint facing = 0;
+ struct vertex_buffer *VB;
+ GLchan (*vbcolor)[4];
+ GLchan (*vbspec)[4];
+
+ // Reciprocal of DepthMax
+ const float ooDepthMax = 1.0f / ctx->DepthMaxF;
+
+ // 1st vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 2nd vert
+ swv = &ss->verts[v1];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 3rd vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 4th vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 5th vert
+ swv = &ss->verts[v3];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 6th vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ gld->PBtwosidelight.pTriangles = (BYTE*)pV;
+ gld->PBtwosidelight.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+*/
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_texture_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_texture_dx7.c
new file mode 100644
index 0000000000..a55a52244b
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_texture_dx7.c
@@ -0,0 +1,2054 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Texture / Bitmap functions
+*
+****************************************************************************/
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx7.h"
+
+//#include <d3dx8tex.h>
+
+#include "texformat.h"
+#include "colormac.h"
+#include "texstore.h"
+#include "image.h"
+// #include "mem.h"
+
+//---------------------------------------------------------------------------
+
+#define GLD_FLIP_HEIGHT(y,h) (gldCtx->dwHeight - (y) - (h))
+
+D3DX_SURFACEFORMAT _gldD3DXFormatFromSurface(IDirectDrawSurface7 *pSurface);
+
+//---------------------------------------------------------------------------
+// 1D texture fetch
+//---------------------------------------------------------------------------
+
+#define CHAN_SRC( t, i, j, k, sz ) \
+ ((GLchan *)(t)->Data + (i) * (sz))
+#define UBYTE_SRC( t, i, j, k, sz ) \
+ ((GLubyte *)(t)->Data + (i) * (sz))
+#define USHORT_SRC( t, i, j, k ) \
+ ((GLushort *)(t)->Data + (i))
+#define FLOAT_SRC( t, i, j, k ) \
+ ((GLfloat *)(t)->Data + (i))
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ GLchan *rgba = (GLchan *) texel;
+ rgba[RCOMP] = src[2];
+ rgba[GCOMP] = src[1];
+ rgba[BCOMP] = src[0];
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+#undef CHAN_SRC
+#undef UBYTE_SRC
+#undef USHORT_SRC
+#undef FLOAT_SRC
+
+//---------------------------------------------------------------------------
+// 2D texture fetch
+//---------------------------------------------------------------------------
+
+#define CHAN_SRC( t, i, j, k, sz ) \
+ ((GLchan *)(t)->Data + ((t)->Width * (j) + (i)) * (sz))
+#define UBYTE_SRC( t, i, j, k, sz ) \
+ ((GLubyte *)(t)->Data + ((t)->Width * (j) + (i)) * (sz))
+#define USHORT_SRC( t, i, j, k ) \
+ ((GLushort *)(t)->Data + ((t)->Width * (j) + (i)))
+#define FLOAT_SRC( t, i, j, k ) \
+ ((GLfloat *)(t)->Data + ((t)->Width * (j) + (i)))
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ GLchan *rgba = (GLchan *) texel;
+ rgba[RCOMP] = src[2];
+ rgba[GCOMP] = src[1];
+ rgba[BCOMP] = src[0];
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+#undef CHAN_SRC
+#undef UBYTE_SRC
+#undef USHORT_SRC
+#undef FLOAT_SRC
+
+//---------------------------------------------------------------------------
+// 3D texture fetch
+//---------------------------------------------------------------------------
+
+#define CHAN_SRC( t, i, j, k, sz ) \
+ (GLchan *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)) * (sz)
+#define UBYTE_SRC( t, i, j, k, sz ) \
+ ((GLubyte *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)) * (sz))
+#define USHORT_SRC( t, i, j, k ) \
+ ((GLushort *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)))
+#define FLOAT_SRC( t, i, j, k ) \
+ ((GLfloat *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)))
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ GLchan *rgba = (GLchan *) texel;
+ rgba[RCOMP] = src[2];
+ rgba[GCOMP] = src[1];
+ rgba[BCOMP] = src[0];
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+#undef CHAN_SRC
+#undef UBYTE_SRC
+#undef USHORT_SRC
+#undef FLOAT_SRC
+
+//---------------------------------------------------------------------------
+// Direct3D texture formats that have no Mesa equivalent
+//---------------------------------------------------------------------------
+
+const struct gl_texture_format _gld_texformat_X8R8G8B8 = {
+ MESA_FORMAT_ARGB8888, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 4, /* TexelBytes */
+ gld_fetch_1d_texel_X8R8G8B8, /* FetchTexel1D */
+ gld_fetch_2d_texel_X8R8G8B8, /* FetchTexel2D */
+ gld_fetch_3d_texel_X8R8G8B8, /* FetchTexel3D */
+};
+
+const struct gl_texture_format _gld_texformat_X1R5G5B5 = {
+ MESA_FORMAT_ARGB1555, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ 5, /* RedBits */
+ 5, /* GreenBits */
+ 5, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 2, /* TexelBytes */
+ gld_fetch_1d_texel_X1R5G5B5, /* FetchTexel1D */
+ gld_fetch_2d_texel_X1R5G5B5, /* FetchTexel2D */
+ gld_fetch_3d_texel_X1R5G5B5, /* FetchTexel3D */
+};
+
+const struct gl_texture_format _gld_texformat_X4R4G4B4 = {
+ MESA_FORMAT_ARGB4444, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+ 4, /* RedBits */
+ 4, /* GreenBits */
+ 4, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 2, /* TexelBytes */
+ gld_fetch_1d_texel_X4R4G4B4, /* FetchTexel1D */
+ gld_fetch_2d_texel_X4R4G4B4, /* FetchTexel2D */
+ gld_fetch_3d_texel_X4R4G4B4, /* FetchTexel3D */
+};
+
+//---------------------------------------------------------------------------
+// Texture unit constants
+//---------------------------------------------------------------------------
+
+// List of possible combinations of texture environments.
+// Example: GLD_TEXENV_MODULATE_RGBA means
+// GL_MODULATE, GL_RGBA base internal format.
+#define GLD_TEXENV_DECAL_RGB 0
+#define GLD_TEXENV_DECAL_RGBA 1
+#define GLD_TEXENV_DECAL_ALPHA 2
+#define GLD_TEXENV_REPLACE_RGB 3
+#define GLD_TEXENV_REPLACE_RGBA 4
+#define GLD_TEXENV_REPLACE_ALPHA 5
+#define GLD_TEXENV_MODULATE_RGB 6
+#define GLD_TEXENV_MODULATE_RGBA 7
+#define GLD_TEXENV_MODULATE_ALPHA 8
+#define GLD_TEXENV_BLEND_RGB 9
+#define GLD_TEXENV_BLEND_RGBA 10
+#define GLD_TEXENV_BLEND_ALPHA 11
+#define GLD_TEXENV_ADD_RGB 12
+#define GLD_TEXENV_ADD_RGBA 13
+#define GLD_TEXENV_ADD_ALPHA 14
+
+// Per-stage (i.e. per-unit) texture environment
+typedef struct {
+ DWORD ColorArg1; // Colour argument 1
+ D3DTEXTUREOP ColorOp; // Colour operation
+ DWORD ColorArg2; // Colour argument 2
+ DWORD AlphaArg1; // Alpha argument 1
+ D3DTEXTUREOP AlphaOp; // Alpha operation
+ DWORD AlphaArg2; // Alpha argument 2
+} GLD_texenv;
+
+// TODO: Do we really need to set ARG1 and ARG2 every time?
+// They seem to always be TEXTURE and CURRENT respectively.
+
+// C = Colour out
+// A = Alpha out
+// Ct = Colour from Texture
+// Cf = Colour from fragment (diffuse)
+// At = Alpha from Texture
+// Af = Alpha from fragment (diffuse)
+// Cc = GL_TEXTURE_ENV_COLOUR (GL_BLEND)
+const GLD_texenv gldTexEnv[] = {
+ // DECAL_RGB: C=Ct, A=Af
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // DECAL_RGBA: C=Cf(1-At)+CtAt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_BLENDTEXTUREALPHA, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // DECAL_ALPHA: <undefined> use DECAL_RGB
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+
+ // REPLACE_RGB: C=Ct, A=Af
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // REPLACE_RGBA: C=Ct, A=At
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT},
+ // REPLACE_ALPHA: C=Cf, A=At
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT},
+
+ // MODULATE_RGB: C=CfCt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // MODULATE_RGBA: C=CfCt, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+ // MODULATE_ALPHA: C=Cf, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+
+ //
+ // DX7 Does not support D3DTOP_LERP
+ // Emulate(?) via D3DTOP_ADDSMOOTH
+ //
+#if 0
+ // BLEND_RGB: C=Cf(1-Ct)+CcCt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // BLEND_RGBA: C=Cf(1-Ct)+CcCt, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+#else
+ // BLEND_RGB: C=Cf(1-Ct)+CcCt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_ADDSMOOTH, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // BLEND_RGBA: C=Cf(1-Ct)+CcCt, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_ADDSMOOTH, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+#endif
+ // BLEND_ALPHA: C=Cf, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+
+ // ADD_RGB: C=Cf+Ct, A=Af
+ {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // ADD_RGBA: C=Cf+Ct, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+ // ADD_ALPHA: C=Cf, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+};
+
+//---------------------------------------------------------------------------
+
+D3DTEXTUREADDRESS _gldConvertWrap(
+ GLenum wrap)
+{
+// ASSERT(wrap==GL_CLAMP || wrap==GL_REPEAT);
+ return (wrap == GL_CLAMP) ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP;
+}
+
+//---------------------------------------------------------------------------
+
+D3DTEXTUREMAGFILTER _gldConvertMagFilter(
+ GLenum magfilter)
+{
+ ASSERT(magfilter==GL_LINEAR || magfilter==GL_NEAREST);
+ return (magfilter == GL_LINEAR) ? D3DTFG_LINEAR : D3DTFG_POINT;
+}
+
+//---------------------------------------------------------------------------
+
+void _gldConvertMinFilter(
+ GLenum minfilter,
+ D3DTEXTUREMINFILTER *min_filter,
+ D3DTEXTUREMIPFILTER *mip_filter)
+{
+ switch (minfilter) {
+ case GL_NEAREST:
+ *min_filter = D3DTFN_POINT;
+ *mip_filter = D3DTFP_NONE;
+ break;
+ case GL_LINEAR:
+ *min_filter = D3DTFN_LINEAR;
+ *mip_filter = D3DTFP_NONE;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ *min_filter = D3DTFN_POINT;
+ *mip_filter = D3DTFP_POINT;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ *min_filter = D3DTFN_LINEAR;
+ *mip_filter = D3DTFP_POINT;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ *min_filter = D3DTFN_POINT;
+ *mip_filter = D3DTFP_LINEAR;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ *min_filter = D3DTFN_LINEAR;
+ *mip_filter = D3DTFP_LINEAR;
+ break;
+ default:
+ ASSERT(0);
+ }
+}
+
+//---------------------------------------------------------------------------
+
+D3DX_SURFACEFORMAT _gldGLFormatToD3DFormat(
+ GLenum internalFormat)
+{
+ switch (internalFormat) {
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ // LUNIMANCE != INTENSITY, but D3D doesn't have I8 textures
+ return D3DX_SF_L8;
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return D3DX_SF_L8;
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return D3DX_SF_A8;
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ return D3DX_SF_X8R8G8B8;
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ return D3DX_SF_A8L8;
+ case GL_R3_G3_B2:
+ // TODO: Mesa does not support RGB332 internally
+ return D3DX_SF_X4R4G4B4; //D3DFMT_R3G3B2;
+ case GL_RGB4:
+ return D3DX_SF_X4R4G4B4;
+ case GL_RGB5:
+ return D3DX_SF_R5G5B5;
+ case 3:
+ case GL_RGB:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return D3DX_SF_R8G8B8;
+ case GL_RGBA4:
+ return D3DX_SF_A4R4G4B4;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA2:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return D3DX_SF_A8R8G8B8;
+ case GL_RGB5_A1:
+ return D3DX_SF_A1R5G5B5;
+ }
+
+ ASSERT(0);
+
+ // Return an acceptable default
+ return D3DX_SF_A8R8G8B8;
+}
+
+//---------------------------------------------------------------------------
+
+GLenum _gldDecodeBaseFormat(
+ IDirectDrawSurface7 *pTex)
+{
+ // Examine Direct3D texture and return base OpenGL internal texture format
+ // NOTE: We can't use any base format info from Mesa because D3D might have
+ // used a different texture format when we used D3DXCreateTexture().
+
+ // Base internal format is one of (Red Book p355):
+ // GL_ALPHA,
+ // GL_LUMINANCE,
+ // GL_LUMINANCE_ALPHA,
+ // GL_INTENSITY,
+ // GL_RGB,
+ // GL_RGBA
+
+ // NOTE: INTENSITY not used (not supported by Direct3D)
+ // LUMINANCE has same texture functions as RGB
+ // LUMINANCE_ALPHA has same texture functions as RGBA
+
+ // TODO: cache format instead of using GetLevelDesc()
+// D3DSURFACE_DESC desc;
+// _GLD_DX7_TEX(GetLevelDesc(pTex, 0, &desc));
+
+ D3DX_SURFACEFORMAT sf;
+
+ sf = _gldD3DXFormatFromSurface(pTex);
+
+ switch (sf) {
+ case D3DX_SF_R8G8B8:
+ case D3DX_SF_X8R8G8B8:
+ case D3DX_SF_R5G6B5:
+ case D3DX_SF_R5G5B5:
+ case D3DX_SF_R3G3B2:
+ case D3DX_SF_X4R4G4B4:
+ case D3DX_SF_PALETTE8:
+ case D3DX_SF_L8:
+ return GL_RGB;
+ case D3DX_SF_A8R8G8B8:
+ case D3DX_SF_A1R5G5B5:
+ case D3DX_SF_A4R4G4B4:
+// case D3DX_SF_A8R3G3B2: // Unsupported by DX7
+// case D3DX_SF_A8P8: // Unsupported by DX7
+ case D3DX_SF_A8L8:
+// case D3DX_SF_A4L4: // Unsupported by DX7
+ return GL_RGBA;
+ case D3DX_SF_A8:
+ return GL_ALPHA;
+ // Compressed texture formats. Need to check these...
+ case D3DX_SF_DXT1:
+ return GL_RGBA;
+// case D3DX_SF_DXT2: // Unsupported by DX7
+ return GL_RGB;
+ case D3DX_SF_DXT3:
+ return GL_RGBA;
+// case D3DX_SF_DXT4: // Unsupported by DX7
+ return GL_RGB;
+ case D3DX_SF_DXT5:
+ return GL_RGBA;
+ }
+
+ // Fell through. Return arbitary default.
+ ASSERT(0); // BANG!
+ return GL_RGBA;
+}
+
+//---------------------------------------------------------------------------
+
+const struct gl_texture_format* _gldMesaFormatForD3DFormat(
+ D3DX_SURFACEFORMAT d3dfmt)
+{
+ switch (d3dfmt) {
+ case D3DX_SF_A8R8G8B8:
+ return &_mesa_texformat_argb8888;
+ case D3DX_SF_R8G8B8:
+ return &_mesa_texformat_rgb888;
+ case D3DX_SF_R5G6B5:
+ return &_mesa_texformat_rgb565;
+ case D3DX_SF_A4R4G4B4:
+ return &_mesa_texformat_argb4444;
+ case D3DX_SF_A1R5G5B5:
+ return &_mesa_texformat_argb1555;
+ case D3DX_SF_A8L8:
+ return &_mesa_texformat_al88;
+ case D3DX_SF_R3G3B2:
+ return &_mesa_texformat_rgb332;
+ case D3DX_SF_A8:
+ return &_mesa_texformat_a8;
+ case D3DX_SF_L8:
+ return &_mesa_texformat_l8;
+ case D3DX_SF_X8R8G8B8:
+ return &_gld_texformat_X8R8G8B8;
+ case D3DX_SF_R5G5B5:
+ return &_gld_texformat_X1R5G5B5;
+ case D3DX_SF_X4R4G4B4:
+ return &_gld_texformat_X4R4G4B4;
+ }
+
+ // If we reach here then we've made an error somewhere else
+ // by allowing a format that is not supported.
+ ASSERT(0);
+
+ return NULL; // Shut up compiler warning
+}
+
+//---------------------------------------------------------------------------
+
+D3DX_SURFACEFORMAT _gldD3DXFormatFromSurface(
+ IDirectDrawSurface7 *pSurface)
+{
+ DDPIXELFORMAT ddpf;
+
+ ddpf.dwSize = sizeof(ddpf);
+
+ // Obtain pixel format of surface
+ _GLD_DX7_TEX(GetPixelFormat(pSurface, &ddpf));
+ // Decode to D3DX surface format
+ return D3DXMakeSurfaceFormat(&ddpf);
+}
+
+//---------------------------------------------------------------------------
+
+void _gldClearSurface(
+ IDirectDrawSurface *pSurface,
+ D3DCOLOR dwColour)
+{
+ DDBLTFX bltFX; // Used for colour fill
+
+ // Initialise struct
+ bltFX.dwSize = sizeof(bltFX);
+ // Set clear colour
+ bltFX.dwFillColor = dwColour;
+ // Clear surface. HW accelerated if available.
+ IDirectDrawSurface7_Blt(pSurface, NULL, NULL, NULL, DDBLT_COLORFILL, &bltFX);
+}
+
+//---------------------------------------------------------------------------
+// Copy* functions
+//---------------------------------------------------------------------------
+
+void gldCopyTexImage1D_DX7(
+ GLcontext *ctx,
+ GLenum target, GLint level,
+ GLenum internalFormat,
+ GLint x, GLint y,
+ GLsizei width, GLint border )
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexImage2D_DX7(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLenum internalFormat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border)
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexSubImage1D_DX7(
+ GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint x, GLint y, GLsizei width )
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexSubImage2D_DX7(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexSubImage3D_DX7(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height )
+{
+ // TODO ?
+}
+
+//---------------------------------------------------------------------------
+// Bitmap/Pixel functions
+//---------------------------------------------------------------------------
+
+#define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y))
+
+#define _GLD_FVF_IMAGE (D3DFVF_XYZRHW | D3DFVF_TEX1)
+
+typedef struct {
+ FLOAT x, y; // 2D raster coords
+ FLOAT z; // depth value
+ FLOAT rhw; // reciprocal homogenous W (always 1.0f)
+ FLOAT tu, tv; // texture coords
+} _GLD_IMAGE_VERTEX;
+
+//---------------------------------------------------------------------------
+
+HRESULT _gldDrawPixels(
+ GLcontext *ctx,
+ BOOL bChromakey, // Alpha test for glBitmap() images
+ GLint x, // GL x position
+ GLint y, // GL y position (needs flipping)
+ GLsizei width, // Width of input image
+ GLsizei height, // Height of input image
+ IDirectDrawSurface7 *pImage)
+{
+ //
+ // Draw input image as texture implementing PixelZoom and clipping.
+ // Any fragment operations currently enabled will be used.
+ //
+
+ // NOTE: This DX7 version does not create a new texture in which
+ // to copy the input image, as the image is already a texture.
+
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ DDSURFACEDESC2 ddsd;
+ _GLD_IMAGE_VERTEX v[4];
+
+ float ZoomWidth, ZoomHeight;
+ float ScaleWidth, ScaleHeight;
+
+ // Fixup for rasterisation rules
+ const float cfEpsilon = 1.0f / (float)height;
+
+ //
+ // Set up the quad like this (ascii-art ahead!)
+ //
+ // 3--2
+ // | |
+ // 0--1
+ //
+ //
+
+ // Set depth
+ v[0].z = v[1].z = v[2].z = v[3].z = ctx->Current.RasterPos[2];
+ // Set Reciprocal Homogenous W
+ v[0].rhw = v[1].rhw = v[2].rhw = v[3].rhw = 1.0f;
+
+ // Set texcoords
+ // Examine texture size - if different to input width and height
+ // then we'll need to munge the texcoords to fit.
+ ddsd.dwSize = sizeof(DDSURFACEDESC2);
+ IDirectDrawSurface7_GetSurfaceDesc(pImage, &ddsd);
+ ScaleWidth = (float)width / (float)ddsd.dwWidth;
+ ScaleHeight = (float)height / (float)ddsd.dwHeight;
+ v[0].tu = 0.0f; v[0].tv = 0.0f;
+ v[1].tu = ScaleWidth; v[1].tv = 0.0f;
+ v[2].tu = ScaleWidth; v[2].tv = ScaleHeight;
+ v[3].tu = 0.0f; v[3].tv = ScaleHeight;
+
+ // Set raster positions
+ ZoomWidth = (float)width * ctx->Pixel.ZoomX;
+ ZoomHeight = (float)height * ctx->Pixel.ZoomY;
+
+ v[0].x = x; v[0].y = GLD_FLIP_Y(y+cfEpsilon);
+ v[1].x = x+ZoomWidth; v[1].y = GLD_FLIP_Y(y+cfEpsilon);
+ v[2].x = x+ZoomWidth; v[2].y = GLD_FLIP_Y(y+ZoomHeight+cfEpsilon);
+ v[3].x = x; v[3].y = GLD_FLIP_Y(y+ZoomHeight+cfEpsilon);
+
+ // Draw image with full HW acceleration
+ // NOTE: Be nice to use a State Block for all this state...
+ IDirect3DDevice7_SetTexture(gld->pDev, 0, pImage);
+ IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
+ IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_CLIPPING, TRUE);
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_MINFILTER, D3DTFN_POINT);
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_MIPFILTER, D3DTFP_POINT);
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_MAGFILTER, D3DTFG_POINT);
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
+ // Ensure texture unit 1 is disabled
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+
+ //
+ // Emulate Chromakey with an Alpha Test.
+ // [Alpha Test is more widely supported anyway]
+ //
+ if (bChromakey) {
+ // Switch on alpha testing
+ IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_ALPHATESTENABLE, TRUE);
+ // Fragment passes is alpha is greater than reference value
+ IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_ALPHAFUNC, D3DCMP_GREATER);
+ // Set alpha reference value between Bitmap alpha values of
+ // zero (transparent) and one (opaque).
+ IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_ALPHAREF, 0x7f);
+ }
+
+ IDirect3DDevice7_DrawPrimitive(gld->pDev, D3DPT_TRIANGLEFAN, _GLD_FVF_IMAGE, &v, 4, 0);
+
+ // Reset state to before we messed it up
+ FLUSH_VERTICES(ctx, _NEW_ALL);
+
+ return S_OK;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_DrawPixels_DX7(
+ GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels )
+{
+ GLD_context *gldCtx;
+ GLD_driver_dx7 *gld;
+
+ IDirectDrawSurface7 *pImage;
+ HRESULT hr;
+ DDSURFACEDESC2 ddsd;
+ DWORD dwFlags;
+ D3DX_SURFACEFORMAT sf;
+ DWORD dwMipmaps;
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ dwFlags = D3DX_TEXTURE_NOMIPMAP;
+ sf = D3DX_SF_A8R8G8B8;
+ dwMipmaps = 1;
+
+ hr = D3DXCreateTexture(
+ gld->pDev,
+ &dwFlags,
+ &width, &height,
+ &sf, // format
+ NULL, // palette
+ &pImage, // Output texture
+ &dwMipmaps);
+ if (FAILED(hr)) {
+ return;
+ }
+
+ // D3DXCreateTexture() may not clear the texture is creates.
+ _gldClearSurface(pImage, 0);
+
+ //
+ // Use Mesa to fill in image
+ //
+
+ // Lock all of surface
+ ddsd.dwSize = sizeof(DDSURFACEDESC2);
+ dwFlags = DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT;
+ hr = IDirectDrawSurface7_Lock(pImage, NULL, &ddsd, dwFlags, NULL);
+ if (FAILED(hr)) {
+ SAFE_RELEASE_SURFACE7(pImage);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store directly in texture
+ _mesa_transfer_teximage(
+ ctx,
+ 2,
+ GL_RGBA,
+ &_mesa_texformat_argb8888,
+ ddsd.lpSurface,
+ width, height, 1, 0, 0, 0,
+ ddsd.lPitch,
+ 0, /* dstImageStride */
+ format, type, pixels, unpack);
+
+ IDirectDrawSurface7_Unlock(pImage, NULL);
+
+ _gldDrawPixels(ctx, FALSE, x, y, width, height, pImage);
+
+ SAFE_RELEASE_SURFACE7(pImage);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_ReadPixels_DX7(
+ GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *pack,
+ GLvoid *dest)
+{
+// TODO
+#if 0
+ GLD_context *gldCtx;
+ GLD_driver_dx7 *gld;
+
+ IDirect3DSurface8 *pBackbuffer = NULL;
+ IDirect3DSurface8 *pNativeImage = NULL;
+ IDirect3DSurface8 *pCanonicalImage = NULL;
+
+ D3DSURFACE_DESC d3dsd;
+ RECT rcSrc; // Source rect
+ POINT ptDst; // Dest point
+ HRESULT hr;
+ D3DLOCKED_RECT d3dLockedRect;
+ struct gl_pixelstore_attrib srcPacking;
+ int i;
+ GLint DstRowStride;
+ const struct gl_texture_format *MesaFormat;
+
+ switch (format) {
+ case GL_STENCIL_INDEX:
+ case GL_DEPTH_COMPONENT:
+ return;
+ }
+
+ MesaFormat = _mesa_choose_tex_format(ctx, format, format, type);
+ DstRowStride = _mesa_image_row_stride(pack, width, format, type);
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ // Get backbuffer
+ hr = IDirect3DDevice8_GetBackBuffer(
+ gld->pDev,
+ 0, // First backbuffer
+ D3DBACKBUFFER_TYPE_MONO,
+ &pBackbuffer);
+ if (FAILED(hr))
+ return;
+
+ // Get backbuffer description
+ hr = IDirect3DSurface8_GetDesc(pBackbuffer, &d3dsd);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX7_return;
+ }
+
+ // Create a surface compatible with backbuffer
+ hr = IDirect3DDevice8_CreateImageSurface(
+ gld->pDev,
+ width,
+ height,
+ d3dsd.Format,
+ &pNativeImage);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX7_return;
+ }
+
+ // Compute source rect and dest point
+ SetRect(&rcSrc, 0, 0, width, height);
+ OffsetRect(&rcSrc, x, GLD_FLIP_HEIGHT(y, height));
+ ptDst.x = ptDst.y = 0;
+
+ // Get source pixels.
+ //
+ // This intermediate surface ensure that we can use CopyRects()
+ // instead of relying on D3DXLoadSurfaceFromSurface(), which may
+ // try and lock the backbuffer. This way seems safer.
+ //
+ hr = IDirect3DDevice8_CopyRects(
+ gld->pDev,
+ pBackbuffer,
+ &rcSrc,
+ 1,
+ pNativeImage,
+ &ptDst);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX7_return;
+ }
+
+ // Create an RGBA8888 surface
+ hr = IDirect3DDevice8_CreateImageSurface(
+ gld->pDev,
+ width,
+ height,
+ D3DFMT_A8R8G8B8,
+ &pCanonicalImage);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX7_return;
+ }
+
+ // Convert to RGBA8888
+ hr = D3DXLoadSurfaceFromSurface(
+ pCanonicalImage, // Dest surface
+ NULL, NULL, // Dest palette, RECT
+ pNativeImage, // Src surface
+ NULL, NULL, // Src palette, RECT
+ D3DX_FILTER_NONE, // Filter
+ 0); // Colourkey
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX7_return;
+ }
+
+ srcPacking.Alignment = 1;
+ srcPacking.ImageHeight = height;
+ srcPacking.LsbFirst = GL_FALSE;
+ srcPacking.RowLength = 0;
+ srcPacking.SkipImages = 0;
+ srcPacking.SkipPixels = 0;
+ srcPacking.SkipRows = 0;
+ srcPacking.SwapBytes = GL_FALSE;
+
+ // Lock all of image
+ hr = IDirect3DSurface8_LockRect(pCanonicalImage, &d3dLockedRect, NULL, 0);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX7_return;
+ }
+
+ // We need to flip the data. Yuck.
+ // Perhaps Mesa has a span packer we can use in future...
+ for (i=0; i<height; i++) {
+ BYTE *pDestRow = (BYTE*)_mesa_image_address(pack, dest, width, height, format, type, 0, i, 0);
+ BYTE *pSrcRow = (BYTE*)d3dLockedRect.pBits + (d3dLockedRect.Pitch * (height-i-1));
+ _mesa_transfer_teximage(
+ ctx,
+ 2,
+ GL_RGBA, // base format
+ MesaFormat, // dst format
+ pDestRow, // dest addr
+ width, 1, 1, 0, 0, 0, // src x,y,z & dst offsets x,y,z
+ DstRowStride, // dst row stride
+ 0, // dstImageStride
+ GL_BGRA, // src format
+ GL_UNSIGNED_BYTE, // src type
+ pSrcRow, // src addr
+ &srcPacking); // packing params of source image
+ }
+
+ IDirect3DSurface8_UnlockRect(pCanonicalImage);
+
+gld_ReadPixels_DX7_return:
+ SAFE_RELEASE_SURFACE8(pCanonicalImage);
+ SAFE_RELEASE_SURFACE8(pNativeImage);
+ SAFE_RELEASE_SURFACE8(pBackbuffer);
+#endif
+}
+
+//---------------------------------------------------------------------------
+
+void gld_CopyPixels_DX7(
+ GLcontext *ctx,
+ GLint srcx,
+ GLint srcy,
+ GLsizei width,
+ GLsizei height,
+ GLint dstx,
+ GLint dsty,
+ GLenum type)
+{
+// TODO
+#if 0
+ //
+ // NOTE: Not allowed to copy vidmem to vidmem!
+ // Therefore we use an intermediate image surface.
+ //
+
+ GLD_context *gldCtx;
+ GLD_driver_dx7 *gld;
+
+ IDirect3DSurface8 *pBackbuffer;
+ D3DSURFACE_DESC d3dsd;
+ IDirect3DSurface8 *pImage;
+ RECT rcSrc; // Source rect
+ POINT ptDst; // Dest point
+ HRESULT hr;
+
+ // Only backbuffer
+ if (type != GL_COLOR)
+ return;
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ // Get backbuffer
+ hr = IDirect3DDevice8_GetBackBuffer(
+ gld->pDev,
+ 0, // First backbuffer
+ D3DBACKBUFFER_TYPE_MONO,
+ &pBackbuffer);
+ if (FAILED(hr))
+ return;
+
+ // Get backbuffer description
+ hr = IDirect3DSurface8_GetDesc(pBackbuffer, &d3dsd);
+ if (FAILED(hr)) {
+ IDirect3DSurface8_Release(pBackbuffer);
+ return;
+ }
+
+ // Create a surface compatible with backbuffer
+ hr = IDirect3DDevice8_CreateImageSurface(
+ gld->pDev,
+ width,
+ height,
+ d3dsd.Format,
+ &pImage);
+ if (FAILED(hr)) {
+ IDirect3DSurface8_Release(pBackbuffer);
+ return;
+ }
+
+ // Compute source rect and dest point
+ SetRect(&rcSrc, 0, 0, width, height);
+ OffsetRect(&rcSrc, srcx, GLD_FLIP_HEIGHT(srcy, height));
+ ptDst.x = ptDst.y = 0;
+
+ // Get source pixels
+ hr = IDirect3DDevice8_CopyRects(
+ gld->pDev,
+ pBackbuffer,
+ &rcSrc,
+ 1,
+ pImage,
+ &ptDst);
+ IDirect3DSurface8_Release(pBackbuffer);
+ if (FAILED(hr)) {
+ IDirect3DSurface8_Release(pImage);
+ return;
+ }
+
+ _gldDrawPixels(ctx, FALSE, dstx, dsty, width, height, pImage);
+
+ IDirect3DSurface8_Release(pImage);
+#endif
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Bitmap_DX7(
+ GLcontext *ctx,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap)
+{
+ GLD_context *gldCtx;
+ GLD_driver_dx7 *gld;
+
+ IDirectDrawSurface7 *pImage; // Bitmap texture
+ HRESULT hr;
+ BYTE *pTempBitmap; // Pointer to unpacked bitmap
+ D3DCOLOR clBitmapOne; // Opaque bitmap colour
+ D3DCOLOR clBitmapZero; // Transparent bitmap colour
+ D3DCOLOR *pBits; // Pointer to texture surface
+ const GLubyte *src;
+ int i, j, k;
+
+ DDSURFACEDESC2 ddsd; // Surface desc returned by lock call
+ DWORD dwFlags;
+ D3DX_SURFACEFORMAT sf;
+ DWORD dwMipmaps;
+
+ // Keep a copy of width/height as D3DXCreateTexture() call may alter input dimensions
+ GLsizei dwWidth = width;
+ GLsizei dwHeight = height;
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ // Bail if no bitmap (only raster pos is updated)
+ if ((bitmap == NULL) && (width==0) && (height==0))
+ return;
+
+ //
+ // TODO: Detect conditions when created texture (pImage) is non-pow2.
+ // Texture coords may need to be adjusted to compensate.
+ //
+
+ clBitmapZero = D3DCOLOR_RGBA(0,0,0,0); // NOTE: Alpha is Zero
+ clBitmapOne = D3DCOLOR_COLORVALUE(
+ ctx->Current.RasterColor[0],
+ ctx->Current.RasterColor[1],
+ ctx->Current.RasterColor[2],
+ 1.0f); // NOTE: Alpha is One
+
+ // Use Mesa to unpack bitmap into a canonical format
+ pTempBitmap = _mesa_unpack_bitmap(width, height, bitmap, unpack);
+ if (pTempBitmap == NULL)
+ return;
+
+ // Flags for texture creation
+ dwFlags = D3DX_TEXTURE_NOMIPMAP;
+ sf = D3DX_SF_A8R8G8B8;
+ dwMipmaps = 1;
+
+ // Create a D3D texture to hold the bitmap
+ hr = D3DXCreateTexture(
+ gld->pDev,
+ &dwFlags,
+ &dwWidth, &dwHeight,
+ &sf, // format
+ NULL, // palette
+ &pImage, // Output texture
+ &dwMipmaps);
+ if (FAILED(hr)) {
+ FREE(pTempBitmap);
+ return;
+ }
+
+ // D3DXCreateTexture may return a texture bigger than we asked for
+ // (i.e. padded to POW2) so let's clear the entire image bitmap.
+ // Additional: Looks like this is not strictly necessary.
+// _gldClearSurface(pImage, clBitmapZero);
+
+ ddsd.dwSize = sizeof(DDSURFACEDESC2);
+ dwFlags = DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT;
+ hr = IDirectDrawSurface7_Lock(pImage, NULL, &ddsd, dwFlags, NULL);
+ if (FAILED(hr)) {
+ FREE(pTempBitmap);
+ SAFE_RELEASE_SURFACE7(pImage);
+ return;
+ }
+
+#if 0
+ // DEBUG CODE
+ if (!(width==ddsd.dwWidth && height==ddsd.dwHeight))
+ ddlogPrintf(GLDLOG_WARN, "gld_Bitmap: In=%d,%d / Tex=%d,%d", width,height,ddsd.dwWidth,ddsd.dwHeight);
+#endif
+
+#if 0
+ // DEBUG CODE
+ ddlogPrintf(GLDLOG_SYSTEM, "gld_Bitmap: In=%d,%d / Tex=%d,%d", width,height,ddsd.dwWidth,ddsd.dwHeight);
+ ddlogPrintf(GLDLOG_SYSTEM, "gld_Bitmap: bpp=%d", ddsd.ddpfPixelFormat.dwRGBBitCount);
+#endif
+
+ // Cast texel pointer to texture surface.
+ // We can do this because we used D3DX_SF_A8R8G8B8 as the format
+ pBits = (D3DCOLOR*)ddsd.lpSurface;
+
+
+ // Copy from the input bitmap into the texture
+ for (i=0; i<height; i++) {
+ GLubyte byte;
+ pBits = (D3DCOLOR*)((BYTE*)ddsd.lpSurface + (i*ddsd.lPitch));
+ src = (const GLubyte *) _mesa_image_address(
+ &_mesa_native_packing, pTempBitmap, width, height, GL_COLOR_INDEX, GL_BITMAP,
+ 0, i, 0);
+ for (j=0; j<(width>>3); j++) {
+ byte = *src++;
+ for (k=0; k<8; k++) {
+ *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero;
+ byte <<= 1;
+ }
+ }
+ // Fill remaining bits from bitmap
+ if (width & 7) {
+ byte = *src;
+ for (k=0; k<(width & 7); k++) {
+ *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero;
+ byte <<= 1;
+ }
+ }
+ }
+
+ // We're done with the unpacked bitmap
+ FREE(pTempBitmap);
+
+ // Finished with texture surface - unlock it
+ IDirectDrawSurface7_Unlock(pImage, NULL);
+
+ // Use internal function to draw bitmap onto rendertarget
+ _gldDrawPixels(ctx, TRUE, x, y, width, height, pImage);
+
+ // We're done with the bitmap texure - release it
+ IDirectDrawSurface7_Release(pImage);
+}
+
+//---------------------------------------------------------------------------
+// Texture functions
+//---------------------------------------------------------------------------
+
+void _gldAllocateTexture(
+ GLcontext *ctx,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ HRESULT hr;
+ IDirectDrawSurface7 *pTex;
+ D3DX_SURFACEFORMAT d3dFormat;
+ DWORD dwFlags;
+ DWORD dwMipmaps;
+ DWORD dwWidth, dwHeight;
+
+ if (!tObj || !texImage)
+ return;
+
+ pTex = (IDirectDrawSurface7*)tObj->DriverData;
+ if (pTex) {
+ // Decide whether we can keep existing D3D texture
+ // by examining top-level surface.
+ DDSURFACEDESC2 ddsd;
+ ddsd.dwSize = sizeof(DDSURFACEDESC2);
+ _GLD_DX7_TEX(GetSurfaceDesc(pTex, &ddsd));
+ // Release existing texture if not compatible
+ if ((ddsd.dwWidth == texImage->Width) ||
+ (ddsd.dwHeight == texImage->Height))
+ {
+ return; // Keep the existing texture
+ }
+ tObj->DriverData = NULL;
+ _GLD_DX7_TEX(Release(pTex));
+ }
+
+ dwFlags = (glb.bUseMipmaps) ? 0 : D3DX_TEXTURE_NOMIPMAP;
+ dwMipmaps = (glb.bUseMipmaps) ? D3DX_DEFAULT : 1;
+ dwWidth = texImage->Width;
+ dwHeight = texImage->Height;
+
+ d3dFormat = _gldGLFormatToD3DFormat(texImage->IntFormat);
+ hr = D3DXCreateTexture(
+ gld->pDev,
+ &dwFlags,
+ &dwWidth,
+ &dwHeight,
+ &d3dFormat,
+ NULL,
+ &pTex,
+ &dwMipmaps);
+ if (FAILED(hr)) {
+ gldLogError(GLDLOG_ERROR, "AllocateTexture failed", hr);
+ }
+ tObj->DriverData = pTex;
+}
+
+//---------------------------------------------------------------------------
+
+const struct gl_texture_format* gld_ChooseTextureFormat_DX7(
+ GLcontext *ctx,
+ GLint internalFormat,
+ GLenum srcFormat,
+ GLenum srcType)
+{
+ // [Based on mesa_choose_tex_format()]
+ //
+ // We will choose only texture formats that are supported
+ // by Direct3D. If the hardware doesn't support a particular
+ // texture format, then the D3DX texture calls that we use
+ // will automatically use a HW supported format.
+ //
+ // The most critical aim is to reduce copying; if we can use
+ // texture-image data directly then it will be a big performance assist.
+ //
+
+ switch (internalFormat) {
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ return &_mesa_texformat_l8; // D3DFMT_L8
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return &_mesa_texformat_l8; // D3DFMT_L8
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return &_mesa_texformat_a8; // D3DFMT_A8
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ return &_mesa_texformat_rgb565; // D3DFMT_R5G6B5
+ // Mesa will convert this for us later...
+ // return &_mesa_texformat_ci8; // D3DFMT_R5G6B5
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ return &_mesa_texformat_al88; // D3DFMT_A8L8
+ case GL_R3_G3_B2:
+ return &_mesa_texformat_rgb332; // D3DFMT_R3G3B2
+ case GL_RGB4:
+ case GL_RGBA4:
+ case GL_RGBA2:
+ return &_mesa_texformat_argb4444; // D3DFMT_A4R4G4B4
+ case 3:
+ case GL_RGB:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return &_mesa_texformat_rgb565;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return &_mesa_texformat_argb8888;
+ case GL_RGB5_A1:
+ return &_mesa_texformat_argb1555;
+ default:
+ _mesa_problem(NULL, "unexpected format in fxDDChooseTextureFormat");
+ return NULL;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+/*
+// Safer(?), slower version.
+void gld_TexImage2D_DX7(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint internalFormat,
+ GLint width,
+ GLint height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ IDirect3DTexture8 *pTex;
+ IDirect3DSurface8 *pSurface;
+ RECT rcSrcRect;
+ HRESULT hr;
+ GLint texelBytes = 4;
+ GLvoid *tempImage;
+
+ if (!tObj || !texImage)
+ return;
+
+ if (level == 0) {
+ _gldAllocateTexture(ctx, tObj, texImage);
+ }
+
+ pTex = (IDirect3DTexture8*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= IDirect3DTexture8_GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = IDirect3DTexture8_GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ tempImage = MALLOC(width * height * texelBytes);
+ if (!tempImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ IDirect3DSurface8_Release(pSurface);
+ return;
+ }
+ // unpack image, apply transfer ops and store in tempImage
+ _mesa_transfer_teximage(ctx, 2, texImage->Format,
+ &_mesa_texformat_argb8888, // dest format
+ tempImage,
+ width, height, 1, 0, 0, 0,
+ width * texelBytes,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+ SetRect(&rcSrcRect, 0, 0, width, height);
+ D3DXLoadSurfaceFromMemory(
+ pSurface,
+ NULL,
+ NULL,
+ tempImage,
+ D3DFMT_A8R8G8B8,
+ width * texelBytes,
+ NULL,
+ &rcSrcRect,
+ D3DX_FILTER_NONE,
+ 0);
+
+ FREE(tempImage);
+ IDirect3DSurface8_Release(pSurface);
+}
+*/
+
+//---------------------------------------------------------------------------
+
+// Faster, more efficient version.
+// Copies subimage straight to dest texture
+void gld_TexImage2D_DX7(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint internalFormat,
+ GLint width,
+ GLint height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ IDirectDrawSurface7 *pTex = NULL;
+ IDirectDrawSurface7 *pSurface = NULL;
+ HRESULT hr;
+ DDSURFACEDESC2 ddsd;
+ int i;
+ DDSCAPS2 ddsCaps;
+
+ if (!tObj || !texImage)
+ return;
+
+ // GLQUAKE FIX
+ // Test for input alpha data with non-alpha internalformat
+ if (((internalFormat==3) || (internalFormat==GL_RGB)) && (format==GL_RGBA)) {
+ // Input format has alpha, but a non-alpha format has been requested.
+ texImage->IntFormat = GL_RGBA;
+ internalFormat = GL_RGBA;
+ }
+
+ if (level == 0) {
+ _gldAllocateTexture(ctx, tObj, texImage);
+ }
+
+ pTex = (IDirectDrawSurface7*)tObj->DriverData;
+ if (!pTex) {
+ ASSERT(0);
+ return; // Texture has not been created
+ }
+
+ pSurface = pTex;
+ if (level != 0) {
+ ddsd.dwSize = sizeof(ddsd);
+ _GLD_DX7_TEX(GetSurfaceDesc(pTex, &ddsd));
+ if ((level > 0) && (level >= ddsd.dwMipMapCount))
+ return; // Level does not exist
+ ZeroMemory(&ddsCaps, sizeof(ddsCaps));
+ for (i=0; i<level; i++) {
+ ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
+ hr = IDirectDrawSurface7_GetAttachedSurface(
+ pSurface,
+ &ddsCaps,
+ &pSurface);
+ if (SUCCEEDED(hr)) {
+ IDirectDrawSurface7_Release(pSurface);
+ } else {
+ ;
+ }
+ }
+ }
+
+ // Lock all of surface
+ ddsd.dwSize = sizeof(ddsd);
+ hr = IDirectDrawSurface7_Lock(pSurface, NULL, &ddsd, 0, 0);
+ if (FAILED(hr)) {
+ IDirectDrawSurface7_Release(pSurface);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store directly in texture
+ _mesa_transfer_teximage(
+ ctx,
+ 2,
+ texImage->Format,
+ //_gldMesaFormatForD3DFormat(d3dsd.Format),
+ _gldMesaFormatForD3DFormat(_gldD3DXFormatFromSurface(pSurface)),
+ ddsd.lpSurface,
+ width, height, 1, 0, 0, 0,
+ ddsd.lPitch,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+ IDirectDrawSurface7_Unlock(pSurface, NULL);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_TexImage1D_DX7(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ // A 1D texture is a 2D texture with a height of zero
+ gld_TexImage2D_DX7(ctx, target, level, internalFormat, width, 1, border, format, type, pixels, packing, texObj, texImage);
+}
+
+//---------------------------------------------------------------------------
+
+/*
+void gld_TexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage )
+{
+ GLD_GET_CONTEXT
+ IDirect3DTexture8 *pTex;
+ IDirect3DSurface8 *pSurface;
+ D3DFORMAT d3dFormat;
+ HRESULT hr;
+ GLint texelBytes = 4;
+ GLvoid *tempImage;
+ RECT rcSrcRect;
+ RECT rcDstRect;
+
+ if (!tObj || !texImage)
+ return;
+
+ pTex = (IDirect3DTexture8*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= _GLD_DX8_TEX(GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = _GLD_DX8_TEX(GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ d3dFormat = _gldGLFormatToD3DFormat(texImage->Format);
+ tempImage = MALLOC(width * height * texelBytes);
+ if (!tempImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ IDirect3DSurface8_Release(pSurface);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store in tempImage
+ _mesa_transfer_teximage(ctx, 2, texImage->Format,
+ &_mesa_texformat_argb8888, // dest format
+ tempImage,
+ width, height, 1, 0, 0, 0,
+ width * texelBytes,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+ // Source rectangle is whole of input image
+ SetRect(&rcSrcRect, 0, 0, width, height);
+
+ // Dest rectangle must be offset to dest image
+ SetRect(&rcDstRect, 0, 0, width, height);
+ OffsetRect(&rcDstRect, xoffset, yoffset);
+
+ D3DXLoadSurfaceFromMemory(
+ pSurface,
+ NULL,
+ &rcDstRect,
+ tempImage,
+ D3DFMT_A8R8G8B8,
+ width * texelBytes,
+ NULL,
+ &rcSrcRect,
+ D3DX_FILTER_NONE,
+ 0);
+
+ FREE(tempImage);
+ IDirect3DSurface8_Release(pSurface);
+}
+*/
+
+//---------------------------------------------------------------------------
+
+// Faster, more efficient version.
+// Copies subimage straight to dest texture
+void gld_TexSubImage2D_DX7( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ IDirectDrawSurface7 *pTex;
+ IDirectDrawSurface7 *pSurface;
+ HRESULT hr;
+ RECT rcDstRect;
+ DDSURFACEDESC2 ddsd;
+ int i;
+ DDSCAPS2 ddsCaps;
+
+ if (!tObj || !texImage)
+ return;
+
+ pTex = (IDirectDrawSurface7*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+
+ __try {
+
+ ddsd.dwSize = sizeof(ddsd);
+ _GLD_DX7_TEX(GetSurfaceDesc(pTex, &ddsd));
+ if ((level > 0) && (level >= ddsd.dwMipMapCount))
+ return; // Level does not exist
+
+ ZeroMemory(&ddsCaps, sizeof(ddsCaps));
+ pSurface = pTex;
+ for (i=0; i<level; i++) {
+ ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
+ hr = IDirectDrawSurface7_GetAttachedSurface(
+ pSurface,
+ &ddsCaps,
+ &pSurface);
+ if(SUCCEEDED(hr)) {
+ IDirectDrawSurface7_Release(pSurface);
+ } else {
+ return;
+ }
+ }
+
+ // Dest rectangle must be offset to dest image
+ SetRect(&rcDstRect, 0, 0, width, height);
+ OffsetRect(&rcDstRect, xoffset, yoffset);
+
+ // Lock sub-rect of surface
+ hr = IDirectDrawSurface7_Lock(pSurface, &rcDstRect, &ddsd, 0, 0);
+ if (FAILED(hr)) {
+ IDirectDrawSurface7_Release(pSurface);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store directly in texture
+ _mesa_transfer_teximage(ctx, 2, texImage->Format,
+ _gldMesaFormatForD3DFormat(_gldD3DXFormatFromSurface(pSurface)),
+ ddsd.lpSurface,
+ width, height, 1,
+ 0, 0, 0, // NOTE: d3dLockedRect.pBits is already offset!!!
+ ddsd.lPitch,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+
+ IDirectDrawSurface7_Unlock(pSurface, &rcDstRect);
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ ;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void gld_TexSubImage1D_DX7( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLsizei width,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ gld_TexSubImage2D_DX7(ctx, target, level, xoffset, 0, width, 1, format, type, pixels, packing, texObj, texImage);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_DeleteTexture_DX7(
+ GLcontext *ctx,
+ struct gl_texture_object *tObj)
+{
+ GLD_context *gld = (GLD_context*)(ctx->DriverCtx);
+
+ __try {
+
+ if (tObj) {
+ IDirectDrawSurface7 *pTex = (IDirectDrawSurface7*)tObj->DriverData;
+ if (pTex) {
+/* // Make sure texture is not bound to a stage before releasing it
+ for (int i=0; i<MAX_TEXTURE_UNITS; i++) {
+ if (gld->CurrentTexture[i] == pTex) {
+ gld->pDev->SetTexture(i, NULL);
+ gld->CurrentTexture[i] = NULL;
+ }
+ }*/
+ _GLD_DX7_TEX(Release(pTex));
+ tObj->DriverData = NULL;
+ }
+ }
+
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ ;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+__inline void _gldSetColorOps(
+ const GLD_driver_dx7 *gld,
+ GLuint unit,
+ DWORD ColorArg1,
+ D3DTEXTUREOP ColorOp,
+ DWORD ColorArg2)
+{
+ _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG1, ColorArg1));
+ _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLOROP, ColorOp));
+ _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG2, ColorArg2));
+}
+
+//---------------------------------------------------------------------------
+
+__inline void _gldSetAlphaOps(
+ const GLD_driver_dx7 *gld,
+ GLuint unit,
+ DWORD AlphaArg1,
+ D3DTEXTUREOP AlphaOp,
+ DWORD AlphaArg2)
+{
+ _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG1, AlphaArg1));
+ _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAOP, AlphaOp));
+ _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG2, AlphaArg2));
+}
+
+//---------------------------------------------------------------------------
+
+void gldUpdateTextureUnit(
+ GLcontext *ctx,
+ GLuint unit,
+ BOOL bPassThrough)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ D3DTEXTUREMINFILTER minfilter;
+ D3DTEXTUREMIPFILTER mipfilter;
+ GLenum BaseFormat;
+ DWORD dwColorArg0;
+ int iTexEnv = 0;
+ GLD_texenv *pTexenv;
+
+ // NOTE: If bPassThrough is FALSE then texture stage can be
+ // disabled otherwise it must pass-through it's current fragment.
+
+ const struct gl_texture_unit *pUnit = &ctx->Texture.Unit[unit];
+ const struct gl_texture_object *tObj = pUnit->_Current;
+
+ IDirectDrawSurface7 *pTex = NULL;
+ if (tObj) {
+ pTex = (IDirectDrawSurface7*)tObj->DriverData;
+ }
+
+ __try {
+
+ // Enable texturing if unit is enabled and a valid D3D texture exists
+ // Mesa 5: TEXTUREn_x altered to TEXTURE_nD_BIT
+ //if (pTex && (pUnit->Enabled & (TEXTURE0_1D | TEXTURE0_2D))) {
+ if (pTex && (pUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT))) {
+ // Enable texturing
+ _GLD_DX7_DEV(SetTexture(gld->pDev, unit, pTex));
+ } else {
+ // Disable texturing, then return
+ _GLD_DX7_DEV(SetTexture(gld->pDev, unit, NULL));
+ if (bPassThrough) {
+ _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE);
+ _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE);
+ } else {
+ _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE);
+ _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE);
+ }
+ return;
+ }
+
+ // Texture parameters
+ _gldConvertMinFilter(tObj->MinFilter, &minfilter, &mipfilter);
+ _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MINFILTER, minfilter));
+ _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MIPFILTER, mipfilter));
+ _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MAGFILTER, _gldConvertMagFilter(tObj->MagFilter)));
+ _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSU, _gldConvertWrap(tObj->WrapS)));
+ _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSV, _gldConvertWrap(tObj->WrapT)));
+
+ // Texture priority
+ _GLD_DX7_TEX(SetPriority(pTex, (DWORD)(tObj->Priority*65535.0f)));
+
+ // Texture environment
+ // TODO: Examine input texture for alpha and use specific alpha/non-alpha ops.
+ // See Page 355 of the Red Book.
+ BaseFormat = _gldDecodeBaseFormat(pTex);
+
+ switch (BaseFormat) {
+ case GL_RGB:
+ iTexEnv = 0;
+ break;
+ case GL_RGBA:
+ iTexEnv = 1;
+ break;
+ case GL_ALPHA:
+ iTexEnv = 2;
+ break;
+ }
+
+ switch (pUnit->EnvMode) {
+ case GL_DECAL:
+ iTexEnv += 0;
+ break;
+ case GL_REPLACE:
+ iTexEnv += 3;
+ break;
+ case GL_MODULATE:
+ iTexEnv += 6;
+ break;
+ case GL_BLEND:
+ // Set blend colour
+ // Unsupported by DX7
+// dwColorArg0 = D3DCOLOR_COLORVALUE(pUnit->EnvColor[0], pUnit->EnvColor[1], pUnit->EnvColor[2], pUnit->EnvColor[3]);
+// _GLD_DX7_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG0, dwColorArg0));
+// gldLogMessage(GLDLOG_WARN, "GL_BLEND\n");
+ iTexEnv += 9;
+ break;
+ case GL_ADD:
+ iTexEnv += 12;
+ break;
+ }
+ pTexenv = (GLD_texenv*)&gldTexEnv[iTexEnv];
+ _gldSetColorOps(gld, unit, pTexenv->ColorArg1, pTexenv->ColorOp, pTexenv->ColorArg2);
+ _gldSetAlphaOps(gld, unit, pTexenv->AlphaArg1, pTexenv->AlphaOp, pTexenv->AlphaArg2);
+
+ }
+ __except(EXCEPTION_EXECUTE_HANDLER) {
+ ;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_TEXTURE_DX7(
+ GLcontext *ctx)
+{
+ // TODO: Support for three (ATI Radeon) or more (nVidia GeForce3) texture units
+
+ BOOL bUnit0Enabled;
+ BOOL bUnit1Enabled;
+
+ if (!ctx)
+ return; // Sanity check
+
+ if (ctx->Const.MaxTextureUnits == 1) {
+ gldUpdateTextureUnit(ctx, 0, TRUE);
+ return;
+ }
+
+ //
+ // NOTE: THE FOLLOWING RELATES TO TWO TEXTURE UNITS, AND TWO ONLY!!
+ //
+
+ // Mesa 5: Texture Units altered
+ bUnit0Enabled = (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE;
+ bUnit1Enabled = (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE;
+
+ // If Unit0 is disabled and Unit1 is enabled then we must pass-though
+ gldUpdateTextureUnit(ctx, 0, (!bUnit0Enabled && bUnit1Enabled) ? TRUE : FALSE);
+ // We can always disable the last texture unit
+ gldUpdateTextureUnit(ctx, 1, FALSE);
+
+#ifdef _DEBUG
+ {
+ // Find out whether device supports current renderstates
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ DWORD dwPasses;
+ _GLD_DX7_DEV(ValidateDevice(gld->pDev, &dwPasses));
+#if 0
+ if (FAILED(hr)) {
+ gldLogError(GLDLOG_ERROR, "ValidateDevice failed", hr);
+ }
+#endif
+ if (dwPasses != 1) {
+ gldLogMessage(GLDLOG_ERROR, "ValidateDevice: Can't do in one pass\n");
+ }
+ }
+#endif
+};
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_vb_d3d_render_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_vb_d3d_render_dx7.c
new file mode 100644
index 0000000000..cecfaa5f70
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_vb_d3d_render_dx7.c
@@ -0,0 +1,288 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GLDirect fastpath pipeline stage
+*
+****************************************************************************/
+
+//---------------------------------------------------------------------------
+
+//#include "../GLDirect.h"
+//#include "../gld_log.h"
+//#include "gld_dx8.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx7.h"
+
+//---------------------------------------------------------------------------
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+// #include "mem.h"
+#include "mtypes.h"
+#include "mmath.h"
+
+#include "math/m_matrix.h"
+#include "math/m_xform.h"
+
+#include "tnl/t_pipeline.h"
+
+//---------------------------------------------------------------------------
+/*
+__inline void _gldSetVertexShaderConstants(
+ GLcontext *ctx,
+ GLD_driver_dx8 *gld)
+{
+ D3DXMATRIX mat, matView, matProj;
+ GLfloat *pM;
+
+ // Mesa 5: Altered to a Stack
+ //pM = ctx->ModelView.m;
+ pM = ctx->ModelviewMatrixStack.Top->m;
+ matView._11 = pM[0];
+ matView._12 = pM[1];
+ matView._13 = pM[2];
+ matView._14 = pM[3];
+ matView._21 = pM[4];
+ matView._22 = pM[5];
+ matView._23 = pM[6];
+ matView._24 = pM[7];
+ matView._31 = pM[8];
+ matView._32 = pM[9];
+ matView._33 = pM[10];
+ matView._34 = pM[11];
+ matView._41 = pM[12];
+ matView._42 = pM[13];
+ matView._43 = pM[14];
+ matView._44 = pM[15];
+
+ // Mesa 5: Altered to a Stack
+ //pM = ctx->ProjectionMatrix.m;
+ pM = ctx->ProjectionMatrixStack.Top->m;
+ matProj._11 = pM[0];
+ matProj._12 = pM[1];
+ matProj._13 = pM[2];
+ matProj._14 = pM[3];
+ matProj._21 = pM[4];
+ matProj._22 = pM[5];
+ matProj._23 = pM[6];
+ matProj._24 = pM[7];
+ matProj._31 = pM[8];
+ matProj._32 = pM[9];
+ matProj._33 = pM[10];
+ matProj._34 = pM[11];
+ matProj._41 = pM[12];
+ matProj._42 = pM[13];
+ matProj._43 = pM[14];
+ matProj._44 = pM[15];
+
+ D3DXMatrixMultiply( &mat, &matView, &matProj );
+ D3DXMatrixTranspose( &mat, &mat );
+
+ _GLD_DX8_DEV(SetVertexShaderConstant(gld->pDev, 0, &mat, 4));
+}
+*/
+//---------------------------------------------------------------------------
+
+static GLboolean gld_d3d_render_stage_run(
+ GLcontext *ctx,
+ struct gl_pipeline_stage *stage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ TNLcontext *tnl;
+ struct vertex_buffer *VB;
+ GLuint new_inputs;
+ render_func *tab;
+ GLint pass;
+ GLD_pb_dx7 *gldPB = &gld->PB3d;
+ DWORD dwFlags;
+
+/*
+ static int count = 0;
+ count++;
+ if (count != 2)
+ return GL_FALSE;
+*/
+ // The "check" function should disable this stage,
+ // but we'll test gld->bUseMesaTnL anyway.
+ if (gld->bUseMesaTnL) {
+ // Do nothing in this stage, but continue pipeline
+ return GL_FALSE;
+ }
+
+ tnl = TNL_CONTEXT(ctx);
+ VB = &tnl->vb;
+ new_inputs = stage->changed_inputs;
+ pass = 0;
+
+ tnl->Driver.Render.Start( ctx );
+
+#if 0
+ // For debugging: Useful to see if an app passes colour data in
+ // an unusual format.
+ switch (VB->ColorPtr[0]->Type) {
+ case GL_FLOAT:
+ ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_FLOAT\n");
+ break;
+ case GL_UNSIGNED_BYTE:
+ ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_UNSIGNED_BYTE\n");
+ break;
+ default:
+ ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: *?*\n");
+ break;
+ }
+#endif
+
+ tnl->Driver.Render.Points = gld_Points3D_DX7;
+ if (ctx->_TriangleCaps & DD_FLATSHADE) {
+ tnl->Driver.Render.Line = gld_Line3DFlat_DX7;
+ tnl->Driver.Render.Triangle = gld_Triangle3DFlat_DX7;
+ tnl->Driver.Render.Quad = gld_Quad3DFlat_DX7;
+ } else {
+ tnl->Driver.Render.Line = gld_Line3DSmooth_DX7;
+ tnl->Driver.Render.Triangle = gld_Triangle3DSmooth_DX7;
+ tnl->Driver.Render.Quad = gld_Quad3DSmooth_DX7;
+ }
+
+// _GLD_DX7_VB(Lock(gldPB->pVB, 0, 0, &gldPB->pPoints, D3DLOCK_DISCARD));
+ dwFlags = DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY;
+ _GLD_DX7_VB(Lock(gldPB->pVB, dwFlags, &gldPB->pPoints, NULL));
+ gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0;
+ // Allocate primitive pointers
+ // gldPB->pPoints is always first
+ gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine);
+ gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle);
+
+ ASSERT(tnl->Driver.Render.BuildVertices);
+ ASSERT(tnl->Driver.Render.PrimitiveNotify);
+ ASSERT(tnl->Driver.Render.Points);
+ ASSERT(tnl->Driver.Render.Line);
+ ASSERT(tnl->Driver.Render.Triangle);
+ ASSERT(tnl->Driver.Render.Quad);
+ ASSERT(tnl->Driver.Render.ResetLineStipple);
+ ASSERT(tnl->Driver.Render.Interp);
+ ASSERT(tnl->Driver.Render.CopyPV);
+ ASSERT(tnl->Driver.Render.ClippedLine);
+ ASSERT(tnl->Driver.Render.ClippedPolygon);
+ ASSERT(tnl->Driver.Render.Finish);
+
+ tab = (VB->Elts ? tnl->Driver.Render.PrimTabElts : tnl->Driver.Render.PrimTabVerts);
+
+ do {
+ GLuint i, length, flags = 0;
+ for (i = 0 ; !(flags & PRIM_LAST) ; i += length)
+ {
+ flags = VB->Primitive[i];
+ length= VB->PrimitiveLength[i];
+ ASSERT(length || (flags & PRIM_LAST));
+ ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1);
+ if (length)
+ tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags );
+ }
+ } while (tnl->Driver.Render.Multipass &&
+ tnl->Driver.Render.Multipass( ctx, ++pass ));
+
+ _GLD_DX7_VB(Unlock(gldPB->pVB));
+
+// _GLD_DX7_DEV(SetStreamSource(gld->pDev, 0, gldPB->pVB, gldPB->dwStride));
+
+ _GLD_DX7_DEV(SetTransform(gld->pDev, D3DTRANSFORMSTATE_PROJECTION, &gld->matProjection));
+ _GLD_DX7_DEV(SetTransform(gld->pDev, D3DTRANSFORMSTATE_WORLD, &gld->matModelView));
+
+ if (gldPB->nPoints) {
+// _GLD_DX7_DEV(DrawPrimitive(gld->pDev, D3DPT_POINTLIST, 0, gldPB->nPoints));
+ _GLD_DX7_DEV(DrawPrimitiveVB(gld->pDev, D3DPT_POINTLIST, gldPB->pVB, 0, gldPB->nPoints, 0));
+ gldPB->nPoints = 0;
+ }
+
+ if (gldPB->nLines) {
+// _GLD_DX7_DEV(DrawPrimitive(gld->pDev, D3DPT_LINELIST, gldPB->iFirstLine, gldPB->nLines));
+ _GLD_DX7_DEV(DrawPrimitiveVB(gld->pDev, D3DPT_LINELIST, gldPB->pVB, gldPB->iFirstLine, gldPB->nLines, 0));
+ gldPB->nLines = 0;
+ }
+
+ if (gldPB->nTriangles) {
+// _GLD_DX7_DEV(DrawPrimitive(gld->pDev, D3DPT_TRIANGLELIST, gldPB->iFirstTriangle, gldPB->nTriangles));
+ _GLD_DX7_DEV(DrawPrimitiveVB(gld->pDev, D3DPT_TRIANGLELIST, gldPB->pVB, gldPB->iFirstTriangle, gldPB->nTriangles, 0));
+ gldPB->nTriangles = 0;
+ }
+
+ return GL_FALSE; /* finished the pipe */
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_d3d_render_stage_check(
+ GLcontext *ctx,
+ struct gl_pipeline_stage *stage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+ // Is this thread safe?
+ stage->active = (gld->bUseMesaTnL) ? GL_FALSE : GL_TRUE;
+ return;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_d3d_render_stage_dtr( struct gl_pipeline_stage *stage )
+{
+}
+
+//---------------------------------------------------------------------------
+
+const struct gl_pipeline_stage _gld_d3d_render_stage =
+{
+ "gld_d3d_render_stage",
+ (_NEW_BUFFERS |
+ _DD_NEW_SEPARATE_SPECULAR |
+ _DD_NEW_FLATSHADE |
+ _NEW_TEXTURE|
+ _NEW_LIGHT|
+ _NEW_POINT|
+ _NEW_FOG|
+ _DD_NEW_TRI_UNFILLED |
+ _NEW_RENDERMODE), /* re-check (new inputs, interp function) */
+ 0, /* re-run (always runs) */
+ GL_TRUE, /* active */
+ 0, 0, /* inputs (set in check_render), outputs */
+ 0, 0, /* changed_inputs, private */
+ gld_d3d_render_stage_dtr, /* destructor */
+ gld_d3d_render_stage_check, /* check */
+ gld_d3d_render_stage_run /* run */
+};
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_vb_mesa_render_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_vb_mesa_render_dx7.c
new file mode 100644
index 0000000000..f122d25c74
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_vb_mesa_render_dx7.c
@@ -0,0 +1,490 @@
+/* $Id: gld_vb_mesa_render_dx7.c,v 1.1 2004/04/20 11:13:11 alanh Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keithw@valinux.com>
+ */
+
+
+/*
+ * Render whole vertex buffers, including projection of vertices from
+ * clip space and clipping of primitives.
+ *
+ * This file makes calls to project vertices and to the point, line
+ * and triangle rasterizers via the function pointers:
+ *
+ * context->Driver.Render.*
+ *
+ */
+
+
+//---------------------------------------------------------------------------
+
+//#include "../GLDirect.h"
+//#include "../gld_log.h"
+//#include "gld_dx8.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx7.h"
+
+//---------------------------------------------------------------------------
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+// #include "mem.h"
+#include "mtypes.h"
+#include "mmath.h"
+
+#include "math/m_matrix.h"
+#include "math/m_xform.h"
+
+#include "tnl/t_pipeline.h"
+
+/**********************************************************************/
+/* Clip single primitives */
+/**********************************************************************/
+
+
+#if defined(USE_IEEE)
+#define NEGATIVE(x) (GET_FLOAT_BITS(x) & (1<<31))
+#define DIFFERENT_SIGNS(x,y) ((GET_FLOAT_BITS(x) ^ GET_FLOAT_BITS(y)) & (1<<31))
+#else
+#define NEGATIVE(x) (x < 0)
+#define DIFFERENT_SIGNS(x,y) (x * y <= 0 && x - y != 0)
+/* Could just use (x*y<0) except for the flatshading requirements.
+ * Maybe there's a better way?
+ */
+#endif
+
+
+#define W(i) coord[i][3]
+#define Z(i) coord[i][2]
+#define Y(i) coord[i][1]
+#define X(i) coord[i][0]
+#define SIZE 4
+#define TAG(x) x##_4
+#include "tnl/t_vb_cliptmp.h"
+
+
+
+/**********************************************************************/
+/* Clip and render whole begin/end objects */
+/**********************************************************************/
+
+#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED)
+#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
+#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
+
+
+/* Vertices, with the possibility of clipping.
+ */
+#define RENDER_POINTS( start, count ) \
+ tnl->Driver.Render.Points( ctx, start, count )
+
+#define RENDER_LINE( v1, v2 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2]; \
+ GLubyte ormask = c1|c2; \
+ if (!ormask) \
+ LineFunc( ctx, v1, v2 ); \
+ else if (!(c1 & c2 & 0x3f)) \
+ clip_line_4( ctx, v1, v2, ormask ); \
+} while (0)
+
+#define RENDER_TRI( v1, v2, v3 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2], c3 = mask[v3]; \
+ GLubyte ormask = c1|c2|c3; \
+ if (!ormask) \
+ TriangleFunc( ctx, v1, v2, v3 ); \
+ else if (!(c1 & c2 & c3 & 0x3f)) \
+ clip_tri_4( ctx, v1, v2, v3, ormask ); \
+} while (0)
+
+#define RENDER_QUAD( v1, v2, v3, v4 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2]; \
+ GLubyte c3 = mask[v3], c4 = mask[v4]; \
+ GLubyte ormask = c1|c2|c3|c4; \
+ if (!ormask) \
+ QuadFunc( ctx, v1, v2, v3, v4 ); \
+ else if (!(c1 & c2 & c3 & c4 & 0x3f)) \
+ clip_quad_4( ctx, v1, v2, v3, v4, ormask ); \
+} while (0)
+
+
+#define LOCAL_VARS \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ const GLuint * const elt = VB->Elts; \
+ const GLubyte *mask = VB->ClipMask; \
+ const GLuint sz = VB->ClipPtr->size; \
+ const line_func LineFunc = tnl->Driver.Render.Line; \
+ const triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
+ const quad_func QuadFunc = tnl->Driver.Render.Quad; \
+ const GLboolean stipple = ctx->Line.StippleFlag; \
+ (void) (LineFunc && TriangleFunc && QuadFunc); \
+ (void) elt; (void) mask; (void) sz; (void) stipple;
+
+#define TAG(x) clip_##x##_verts
+#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
+#define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx )
+#define RESET_OCCLUSION ctx->OcclusionResult = GL_TRUE
+#define PRESERVE_VB_DEFS
+#include "tnl/t_vb_rendertmp.h"
+
+
+
+/* Elts, with the possibility of clipping.
+ */
+#undef ELT
+#undef TAG
+#define ELT(x) elt[x]
+#define TAG(x) clip_##x##_elts
+#include "tnl/t_vb_rendertmp.h"
+
+/* TODO: do this for all primitives, verts and elts:
+ */
+static void clip_elt_triangles( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ render_func render_tris = tnl->Driver.Render.PrimTabElts[GL_TRIANGLES];
+ struct vertex_buffer *VB = &tnl->vb;
+ const GLuint * const elt = VB->Elts;
+ GLubyte *mask = VB->ClipMask;
+ GLuint last = count-2;
+ GLuint j;
+ (void) flags;
+
+ tnl->Driver.Render.PrimitiveNotify( ctx, GL_TRIANGLES );
+
+ for (j=start; j < last; j+=3 ) {
+ GLubyte c1 = mask[elt[j]];
+ GLubyte c2 = mask[elt[j+1]];
+ GLubyte c3 = mask[elt[j+2]];
+ GLubyte ormask = c1|c2|c3;
+ if (ormask) {
+ if (start < j)
+ render_tris( ctx, start, j, 0 );
+ if (!(c1&c2&c3&0x3f))
+ clip_tri_4( ctx, elt[j], elt[j+1], elt[j+2], ormask );
+ start = j+3;
+ }
+ }
+
+ if (start < j)
+ render_tris( ctx, start, j, 0 );
+}
+
+/**********************************************************************/
+/* Render whole begin/end objects */
+/**********************************************************************/
+
+#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED)
+#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
+#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
+
+
+/* Vertices, no clipping.
+ */
+#define RENDER_POINTS( start, count ) \
+ tnl->Driver.Render.Points( ctx, start, count )
+
+#define RENDER_LINE( v1, v2 ) \
+ LineFunc( ctx, v1, v2 )
+
+#define RENDER_TRI( v1, v2, v3 ) \
+ TriangleFunc( ctx, v1, v2, v3 )
+
+#define RENDER_QUAD( v1, v2, v3, v4 ) \
+ QuadFunc( ctx, v1, v2, v3, v4 )
+
+#define TAG(x) _gld_tnl_##x##_verts
+
+#define LOCAL_VARS \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ const GLuint * const elt = VB->Elts; \
+ const line_func LineFunc = tnl->Driver.Render.Line; \
+ const triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
+ const quad_func QuadFunc = tnl->Driver.Render.Quad; \
+ (void) (LineFunc && TriangleFunc && QuadFunc); \
+ (void) elt;
+
+#define RESET_STIPPLE tnl->Driver.Render.ResetLineStipple( ctx )
+#define RESET_OCCLUSION ctx->OcclusionResult = GL_TRUE
+#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
+#define RENDER_TAB_QUALIFIER
+#define PRESERVE_VB_DEFS
+#include "tnl/t_vb_rendertmp.h"
+
+
+/* Elts, no clipping.
+ */
+#undef ELT
+#define TAG(x) _gld_tnl_##x##_elts
+#define ELT(x) elt[x]
+#include "tnl/t_vb_rendertmp.h"
+
+
+/**********************************************************************/
+/* Helper functions for drivers */
+/**********************************************************************/
+/*
+void _tnl_RenderClippedPolygon( GLcontext *ctx, const GLuint *elts, GLuint n )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint *tmp = VB->Elts;
+
+ VB->Elts = (GLuint *)elts;
+ tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
+ VB->Elts = tmp;
+}
+
+void _tnl_RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->Driver.Render.Line( ctx, ii, jj );
+}
+*/
+
+
+/**********************************************************************/
+/* Clip and render whole vertex buffers */
+/**********************************************************************/
+
+points_func _gldSetupPoints[4] = {
+ gld_Points2D_DX7,
+ gld_Points2D_DX7,
+ gld_Points2D_DX7,
+ gld_Points2D_DX7
+};
+line_func _gldSetupLine[4] = {
+ gld_Line2DFlat_DX7,
+ gld_Line2DSmooth_DX7,
+ gld_Line2DFlat_DX7,
+ gld_Line2DSmooth_DX7,
+};
+triangle_func _gldSetupTriangle[4] = {
+ gld_Triangle2DFlat_DX7,
+ gld_Triangle2DSmooth_DX7,
+ gld_Triangle2DFlatExtras_DX7,
+ gld_Triangle2DSmoothExtras_DX7
+};
+quad_func _gldSetupQuad[4] = {
+ gld_Quad2DFlat_DX7,
+ gld_Quad2DSmooth_DX7,
+ gld_Quad2DFlatExtras_DX7,
+ gld_Quad2DSmoothExtras_DX7
+};
+
+//---------------------------------------------------------------------------
+
+static GLboolean _gld_mesa_render_stage_run(
+ GLcontext *ctx,
+ struct gl_pipeline_stage *stage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx7 *gld = GLD_GET_DX7_DRIVER(gldCtx);
+
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint new_inputs = stage->changed_inputs;
+ render_func *tab;
+ GLint pass = 0;
+ GLD_pb_dx7 *gldPB;
+ DWORD dwFlags;
+
+ /* Allow the drivers to lock before projected verts are built so
+ * that window coordinates are guarenteed not to change before
+ * rendering.
+ */
+ ASSERT(tnl->Driver.Render.Start);
+
+ tnl->Driver.Render.Start( ctx );
+
+ gldPB = &gld->PB2d;
+ tnl->Driver.Render.Points = _gldSetupPoints[gld->iSetupFunc];
+ tnl->Driver.Render.Line = _gldSetupLine[gld->iSetupFunc];
+ tnl->Driver.Render.Triangle = _gldSetupTriangle[gld->iSetupFunc];
+ tnl->Driver.Render.Quad = _gldSetupQuad[gld->iSetupFunc];
+
+ dwFlags = DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY;
+ _GLD_DX7_VB(Lock(gldPB->pVB, dwFlags, &gldPB->pPoints, NULL));
+ gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0;
+
+ // Allocate primitive pointers - gldPB->pPoints is always first
+ gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine);
+ gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle);
+
+ ASSERT(tnl->Driver.Render.BuildVertices);
+ ASSERT(tnl->Driver.Render.PrimitiveNotify);
+ ASSERT(tnl->Driver.Render.Points);
+ ASSERT(tnl->Driver.Render.Line);
+ ASSERT(tnl->Driver.Render.Triangle);
+ ASSERT(tnl->Driver.Render.Quad);
+ ASSERT(tnl->Driver.Render.ResetLineStipple);
+ ASSERT(tnl->Driver.Render.Interp);
+ ASSERT(tnl->Driver.Render.CopyPV);
+ ASSERT(tnl->Driver.Render.ClippedLine);
+ ASSERT(tnl->Driver.Render.ClippedPolygon);
+ ASSERT(tnl->Driver.Render.Finish);
+
+ tnl->Driver.Render.BuildVertices( ctx, 0, VB->Count, new_inputs );
+
+ if (VB->ClipOrMask) {
+ tab = VB->Elts ? clip_render_tab_elts : clip_render_tab_verts;
+ clip_render_tab_elts[GL_TRIANGLES] = clip_elt_triangles;
+ }
+ else {
+ tab = (VB->Elts ?
+ tnl->Driver.Render.PrimTabElts :
+ tnl->Driver.Render.PrimTabVerts);
+ }
+
+ do {
+ GLuint i, length, flags = 0;
+ for (i = 0 ; !(flags & PRIM_LAST) ; i += length) {
+ flags = VB->Primitive[i];
+ length= VB->PrimitiveLength[i];
+ ASSERT(length || (flags & PRIM_LAST));
+ ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1);
+ if (length)
+ tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags );
+ }
+ } while (tnl->Driver.Render.Multipass &&
+ tnl->Driver.Render.Multipass( ctx, ++pass ));
+
+
+// tnl->Driver.Render.Finish( ctx );
+
+ _GLD_DX7_VB(Unlock(gldPB->pVB));
+
+ if (gldPB->nPoints) {
+ _GLD_DX7_DEV(DrawPrimitiveVB(gld->pDev, D3DPT_POINTLIST, gldPB->pVB, 0, gldPB->nPoints, 0));
+ gldPB->nPoints = 0;
+ }
+
+ if (gldPB->nLines) {
+ _GLD_DX7_DEV(DrawPrimitiveVB(gld->pDev, D3DPT_LINELIST, gldPB->pVB, gldPB->iFirstLine, gldPB->nLines*2, 0));
+ gldPB->nLines = 0;
+ }
+
+ if (gldPB->nTriangles) {
+ _GLD_DX7_DEV(DrawPrimitiveVB(gld->pDev, D3DPT_TRIANGLELIST, gldPB->pVB, gldPB->iFirstTriangle, gldPB->nTriangles*3, 0));
+ gldPB->nTriangles = 0;
+ }
+
+ return GL_FALSE; /* finished the pipe */
+}
+
+
+/**********************************************************************/
+/* Render pipeline stage */
+/**********************************************************************/
+
+
+
+/* Quite a bit of work involved in finding out the inputs for the
+ * render stage.
+ */
+static void _gld_mesa_render_stage_check(
+ GLcontext *ctx,
+ struct gl_pipeline_stage *stage)
+{
+ GLuint inputs = VERT_BIT_CLIP;
+ GLuint i;
+
+ if (ctx->Visual.rgbMode) {
+ inputs |= VERT_BIT_COLOR0;
+
+ if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
+ inputs |= VERT_BIT_COLOR1; //VERT_BIT_SPEC_RGB;
+
+ //if (ctx->Texture._ReallyEnabled) {
+ for (i=0; i<ctx->Const.MaxTextureUnits; i++) {
+ if (ctx->Texture.Unit[i]._ReallyEnabled)
+ inputs |= VERT_BIT_TEX(i);
+ }
+ //}
+ } else {
+ inputs |= VERT_BIT_INDEX;
+ }
+
+ if (ctx->Point._Attenuated)
+ inputs |= VERT_BIT_POINT_SIZE;
+
+ /* How do drivers turn this off?
+ */
+ if (ctx->Fog.Enabled)
+ inputs |= VERT_BIT_FOG; // VERT_FOG_COORD;
+
+ if (ctx->_TriangleCaps & DD_TRI_UNFILLED)
+ inputs |= VERT_BIT_EDGEFLAG;
+
+ if (ctx->RenderMode==GL_FEEDBACK)
+ inputs |= VERT_BITS_TEX_ANY;
+
+ stage->inputs = inputs;
+}
+
+//---------------------------------------------------------------------------
+
+// Destructor
+static void _gld_mesa_render_stage_dtr(
+ struct gl_pipeline_stage *stage)
+{
+}
+
+//---------------------------------------------------------------------------
+
+const struct gl_pipeline_stage _gld_mesa_render_stage =
+{
+ "gld_mesa_render_stage",
+ (_NEW_BUFFERS |
+ _DD_NEW_SEPARATE_SPECULAR |
+ _DD_NEW_FLATSHADE |
+ _NEW_TEXTURE|
+ _NEW_LIGHT|
+ _NEW_POINT|
+ _NEW_FOG|
+ _DD_NEW_TRI_UNFILLED |
+ _NEW_RENDERMODE), // re-check (new inputs, interp function)
+ 0, /* re-run (always runs) */
+ GL_TRUE, /* active */
+ 0, 0, /* inputs (set in check_render), outputs */
+ 0, 0, /* changed_inputs, private */
+ _gld_mesa_render_stage_dtr, /* destructor */
+ _gld_mesa_render_stage_check, /* check */
+ _gld_mesa_render_stage_run /* run */
+};
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx7/gld_wgl_dx7.c b/src/mesa/drivers/windows/gldirect/dx7/gld_wgl_dx7.c
new file mode 100644
index 0000000000..8039513080
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx7/gld_wgl_dx7.c
@@ -0,0 +1,1611 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GLDirect Direct3D 8.x WGL (WindowsGL)
+*
+****************************************************************************/
+
+#include "dglcontext.h"
+#include "gld_driver.h"
+//#include "gld_dxerr8.h"
+#include "gld_dx7.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+
+// Copied from dglcontect.c
+#define GLDERR_NONE 0
+#define GLDERR_MEM 1
+#define GLDERR_DDRAW 2
+#define GLDERR_D3D 3
+#define GLDERR_BPP 4
+#define GLDERR_DDS 5
+// This external var keeps track of any error
+extern int nContextError;
+
+// Uncomment this for persistant resources
+//#define _GLD_PERSISTANT
+
+#define DDLOG_CRITICAL_OR_WARN DDLOG_CRITICAL
+
+extern void _gld_mesa_warning(GLcontext *, char *);
+extern void _gld_mesa_fatal(GLcontext *, char *);
+
+//---------------------------------------------------------------------------
+
+static char szColorDepthWarning[] =
+"GLDirect does not support the current desktop\n\
+color depth.\n\n\
+You may need to change the display resolution to\n\
+16 bits per pixel or higher color depth using\n\
+the Windows Display Settings control panel\n\
+before running this OpenGL application.\n";
+
+// The only depth-stencil formats currently supported by Direct3D
+// Surface Format Depth Stencil Total Bits
+// D3DFMT_D32 32 - 32
+// D3DFMT_D15S1 15 1 16
+// D3DFMT_D24S8 24 8 32
+// D3DFMT_D16 16 - 16
+// D3DFMT_D24X8 24 - 32
+// D3DFMT_D24X4S4 24 4 32
+
+// This pixel format will be used as a template when compiling the list
+// of pixel formats supported by the hardware. Many fields will be
+// filled in at runtime.
+// PFD flag defaults are upgraded to match ChoosePixelFormat() -- DaveM
+static DGL_pixelFormat pfTemplateHW =
+{
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), // Size of the data structure
+ 1, // Structure version - should be 1
+ // Flags:
+ PFD_DRAW_TO_WINDOW | // The buffer can draw to a window or device surface.
+ PFD_DRAW_TO_BITMAP | // The buffer can draw to a bitmap. (DaveM)
+ PFD_SUPPORT_GDI | // The buffer supports GDI drawing. (DaveM)
+ PFD_SUPPORT_OPENGL | // The buffer supports OpenGL drawing.
+ PFD_DOUBLEBUFFER | // The buffer is double-buffered.
+ 0, // Placeholder for easy commenting of above flags
+ PFD_TYPE_RGBA, // Pixel type RGBA.
+ 16, // Total colour bitplanes (excluding alpha bitplanes)
+ 5, 0, // Red bits, shift
+ 5, 0, // Green bits, shift
+ 5, 0, // Blue bits, shift
+ 0, 0, // Alpha bits, shift (destination alpha)
+ 0, // Accumulator bits (total)
+ 0, 0, 0, 0, // Accumulator bits: Red, Green, Blue, Alpha
+ 0, // Depth bits
+ 0, // Stencil bits
+ 0, // Number of auxiliary buffers
+ 0, // Layer type
+ 0, // Specifies the number of overlay and underlay planes.
+ 0, // Layer mask
+ 0, // Specifies the transparent color or index of an underlay plane.
+ 0 // Damage mask
+ },
+ D3DX_SF_UNKNOWN, // No depth/stencil buffer
+};
+
+//---------------------------------------------------------------------------
+// Vertex Shaders
+//---------------------------------------------------------------------------
+/*
+// Vertex Shader Declaration
+static DWORD dwTwoSidedLightingDecl[] =
+{
+ D3DVSD_STREAM(0),
+ D3DVSD_REG(0, D3DVSDT_FLOAT3), // XYZ position
+ D3DVSD_REG(1, D3DVSDT_FLOAT3), // XYZ normal
+ D3DVSD_REG(2, D3DVSDT_D3DCOLOR), // Diffuse color
+ D3DVSD_REG(3, D3DVSDT_D3DCOLOR), // Specular color
+ D3DVSD_REG(4, D3DVSDT_FLOAT2), // 2D texture unit 0
+ D3DVSD_REG(5, D3DVSDT_FLOAT2), // 2D texture unit 1
+ D3DVSD_END()
+};
+
+// Vertex Shader for two-sided lighting
+static char *szTwoSidedLightingVS =
+// This is a test shader!
+"vs.1.0\n"
+"m4x4 oPos,v0,c0\n"
+"mov oD0,v2\n"
+"mov oD1,v3\n"
+"mov oT0,v4\n"
+"mov oT1,v5\n"
+;
+*/
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+
+typedef struct {
+// HINSTANCE hD3D8DLL; // Handle to d3d8.dll
+// FNDIRECT3DCREATE7 fnDirect3DCreate7; // Direct3DCreate8 function prototype
+// BOOL bDirect3D; // Persistant Direct3D7 exists
+// BOOL bDirect3DDevice; // Persistant Direct3DDevice7 exists
+// IDirect3D7 *pD3D; // Persistant Direct3D7
+// IDirect3DDevice7 *pDev; // Persistant Direct3DDevice7
+ BOOL bD3DXStarted;
+} GLD_dx7_globals;
+
+// These are "global" to all DX7 contexts. KeithH
+static GLD_dx7_globals dx7Globals;
+
+// Added for correct clipping of multiple open windows. (DaveM)
+LPDIRECTDRAWSURFACE7 lpDDSPrimary = NULL;
+LPDIRECTDRAWCLIPPER lpDDClipper = NULL;
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+
+BOOL gldGetDXErrorString_DX(
+ HRESULT hr,
+ char *buf,
+ int nBufSize)
+{
+ //
+ // Return a string describing the input HRESULT error code
+ //
+
+ D3DXGetErrorString(hr, nBufSize, buf);
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+//
+// DX7 does not support multisample
+/*
+static D3DMULTISAMPLE_TYPE _gldGetDeviceMultiSampleType(
+ IDirect3D8 *pD3D8,
+ D3DFORMAT SurfaceFormat,
+ D3DDEVTYPE d3dDevType,
+ BOOL Windowed)
+{
+ int i;
+ HRESULT hr;
+
+ if (glb.dwMultisample == GLDS_MULTISAMPLE_NONE)
+ return D3DMULTISAMPLE_NONE;
+
+ if (glb.dwMultisample == GLDS_MULTISAMPLE_FASTEST) {
+ // Find fastest multisample
+ for (i=2; i<17; i++) {
+ hr = IDirect3D8_CheckDeviceMultiSampleType(
+ pD3D8,
+ glb.dwAdapter,
+ d3dDevType,
+ SurfaceFormat,
+ Windowed,
+ (D3DMULTISAMPLE_TYPE)i);
+ if (SUCCEEDED(hr)) {
+ return (D3DMULTISAMPLE_TYPE)i;
+ }
+ }
+ } else {
+ // Find nicest multisample
+ for (i=16; i>1; i--) {
+ hr = IDirect3D8_CheckDeviceMultiSampleType(
+ pD3D8,
+ glb.dwAdapter,
+ d3dDevType,
+ SurfaceFormat,
+ Windowed,
+ (D3DMULTISAMPLE_TYPE)i);
+ if (SUCCEEDED(hr)) {
+ return (D3DMULTISAMPLE_TYPE)i;
+ }
+ }
+ }
+
+ // Nothing found - return default
+ return D3DMULTISAMPLE_NONE;
+}
+*/
+//---------------------------------------------------------------------------
+
+void _gldDestroyPrimitiveBuffer(
+ GLD_pb_dx7 *gldVB)
+{
+ SAFE_RELEASE(gldVB->pVB);
+
+ // Sanity check...
+ gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0;
+}
+
+//---------------------------------------------------------------------------
+
+HRESULT _gldCreatePrimitiveBuffer(
+ GLcontext *ctx,
+ GLD_driver_dx7 *lpCtx,
+ GLD_pb_dx7 *gldVB)
+{
+ HRESULT hResult;
+ char *szCreateVertexBufferFailed = "CreateVertexBuffer failed";
+ DWORD dwMaxVertices; // Max number of vertices in vertex buffer
+ DWORD dwVBSize; // Total size of vertex buffer
+ D3DVERTEXBUFFERDESC vbdesc;
+
+ // If CVA (Compiled Vertex Array) is used by an OpenGL app, then we
+ // will need enough vertices to cater for Mesa::Const.MaxArrayLockSize.
+ // We'll use IMM_SIZE if it's larger (which it should not be).
+ dwMaxVertices = (IMM_SIZE < MAX_ARRAY_LOCK_SIZE) ? MAX_ARRAY_LOCK_SIZE : IMM_SIZE;
+
+ // Max vertex buffer size limited in DX7. (DaveM)
+ if (dwMaxVertices*9 > D3DMAXNUMVERTICES)
+ dwMaxVertices = D3DMAXNUMVERTICES/9;
+
+ // Now calculate how many vertices to allow for in total
+ // 1 per point, 2 per line, 6 per quad = 9
+ dwVBSize = dwMaxVertices * 9 * gldVB->dwStride;
+
+ vbdesc.dwSize = sizeof(vbdesc);
+ vbdesc.dwCaps = gldVB->dwCreateFlags;
+ vbdesc.dwFVF = gldVB->dwFVF;
+ vbdesc.dwNumVertices = dwMaxVertices * 9;
+
+/* hResult = IDirect3DDevice8_CreateVertexBuffer(
+ lpCtx->pDev,
+ dwVBSize,
+RAgldVB->dwUsage,
+ gldVB->dwFVF,
+ gldVB->dwPool,
+ &gldVB->pVB);*/
+ hResult = IDirect3D7_CreateVertexBuffer(
+ lpCtx->pD3D,
+ &vbdesc,
+ &gldVB->pVB,
+ 0);
+ if (FAILED(hResult)) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, szCreateVertexBufferFailed);
+ return hResult;
+ }
+
+ gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0;
+ gldVB->pPoints = gldVB->pLines = gldVB->pTriangles = NULL;
+ gldVB->iFirstLine = dwMaxVertices; // Index of first line in VB
+ gldVB->iFirstTriangle = dwMaxVertices*3; // Index of first triangle in VB
+
+ return S_OK;
+}
+
+//---------------------------------------------------------------------------
+// Function: _gldCreateVertexShaders
+// Create DX8 Vertex Shaders.
+//---------------------------------------------------------------------------
+/*
+void _gldCreateVertexShaders(
+ GLD_driver_dx8 *gld)
+{
+ DWORD dwFlags;
+ LPD3DXBUFFER pVSOpcodeBuffer; // Vertex Shader opcode buffer
+ HRESULT hr;
+
+#ifdef _DEBUG
+ dwFlags = D3DXASM_DEBUG;
+#else
+ dwFlags = 0; // D3DXASM_SKIPVALIDATION;
+#endif
+
+ ddlogMessage(DDLOG_INFO, "Creating shaders...\n");
+
+ // Init the shader handle
+ gld->VStwosidelight.hShader = 0;
+
+ if (gld->d3dCaps8.MaxStreams == 0) {
+ // Lame DX8 driver doesn't support streams
+ // Not fatal, as defaults will be used
+ ddlogMessage(DDLOG_WARN, "Driver doesn't support Vertex Shaders (MaxStreams==0)\n");
+ return;
+ }
+
+ // ** THIS DISABLES VERTEX SHADER SUPPORT **
+// return;
+ // ** THIS DISABLES VERTEX SHADER SUPPORT **
+
+ //
+ // Two-sided lighting
+ //
+
+#if 0
+ //
+ // DEBUGGING: Load shader from a text file
+ //
+ {
+ LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer
+ hr = D3DXAssembleShaderFromFile(
+ "twoside.vsh",
+ dwFlags,
+ NULL, // No constants
+ &pVSOpcodeBuffer,
+ &pVSErrorBuffer);
+ if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer))
+ ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer));
+ SAFE_RELEASE(pVSErrorBuffer);
+ }
+#else
+ {
+ LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer
+ // Assemble ascii shader text into shader opcodes
+ hr = D3DXAssembleShader(
+ szTwoSidedLightingVS,
+ strlen(szTwoSidedLightingVS),
+ dwFlags,
+ NULL, // No constants
+ &pVSOpcodeBuffer,
+ &pVSErrorBuffer);
+ if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer))
+ ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer));
+ SAFE_RELEASE(pVSErrorBuffer);
+ }
+#endif
+ if (FAILED(hr)) {
+ ddlogError(DDLOG_WARN, "AssembleShader failed", hr);
+ SAFE_RELEASE(pVSOpcodeBuffer);
+ return;
+ }
+
+// This is for debugging. Remove to enable vertex shaders in HW
+#define _GLD_FORCE_SW_VS 0
+
+ if (_GLD_FORCE_SW_VS) {
+ // _GLD_FORCE_SW_VS should be disabled for Final Release
+ ddlogMessage(DDLOG_SYSTEM, "[Forcing shaders in SW]\n");
+ }
+
+ // Try and create shader in hardware.
+ // NOTE: The D3D Ref device appears to succeed when trying to
+ // create the device in hardware, but later complains
+ // when trying to set it with SetVertexShader(). Go figure.
+ if (_GLD_FORCE_SW_VS || glb.dwDriver == GLDS_DRIVER_REF) {
+ // Don't try and create a hardware shader with the Ref device
+ hr = E_FAIL; // COM error/fail result
+ } else {
+ gld->VStwosidelight.bHardware = TRUE;
+ hr = IDirect3DDevice8_CreateVertexShader(
+ gld->pDev,
+ dwTwoSidedLightingDecl,
+ pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer),
+ &gld->VStwosidelight.hShader,
+ 0);
+ }
+ if (FAILED(hr)) {
+ ddlogMessage(DDLOG_INFO, "... HW failed, trying SW...\n");
+ // Failed. Try and create shader for software processing
+ hr = IDirect3DDevice8_CreateVertexShader(
+ gld->pDev,
+ dwTwoSidedLightingDecl,
+ pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer),
+ &gld->VStwosidelight.hShader,
+ D3DUSAGE_SOFTWAREPROCESSING);
+ if (FAILED(hr)) {
+ gld->VStwosidelight.hShader = 0; // Sanity check
+ ddlogError(DDLOG_WARN, "CreateVertexShader failed", hr);
+ return;
+ }
+ // Succeeded, but for software processing
+ gld->VStwosidelight.bHardware = FALSE;
+ }
+
+ SAFE_RELEASE(pVSOpcodeBuffer);
+
+ ddlogMessage(DDLOG_INFO, "... OK\n");
+}
+
+//---------------------------------------------------------------------------
+
+void _gldDestroyVertexShaders(
+ GLD_driver_dx8 *gld)
+{
+ if (gld->VStwosidelight.hShader) {
+ IDirect3DDevice8_DeleteVertexShader(gld->pDev, gld->VStwosidelight.hShader);
+ gld->VStwosidelight.hShader = 0;
+ }
+}
+*/
+//---------------------------------------------------------------------------
+
+BOOL gldCreateDrawable_DX(
+ DGL_ctx *ctx,
+// BOOL bDefaultDriver,
+ BOOL bDirectDrawPersistant,
+ BOOL bPersistantBuffers)
+{
+ //
+ // bDirectDrawPersistant: applies to IDirect3D8
+ // bPersistantBuffers: applies to IDirect3DDevice8
+ //
+
+// D3DDEVTYPE d3dDevType;
+// D3DPRESENT_PARAMETERS d3dpp;
+// D3DDISPLAYMODE d3ddm;
+// DWORD dwBehaviourFlags;
+// D3DADAPTER_IDENTIFIER8 d3dIdent;
+
+ HRESULT hr;
+ GLD_driver_dx7 *lpCtx = NULL;
+ D3DX_VIDMODEDESC d3ddm;
+
+ // Parameters for D3DXCreateContextEx
+ // These will be different for fullscreen and windowed
+ DWORD dwDeviceIndex;
+ DWORD dwFlags;
+ HWND hwnd;
+ HWND hwndFocus;
+ DWORD numColorBits;
+ DWORD numAlphaBits;
+ DWORD numDepthBits;
+ DWORD numStencilBits;
+ DWORD numBackBuffers;
+ DWORD dwWidth;
+ DWORD dwHeight;
+ DWORD refreshRate;
+
+ // Error if context is NULL.
+ if (ctx == NULL)
+ return FALSE;
+
+ if (ctx->glPriv) {
+ lpCtx = ctx->glPriv;
+ // Release any existing interfaces (in reverse order)
+ SAFE_RELEASE(lpCtx->pDev);
+ SAFE_RELEASE(lpCtx->pD3D);
+ lpCtx->pD3DXContext->lpVtbl->Release(lpCtx->pD3DXContext);
+ lpCtx->pD3DXContext = NULL;
+ } else {
+ lpCtx = (GLD_driver_dx7*)malloc(sizeof(GLD_driver_dx7));
+ ZeroMemory(lpCtx, sizeof(lpCtx));
+ }
+
+// d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
+ // Use REF device if requested. Otherwise D3DX_DEFAULT will choose highest level
+ // of HW acceleration.
+ dwDeviceIndex = (glb.dwDriver == GLDS_DRIVER_REF) ? D3DX_HWLEVEL_REFERENCE : D3DX_DEFAULT;
+
+ // TODO: Check this
+// if (bDefaultDriver)
+// d3dDevType = D3DDEVTYPE_REF;
+
+#ifdef _GLD_PERSISTANT
+ // Use persistant interface if needed
+ if (bDirectDrawPersistant && dx7Globals.bDirect3D) {
+ lpCtx->pD3D = dx7Globals.pD3D;
+ IDirect3D7_AddRef(lpCtx->pD3D);
+ goto SkipDirectDrawCreate;
+ }
+#endif
+/*
+ // Create Direct3D7 object
+ lpCtx->pD3D = dx7Globals.fnDirect3DCreate8(D3D_SDK_VERSION_DX8_SUPPORT_WIN95);
+ if (lpCtx->pD3D == NULL) {
+ MessageBox(NULL, "Unable to initialize Direct3D8", "GLDirect", MB_OK);
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D8 interface");
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+*/
+
+#ifdef _GLD_PERSISTANT
+ // Cache Direct3D interface for subsequent GLRCs
+ if (bDirectDrawPersistant && !dx8Globals.bDirect3D) {
+ dx7Globals.pD3D = lpCtx->pD3D;
+ IDirect3D7_AddRef(dx7Globals.pD3D);
+ dx7Globals.bDirect3D = TRUE;
+ }
+SkipDirectDrawCreate:
+#endif
+/*
+ // Get the display mode so we can make a compatible backbuffer
+ hResult = IDirect3D8_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hResult)) {
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+*/
+
+#if 0
+ // Get device caps
+ hResult = IDirect3D8_GetDeviceCaps(lpCtx->pD3D, glb.dwAdapter, d3dDevType, &lpCtx->d3dCaps8);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D8_GetDeviceCaps failed", hResult);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Check for hardware transform & lighting
+ lpCtx->bHasHWTnL = lpCtx->d3dCaps8.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE;
+
+ // If this flag is present then we can't default to Mesa
+ // SW rendering between BeginScene() and EndScene().
+ if (lpCtx->d3dCaps8.Caps2 & D3DCAPS2_NO2DDURING3DSCENE) {
+ ddlogMessage(DDLOG_WARN,
+ "Warning : No 2D allowed during 3D scene.\n");
+ }
+#endif
+
+ //
+ // Create the Direct3D context
+ //
+
+#ifdef _GLD_PERSISTANT
+ // Re-use original IDirect3DDevice if persistant buffers exist.
+ // Note that we test for persistant IDirect3D8 as well
+ // bDirectDrawPersistant == persistant IDirect3D8 (DirectDraw8 does not exist)
+ if (bDirectDrawPersistant && bPersistantBuffers && dx7Globals.pD3D && dx7Globals.pDev) {
+ lpCtx->pDev = dx7Globals.pDev;
+ IDirect3DDevice7_AddRef(dx7Globals.pDev);
+ goto skip_direct3ddevice_create;
+ }
+#endif
+/*
+ // Clear the presentation parameters (sets all members to zero)
+ ZeroMemory(&d3dpp, sizeof(d3dpp));
+
+ // Recommended by MS; needed for MultiSample.
+ // Be careful if altering this for FullScreenBlit
+ d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+
+ d3dpp.BackBufferFormat = d3ddm.Format;
+ d3dpp.BackBufferCount = 1;
+ d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(lpCtx->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen);
+ d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData;
+ d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE;
+
+ if (ctx->bFullscreen) {
+ ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen
+ d3dpp.Windowed = FALSE;
+ d3dpp.BackBufferWidth = d3ddm.Width;
+ d3dpp.BackBufferHeight = d3ddm.Height;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
+
+ // Support for vertical retrace synchronisation.
+ // Set default presentation interval in case caps bits are missing
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ if (glb.bWaitForRetrace) {
+ if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE;
+ } else {
+ if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+ }
+ } else {
+ ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages
+ d3dpp.Windowed = TRUE;
+ d3dpp.BackBufferWidth = ctx->dwWidth;
+ d3dpp.BackBufferHeight = ctx->dwHeight;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = 0;
+ // FullScreen_PresentationInterval must be default for Windowed mode
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ }
+
+ // Decide if we can use hardware TnL
+ dwBehaviourFlags = (lpCtx->bHasHWTnL) ?
+ D3DCREATE_MIXED_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING;
+ // Add flag to tell D3D to be thread-safe
+ if (glb.bMultiThreaded)
+ dwBehaviourFlags |= D3DCREATE_MULTITHREADED;
+ hResult = IDirect3D8_CreateDevice(lpCtx->pD3D,
+ glb.dwAdapter,
+ d3dDevType,
+ ctx->hWnd,
+ dwBehaviourFlags,
+ &d3dpp,
+ &lpCtx->pDev);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D8_CreateDevice failed", hResult);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+*/
+
+ // Create D3DX context
+ if (ctx->bFullscreen) {
+ //
+ // FULLSCREEN
+ //
+
+ // Get display mode
+ D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm);
+
+ // Fullscreen Parameters
+ dwFlags = D3DX_CONTEXT_FULLSCREEN;
+ hwnd = ctx->hWnd;
+ hwndFocus = ctx->hWnd;
+ numColorBits = ctx->lpPF->pfd.cColorBits;
+ numAlphaBits = ctx->lpPF->pfd.cAlphaBits;
+ numDepthBits = ctx->lpPF->pfd.cDepthBits + ctx->lpPF->pfd.cStencilBits;
+ numStencilBits = ctx->lpPF->pfd.cStencilBits;
+ numBackBuffers = D3DX_DEFAULT; // Default is 1 backbuffer
+ dwWidth = d3ddm.width;
+ dwHeight = d3ddm.height;
+ refreshRate = d3ddm.refreshRate; // D3DX_DEFAULT;
+ } else {
+ //
+ // WINDOWED
+ //
+
+ // Windowed Parameters
+ dwFlags = 0; // No flags means "windowed"
+ hwnd = ctx->hWnd;
+ hwndFocus = (HWND)D3DX_DEFAULT;
+ numColorBits = D3DX_DEFAULT; // Use Desktop depth
+ numAlphaBits = ctx->lpPF->pfd.cAlphaBits;
+ numDepthBits = ctx->lpPF->pfd.cDepthBits + ctx->lpPF->pfd.cStencilBits;
+ numStencilBits = ctx->lpPF->pfd.cStencilBits;
+ numBackBuffers = D3DX_DEFAULT; // Default is 1 backbuffer
+ dwWidth = ctx->dwWidth;
+ dwHeight = ctx->dwHeight;
+ refreshRate = D3DX_DEFAULT;
+ }
+ hr = D3DXCreateContextEx(dwDeviceIndex, dwFlags, hwnd, hwndFocus,
+ numColorBits, numAlphaBits, numDepthBits, numStencilBits,
+ numBackBuffers,
+ dwWidth, dwHeight, refreshRate,
+ &lpCtx->pD3DXContext);
+ if (FAILED(hr)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "D3DXCreateContextEx failed", hr);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Obtain D3D7 interfaces from ID3DXContext
+// lpCtx->pDD = ID3DXContext_GetDD(lpCtx->pD3DXContext);
+ lpCtx->pDD = lpCtx->pD3DXContext->lpVtbl->GetDD(lpCtx->pD3DXContext);
+ if (lpCtx->pDD == NULL)
+ goto return_with_error;
+ lpCtx->pD3D = lpCtx->pD3DXContext->lpVtbl->GetD3D(lpCtx->pD3DXContext);
+ if (lpCtx->pD3D == NULL)
+ goto return_with_error;
+ lpCtx->pDev = lpCtx->pD3DXContext->lpVtbl->GetD3DDevice(lpCtx->pD3DXContext);
+ if (lpCtx->pDev == NULL)
+ goto return_with_error;
+
+ // Need to manage clipper manually for multiple windows
+ // since DX7 D3DX utility lib does not appear to do that. (DaveM)
+ if (!ctx->bFullscreen) {
+ // Get primary surface too
+ lpDDSPrimary = lpCtx->pD3DXContext->lpVtbl->GetPrimary(lpCtx->pD3DXContext);
+ if (lpDDSPrimary == NULL) {
+ ddlogPrintf(DDLOG_WARN, "GetPrimary");
+ goto return_with_error;
+ }
+ // Create clipper for correct window updates
+ if (IDirectDraw7_CreateClipper(lpCtx->pDD, 0, &lpDDClipper, NULL) != DD_OK) {
+ ddlogPrintf(DDLOG_WARN, "CreateClipper");
+ goto return_with_error;
+ }
+ // Set the window that the clipper belongs to
+ if (IDirectDrawClipper_SetHWnd(lpDDClipper, 0, hwnd) != DD_OK) {
+ ddlogPrintf(DDLOG_WARN, "SetHWnd");
+ goto return_with_error;
+ }
+ // Attach the clipper to the primary surface
+ if (IDirectDrawSurface7_SetClipper(lpDDSPrimary, lpDDClipper) != DD_OK) {
+ ddlogPrintf(DDLOG_WARN, "SetClipper");
+ goto return_with_error;
+ }
+ }
+
+ // Get device caps
+ IDirect3DDevice7_GetCaps(lpCtx->pDev, &lpCtx->d3dCaps);
+
+ // Determine HW TnL
+ lpCtx->bHasHWTnL = lpCtx->d3dCaps.dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE;
+
+#ifdef _GLD_PERSISTANT
+ if (bDirectDrawPersistant && bPersistantBuffers && dx7Globals.pD3D) {
+ dx7Globals.pDev = lpCtx->pDev;
+ dx7Globals.bDirect3DDevice = TRUE;
+ }
+#endif
+
+#if 0
+ // Dump some useful stats
+ hResult = IDirect3D8_GetAdapterIdentifier(
+ lpCtx->pD3D,
+ glb.dwAdapter,
+ D3DENUM_NO_WHQL_LEVEL, // Avoids 1 to 2 second delay
+ &d3dIdent);
+ if (SUCCEEDED(hResult)) {
+ ddlogPrintf(DDLOG_INFO, "[Driver Description: %s]", &d3dIdent.Description);
+ ddlogPrintf(DDLOG_INFO, "[Driver file: %s %d.%d.%02d.%d]",
+ d3dIdent.Driver,
+ HIWORD(d3dIdent.DriverVersion.HighPart),
+ LOWORD(d3dIdent.DriverVersion.HighPart),
+ HIWORD(d3dIdent.DriverVersion.LowPart),
+ LOWORD(d3dIdent.DriverVersion.LowPart));
+ ddlogPrintf(DDLOG_INFO, "[VendorId: 0x%X, DeviceId: 0x%X, SubSysId: 0x%X, Revision: 0x%X]",
+ d3dIdent.VendorId, d3dIdent.DeviceId, d3dIdent.SubSysId, d3dIdent.Revision);
+ }
+#endif
+
+ // Init projection matrix for D3D TnL
+ D3DXMatrixIdentity((D3DXMATRIX*)&lpCtx->matProjection);
+ lpCtx->matModelView = lpCtx->matProjection;
+// gld->bUseMesaProjection = TRUE;
+
+skip_direct3ddevice_create:
+
+ // Create buffers to hold primitives
+ lpCtx->PB2d.dwFVF = GLD_FVF_2D_VERTEX;
+// lpCtx->PB2d.dwPool = D3DPOOL_SYSTEMMEM;
+ lpCtx->PB2d.dwStride = sizeof(GLD_2D_VERTEX);
+ lpCtx->PB2d.dwCreateFlags = D3DVBCAPS_DONOTCLIP |
+ D3DVBCAPS_SYSTEMMEMORY |
+ D3DVBCAPS_WRITEONLY;
+ hr = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB2d);
+ if (FAILED(hr))
+ goto return_with_error;
+
+ lpCtx->PB3d.dwFVF = GLD_FVF_3D_VERTEX;
+// lpCtx->PB3d.dwPool = D3DPOOL_DEFAULT;
+ lpCtx->PB3d.dwStride = sizeof(GLD_3D_VERTEX);
+ lpCtx->PB3d.dwCreateFlags = D3DVBCAPS_WRITEONLY;
+
+ hr = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB3d);
+ if (FAILED(hr))
+ goto return_with_error;
+
+ // Zero the pipeline usage counters
+ lpCtx->PipelineUsage.qwMesa.QuadPart =
+// lpCtx->PipelineUsage.dwD3D2SVS.QuadPart =
+ lpCtx->PipelineUsage.qwD3DFVF.QuadPart = 0;
+
+ // Assign drawable to GL private
+ ctx->glPriv = lpCtx;
+ return TRUE;
+
+return_with_error:
+ // Clean up and bail
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB3d);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB2d);
+
+ SAFE_RELEASE(lpCtx->pDev);
+ SAFE_RELEASE(lpCtx->pD3D);
+ //SAFE_RELEASE(lpCtx->pD3DXContext);
+ lpCtx->pD3DXContext->lpVtbl->Release(lpCtx->pD3DXContext);
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldResizeDrawable_DX(
+ DGL_ctx *ctx,
+ BOOL bDefaultDriver,
+ BOOL bPersistantInterface,
+ BOOL bPersistantBuffers)
+{
+ GLD_driver_dx7 *gld = NULL;
+// D3DDEVTYPE d3dDevType;
+// D3DPRESENT_PARAMETERS d3dpp;
+// D3DDISPLAYMODE d3ddm;
+ D3DX_VIDMODEDESC d3ddm;
+ HRESULT hr;
+ DWORD dwWidth, dwHeight;
+
+ // Error if context is NULL.
+ if (ctx == NULL)
+ return FALSE;
+
+ gld = ctx->glPriv;
+ if (gld == NULL)
+ return FALSE;
+
+ if (ctx->bSceneStarted) {
+ IDirect3DDevice7_EndScene(gld->pDev);
+ ctx->bSceneStarted = FALSE;
+ }
+/*
+ d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
+ if (!bDefaultDriver)
+ d3dDevType = D3DDEVTYPE_REF; // Force Direct3D Reference Rasterise (software)
+
+ // Get the display mode so we can make a compatible backbuffer
+ hResult = IDirect3D8_GetAdapterDisplayMode(gld->pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hResult)) {
+ nContextError = GLDERR_D3D;
+// goto return_with_error;
+ return FALSE;
+ }
+*/
+ // Release objects before Reset()
+ _gldDestroyPrimitiveBuffer(&gld->PB3d);
+ _gldDestroyPrimitiveBuffer(&gld->PB2d);
+
+/*
+ // Clear the presentation parameters (sets all members to zero)
+ ZeroMemory(&d3dpp, sizeof(d3dpp));
+
+ // Recommended by MS; needed for MultiSample.
+ // Be careful if altering this for FullScreenBlit
+ d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+
+ d3dpp.BackBufferFormat = d3ddm.Format;
+ d3dpp.BackBufferCount = 1;
+ d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(gld->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen);
+ d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData;
+ d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE;
+
+ // TODO: Sync to refresh
+
+ if (ctx->bFullscreen) {
+ ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen
+ d3dpp.Windowed = FALSE;
+ d3dpp.BackBufferWidth = d3ddm.Width;
+ d3dpp.BackBufferHeight = d3ddm.Height;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ // Get better benchmark results? KeithH
+// d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_UNLIMITED;
+ } else {
+ ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages
+ d3dpp.Windowed = TRUE;
+ d3dpp.BackBufferWidth = ctx->dwWidth;
+ d3dpp.BackBufferHeight = ctx->dwHeight;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = 0;
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ }
+ hResult = IDirect3DDevice8_Reset(gld->pDev, &d3dpp);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Reset failed", hResult);
+ return FALSE;
+ //goto cleanup_and_return_with_error;
+ }
+*/
+ // Obtain dimensions of 'window'
+ if (ctx->bFullscreen) {
+ D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm);
+ dwWidth = d3ddm.width;
+ dwHeight = d3ddm.height;
+ } else {
+ dwWidth = ctx->dwWidth;
+ dwHeight = ctx->dwHeight;
+ }
+
+ // Resize context
+ hr = gld->pD3DXContext->lpVtbl->Resize(gld->pD3DXContext, dwWidth, dwHeight);
+ if (FAILED(hr)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "gldResizeDrawable_DX: Resize failed", hr);
+ return FALSE;
+ }
+
+ // Clear the resized surface (DaveM)
+ {
+ D3DVIEWPORT7 vp1, vp2;
+ IDirect3DDevice7_GetViewport(gld->pDev, &vp1);
+ IDirect3DDevice7_GetViewport(gld->pDev, &vp2);
+ vp2.dwX = 0;
+ vp2.dwY = 0;
+ vp2.dwWidth = dwWidth;
+ vp2.dwHeight = dwHeight;
+ IDirect3DDevice7_SetViewport(gld->pDev, &vp2);
+ hr = gld->pD3DXContext->lpVtbl->Clear(gld->pD3DXContext, D3DCLEAR_TARGET);
+ if (FAILED(hr))
+ ddlogError(DDLOG_WARN, "gldResizeDrawable_DX: Clear failed", hr);
+ IDirect3DDevice7_SetViewport(gld->pDev, &vp1);
+ }
+
+ //
+ // Recreate objects
+ //
+ _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB2d);
+ _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB3d);
+
+ // Signal a complete state update
+ ctx->glCtx->Driver.UpdateState(ctx->glCtx, _NEW_ALL);
+
+ // Begin a new scene
+ IDirect3DDevice7_BeginScene(gld->pDev);
+ ctx->bSceneStarted = TRUE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldDestroyDrawable_DX(
+ DGL_ctx *ctx)
+{
+ GLD_driver_dx7 *lpCtx = NULL;
+
+ // Error if context is NULL.
+ if (!ctx)
+ return FALSE;
+
+ // Error if the drawable does not exist.
+ if (!ctx->glPriv)
+ return FALSE;
+
+ lpCtx = ctx->glPriv;
+
+#ifdef _DEBUG
+ // Dump out stats
+ ddlogPrintf(DDLOG_SYSTEM, "Usage: M:0x%X%X, D:0x%X%X",
+ lpCtx->PipelineUsage.qwMesa.HighPart,
+ lpCtx->PipelineUsage.qwMesa.LowPart,
+ lpCtx->PipelineUsage.qwD3DFVF.HighPart,
+ lpCtx->PipelineUsage.qwD3DFVF.LowPart);
+#endif
+
+ // Destroy Primtive Buffers
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB3d);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB2d);
+
+ // Release DX interfaces (in reverse order)
+ SAFE_RELEASE(lpCtx->pDev);
+ SAFE_RELEASE(lpCtx->pD3D);
+ //SAFE_RELEASE(lpCtx->pD3DXContext);
+ lpCtx->pD3DXContext->lpVtbl->Release(lpCtx->pD3DXContext);
+
+ // Free the private drawable data
+ free(ctx->glPriv);
+ ctx->glPriv = NULL;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldCreatePrivateGlobals_DX(void)
+{
+/*
+ ZeroMemory(&dx7Globals, sizeof(dx7Globals));
+
+ // Load d3d8.dll
+ dx8Globals.hD3D8DLL = LoadLibrary("D3D8.DLL");
+ if (dx8Globals.hD3D8DLL == NULL)
+ return FALSE;
+
+ // Now try and obtain Direct3DCreate8
+ dx8Globals.fnDirect3DCreate8 = (FNDIRECT3DCREATE8)GetProcAddress(dx8Globals.hD3D8DLL, "Direct3DCreate8");
+ if (dx8Globals.fnDirect3DCreate8 == NULL) {
+ FreeLibrary(dx8Globals.hD3D8DLL);
+ return FALSE;
+ }
+*/
+
+ // Initialise D3DX
+ return FAILED(D3DXInitialize()) ? FALSE : TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldDestroyPrivateGlobals_DX(void)
+{
+/*
+ if (dx7Globals.bDirect3DDevice) {
+ SAFE_RELEASE(dx7Globals.pDev);
+ dx7Globals.bDirect3DDevice = FALSE;
+ }
+ if (dx7Globals.bDirect3D) {
+ SAFE_RELEASE(dx7Globals.pD3D);
+ dx7Globals.bDirect3D = FALSE;
+ }
+
+ FreeLibrary(dx8Globals.hD3D8DLL);
+ dx8Globals.hD3D8DLL = NULL;
+ dx8Globals.fnDirect3DCreate8 = NULL;
+*/
+ return FAILED(D3DXUninitialize()) ? FALSE : TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+static void _BitsFromDisplayFormat(
+ D3DX_SURFACEFORMAT fmt,
+ BYTE *cColorBits,
+ BYTE *cRedBits,
+ BYTE *cGreenBits,
+ BYTE *cBlueBits,
+ BYTE *cAlphaBits)
+{
+ switch (fmt) {
+/* case D3DX_SF_X1R5G5B5:
+ *cColorBits = 16;
+ *cRedBits = 5;
+ *cGreenBits = 5;
+ *cBlueBits = 5;
+ *cAlphaBits = 0;
+ return;*/
+ case D3DX_SF_R5G5B5:
+ *cColorBits = 16;
+ *cRedBits = 5;
+ *cGreenBits = 5;
+ *cBlueBits = 5;
+ *cAlphaBits = 0;
+ return;
+ case D3DX_SF_R5G6B5:
+ *cColorBits = 16;
+ *cRedBits = 5;
+ *cGreenBits = 6;
+ *cBlueBits = 5;
+ *cAlphaBits = 0;
+ return;
+ case D3DX_SF_X8R8G8B8:
+ *cColorBits = 32;
+ *cRedBits = 8;
+ *cGreenBits = 8;
+ *cBlueBits = 8;
+ *cAlphaBits = 0;
+ return;
+ case D3DX_SF_A8R8G8B8:
+ *cColorBits = 32;
+ *cRedBits = 8;
+ *cGreenBits = 8;
+ *cBlueBits = 8;
+ *cAlphaBits = 8;
+ return;
+ }
+
+ // Should not get here!
+ *cColorBits = 32;
+ *cRedBits = 8;
+ *cGreenBits = 8;
+ *cBlueBits = 8;
+ *cAlphaBits = 0;
+}
+
+//---------------------------------------------------------------------------
+
+static void _BitsFromDepthStencilFormat(
+ D3DX_SURFACEFORMAT fmt,
+ BYTE *cDepthBits,
+ BYTE *cStencilBits)
+{
+ // NOTE: GL expects either 32 or 16 as depth bits.
+ switch (fmt) {
+ case D3DX_SF_Z16S0:
+ *cDepthBits = 16;
+ *cStencilBits = 0;
+ return;
+ case D3DX_SF_Z32S0:
+ *cDepthBits = 32;
+ *cStencilBits = 0;
+ return;
+ case D3DX_SF_Z15S1:
+ *cDepthBits = 15;
+ *cStencilBits = 1;
+ return;
+ case D3DX_SF_Z24S8:
+ *cDepthBits = 24;
+ *cStencilBits = 8;
+ return;
+ case D3DX_SF_S1Z15:
+ *cDepthBits = 15;
+ *cStencilBits = 1;
+ return;
+ case D3DX_SF_S8Z24:
+ *cDepthBits = 24;
+ *cStencilBits = 8;
+ return;
+ }
+}
+
+//---------------------------------------------------------------------------
+/*
+BOOL GLD_CheckDepthStencilMatch(
+ DWORD dwDeviceIndex,
+ D3DX_SURFACEFORMAT sfWant)
+{
+ // Emulate function built in to DX9
+ D3DX_SURFACEFORMAT sfFound;
+ int i;
+ int nFormats = D3DXGetMaxSurfaceFormats(dwDeviceIndex, NULL, D3DX_SC_DEPTHBUFFER);
+ if (nFormats) {
+ for (i=0; i<nFormats; i++) {
+ D3DXGetSurfaceFormat(dwDeviceIndex, NULL, D3DX_SC_DEPTHBUFFER, i, &sfFound); }
+ if (sfFound == sfWant)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+*/
+//---------------------------------------------------------------------------
+
+D3DX_SURFACEFORMAT _gldFindCompatibleDepthStencilFormat(
+ DWORD dwDeviceIndex)
+{
+ // Jump through some hoops...
+
+ ID3DXContext *pD3DXContext = NULL;
+ IDirectDrawSurface7 *pZBuffer = NULL;
+ DDPIXELFORMAT ddpf;
+ HWND hWnd;
+
+ // Get an HWND - use Desktop's
+ hWnd = GetDesktopWindow();
+
+ // Create a fully specified default context.
+ D3DXCreateContextEx(dwDeviceIndex, 0, hWnd, (HWND)D3DX_DEFAULT,
+ D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT,
+ D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT,
+ &pD3DXContext);
+
+ // Obtain depth buffer that was created in context
+ pZBuffer = pD3DXContext->lpVtbl->GetZBuffer(pD3DXContext);
+
+ // Get pixel format of depth buffer
+ ddpf.dwSize = sizeof(ddpf);
+ pZBuffer->lpVtbl->GetPixelFormat(pZBuffer, &ddpf);
+ // Done with surface - release it
+ pZBuffer->lpVtbl->Release(pZBuffer);
+
+ // Done with D3DX context
+ pD3DXContext->lpVtbl->Release(pD3DXContext);
+
+ // Convert and return
+ return D3DXMakeSurfaceFormat(&ddpf);
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldBuildPixelformatList_DX(void)
+{
+ D3DX_DEVICEDESC d3dxdd;
+ D3DX_VIDMODEDESC d3ddm;
+ D3DX_SURFACEFORMAT fmt[64]; // 64 should be enough...
+ DWORD dwDeviceIndex;
+ DWORD surfClassFlags;
+// IDirect3D7 *pD3D = NULL;
+ HRESULT hr;
+ int nSupportedFormats = 0; // Total formats
+ int nDepthOnlyFormats = 0;
+ int nDepthStencilFormats = 0;
+ int i;
+ DGL_pixelFormat *pPF;
+ BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits;
+// char buf[128];
+// char cat[8];
+
+ // Direct3D (SW or HW)
+ // These are arranged so that 'best' pixelformat
+ // is higher in the list (for ChoosePixelFormat).
+/* const D3DFORMAT DepthStencil[4] = {
+ D3DX_SF_Z16S0, //D3DX_SF_D16,
+ D3DX_SF_Z15S1, //D3DX_SF_D15S1,
+ D3DX_SF_Z32S0, //D3DX_SF_D32,
+ D3DX_SF_Z24S8, //D3DX_SF_D24S8,
+ //D3DX_SF_D24X8,
+ //D3DX_SF_D24X4S4,
+ };*/
+
+ // Dump DX version
+ ddlogMessage(GLDLOG_SYSTEM, "DirectX Version : 7.0\n");
+
+ // Release any existing pixelformat list
+ if (glb.lpPF) {
+ free(glb.lpPF);
+ }
+
+ glb.nPixelFormatCount = 0;
+ glb.lpPF = NULL;
+
+ //
+ // Pixelformats for Direct3D (SW or HW) rendering
+ //
+
+ dwDeviceIndex = (glb.dwDriver == GLDS_DRIVER_REF) ? D3DX_HWLEVEL_REFERENCE : D3DX_DEFAULT;
+
+ // Dump description
+ D3DXGetDeviceDescription(dwDeviceIndex, &d3dxdd);
+ ddlogPrintf(GLDLOG_SYSTEM, "Device: %s", d3dxdd.driverDesc);
+
+ // Get display mode
+ D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm);
+
+#if 0
+ // Phooey - this don't work...
+/*
+ // Since D3DXGetMaxSurfaceFormats() can lie to us, we'll need a workaround.
+ // Explicitly test for matching depth/stencil to display bpp.
+ if (d3ddm.bpp <= 16) {
+ if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z16S0))
+ fmt[nSupportedFormats++] = D3DX_SF_Z16S0;
+ if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z15S1))
+ fmt[nSupportedFormats++] = D3DX_SF_Z15S1;
+ if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_S1Z15))
+ fmt[nSupportedFormats++] = D3DX_SF_S1Z15;
+ // Didn't find anything? Try default
+ if (nSupportedFormats == 0) {
+ if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z32S0))
+ fmt[nSupportedFormats++] = D3DX_SF_Z32S0;
+ }
+ } else {
+ if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z32S0))
+ fmt[nSupportedFormats++] = D3DX_SF_Z32S0;
+ if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z24S8))
+ fmt[nSupportedFormats++] = D3DX_SF_Z24S8;
+ if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_S8Z24))
+ fmt[nSupportedFormats++] = D3DX_SF_S8Z24;
+ // Didn't find anything? Try default
+ if (nSupportedFormats == 0) {
+ if (GLD_CheckDepthStencilMatch(dwDeviceIndex, D3DX_SF_Z16S0))
+ fmt[nSupportedFormats++] = D3DX_SF_Z16S0;
+ }
+ }
+*/
+ // Go the Whole Hog...
+ fmt[nSupportedFormats++] = _gldFindCompatibleDepthStencilFormat(dwDeviceIndex);
+#else
+ //
+ // Depth buffer formats WITHOUT stencil
+ //
+ surfClassFlags = D3DX_SC_DEPTHBUFFER;
+ nDepthOnlyFormats = D3DXGetMaxSurfaceFormats(dwDeviceIndex, NULL, surfClassFlags);
+ //
+ // Depth buffer formats WITH stencil
+ //
+ surfClassFlags = D3DX_SC_DEPTHBUFFER | D3DX_SC_STENCILBUFFER;
+ nDepthStencilFormats = D3DXGetMaxSurfaceFormats(dwDeviceIndex, NULL, surfClassFlags);
+
+ // Work out how many formats we have in total
+ if ((nDepthOnlyFormats + nDepthStencilFormats) == 0)
+ return FALSE; // Bail: no compliant pixelformats
+
+ // Get depth buffer formats WITHOUT stencil
+ surfClassFlags = D3DX_SC_DEPTHBUFFER;
+ for (i=0; i<nDepthOnlyFormats; i++) {
+ D3DXGetSurfaceFormat(dwDeviceIndex, NULL, surfClassFlags, i, &fmt[nSupportedFormats++]);
+ }
+ // NOTE: For some reason we already get stencil formats when only specifying D3DX_SC_DEPTHBUFFER
+ /*
+ // Get depth buffer formats WITH stencil
+ surfClassFlags = D3DX_SC_DEPTHBUFFER | D3DX_SC_STENCILBUFFER;
+ for (i=0; i<nDepthStencilFormats; i++) {
+ D3DXGetSurfaceFormat(dwDeviceIndex, NULL, surfClassFlags, i, &fmt[nSupportedFormats++]);
+ }
+ */
+#endif
+
+ // Total count of pixelformats is:
+ // (nSupportedFormats+1)*2
+ glb.lpPF = (DGL_pixelFormat *)calloc((nSupportedFormats)*2, sizeof(DGL_pixelFormat));
+ glb.nPixelFormatCount = (nSupportedFormats)*2;
+ if (glb.lpPF == NULL) {
+ glb.nPixelFormatCount = 0;
+ return FALSE;
+ }
+
+ // Get a copy of pointer that we can alter
+ pPF = glb.lpPF;
+
+ // Cache colour bits from display format
+// _BitsFromDisplayFormat(d3ddm.Format, &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits);
+ // Get display mode
+ D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm);
+ cColorBits = d3ddm.bpp;
+ cAlphaBits = 0;
+ switch (d3ddm.bpp) {
+ case 15:
+ cRedBits = 5; cGreenBits = 5; cBlueBits = 5;
+ break;
+ case 16:
+ cRedBits = 5; cGreenBits = 6; cBlueBits = 5;
+ break;
+ case 24:
+ case 32:
+ cRedBits = 8; cGreenBits = 8; cBlueBits = 8;
+ break;
+ default:
+ cRedBits = 5; cGreenBits = 5; cBlueBits = 5;
+ }
+
+ //
+ // Add single-buffer formats
+ //
+
+/* // Single-buffer, no depth-stencil buffer
+ memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ pPF->pfd.cDepthBits = 0;
+ pPF->pfd.cStencilBits = 0;
+ pPF->dwDriverData = D3DX_SF_UNKNOWN;
+ pPF++;*/
+
+ for (i=0; i<nSupportedFormats; i++, pPF++) {
+ memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits);
+ pPF->dwDriverData = fmt[i];
+ }
+
+ //
+ // Add double-buffer formats
+ //
+
+/* memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ pPF->pfd.cDepthBits = 0;
+ pPF->pfd.cStencilBits = 0;
+ pPF->dwDriverData = D3DX_SF_UNKNOWN;
+ pPF++;*/
+
+ for (i=0; i<nSupportedFormats; i++, pPF++) {
+ memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits);
+ pPF->dwDriverData = fmt[i];
+ }
+
+ // Popup warning message if non RGB color mode
+ {
+ // This is a hack. KeithH
+ HDC hdcDesktop = GetDC(NULL);
+ DWORD dwDisplayBitDepth = GetDeviceCaps(hdcDesktop, BITSPIXEL);
+ ReleaseDC(0, hdcDesktop);
+ if (dwDisplayBitDepth <= 8) {
+ ddlogPrintf(DDLOG_WARN, "Current Color Depth %d bpp is not supported", dwDisplayBitDepth);
+ MessageBox(NULL, szColorDepthWarning, "GLDirect", MB_OK | MB_ICONWARNING);
+ }
+ }
+
+ // Mark list as 'current'
+ glb.bPixelformatsDirty = FALSE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldInitialiseMesa_DX(
+ DGL_ctx *lpCtx)
+{
+ GLD_driver_dx7 *gld = NULL;
+ int MaxTextureSize, TextureLevels;
+ BOOL bSoftwareTnL;
+
+ if (lpCtx == NULL)
+ return FALSE;
+
+ gld = lpCtx->glPriv;
+ if (gld == NULL)
+ return FALSE;
+
+ if (glb.bMultitexture) {
+ lpCtx->glCtx->Const.MaxTextureUnits = gld->d3dCaps.wMaxSimultaneousTextures;
+ // Only support MAX_TEXTURE_UNITS texture units.
+ // ** If this is altered then the FVF formats must be reviewed **.
+ if (lpCtx->glCtx->Const.MaxTextureUnits > GLD_MAX_TEXTURE_UNITS_DX7)
+ lpCtx->glCtx->Const.MaxTextureUnits = GLD_MAX_TEXTURE_UNITS_DX7;
+ } else {
+ // Multitexture override
+ lpCtx->glCtx->Const.MaxTextureUnits = 1;
+ }
+
+ // max texture size
+// MaxTextureSize = min(gld->d3dCaps8.MaxTextureHeight, gld->d3dCaps8.MaxTextureWidth);
+ MaxTextureSize = min(gld->d3dCaps.dwMaxTextureHeight, gld->d3dCaps.dwMaxTextureWidth);
+ if (MaxTextureSize == 0)
+ MaxTextureSize = 256; // Sanity check
+
+ //
+ // HACK!!
+ if (MaxTextureSize > 1024)
+ MaxTextureSize = 1024; // HACK - CLAMP TO 1024
+ // HACK!!
+ //
+
+ // TODO: Check this again for Mesa 5
+ // Got to set MAX_TEXTURE_SIZE as max levels.
+ // Who thought this stupid idea up? ;)
+ TextureLevels = 0;
+ // Calculate power-of-two.
+ while (MaxTextureSize) {
+ TextureLevels++;
+ MaxTextureSize >>= 1;
+ }
+ lpCtx->glCtx->Const.MaxTextureLevels = (TextureLevels) ? TextureLevels : 8;
+
+ // Defaults
+ IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_LIGHTING, FALSE);
+ IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
+ IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_DITHERENABLE, TRUE);
+ IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD);
+
+ // Set texture coord set to be used with each stage
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 0, D3DTSS_TEXCOORDINDEX, 0);
+ IDirect3DDevice7_SetTextureStageState(gld->pDev, 1, D3DTSS_TEXCOORDINDEX, 1);
+
+ // Set up Depth buffer
+ IDirect3DDevice7_SetRenderState(gld->pDev, D3DRENDERSTATE_ZENABLE,
+ (lpCtx->lpPF->dwDriverData!=D3DX_SF_UNKNOWN) ? D3DZB_TRUE : D3DZB_FALSE);
+
+ // Set the view matrix
+ {
+ D3DXMATRIX vm;
+#if 1
+ D3DXMatrixIdentity(&vm);
+#else
+ D3DXVECTOR3 Eye(0.0f, 0.0f, 0.0f);
+ D3DXVECTOR3 At(0.0f, 0.0f, -1.0f);
+ D3DXVECTOR3 Up(0.0f, 1.0f, 0.0f);
+ D3DXMatrixLookAtRH(&vm, &Eye, &At, &Up);
+ vm._31 = -vm._31;
+ vm._32 = -vm._32;
+ vm._33 = -vm._33;
+ vm._34 = -vm._34;
+#endif
+ IDirect3DDevice7_SetTransform(gld->pDev, D3DTRANSFORMSTATE_VIEW, &vm);
+ }
+
+// DX7 does not support D3DRS_SOFTWAREVERTEXPROCESSING
+/*
+ if (gld->bHasHWTnL) {
+ if (glb.dwTnL == GLDS_TNL_DEFAULT)
+ bSoftwareTnL = FALSE; // HW TnL
+ else {
+ bSoftwareTnL = ((glb.dwTnL == GLDS_TNL_MESA) || (glb.dwTnL == GLDS_TNL_D3DSW)) ? TRUE : FALSE;
+ }
+ } else {
+ // No HW TnL, so no choice possible
+ bSoftwareTnL = TRUE;
+ }
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, bSoftwareTnL);
+*/
+
+// Dump this in a Release build as well, now.
+//#ifdef _DEBUG
+ ddlogPrintf(DDLOG_INFO, "HW TnL: %s",
+// gld->bHasHWTnL ? (bSoftwareTnL ? "Disabled" : "Enabled") : "Unavailable");
+ gld->bHasHWTnL ? "Enabled" : "Unavailable");
+//#endif
+
+ // Set up interfaces to Mesa
+ gldEnableExtensions_DX7(lpCtx->glCtx);
+ gldInstallPipeline_DX7(lpCtx->glCtx);
+ gldSetupDriverPointers_DX7(lpCtx->glCtx);
+
+ // Signal a complete state update
+ lpCtx->glCtx->Driver.UpdateState(lpCtx->glCtx, _NEW_ALL);
+
+ // Start a scene
+ IDirect3DDevice7_BeginScene(gld->pDev);
+ lpCtx->bSceneStarted = TRUE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldSwapBuffers_DX(
+ DGL_ctx *ctx,
+ HDC hDC,
+ HWND hWnd)
+{
+ HRESULT hr;
+ GLD_driver_dx7 *gld = NULL;
+ DWORD dwFlags;
+
+ if (ctx == NULL)
+ return FALSE;
+
+ gld = ctx->glPriv;
+ if (gld == NULL)
+ return FALSE;
+
+
+ // End the scene if one is started
+ if (ctx->bSceneStarted) {
+ IDirect3DDevice7_EndScene(gld->pDev);
+ ctx->bSceneStarted = FALSE;
+ }
+
+ // Needed by D3DX for MDI multi-window apps (DaveM)
+ if (lpDDClipper)
+ IDirectDrawClipper_SetHWnd(lpDDClipper, 0, hWnd);
+
+ // Swap the buffers. hWnd may override the hWnd used for CreateDevice()
+// hr = IDirect3DDevice8_Present(gld->pDev, NULL, NULL, hWnd, NULL);
+
+ // Set refresh sync flag
+ dwFlags = glb.bWaitForRetrace ? 0 : D3DX_UPDATE_NOVSYNC;
+ // Render and show frame
+ hr = gld->pD3DXContext->lpVtbl->UpdateFrame(gld->pD3DXContext, dwFlags);
+ if (FAILED(hr))
+ ddlogError(DDLOG_WARN, "gldSwapBuffers_DX: UpdateFrame", hr);
+
+ if (hr == DDERR_SURFACELOST) {
+ hr = gld->pD3DXContext->lpVtbl->RestoreSurfaces(gld->pD3DXContext);
+ if (FAILED(hr))
+ ddlogError(DDLOG_WARN, "gldSwapBuffers_DX: RestoreSurfaces", hr);
+ }
+
+exit_swap:
+ // Begin a new scene
+ IDirect3DDevice7_BeginScene(gld->pDev);
+ ctx->bSceneStarted = TRUE;
+
+ return (FAILED(hr)) ? FALSE : TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldGetDisplayMode_DX(
+ DGL_ctx *ctx,
+ GLD_displayMode *glddm)
+{
+// D3DDISPLAYMODE d3ddm;
+ D3DX_VIDMODEDESC d3ddm;
+ HRESULT hr;
+ GLD_driver_dx7 *lpCtx = NULL;
+ BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits;
+
+ if ((glddm == NULL) || (ctx == NULL))
+ return FALSE;
+
+ lpCtx = ctx->glPriv;
+ if (lpCtx == NULL)
+ return FALSE;
+
+ if (lpCtx->pD3D == NULL)
+ return FALSE;
+
+// hr = IDirect3D8_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm);
+ hr = D3DXGetCurrentVideoMode(D3DX_DEFAULT, &d3ddm);
+ if (FAILED(hr))
+ return FALSE;
+
+ // Get info from the display format
+// _BitsFromDisplayFormat(d3ddm.Format,
+// &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits);
+
+ glddm->Width = d3ddm.width;
+ glddm->Height = d3ddm.height;
+ glddm->BPP = d3ddm.bpp;
+ glddm->Refresh = d3ddm.refreshRate;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c
new file mode 100644
index 0000000000..892a22eb8f
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_driver_dx8.c
@@ -0,0 +1,1175 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Driver interface code to Mesa
+*
+****************************************************************************/
+
+//#include <windows.h>
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx8.h"
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "array_cache/acache.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast_setup/ss_context.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+extern BOOL dglSwapBuffers(HDC hDC);
+
+// HACK: Hack the _33 member of the OpenGL perspective projection matrix
+const float _fPersp_33 = 1.6f;
+
+//---------------------------------------------------------------------------
+// Internal functions
+//---------------------------------------------------------------------------
+
+void _gld_mesa_warning(
+ __GLcontext *gc,
+ char *str)
+{
+ // Intercept Mesa's internal warning mechanism
+ gldLogPrintf(GLDLOG_WARN, "Mesa warning: %s", str);
+}
+
+//---------------------------------------------------------------------------
+
+void _gld_mesa_fatal(
+ __GLcontext *gc,
+ char *str)
+{
+ // Intercept Mesa's internal fatal-message mechanism
+ gldLogPrintf(GLDLOG_CRITICAL, "Mesa FATAL: %s", str);
+
+ // Mesa calls abort(0) here.
+ ddlogClose();
+ exit(0);
+}
+
+//---------------------------------------------------------------------------
+
+D3DSTENCILOP _gldConvertStencilOp(
+ GLenum StencilOp)
+{
+ // Used by Stencil: pass, fail and zfail
+
+ switch (StencilOp) {
+ case GL_KEEP:
+ return D3DSTENCILOP_KEEP;
+ case GL_ZERO:
+ return D3DSTENCILOP_ZERO;
+ case GL_REPLACE:
+ return D3DSTENCILOP_REPLACE;
+ case GL_INCR:
+ return D3DSTENCILOP_INCRSAT;
+ case GL_DECR:
+ return D3DSTENCILOP_DECRSAT;
+ case GL_INVERT:
+ return D3DSTENCILOP_INVERT;
+ case GL_INCR_WRAP_EXT: // GL_EXT_stencil_wrap
+ return D3DSTENCILOP_INCR;
+ case GL_DECR_WRAP_EXT: // GL_EXT_stencil_wrap
+ return D3DSTENCILOP_DECR;
+ }
+
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "_gldConvertStencilOp: Unknown StencilOp\n");
+#endif
+
+ return D3DSTENCILOP_KEEP;
+}
+
+//---------------------------------------------------------------------------
+
+D3DCMPFUNC _gldConvertCompareFunc(
+ GLenum CmpFunc)
+{
+ // Used for Alpha func, depth func and stencil func.
+
+ switch (CmpFunc) {
+ case GL_NEVER:
+ return D3DCMP_NEVER;
+ case GL_LESS:
+ return D3DCMP_LESS;
+ case GL_EQUAL:
+ return D3DCMP_EQUAL;
+ case GL_LEQUAL:
+ return D3DCMP_LESSEQUAL;
+ case GL_GREATER:
+ return D3DCMP_GREATER;
+ case GL_NOTEQUAL:
+ return D3DCMP_NOTEQUAL;
+ case GL_GEQUAL:
+ return D3DCMP_GREATEREQUAL;
+ case GL_ALWAYS:
+ return D3DCMP_ALWAYS;
+ };
+
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "_gldConvertCompareFunc: Unknown CompareFunc\n");
+#endif
+
+ return D3DCMP_ALWAYS;
+}
+
+//---------------------------------------------------------------------------
+
+D3DBLEND _gldConvertBlendFunc(
+ GLenum blend,
+ GLenum DefaultBlend)
+{
+ switch (blend) {
+ case GL_ZERO:
+ return D3DBLEND_ZERO;
+ case GL_ONE:
+ return D3DBLEND_ONE;
+ case GL_DST_COLOR:
+ return D3DBLEND_DESTCOLOR;
+ case GL_SRC_COLOR:
+ return D3DBLEND_SRCCOLOR;
+ case GL_ONE_MINUS_DST_COLOR:
+ return D3DBLEND_INVDESTCOLOR;
+ case GL_ONE_MINUS_SRC_COLOR:
+ return D3DBLEND_INVSRCCOLOR;
+ case GL_SRC_ALPHA:
+ return D3DBLEND_SRCALPHA;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ return D3DBLEND_INVSRCALPHA;
+ case GL_DST_ALPHA:
+ return D3DBLEND_DESTALPHA;
+ case GL_ONE_MINUS_DST_ALPHA:
+ return D3DBLEND_INVDESTALPHA;
+ case GL_SRC_ALPHA_SATURATE:
+ return D3DBLEND_SRCALPHASAT;
+ }
+
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "_gldConvertBlendFunc: Unknown BlendFunc\n");
+#endif
+
+ return DefaultBlend;
+}
+
+//---------------------------------------------------------------------------
+// Misc. functions
+//---------------------------------------------------------------------------
+
+void gld_Noop_DX8(
+ GLcontext *ctx)
+{
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "gld_Noop called!\n");
+#endif
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Error_DX8(
+ GLcontext *ctx)
+{
+#ifdef _DEBUG
+ // Quite useless.
+// gldLogMessage(GLDLOG_ERROR, "ctx->Driver.Error called!\n");
+#endif
+}
+
+//---------------------------------------------------------------------------
+// Required Mesa functions
+//---------------------------------------------------------------------------
+
+static GLboolean gld_set_draw_buffer_DX8(
+ GLcontext *ctx,
+ GLenum mode)
+{
+ (void) ctx;
+ if ((mode==GL_FRONT_LEFT) || (mode == GL_BACK_LEFT)) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_set_read_buffer_DX8(
+ GLcontext *ctx,
+ GLframebuffer *buffer,
+ GLenum mode)
+{
+ /* separate read buffer not supported */
+/*
+ ASSERT(buffer == ctx->DrawBuffer);
+ ASSERT(mode == GL_FRONT_LEFT);
+*/
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Clear_DX8(
+ GLcontext *ctx,
+ GLbitfield mask,
+ GLboolean all,
+ GLint x,
+ GLint y,
+ GLint width,
+ GLint height)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ DWORD dwFlags = 0;
+ D3DCOLOR Color = 0;
+ float Z = 0.0f;
+ DWORD Stencil = 0;
+ D3DRECT d3dClearRect;
+
+ // TODO: Colourmask
+ const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
+
+ if (!gld->pDev)
+ return;
+
+ if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) {
+ GLubyte col[4];
+ CLAMPED_FLOAT_TO_UBYTE(col[0], ctx->Color.ClearColor[0]);
+ CLAMPED_FLOAT_TO_UBYTE(col[1], ctx->Color.ClearColor[1]);
+ CLAMPED_FLOAT_TO_UBYTE(col[2], ctx->Color.ClearColor[2]);
+ CLAMPED_FLOAT_TO_UBYTE(col[3], ctx->Color.ClearColor[3]);
+ dwFlags |= D3DCLEAR_TARGET;
+ Color = D3DCOLOR_RGBA(col[0], col[1], col[2], col[3]);
+// ctx->Color.ClearColor[1],
+// ctx->Color.ClearColor[2],
+// ctx->Color.ClearColor[3]);
+ }
+
+ if (mask & DD_DEPTH_BIT) {
+ // D3D8 will fail the Clear call if we try and clear a
+ // depth buffer and we haven't created one.
+ // Also, some apps try and clear a depth buffer,
+ // when a depth buffer hasn't been requested by the app.
+ if (ctx->Visual.depthBits == 0) {
+ mask &= ~DD_DEPTH_BIT; // Remove depth bit from mask
+ } else {
+ dwFlags |= D3DCLEAR_ZBUFFER;
+ Z = ctx->Depth.Clear;
+ }
+ }
+
+ if (mask & DD_STENCIL_BIT) {
+ if (ctx->Visual.stencilBits == 0) {
+ // No stencil bits in depth buffer
+ mask &= ~DD_STENCIL_BIT; // Remove stencil bit from mask
+ } else {
+ dwFlags |= D3DCLEAR_STENCIL;
+ Stencil = ctx->Stencil.Clear;
+ }
+ }
+
+ // Some apps do really weird things with the rect, such as Quake3.
+ if ((x < 0) || (y < 0) || (width <= 0) || (height <= 0)) {
+ all = GL_TRUE;
+ }
+
+ if (!all) {
+ // Calculate clear subrect
+ d3dClearRect.x1 = x;
+ d3dClearRect.y1 = gldCtx->dwHeight - (y + height);
+ d3dClearRect.x2 = x + width;
+ d3dClearRect.y2 = d3dClearRect.y1 + height;
+ }
+
+ // dwFlags will be zero if there's nothing to clear
+ if (dwFlags) {
+ _GLD_DX8_DEV(Clear(
+ gld->pDev,
+ all ? 0 : 1,
+ all ? NULL : &d3dClearRect,
+ dwFlags,
+ Color, Z, Stencil));
+ }
+
+ if (mask & DD_ACCUM_BIT) {
+ // Clear accumulation buffer
+ }
+}
+
+//---------------------------------------------------------------------------
+
+// Mesa 5: Parameter change
+static void gld_buffer_size_DX8(
+// GLcontext *ctx,
+ GLframebuffer *fb,
+ GLuint *width,
+ GLuint *height)
+{
+// GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+
+ *width = fb->Width; // gldCtx->dwWidth;
+ *height = fb->Height; // gldCtx->dwHeight;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_Finish_DX8(
+ GLcontext *ctx)
+{
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_Flush_DX8(
+ GLcontext *ctx)
+{
+ GLD_context *gld = GLD_GET_CONTEXT(ctx);
+
+ // TODO: Detect apps that glFlush() then SwapBuffers() ?
+
+ if (gld->EmulateSingle) {
+ // Emulating a single-buffered context.
+ // [Direct3D doesn't allow rendering to front buffer]
+ dglSwapBuffers(gld->hDC);
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_STENCIL(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ // Two-sided stencil. New for Mesa 5
+ const GLuint uiFace = 0UL;
+
+ struct gl_stencil_attrib *pStencil = &ctx->Stencil;
+
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILENABLE, pStencil->Enabled ? TRUE : FALSE));
+ if (pStencil->Enabled) {
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILFUNC, _gldConvertCompareFunc(pStencil->Function[uiFace])));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILREF, pStencil->Ref[uiFace]));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILMASK, pStencil->ValueMask[uiFace]));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILWRITEMASK, pStencil->WriteMask[uiFace]));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILFAIL, _gldConvertStencilOp(pStencil->FailFunc[uiFace])));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILZFAIL, _gldConvertStencilOp(pStencil->ZFailFunc[uiFace])));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_STENCILPASS, _gldConvertStencilOp(pStencil->ZPassFunc[uiFace])));
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_COLOR(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ DWORD dwFlags = 0;
+ D3DBLEND src;
+ D3DBLEND dest;
+
+ // Alpha func
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ALPHAFUNC, _gldConvertCompareFunc(ctx->Color.AlphaFunc)));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ALPHAREF, (DWORD)ctx->Color.AlphaRef));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ALPHATESTENABLE, ctx->Color.AlphaEnabled));
+
+ // Blend func
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ALPHABLENDENABLE, ctx->Color.BlendEnabled));
+ src = _gldConvertBlendFunc(ctx->Color.BlendSrcRGB, GL_ONE);
+ dest = _gldConvertBlendFunc(ctx->Color.BlendDstRGB, GL_ZERO);
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_SRCBLEND, src));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_DESTBLEND, dest));
+
+ // Color mask
+ if (ctx->Color.ColorMask[0]) dwFlags |= D3DCOLORWRITEENABLE_RED;
+ if (ctx->Color.ColorMask[1]) dwFlags |= D3DCOLORWRITEENABLE_GREEN;
+ if (ctx->Color.ColorMask[2]) dwFlags |= D3DCOLORWRITEENABLE_BLUE;
+ if (ctx->Color.ColorMask[3]) dwFlags |= D3DCOLORWRITEENABLE_ALPHA;
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_COLORWRITEENABLE, dwFlags));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_DEPTH(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ZENABLE, ctx->Depth.Test ? D3DZB_TRUE : D3DZB_FALSE));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ZFUNC, _gldConvertCompareFunc(ctx->Depth.Func)));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ZWRITEENABLE, ctx->Depth.Mask ? TRUE : FALSE));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_POLYGON(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ D3DFILLMODE d3dFillMode = D3DFILL_SOLID;
+ D3DCULL d3dCullMode = D3DCULL_NONE;
+ int iOffset = 0;
+
+ // Fillmode
+ switch (ctx->Polygon.FrontMode) {
+ case GL_POINT:
+ d3dFillMode = D3DFILL_POINT;
+ break;
+ case GL_LINE:
+ d3dFillMode = D3DFILL_WIREFRAME;
+ break;
+ case GL_FILL:
+ d3dFillMode = D3DFILL_SOLID;
+ break;
+ }
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FILLMODE, d3dFillMode));
+
+ if (ctx->Polygon.CullFlag) {
+ switch (ctx->Polygon.CullFaceMode) {
+ case GL_BACK:
+ if (ctx->Polygon.FrontFace == GL_CCW)
+ d3dCullMode = D3DCULL_CW;
+ else
+ d3dCullMode = D3DCULL_CCW;
+ break;
+ case GL_FRONT:
+ if (ctx->Polygon.FrontFace == GL_CCW)
+ d3dCullMode = D3DCULL_CCW;
+ else
+ d3dCullMode = D3DCULL_CW;
+ break;
+ case GL_FRONT_AND_BACK:
+ d3dCullMode = D3DCULL_NONE;
+ break;
+ default:
+ break;
+ }
+ } else {
+ d3dCullMode = D3DCULL_NONE;
+ }
+// d3dCullMode = D3DCULL_NONE; // TODO: DEBUGGING
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_CULLMODE, d3dCullMode));
+
+ // Polygon offset
+ // ZBIAS ranges from 0 to 16 and can only move towards the viewer
+ // Mesa5: ctx->Polygon._OffsetAny removed
+ if (ctx->Polygon.OffsetFill) {
+ iOffset = (int)ctx->Polygon.OffsetUnits;
+ if (iOffset < 0)
+ iOffset = -iOffset;
+ else
+ iOffset = 0; // D3D can't push away
+ }
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_ZBIAS, iOffset));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_FOG(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ D3DCOLOR d3dFogColour;
+ D3DFOGMODE d3dFogMode = D3DFOG_LINEAR;
+
+ // TODO: Fog is calculated seperately in the Mesa pipeline
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGENABLE, FALSE));
+ return;
+
+ // Fog enable
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGENABLE, ctx->Fog.Enabled));
+ if (!ctx->Fog.Enabled) {
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGTABLEMODE, D3DFOG_NONE));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGVERTEXMODE, D3DFOG_NONE));
+ return; // If disabled, don't bother setting any fog state
+ }
+
+ // Fog colour
+ d3dFogColour = D3DCOLOR_COLORVALUE( ctx->Fog.Color[0],
+ ctx->Fog.Color[1],
+ ctx->Fog.Color[2],
+ ctx->Fog.Color[3]);
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGCOLOR, d3dFogColour));
+
+ // Fog density
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGDENSITY, *((DWORD*) (&ctx->Fog.Density))));
+
+ // Fog start
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGSTART, *((DWORD*) (&ctx->Fog.Start))));
+
+ // Fog end
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGEND, *((DWORD*) (&ctx->Fog.End))));
+
+ // Fog mode
+ switch (ctx->Fog.Mode) {
+ case GL_LINEAR:
+ d3dFogMode = D3DFOG_LINEAR;
+ break;
+ case GL_EXP:
+ d3dFogMode = D3DFOG_EXP;
+ break;
+ case GL_EXP2:
+ d3dFogMode = D3DFOG_EXP2;
+ break;
+ }
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGTABLEMODE, d3dFogMode));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_FOGVERTEXMODE, D3DFOG_NONE));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_LIGHT(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+ DWORD dwSpecularEnable;
+
+ // Shademode
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_SHADEMODE, (ctx->Light.ShadeModel == GL_SMOOTH) ? D3DSHADE_GOURAUD : D3DSHADE_FLAT));
+
+ // Separate specular colour
+ if (ctx->Light.Enabled)
+ dwSpecularEnable = (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) ? TRUE: FALSE;
+ else
+ dwSpecularEnable = FALSE;
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_SPECULARENABLE, dwSpecularEnable));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_MODELVIEW(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ D3DMATRIX m;
+ //GLfloat *pM = ctx->ModelView.m;
+ // Mesa5: Model-view is now a stack
+ GLfloat *pM = ctx->ModelviewMatrixStack.Top->m;
+ m._11 = pM[0];
+ m._12 = pM[1];
+ m._13 = pM[2];
+ m._14 = pM[3];
+ m._21 = pM[4];
+ m._22 = pM[5];
+ m._23 = pM[6];
+ m._24 = pM[7];
+ m._31 = pM[8];
+ m._32 = pM[9];
+ m._33 = pM[10];
+ m._34 = pM[11];
+ m._41 = pM[12];
+ m._42 = pM[13];
+ m._43 = pM[14];
+ m._44 = pM[15];
+
+ gld->matModelView = m;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_PROJECTION(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ D3DMATRIX m;
+ //GLfloat *pM = ctx->ProjectionMatrix.m;
+ // Mesa 5: Now a stack
+ GLfloat *pM = ctx->ProjectionMatrixStack.Top->m;
+ m._11 = pM[0];
+ m._12 = pM[1];
+ m._13 = pM[2];
+ m._14 = pM[3];
+
+ m._21 = pM[4];
+ m._22 = pM[5];
+ m._23 = pM[6];
+ m._24 = pM[7];
+
+ m._31 = pM[8];
+ m._32 = pM[9];
+ m._33 = pM[10] / _fPersp_33; // / 1.6f;
+ m._34 = pM[11];
+
+ m._41 = pM[12];
+ m._42 = pM[13];
+ m._43 = pM[14] / 2.0f;
+ m._44 = pM[15];
+
+ gld->matProjection = m;
+}
+
+//---------------------------------------------------------------------------
+/*
+void gldFrustumHook_DX8(
+ GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top,
+ GLdouble nearval,
+ GLdouble farval)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ // Pass values on to Mesa first (in case we mess with them)
+ _mesa_Frustum(left, right, bottom, top, nearval, farval);
+
+ _fPersp_33 = farval / (nearval - farval);
+
+// ddlogPrintf(GLDLOG_SYSTEM, "Frustum: %f", farval/nearval);
+}
+
+//---------------------------------------------------------------------------
+
+void gldOrthoHook_DX8(
+ GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top,
+ GLdouble nearval,
+ GLdouble farval)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ // Pass values on to Mesa first (in case we mess with them)
+ _mesa_Ortho(left, right, bottom, top, nearval, farval);
+
+ _fPersp_33 = 1.6f;
+
+// ddlogPrintf(GLDLOG_SYSTEM, "Ortho: %f", farval/nearval);
+}
+*/
+//---------------------------------------------------------------------------
+
+void gld_NEW_VIEWPORT(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ D3DVIEWPORT8 d3dvp;
+// GLint x, y;
+// GLsizei w, h;
+
+ // Set depth range
+ _GLD_DX8_DEV(GetViewport(gld->pDev, &d3dvp));
+ // D3D can't do Quake1/Quake2 z-trick
+ if (ctx->Viewport.Near <= ctx->Viewport.Far) {
+ d3dvp.MinZ = ctx->Viewport.Near;
+ d3dvp.MaxZ = ctx->Viewport.Far;
+ } else {
+ d3dvp.MinZ = ctx->Viewport.Far;
+ d3dvp.MaxZ = ctx->Viewport.Near;
+ }
+/* x = ctx->Viewport.X;
+ y = ctx->Viewport.Y;
+ w = ctx->Viewport.Width;
+ h = ctx->Viewport.Height;
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (w > gldCtx->dwWidth) w = gldCtx->dwWidth;
+ if (h > gldCtx->dwHeight) h = gldCtx->dwHeight;
+ // Ditto for D3D viewport dimensions
+ if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x;
+ if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y;
+ d3dvp.X = x;
+ d3dvp.Y = gldCtx->dwHeight - (y + h);
+ d3dvp.Width = w;
+ d3dvp.Height = h;*/
+ _GLD_DX8_DEV(SetViewport(gld->pDev, &d3dvp));
+
+// gld->fFlipWindowY = (float)gldCtx->dwHeight;
+}
+
+//---------------------------------------------------------------------------
+
+__inline BOOL _gldAnyEvalEnabled(
+ GLcontext *ctx)
+{
+ struct gl_eval_attrib *eval = &ctx->Eval;
+
+ if ((eval->AutoNormal) ||
+ (eval->Map1Color4) ||
+ (eval->Map1Index) ||
+ (eval->Map1Normal) ||
+ (eval->Map1TextureCoord1) ||
+ (eval->Map1TextureCoord2) ||
+ (eval->Map1TextureCoord3) ||
+ (eval->Map1TextureCoord4) ||
+ (eval->Map1Vertex3) ||
+ (eval->Map1Vertex4) ||
+ (eval->Map2Color4) ||
+ (eval->Map2Index) ||
+ (eval->Map2Normal) ||
+ (eval->Map2TextureCoord1) ||
+ (eval->Map2TextureCoord2) ||
+ (eval->Map2TextureCoord3) ||
+ (eval->Map2TextureCoord4) ||
+ (eval->Map2Vertex3) ||
+ (eval->Map2Vertex4)
+ )
+ return TRUE;
+
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL _gldChooseInternalPipeline(
+ GLcontext *ctx,
+ GLD_driver_dx8 *gld)
+{
+// return TRUE; // DEBUGGING: ALWAYS USE MESA
+// return FALSE; // DEBUGGING: ALWAYS USE D3D
+
+ if ((glb.dwTnL == GLDS_TNL_MESA) || (gld->bHasHWTnL == FALSE))
+ {
+ gld->PipelineUsage.qwMesa.QuadPart++;
+ return TRUE; // Force Mesa TnL
+ }
+
+ if ((ctx->Light.Enabled) ||
+ (1) ||
+ (ctx->Texture._TexGenEnabled) ||
+ (ctx->Texture._TexMatEnabled) ||
+// (ctx->Transform._AnyClip) ||
+ (ctx->Scissor.Enabled) ||
+ _gldAnyEvalEnabled(ctx) // Put this last so we can early-out
+ )
+ {
+ gld->PipelineUsage.qwMesa.QuadPart++;
+ return TRUE;
+ }
+
+ gld->PipelineUsage.qwD3DFVF.QuadPart++;
+ return FALSE;
+
+/* // Force Mesa pipeline?
+ if (glb.dwTnL == GLDS_TNL_MESA) {
+ gld->PipelineUsage.dwMesa.QuadPart++;
+ return GLD_PIPELINE_MESA;
+ }
+
+ // Test for functionality not exposed in the D3D pathways
+ if ((ctx->Texture._GenFlags)) {
+ gld->PipelineUsage.dwMesa.QuadPart++;
+ return GLD_PIPELINE_MESA;
+ }
+
+ // Now decide if vertex shader can be used.
+ // If two sided lighting is enabled then we must either
+ // use Mesa TnL or the vertex shader
+ if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
+ if (gld->VStwosidelight.hShader && !ctx->Fog.Enabled) {
+ // Use Vertex Shader
+ gld->PipelineUsage.dwD3D2SVS.QuadPart++;
+ return GLD_PIPELINE_D3D_VS_TWOSIDE;
+ } else {
+ // Use Mesa TnL
+ gld->PipelineUsage.dwMesa.QuadPart++;
+ return GLD_PIPELINE_MESA;
+ }
+ }
+
+ // Must be D3D fixed-function pipeline
+ gld->PipelineUsage.dwD3DFVF.QuadPart++;
+ return GLD_PIPELINE_D3D_FVF;
+*/
+}
+
+//---------------------------------------------------------------------------
+
+void gld_update_state_DX8(
+ GLcontext *ctx,
+ GLuint new_state)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLD_pb_dx8 *gldPB;
+
+ if (!gld || !gld->pDev)
+ return;
+
+ _swsetup_InvalidateState( ctx, new_state );
+ _ac_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+
+ // SetupIndex will be used in the pipelines for choosing setup function
+ if ((ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE | DD_SEPARATE_SPECULAR)) ||
+ (ctx->Fog.Enabled))
+ {
+ if (ctx->_TriangleCaps & DD_FLATSHADE)
+ gld->iSetupFunc = GLD_SI_FLAT_EXTRAS;
+ else
+ gld->iSetupFunc = GLD_SI_SMOOTH_EXTRAS;
+ } else {
+ if (ctx->_TriangleCaps & DD_FLATSHADE)
+ gld->iSetupFunc = GLD_SI_FLAT; // Setup flat shade + texture
+ else
+ gld->iSetupFunc = GLD_SI_SMOOTH; // Setup smooth shade + texture
+ }
+
+ gld->bUseMesaTnL = _gldChooseInternalPipeline(ctx, gld);
+ if (gld->bUseMesaTnL) {
+ gldPB = &gld->PB2d;
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, TRUE));
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_CLIPPING, FALSE));
+ _GLD_DX8_DEV(SetVertexShader(gld->pDev, gldPB->dwFVF));
+ } else {
+ gldPB = &gld->PB3d;
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_CLIPPING, TRUE));
+// if (gld->TnLPipeline == GLD_PIPELINE_D3D_VS_TWOSIDE) {
+// _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->VStwosidelight.bHardware));
+// _GLD_DX8_DEV(SetVertexShader(gld->pDev, gld->VStwosidelight.hShader));
+// } else {
+ _GLD_DX8_DEV(SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->bHasHWTnL));
+ _GLD_DX8_DEV(SetVertexShader(gld->pDev, gldPB->dwFVF));
+// }
+ }
+
+#define _GLD_TEST_STATE(a) \
+ if (new_state & (a)) { \
+ gld##a(ctx); \
+ new_state &= ~(a); \
+ }
+
+#define _GLD_TEST_STATE_DX8(a) \
+ if (new_state & (a)) { \
+ gld##a##_DX8(ctx); \
+ new_state &= ~(a); \
+ }
+
+#define _GLD_IGNORE_STATE(a) new_state &= ~(a);
+
+// if (!gld->bUseMesaTnL) {
+ // Not required if Mesa is doing the TnL.
+ // Problem: If gld->bUseMesaTnL is TRUE when these are signaled,
+ // then we'll miss updating the D3D TnL pipeline.
+ // Therefore, don't test for gld->bUseMesaTnL
+ _GLD_TEST_STATE(_NEW_MODELVIEW);
+ _GLD_TEST_STATE(_NEW_PROJECTION);
+// }
+
+ _GLD_TEST_STATE_DX8(_NEW_TEXTURE); // extern, so guard with _DX8
+ _GLD_TEST_STATE(_NEW_COLOR);
+ _GLD_TEST_STATE(_NEW_DEPTH);
+ _GLD_TEST_STATE(_NEW_POLYGON);
+ _GLD_TEST_STATE(_NEW_STENCIL);
+ _GLD_TEST_STATE(_NEW_FOG);
+ _GLD_TEST_STATE(_NEW_LIGHT);
+ _GLD_TEST_STATE(_NEW_VIEWPORT);
+
+ _GLD_IGNORE_STATE(_NEW_TRANSFORM);
+
+
+// Stubs for future use.
+/* _GLD_TEST_STATE(_NEW_TEXTURE_MATRIX);
+ _GLD_TEST_STATE(_NEW_COLOR_MATRIX);
+ _GLD_TEST_STATE(_NEW_ACCUM);
+ _GLD_TEST_STATE(_NEW_EVAL);
+ _GLD_TEST_STATE(_NEW_HINT);
+ _GLD_TEST_STATE(_NEW_LINE);
+ _GLD_TEST_STATE(_NEW_PIXEL);
+ _GLD_TEST_STATE(_NEW_POINT);
+ _GLD_TEST_STATE(_NEW_POLYGONSTIPPLE);
+ _GLD_TEST_STATE(_NEW_SCISSOR);
+ _GLD_TEST_STATE(_NEW_PACKUNPACK);
+ _GLD_TEST_STATE(_NEW_ARRAY);
+ _GLD_TEST_STATE(_NEW_RENDERMODE);
+ _GLD_TEST_STATE(_NEW_BUFFERS);
+ _GLD_TEST_STATE(_NEW_MULTISAMPLE);
+*/
+
+// For debugging.
+#if 0
+#define _GLD_TEST_UNHANDLED_STATE(a) \
+ if (new_state & (a)) { \
+ gldLogMessage(GLDLOG_ERROR, "Unhandled " #a "\n"); \
+ }
+ _GLD_TEST_UNHANDLED_STATE(_NEW_TEXTURE_MATRIX);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_COLOR_MATRIX);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_ACCUM);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_EVAL);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_HINT);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_LINE);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_PIXEL);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_POINT);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_POLYGONSTIPPLE);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_SCISSOR);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_PACKUNPACK);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_ARRAY);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_RENDERMODE);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_BUFFERS);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_MULTISAMPLE);
+#undef _GLD_UNHANDLED_STATE
+#endif
+
+#undef _GLD_TEST_STATE
+}
+
+//---------------------------------------------------------------------------
+// Viewport
+//---------------------------------------------------------------------------
+
+void gld_Viewport_DX8(
+ GLcontext *ctx,
+ GLint x,
+ GLint y,
+ GLsizei w,
+ GLsizei h)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ D3DVIEWPORT8 d3dvp;
+
+ if (!gld || !gld->pDev)
+ return;
+
+ // This is a hack. When the app is minimized, Mesa passes
+ // w=1 and h=1 for viewport dimensions. Without this test
+ // we get a GPF in gld_wgl_resize_buffers().
+ if ((w==1) && (h==1))
+ return;
+
+ // Call ResizeBuffersMESA. This function will early-out
+ // if no resize is needed.
+ //ctx->Driver.ResizeBuffersMESA(ctx);
+ // Mesa 5: Changed parameters
+ ctx->Driver.ResizeBuffers(gldCtx->glBuffer);
+
+#if 0
+ ddlogPrintf(GLDLOG_SYSTEM, ">> Viewport x=%d y=%d w=%d h=%d", x,y,w,h);
+#endif
+
+ // ** D3D viewport must not be outside the render target surface **
+ // Sanity check the GL viewport dimensions
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (w > gldCtx->dwWidth) w = gldCtx->dwWidth;
+ if (h > gldCtx->dwHeight) h = gldCtx->dwHeight;
+ // Ditto for D3D viewport dimensions
+ if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x;
+ if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y;
+
+ d3dvp.X = x;
+ d3dvp.Y = gldCtx->dwHeight - (y + h);
+ d3dvp.Width = w;
+ d3dvp.Height = h;
+ if (ctx->Viewport.Near <= ctx->Viewport.Far) {
+ d3dvp.MinZ = ctx->Viewport.Near;
+ d3dvp.MaxZ = ctx->Viewport.Far;
+ } else {
+ d3dvp.MinZ = ctx->Viewport.Far;
+ d3dvp.MaxZ = ctx->Viewport.Near;
+ }
+
+ // TODO: DEBUGGING
+// d3dvp.MinZ = 0.0f;
+// d3dvp.MaxZ = 1.0f;
+
+ _GLD_DX8_DEV(SetViewport(gld->pDev, &d3dvp));
+
+}
+
+//---------------------------------------------------------------------------
+
+extern BOOL dglWglResizeBuffers(GLcontext *ctx, BOOL bDefaultDriver);
+
+// Mesa 5: Parameter change
+void gldResizeBuffers_DX8(
+// GLcontext *ctx)
+ GLframebuffer *fb)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ dglWglResizeBuffers(ctx, TRUE);
+}
+
+//---------------------------------------------------------------------------
+#ifdef _DEBUG
+// This is only for debugging.
+// To use, plug into ctx->Driver.Enable pointer below.
+void gld_Enable(
+ GLcontext *ctx,
+ GLenum e,
+ GLboolean b)
+{
+ char buf[1024];
+ sprintf(buf, "Enable: %s (%s)\n", _mesa_lookup_enum_by_nr(e), b?"TRUE":"FALSE");
+ ddlogMessage(DDLOG_SYSTEM, buf);
+}
+#endif
+//---------------------------------------------------------------------------
+// Driver pointer setup
+//---------------------------------------------------------------------------
+
+extern const GLubyte* _gldGetStringGeneric(GLcontext*, GLenum);
+
+void gldSetupDriverPointers_DX8(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ // Mandatory functions
+ ctx->Driver.GetString = _gldGetStringGeneric;
+ ctx->Driver.UpdateState = gld_update_state_DX8;
+ ctx->Driver.Clear = gld_Clear_DX8;
+ ctx->Driver.DrawBuffer = gld_set_draw_buffer_DX8;
+ ctx->Driver.GetBufferSize = gld_buffer_size_DX8;
+ ctx->Driver.Finish = gld_Finish_DX8;
+ ctx->Driver.Flush = gld_Flush_DX8;
+ ctx->Driver.Error = gld_Error_DX8;
+
+ // Hardware accumulation buffer
+ ctx->Driver.Accum = NULL; // TODO: gld_Accum;
+
+ // Bitmap functions
+ ctx->Driver.CopyPixels = gld_CopyPixels_DX8;
+ ctx->Driver.DrawPixels = gld_DrawPixels_DX8;
+ ctx->Driver.ReadPixels = gld_ReadPixels_DX8;
+ ctx->Driver.Bitmap = gld_Bitmap_DX8;
+
+ // Buffer resize
+ ctx->Driver.ResizeBuffers = gldResizeBuffers_DX8;
+
+ // Texture image functions
+ ctx->Driver.ChooseTextureFormat = gld_ChooseTextureFormat_DX8;
+ ctx->Driver.TexImage1D = gld_TexImage1D_DX8;
+ ctx->Driver.TexImage2D = gld_TexImage2D_DX8;
+ ctx->Driver.TexImage3D = _mesa_store_teximage3d;
+ ctx->Driver.TexSubImage1D = gld_TexSubImage1D_DX8;
+ ctx->Driver.TexSubImage2D = gld_TexSubImage2D_DX8;
+ ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
+
+ ctx->Driver.CopyTexImage1D = gldCopyTexImage1D_DX8; //NULL;
+ ctx->Driver.CopyTexImage2D = gldCopyTexImage2D_DX8; //NULL;
+ ctx->Driver.CopyTexSubImage1D = gldCopyTexSubImage1D_DX8; //NULL;
+ ctx->Driver.CopyTexSubImage2D = gldCopyTexSubImage2D_DX8; //NULL;
+ ctx->Driver.CopyTexSubImage3D = gldCopyTexSubImage3D_DX8;
+ ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
+
+ // Texture object functions
+ ctx->Driver.BindTexture = NULL;
+ ctx->Driver.CreateTexture = NULL; // Not yet implemented by Mesa!;
+ ctx->Driver.DeleteTexture = gld_DeleteTexture_DX8;
+ ctx->Driver.PrioritizeTexture = NULL;
+
+ // Imaging functionality
+ ctx->Driver.CopyColorTable = NULL;
+ ctx->Driver.CopyColorSubTable = NULL;
+ ctx->Driver.CopyConvolutionFilter1D = NULL;
+ ctx->Driver.CopyConvolutionFilter2D = NULL;
+
+ // State changing functions
+ ctx->Driver.AlphaFunc = NULL; //gld_AlphaFunc;
+ ctx->Driver.BlendFunc = NULL; //gld_BlendFunc;
+ ctx->Driver.ClearColor = NULL; //gld_ClearColor;
+ ctx->Driver.ClearDepth = NULL; //gld_ClearDepth;
+ ctx->Driver.ClearStencil = NULL; //gld_ClearStencil;
+ ctx->Driver.ColorMask = NULL; //gld_ColorMask;
+ ctx->Driver.CullFace = NULL; //gld_CullFace;
+ ctx->Driver.ClipPlane = NULL; //gld_ClipPlane;
+ ctx->Driver.FrontFace = NULL; //gld_FrontFace;
+ ctx->Driver.DepthFunc = NULL; //gld_DepthFunc;
+ ctx->Driver.DepthMask = NULL; //gld_DepthMask;
+ ctx->Driver.DepthRange = NULL;
+ ctx->Driver.Enable = NULL; //gld_Enable;
+ ctx->Driver.Fogfv = NULL; //gld_Fogfv;
+ ctx->Driver.Hint = NULL; //gld_Hint;
+ ctx->Driver.Lightfv = NULL; //gld_Lightfv;
+ ctx->Driver.LightModelfv = NULL; //gld_LightModelfv;
+ ctx->Driver.LineStipple = NULL; //gld_LineStipple;
+ ctx->Driver.LineWidth = NULL; //gld_LineWidth;
+ ctx->Driver.LogicOpcode = NULL; //gld_LogicOpcode;
+ ctx->Driver.PointParameterfv = NULL; //gld_PointParameterfv;
+ ctx->Driver.PointSize = NULL; //gld_PointSize;
+ ctx->Driver.PolygonMode = NULL; //gld_PolygonMode;
+ ctx->Driver.PolygonOffset = NULL; //gld_PolygonOffset;
+ ctx->Driver.PolygonStipple = NULL; //gld_PolygonStipple;
+ ctx->Driver.RenderMode = NULL; //gld_RenderMode;
+ ctx->Driver.Scissor = NULL; //gld_Scissor;
+ ctx->Driver.ShadeModel = NULL; //gld_ShadeModel;
+ ctx->Driver.StencilFunc = NULL; //gld_StencilFunc;
+ ctx->Driver.StencilMask = NULL; //gld_StencilMask;
+ ctx->Driver.StencilOp = NULL; //gld_StencilOp;
+ ctx->Driver.TexGen = NULL; //gld_TexGen;
+ ctx->Driver.TexEnv = NULL;
+ ctx->Driver.TexParameter = NULL;
+ ctx->Driver.TextureMatrix = NULL; //gld_TextureMatrix;
+ ctx->Driver.Viewport = gld_Viewport_DX8;
+
+ _swsetup_Wakeup(ctx);
+
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+ tnl->Driver.Render.ResetLineStipple = gld_ResetLineStipple_DX8;
+ tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
+ tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine;
+
+ // Hook into glFrustum() and glOrtho()
+// ctx->Exec->Frustum = gldFrustumHook_DX8;
+// ctx->Exec->Ortho = gldOrthoHook_DX8;
+
+}
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_dx8.h b/src/mesa/drivers/windows/gldirect/dx8/gld_dx8.h
new file mode 100644
index 0000000000..7efec7cae8
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_dx8.h
@@ -0,0 +1,324 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GLDirect Direct3D 8.0 header file
+*
+****************************************************************************/
+
+#ifndef _GLD_DX8_H
+#define _GLD_DX8_H
+
+//---------------------------------------------------------------------------
+// Windows includes
+//---------------------------------------------------------------------------
+
+//#ifndef STRICT
+//#define STRICT
+//#endif
+
+//#define WIN32_LEAN_AND_MEAN
+//#include <windows.h>
+#include <d3d8.h>
+#include <d3dx8.h>
+
+// MS screwed up with the DX8.1 SDK - there's no compile-time
+// method of compiling for 8.0 via the 8.1 SDK unless you
+// "make sure you don't use any 8.1 interfaces".
+// We CAN use 8.1 D3DX static functions, though - just not new 8.1 interfaces.
+//
+// D3D_SDK_VERSION is 120 for 8.0 (supported by Windows 95).
+// D3D_SDK_VERSION is 220 for 8.1 (NOT supported by Windows 95).
+//
+#define D3D_SDK_VERSION_DX8_SUPPORT_WIN95 120
+
+// Typedef for obtaining function from d3d8.dll
+typedef IDirect3D8* (WINAPI *FNDIRECT3DCREATE8) (UINT);
+
+
+//---------------------------------------------------------------------------
+// Defines
+//---------------------------------------------------------------------------
+
+#ifdef _DEBUG
+#define _GLD_TEST_HRESULT(h) \
+{ \
+ HRESULT _hr = (h); \
+ if (FAILED(_hr)) { \
+ gldLogError(GLDLOG_ERROR, #h, _hr); \
+ } \
+}
+#define _GLD_DX8(func) _GLD_TEST_HRESULT(IDirect3D8_##func##)
+#define _GLD_DX8_DEV(func) _GLD_TEST_HRESULT(IDirect3DDevice8_##func##)
+#define _GLD_DX8_VB(func) _GLD_TEST_HRESULT(IDirect3DVertexBuffer8_##func##)
+#define _GLD_DX8_TEX(func) _GLD_TEST_HRESULT(IDirect3DTexture8_##func##)
+#else
+#define _GLD_DX8(func) IDirect3D8_##func
+#define _GLD_DX8_DEV(func) IDirect3DDevice8_##func
+#define _GLD_DX8_VB(func) IDirect3DVertexBuffer8_##func
+#define _GLD_DX8_TEX(func) IDirect3DTexture8_##func
+#endif
+
+#define SAFE_RELEASE(p) \
+{ \
+ if (p) { \
+ (p)->lpVtbl->Release(p); \
+ (p) = NULL; \
+ } \
+}
+
+#define SAFE_RELEASE_VB8(p) \
+{ \
+ if (p) { \
+ IDirect3DVertexBuffer8_Release((p)); \
+ (p) = NULL; \
+ } \
+}
+
+#define SAFE_RELEASE_SURFACE8(p) \
+{ \
+ if (p) { \
+ IDirect3DSurface8_Release((p)); \
+ (p) = NULL; \
+ } \
+}
+
+// Setup index.
+enum {
+ GLD_SI_FLAT = 0,
+ GLD_SI_SMOOTH = 1,
+ GLD_SI_FLAT_EXTRAS = 2,
+ GLD_SI_SMOOTH_EXTRAS = 3,
+};
+/*
+// Internal pipeline
+typedef enum {
+ GLD_PIPELINE_MESA = 0, // Mesa pipeline
+ GLD_PIPELINE_D3D_FVF = 1, // Direct3D Fixed-function pipeline
+ GLD_PIPELINE_D3D_VS_TWOSIDE = 2 // Direct3D two-sided-lighting vertex shader
+} GLD_tnl_pipeline;
+*/
+//---------------------------------------------------------------------------
+// Vertex definitions for Fixed-Function pipeline
+//---------------------------------------------------------------------------
+
+//
+// NOTE: If the number of texture units is altered then most of
+// the texture code will need to be revised.
+//
+
+#define GLD_MAX_TEXTURE_UNITS_DX8 2
+
+//
+// 2D vertex transformed by Mesa
+//
+#define GLD_FVF_2D_VERTEX ( D3DFVF_XYZRHW | \
+ D3DFVF_DIFFUSE | \
+ D3DFVF_SPECULAR | \
+ D3DFVF_TEX2)
+typedef struct {
+ FLOAT x, y; // 2D raster coords
+ FLOAT sz; // Screen Z (depth)
+ FLOAT rhw; // Reciprocal homogenous W
+ DWORD diffuse; // Diffuse colour
+ DWORD specular; // For separate-specular support
+ FLOAT t0_u, t0_v; // 1st set of texture coords
+ FLOAT t1_u, t1_v; // 2nd set of texture coords
+} GLD_2D_VERTEX;
+
+
+//
+// 3D vertex transformed by Direct3D
+//
+#define GLD_FVF_3D_VERTEX ( D3DFVF_XYZ | \
+ D3DFVF_DIFFUSE | \
+ D3DFVF_TEX2)
+
+typedef struct {
+ D3DXVECTOR3 Position; // XYZ Vector in object space
+ D3DCOLOR Diffuse; // Diffuse colour
+ D3DXVECTOR2 TexUnit0; // Texture unit 0
+ D3DXVECTOR2 TexUnit1; // Texture unit 1
+} GLD_3D_VERTEX;
+
+//---------------------------------------------------------------------------
+// Vertex Shaders
+//---------------------------------------------------------------------------
+/*
+// DX8 Vertex Shader
+typedef struct {
+ DWORD hShader; // If NULL, shader is invalid and cannot be used
+ BOOL bHardware; // If TRUE then shader was created for hardware,
+ // otherwise shader was created for software.
+} GLD_vertexShader;
+*/
+//---------------------------------------------------------------------------
+// Structs
+//---------------------------------------------------------------------------
+
+// This keeps a count of how many times we choose each individual internal
+// pathway. Useful for seeing if a certain pathway was ever used by an app, and
+// how much each pathway is biased.
+// Zero the members at context creation and dump stats at context deletion.
+typedef struct {
+ // Note: DWORD is probably too small
+ ULARGE_INTEGER qwMesa; // Mesa TnL pipeline
+ ULARGE_INTEGER qwD3DFVF; // Direct3D Fixed-Function pipeline
+// ULARGE_INTEGER dwD3D2SVS; // Direct3D Two-Sided Vertex Shader pipeline
+} GLD_pipeline_usage;
+
+// GLDirect Primitive Buffer (points, lines, triangles and quads)
+typedef struct {
+ // Data for IDirect3DDevice8::CreateVertexBuffer()
+ DWORD dwStride; // Stride of vertex
+ DWORD dwUsage; // Usage flags
+ DWORD dwFVF; // Direct3D Flexible Vertex Format
+ DWORD dwPool; // Pool flags
+
+ IDirect3DVertexBuffer8 *pVB; // Holds points, lines, tris and quads.
+
+ // Point list is assumed to be at start of buffer
+ DWORD iFirstLine; // Index of start of line list
+ DWORD iFirstTriangle; // Index of start of triangle list
+
+ BYTE *pPoints; // Pointer to next free point
+ BYTE *pLines; // Pointer to next free line
+ BYTE *pTriangles; // Pointer to next free triangle
+
+ DWORD nPoints; // Number of points ready to render
+ DWORD nLines; // Number of lines ready to render
+ DWORD nTriangles; // Number of triangles ready to render
+} GLD_pb_dx8;
+
+// GLDirect DX8 driver data
+typedef struct {
+ // GLDirect vars
+ BOOL bDoublebuffer; // Doublebuffer (otherwise single-buffered)
+ BOOL bDepthStencil; // Depth buffer needed (stencil optional)
+ D3DFORMAT RenderFormat; // Format of back/front buffer
+ D3DFORMAT DepthFormat; // Format of depth/stencil
+// float fFlipWindowY; // Value for flipping viewport Y coord
+
+ // Direct3D vars
+ D3DCAPS8 d3dCaps8;
+ BOOL bHasHWTnL; // Device has Hardware Transform/Light?
+ IDirect3D8 *pD3D; // Base Direct3D8 interface
+ IDirect3DDevice8 *pDev; // Direct3D8 Device interface
+ GLD_pb_dx8 PB2d; // Vertices transformed by Mesa
+ GLD_pb_dx8 PB3d; // Vertices transformed by Direct3D
+ D3DPRIMITIVETYPE d3dpt; // Current Direct3D primitive type
+ D3DXMATRIX matProjection; // Projection matrix for D3D TnL
+ D3DXMATRIX matModelView; // Model/View matrix for D3D TnL
+ int iSetupFunc; // Which setup functions to use
+ BOOL bUseMesaTnL; // Whether to use Mesa or D3D for TnL
+
+ // Direct3D vars for two-sided lighting
+// GLD_vertexShader VStwosidelight; // Vertex Shader for two-sided lighting
+// D3DXMATRIX matWorldViewProj;// World/View/Projection matrix for shaders
+
+
+// GLD_tnl_pipeline TnLPipeline; // Index of current internal pipeline
+ GLD_pipeline_usage PipelineUsage;
+} GLD_driver_dx8;
+
+#define GLD_GET_DX8_DRIVER(c) (GLD_driver_dx8*)(c)->glPriv
+
+//---------------------------------------------------------------------------
+// Function prototypes
+//---------------------------------------------------------------------------
+
+PROC gldGetProcAddress_DX8(LPCSTR a);
+void gldEnableExtensions_DX8(GLcontext *ctx);
+void gldInstallPipeline_DX8(GLcontext *ctx);
+void gldSetupDriverPointers_DX8(GLcontext *ctx);
+//void gldResizeBuffers_DX8(GLcontext *ctx);
+void gldResizeBuffers_DX8(GLframebuffer *fb);
+
+
+// Texture functions
+
+void gldCopyTexImage1D_DX8(GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
+void gldCopyTexImage2D_DX8(GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+void gldCopyTexSubImage1D_DX8(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width );
+void gldCopyTexSubImage2D_DX8(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height );
+void gldCopyTexSubImage3D_DX8(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height );
+
+void gld_NEW_TEXTURE_DX8(GLcontext *ctx);
+void gld_DrawPixels_DX8(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels);
+void gld_ReadPixels_DX8(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, GLvoid *dest);
+void gld_CopyPixels_DX8(GLcontext *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLint dstx, GLint dsty, GLenum type);
+void gld_Bitmap_DX8(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap);
+const struct gl_texture_format* gld_ChooseTextureFormat_DX8(GLcontext *ctx, GLint internalFormat, GLenum srcFormat, GLenum srcType);
+void gld_TexImage2D_DX8(GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint height, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *tObj, struct gl_texture_image *texImage);
+void gld_TexImage1D_DX8(GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage );
+void gld_TexSubImage2D_DX8( GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage );
+void gld_TexSubImage1D_DX8(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage);
+void gld_DeleteTexture_DX8(GLcontext *ctx, struct gl_texture_object *tObj);
+void gld_ResetLineStipple_DX8(GLcontext *ctx);
+
+// 2D primitive functions
+
+void gld_Points2D_DX8(GLcontext *ctx, GLuint first, GLuint last);
+
+void gld_Line2DFlat_DX8(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Line2DSmooth_DX8(GLcontext *ctx, GLuint v0, GLuint v1);
+
+void gld_Triangle2DFlat_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DSmooth_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DFlatExtras_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DSmoothExtras_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+
+void gld_Quad2DFlat_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DSmooth_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DFlatExtras_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DSmoothExtras_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+
+// 3D primitive functions
+
+void gld_Points3D_DX8(GLcontext *ctx, GLuint first, GLuint last);
+void gld_Line3DFlat_DX8(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Triangle3DFlat_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Quad3DFlat_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Line3DSmooth_DX8(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Triangle3DSmooth_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Quad3DSmooth_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+
+// Primitive functions for Two-sided-lighting Vertex Shader
+
+void gld_Points2DTwoside_DX8(GLcontext *ctx, GLuint first, GLuint last);
+void gld_Line2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Line2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Triangle2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Quad2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+
+#endif
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_dxerr8.h b/src/mesa/drivers/windows/gldirect/dx8/gld_dxerr8.h
new file mode 100644
index 0000000000..f8e92b936e
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_dxerr8.h
@@ -0,0 +1,77 @@
+/*==========================================================================;
+ *
+ *
+ * File: dxerr8.h
+ * Content: DirectX Error Library Include File
+ *
+ ****************************************************************************/
+
+#ifndef _GLD_DXERR8_H_
+#define _GLD_DXERR8_H_
+
+
+#include <d3d8.h>
+
+//
+// DXGetErrorString8
+//
+// Desc: Converts an DirectX HRESULT to a string
+//
+// Args: HRESULT hr Can be any error code from
+// DPLAY D3D8 D3DX8 DMUSIC DSOUND
+//
+// Return: Converted string
+//
+const char* __stdcall DXGetErrorString8A(HRESULT hr);
+const WCHAR* __stdcall DXGetErrorString8W(HRESULT hr);
+
+#ifdef UNICODE
+ #define DXGetErrorString8 DXGetErrorString8W
+#else
+ #define DXGetErrorString8 DXGetErrorString8A
+#endif
+
+
+//
+// DXTrace
+//
+// Desc: Outputs a formatted error message to the debug stream
+//
+// Args: CHAR* strFile The current file, typically passed in using the
+// __FILE__ macro.
+// DWORD dwLine The current line number, typically passed in using the
+// __LINE__ macro.
+// HRESULT hr An HRESULT that will be traced to the debug stream.
+// CHAR* strMsg A string that will be traced to the debug stream (may be NULL)
+// BOOL bPopMsgBox If TRUE, then a message box will popup also containing the passed info.
+//
+// Return: The hr that was passed in.
+//
+//HRESULT __stdcall DXTraceA( char* strFile, DWORD dwLine, HRESULT hr, char* strMsg, BOOL bPopMsgBox = FALSE );
+//HRESULT __stdcall DXTraceW( char* strFile, DWORD dwLine, HRESULT hr, WCHAR* strMsg, BOOL bPopMsgBox = FALSE );
+HRESULT __stdcall DXTraceA( char* strFile, DWORD dwLine, HRESULT hr, char* strMsg, BOOL bPopMsgBox);
+HRESULT __stdcall DXTraceW( char* strFile, DWORD dwLine, HRESULT hr, WCHAR* strMsg, BOOL bPopMsgBox);
+
+#ifdef UNICODE
+ #define DXTrace DXTraceW
+#else
+ #define DXTrace DXTraceA
+#endif
+
+
+//
+// Helper macros
+//
+#if defined(DEBUG) | defined(_DEBUG)
+ #define DXTRACE_MSG(str) DXTrace( __FILE__, (DWORD)__LINE__, 0, str, FALSE )
+ #define DXTRACE_ERR(str,hr) DXTrace( __FILE__, (DWORD)__LINE__, hr, str, TRUE )
+ #define DXTRACE_ERR_NOMSGBOX(str,hr) DXTrace( __FILE__, (DWORD)__LINE__, hr, str, FALSE )
+#else
+ #define DXTRACE_MSG(str) (0L)
+ #define DXTRACE_ERR(str,hr) (hr)
+ #define DXTRACE_ERR_NOMSGBOX(str,hr) (hr)
+#endif
+
+
+#endif
+
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_ext_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_ext_dx8.c
new file mode 100644
index 0000000000..36265fc4e9
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_ext_dx8.c
@@ -0,0 +1,344 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GL extensions
+*
+****************************************************************************/
+
+//#include "../GLDirect.h"
+//#include "../gld_log.h"
+//#include "../gld_settings.h"
+
+#include <windows.h>
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glext.h>
+
+//#include "ddlog.h"
+//#include "gld_dx8.h"
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "array_cache/acache.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast_setup/ss_context.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+#include "dglcontext.h"
+#include "extensions.h"
+
+// For some reason this is not defined in an above header...
+extern void _mesa_enable_imaging_extensions(GLcontext *ctx);
+
+//---------------------------------------------------------------------------
+// Hack for the SGIS_multitexture extension that was removed from Mesa
+// NOTE: SGIS_multitexture enums also clash with GL_SGIX_async_pixel
+
+ // NOTE: Quake2 ran *slower* with this enabled, so I've
+ // disabled it for now.
+ // To enable, uncomment:
+ // _mesa_add_extension(ctx, GL_TRUE, szGL_SGIS_multitexture, 0);
+
+//---------------------------------------------------------------------------
+
+enum {
+ /* Quake2 GL_SGIS_multitexture */
+ GL_SELECTED_TEXTURE_SGIS = 0x835B,
+ GL_SELECTED_TEXTURE_COORD_SET_SGIS = 0x835C,
+ GL_MAX_TEXTURES_SGIS = 0x835D,
+ GL_TEXTURE0_SGIS = 0x835E,
+ GL_TEXTURE1_SGIS = 0x835F,
+ GL_TEXTURE2_SGIS = 0x8360,
+ GL_TEXTURE3_SGIS = 0x8361,
+ GL_TEXTURE_COORD_SET_SOURCE_SGIS = 0x8363,
+};
+
+//---------------------------------------------------------------------------
+
+void APIENTRY gldSelectTextureSGIS(
+ GLenum target)
+{
+ GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS);
+ glActiveTextureARB(ARB_target);
+}
+
+//---------------------------------------------------------------------------
+
+void APIENTRY gldMTexCoord2fSGIS(
+ GLenum target,
+ GLfloat s,
+ GLfloat t)
+{
+ GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS);
+ glMultiTexCoord2fARB(ARB_target, s, t);
+}
+
+//---------------------------------------------------------------------------
+
+void APIENTRY gldMTexCoord2fvSGIS(
+ GLenum target,
+ const GLfloat *v)
+{
+ GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS);
+ glMultiTexCoord2fvARB(ARB_target, v);
+}
+
+//---------------------------------------------------------------------------
+// Extensions
+//---------------------------------------------------------------------------
+
+typedef struct {
+ PROC proc;
+ char *name;
+} GLD_extension;
+
+GLD_extension GLD_extList[] = {
+#ifdef GL_EXT_polygon_offset
+ { (PROC)glPolygonOffsetEXT, "glPolygonOffsetEXT" },
+#endif
+ { (PROC)glBlendEquationEXT, "glBlendEquationEXT" },
+ { (PROC)glBlendColorEXT, "glBlendColorExt" },
+ { (PROC)glVertexPointerEXT, "glVertexPointerEXT" },
+ { (PROC)glNormalPointerEXT, "glNormalPointerEXT" },
+ { (PROC)glColorPointerEXT, "glColorPointerEXT" },
+ { (PROC)glIndexPointerEXT, "glIndexPointerEXT" },
+ { (PROC)glTexCoordPointerEXT, "glTexCoordPointer" },
+ { (PROC)glEdgeFlagPointerEXT, "glEdgeFlagPointerEXT" },
+ { (PROC)glGetPointervEXT, "glGetPointervEXT" },
+ { (PROC)glArrayElementEXT, "glArrayElementEXT" },
+ { (PROC)glDrawArraysEXT, "glDrawArrayEXT" },
+ { (PROC)glAreTexturesResidentEXT, "glAreTexturesResidentEXT" },
+ { (PROC)glBindTextureEXT, "glBindTextureEXT" },
+ { (PROC)glDeleteTexturesEXT, "glDeleteTexturesEXT" },
+ { (PROC)glGenTexturesEXT, "glGenTexturesEXT" },
+ { (PROC)glIsTextureEXT, "glIsTextureEXT" },
+ { (PROC)glPrioritizeTexturesEXT, "glPrioritizeTexturesEXT" },
+ { (PROC)glCopyTexSubImage3DEXT, "glCopyTexSubImage3DEXT" },
+ { (PROC)glTexImage3DEXT, "glTexImage3DEXT" },
+ { (PROC)glTexSubImage3DEXT, "glTexSubImage3DEXT" },
+ { (PROC)glPointParameterfEXT, "glPointParameterfEXT" },
+ { (PROC)glPointParameterfvEXT, "glPointParameterfvEXT" },
+
+ { (PROC)glLockArraysEXT, "glLockArraysEXT" },
+ { (PROC)glUnlockArraysEXT, "glUnlockArraysEXT" },
+ { NULL, "\0" }
+};
+
+GLD_extension GLD_multitexList[] = {
+/*
+ { (PROC)glMultiTexCoord1dSGIS, "glMTexCoord1dSGIS" },
+ { (PROC)glMultiTexCoord1dvSGIS, "glMTexCoord1dvSGIS" },
+ { (PROC)glMultiTexCoord1fSGIS, "glMTexCoord1fSGIS" },
+ { (PROC)glMultiTexCoord1fvSGIS, "glMTexCoord1fvSGIS" },
+ { (PROC)glMultiTexCoord1iSGIS, "glMTexCoord1iSGIS" },
+ { (PROC)glMultiTexCoord1ivSGIS, "glMTexCoord1ivSGIS" },
+ { (PROC)glMultiTexCoord1sSGIS, "glMTexCoord1sSGIS" },
+ { (PROC)glMultiTexCoord1svSGIS, "glMTexCoord1svSGIS" },
+ { (PROC)glMultiTexCoord2dSGIS, "glMTexCoord2dSGIS" },
+ { (PROC)glMultiTexCoord2dvSGIS, "glMTexCoord2dvSGIS" },
+ { (PROC)glMultiTexCoord2fSGIS, "glMTexCoord2fSGIS" },
+ { (PROC)glMultiTexCoord2fvSGIS, "glMTexCoord2fvSGIS" },
+ { (PROC)glMultiTexCoord2iSGIS, "glMTexCoord2iSGIS" },
+ { (PROC)glMultiTexCoord2ivSGIS, "glMTexCoord2ivSGIS" },
+ { (PROC)glMultiTexCoord2sSGIS, "glMTexCoord2sSGIS" },
+ { (PROC)glMultiTexCoord2svSGIS, "glMTexCoord2svSGIS" },
+ { (PROC)glMultiTexCoord3dSGIS, "glMTexCoord3dSGIS" },
+ { (PROC)glMultiTexCoord3dvSGIS, "glMTexCoord3dvSGIS" },
+ { (PROC)glMultiTexCoord3fSGIS, "glMTexCoord3fSGIS" },
+ { (PROC)glMultiTexCoord3fvSGIS, "glMTexCoord3fvSGIS" },
+ { (PROC)glMultiTexCoord3iSGIS, "glMTexCoord3iSGIS" },
+ { (PROC)glMultiTexCoord3ivSGIS, "glMTexCoord3ivSGIS" },
+ { (PROC)glMultiTexCoord3sSGIS, "glMTexCoord3sSGIS" },
+ { (PROC)glMultiTexCoord3svSGIS, "glMTexCoord3svSGIS" },
+ { (PROC)glMultiTexCoord4dSGIS, "glMTexCoord4dSGIS" },
+ { (PROC)glMultiTexCoord4dvSGIS, "glMTexCoord4dvSGIS" },
+ { (PROC)glMultiTexCoord4fSGIS, "glMTexCoord4fSGIS" },
+ { (PROC)glMultiTexCoord4fvSGIS, "glMTexCoord4fvSGIS" },
+ { (PROC)glMultiTexCoord4iSGIS, "glMTexCoord4iSGIS" },
+ { (PROC)glMultiTexCoord4ivSGIS, "glMTexCoord4ivSGIS" },
+ { (PROC)glMultiTexCoord4sSGIS, "glMTexCoord4sSGIS" },
+ { (PROC)glMultiTexCoord4svSGIS, "glMTexCoord4svSGIS" },
+ { (PROC)glMultiTexCoordPointerSGIS, "glMTexCoordPointerSGIS" },
+ { (PROC)glSelectTextureSGIS, "glSelectTextureSGIS" },
+ { (PROC)glSelectTextureCoordSetSGIS, "glSelectTextureCoordSetSGIS" },
+*/
+ { (PROC)glActiveTextureARB, "glActiveTextureARB" },
+ { (PROC)glClientActiveTextureARB, "glClientActiveTextureARB" },
+ { (PROC)glMultiTexCoord1dARB, "glMultiTexCoord1dARB" },
+ { (PROC)glMultiTexCoord1dvARB, "glMultiTexCoord1dvARB" },
+ { (PROC)glMultiTexCoord1fARB, "glMultiTexCoord1fARB" },
+ { (PROC)glMultiTexCoord1fvARB, "glMultiTexCoord1fvARB" },
+ { (PROC)glMultiTexCoord1iARB, "glMultiTexCoord1iARB" },
+ { (PROC)glMultiTexCoord1ivARB, "glMultiTexCoord1ivARB" },
+ { (PROC)glMultiTexCoord1sARB, "glMultiTexCoord1sARB" },
+ { (PROC)glMultiTexCoord1svARB, "glMultiTexCoord1svARB" },
+ { (PROC)glMultiTexCoord2dARB, "glMultiTexCoord2dARB" },
+ { (PROC)glMultiTexCoord2dvARB, "glMultiTexCoord2dvARB" },
+ { (PROC)glMultiTexCoord2fARB, "glMultiTexCoord2fARB" },
+ { (PROC)glMultiTexCoord2fvARB, "glMultiTexCoord2fvARB" },
+ { (PROC)glMultiTexCoord2iARB, "glMultiTexCoord2iARB" },
+ { (PROC)glMultiTexCoord2ivARB, "glMultiTexCoord2ivARB" },
+ { (PROC)glMultiTexCoord2sARB, "glMultiTexCoord2sARB" },
+ { (PROC)glMultiTexCoord2svARB, "glMultiTexCoord2svARB" },
+ { (PROC)glMultiTexCoord3dARB, "glMultiTexCoord3dARB" },
+ { (PROC)glMultiTexCoord3dvARB, "glMultiTexCoord3dvARB" },
+ { (PROC)glMultiTexCoord3fARB, "glMultiTexCoord3fARB" },
+ { (PROC)glMultiTexCoord3fvARB, "glMultiTexCoord3fvARB" },
+ { (PROC)glMultiTexCoord3iARB, "glMultiTexCoord3iARB" },
+ { (PROC)glMultiTexCoord3ivARB, "glMultiTexCoord3ivARB" },
+ { (PROC)glMultiTexCoord3sARB, "glMultiTexCoord3sARB" },
+ { (PROC)glMultiTexCoord3svARB, "glMultiTexCoord3svARB" },
+ { (PROC)glMultiTexCoord4dARB, "glMultiTexCoord4dARB" },
+ { (PROC)glMultiTexCoord4dvARB, "glMultiTexCoord4dvARB" },
+ { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4fARB" },
+ { (PROC)glMultiTexCoord4fvARB, "glMultiTexCoord4fvARB" },
+ { (PROC)glMultiTexCoord4iARB, "glMultiTexCoord4iARB" },
+ { (PROC)glMultiTexCoord4ivARB, "glMultiTexCoord4ivARB" },
+ { (PROC)glMultiTexCoord4sARB, "glMultiTexCoord4sARB" },
+ { (PROC)glMultiTexCoord4svARB, "glMultiTexCoord4svARB" },
+
+ // Descent3 doesn't use correct string, hence this hack
+ { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4f" },
+
+ // Quake2 SGIS multitexture
+ { (PROC)gldSelectTextureSGIS, "glSelectTextureSGIS" },
+ { (PROC)gldMTexCoord2fSGIS, "glMTexCoord2fSGIS" },
+ { (PROC)gldMTexCoord2fvSGIS, "glMTexCoord2fvSGIS" },
+
+ { NULL, "\0" }
+};
+
+//---------------------------------------------------------------------------
+
+PROC gldGetProcAddress_DX(
+ LPCSTR a)
+{
+ int i;
+ PROC proc = NULL;
+
+ for (i=0; GLD_extList[i].proc; i++) {
+ if (!strcmp(a, GLD_extList[i].name)) {
+ proc = GLD_extList[i].proc;
+ break;
+ }
+ }
+
+ if (glb.bMultitexture) {
+ for (i=0; GLD_multitexList[i].proc; i++) {
+ if (!strcmp(a, GLD_multitexList[i].name)) {
+ proc = GLD_multitexList[i].proc;
+ break;
+ }
+ }
+ }
+
+ gldLogPrintf(GLDLOG_INFO, "GetProcAddress: %s (%s)", a, proc ? "OK" : "Failed");
+
+ return proc;
+}
+
+//---------------------------------------------------------------------------
+
+void gldEnableExtensions_DX8(
+ GLcontext *ctx)
+{
+ GLuint i;
+
+ // Mesa enables some extensions by default.
+ // This table decides which ones we want to switch off again.
+
+ // NOTE: GL_EXT_compiled_vertex_array appears broken.
+
+ const char *gld_disable_extensions[] = {
+// "GL_ARB_transpose_matrix",
+// "GL_EXT_compiled_vertex_array",
+// "GL_EXT_polygon_offset",
+// "GL_EXT_rescale_normal",
+ "GL_EXT_texture3D",
+// "GL_NV_texgen_reflection",
+ NULL
+ };
+
+ const char *gld_multitex_extensions[] = {
+ "GL_ARB_multitexture", // Quake 3
+ NULL
+ };
+
+ // Quake 2 engines
+ const char *szGL_SGIS_multitexture = "GL_SGIS_multitexture";
+
+ const char *gld_enable_extensions[] = {
+ "GL_EXT_texture_env_add", // Quake 3
+ "GL_ARB_texture_env_add", // Quake 3
+ NULL
+ };
+
+ for (i=0; gld_disable_extensions[i]; i++) {
+ _mesa_disable_extension(ctx, gld_disable_extensions[i]);
+ }
+
+ for (i=0; gld_enable_extensions[i]; i++) {
+ _mesa_enable_extension(ctx, gld_enable_extensions[i]);
+ }
+
+ if (glb.bMultitexture) {
+ for (i=0; gld_multitex_extensions[i]; i++) {
+ _mesa_enable_extension(ctx, gld_multitex_extensions[i]);
+ }
+
+ // GL_SGIS_multitexture
+ // NOTE: Quake2 ran *slower* with this enabled, so I've
+ // disabled it for now.
+ // Fair bit slower on GeForce256,
+ // Much slower on 3dfx Voodoo5 5500.
+// _mesa_add_extension(ctx, GL_TRUE, szGL_SGIS_multitexture, 0);
+
+ }
+
+ _mesa_enable_imaging_extensions(ctx);
+ _mesa_enable_1_3_extensions(ctx);
+ _mesa_enable_1_4_extensions(ctx);
+}
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_pipeline_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_pipeline_dx8.c
new file mode 100644
index 0000000000..ed7aac1e63
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_pipeline_dx8.c
@@ -0,0 +1,77 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Mesa transformation pipeline with GLDirect fastpath
+*
+****************************************************************************/
+
+//#include "../GLDirect.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx8.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+//---------------------------------------------------------------------------
+
+extern struct gl_pipeline_stage _gld_d3d_render_stage;
+extern struct gl_pipeline_stage _gld_mesa_render_stage;
+
+static const struct gl_pipeline_stage *gld_pipeline[] = {
+ &_gld_d3d_render_stage, // Direct3D TnL
+ &_tnl_vertex_transform_stage,
+ &_tnl_normal_transform_stage,
+ &_tnl_lighting_stage,
+ &_tnl_fog_coordinate_stage, /* TODO: Omit fog stage. ??? */
+ &_tnl_texgen_stage,
+ &_tnl_texture_transform_stage,
+ &_tnl_point_attenuation_stage,
+ &_gld_mesa_render_stage, // Mesa TnL, D3D rendering
+ 0,
+};
+
+//---------------------------------------------------------------------------
+
+void gldInstallPipeline_DX8(
+ GLcontext *ctx)
+{
+ // Remove any existing pipeline stages,
+ // then install GLDirect pipeline stages.
+
+ _tnl_destroy_pipeline(ctx);
+ _tnl_install_pipeline(ctx, gld_pipeline);
+}
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c
new file mode 100644
index 0000000000..aa647a5948
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_primitive_dx8.c
@@ -0,0 +1,1446 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Primitive (points/lines/tris/quads) rendering
+*
+****************************************************************************/
+
+//#include "../GLDirect.h"
+
+//#include "gld_dx8.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx8.h"
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "array_cache/acache.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast_setup/ss_context.h"
+#include "swrast/s_context.h"
+#include "swrast/s_depth.h"
+#include "swrast/s_lines.h"
+#include "swrast/s_triangle.h"
+#include "swrast/s_trispan.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+// Disable compiler complaints about unreferenced local variables
+#pragma warning (disable:4101)
+
+//---------------------------------------------------------------------------
+// Helper defines for primitives
+//---------------------------------------------------------------------------
+
+//static const float ooZ = 1.0f / 65536.0f; // One over Z
+
+#define GLD_COLOUR (D3DCOLOR_RGBA(swv->color[0], swv->color[1], swv->color[2], swv->color[3]))
+#define GLD_SPECULAR (D3DCOLOR_RGBA(swv->specular[0], swv->specular[1], swv->specular[2], swv->specular[3]))
+#define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y))
+
+//---------------------------------------------------------------------------
+// 2D vertex setup
+//---------------------------------------------------------------------------
+
+#define GLD_SETUP_2D_VARS_POINTS \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); \
+ GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pPoints; \
+ SScontext *ss = SWSETUP_CONTEXT(ctx); \
+ SWvertex *swv; \
+ DWORD dwSpecularColour; \
+ DWORD dwFlatColour
+
+#define GLD_SETUP_2D_VARS_LINES \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); \
+ GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pLines; \
+ SScontext *ss = SWSETUP_CONTEXT(ctx); \
+ SWvertex *swv; \
+ DWORD dwSpecularColour; \
+ DWORD dwFlatColour
+
+#define GLD_SETUP_2D_VARS_TRIANGLES \
+ BOOL bFog = ctx->Fog.Enabled; \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); \
+ GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pTriangles; \
+ SScontext *ss = SWSETUP_CONTEXT(ctx); \
+ SWvertex *swv; \
+ DWORD dwSpecularColour; \
+ DWORD dwFlatColour; \
+ GLuint facing = 0; \
+ struct vertex_buffer *VB; \
+ GLchan (*vbcolor)[4]; \
+ GLchan (*vbspec)[4]
+
+#define GLD_SETUP_GET_SWVERT(s) \
+ swv = &ss->verts[##s]
+
+#define GLD_SETUP_2D_VERTEX \
+ pV->x = swv->win[0]; \
+ pV->y = GLD_FLIP_Y(swv->win[1]); \
+ pV->rhw = swv->win[3]
+
+#define GLD_SETUP_SMOOTH_COLOUR \
+ pV->diffuse = GLD_COLOUR
+
+#define GLD_SETUP_GET_FLAT_COLOUR \
+ dwFlatColour = GLD_COLOUR
+#define GLD_SETUP_GET_FLAT_FOG_COLOUR \
+ dwFlatColour = _gldComputeFog(ctx, swv)
+
+#define GLD_SETUP_USE_FLAT_COLOUR \
+ pV->diffuse = dwFlatColour
+
+#define GLD_SETUP_GET_FLAT_SPECULAR \
+ dwSpecularColour= GLD_SPECULAR
+
+#define GLD_SETUP_USE_FLAT_SPECULAR \
+ pV->specular = dwSpecularColour
+
+#define GLD_SETUP_DEPTH \
+ pV->sz = swv->win[2] / ctx->DepthMaxF
+// pV->z = swv->win[2] * ooZ;
+
+#define GLD_SETUP_SPECULAR \
+ pV->specular = GLD_SPECULAR
+
+#define GLD_SETUP_FOG \
+ pV->diffuse = _gldComputeFog(ctx, swv)
+
+#define GLD_SETUP_TEX0 \
+ pV->t0_u = swv->texcoord[0][0]; \
+ pV->t0_v = swv->texcoord[0][1]
+
+#define GLD_SETUP_TEX1 \
+ pV->t1_u = swv->texcoord[1][0]; \
+ pV->t1_v = swv->texcoord[1][1]
+
+#define GLD_SETUP_LIGHTING(v) \
+ if (facing == 1) { \
+ pV->diffuse = D3DCOLOR_RGBA(vbcolor[##v][0], vbcolor[##v][1], vbcolor[##v][2], vbcolor[##v][3]); \
+ if (vbspec) { \
+ pV->specular = D3DCOLOR_RGBA(vbspec[##v][0], vbspec[##v][1], vbspec[##v][2], vbspec[##v][3]); \
+ } \
+ } else { \
+ if (bFog) \
+ GLD_SETUP_FOG; \
+ else \
+ GLD_SETUP_SMOOTH_COLOUR; \
+ GLD_SETUP_SPECULAR; \
+ }
+
+#define GLD_SETUP_GET_FLAT_LIGHTING(v) \
+ if (facing == 1) { \
+ dwFlatColour = D3DCOLOR_RGBA(vbcolor[##v][0], vbcolor[##v][1], vbcolor[##v][2], vbcolor[##v][3]); \
+ if (vbspec) { \
+ dwSpecularColour = D3DCOLOR_RGBA(vbspec[##v][0], vbspec[##v][1], vbspec[##v][2], vbspec[##v][3]); \
+ } \
+ }
+
+#define GLD_SETUP_TWOSIDED_LIGHTING \
+ /* Two-sided lighting */ \
+ if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) { \
+ SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts; \
+ SWvertex *v[3]; \
+ GLfloat ex,ey,fx,fy,cc; \
+ /* Get vars for later */ \
+ VB = &TNL_CONTEXT(ctx)->vb; \
+ vbcolor = (GLchan (*)[4])VB->ColorPtr[1]->Ptr; \
+ if (VB->SecondaryColorPtr[1]) { \
+ vbspec = (GLchan (*)[4])VB->SecondaryColorPtr[1]->Ptr; \
+ } else { \
+ vbspec = NULL; \
+ } \
+ v[0] = &verts[v0]; \
+ v[1] = &verts[v1]; \
+ v[2] = &verts[v2]; \
+ ex = v[0]->win[0] - v[2]->win[0]; \
+ ey = v[0]->win[1] - v[2]->win[1]; \
+ fx = v[1]->win[0] - v[2]->win[0]; \
+ fy = v[1]->win[1] - v[2]->win[1]; \
+ cc = ex*fy - ey*fx; \
+ facing = (cc < 0.0) ^ ctx->Polygon._FrontBit; \
+ }
+
+//---------------------------------------------------------------------------
+// 3D vertex setup
+//---------------------------------------------------------------------------
+
+#define GLD_SETUP_3D_VARS_POINTS \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); \
+ GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pPoints; \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ GLfloat (*p4f)[4]; \
+ GLfloat (*tc)[4]; \
+ DWORD dwColor;
+
+#define GLD_SETUP_3D_VARS_LINES \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); \
+ GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pLines; \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ GLfloat (*p4f)[4]; \
+ GLfloat (*tc)[4]; \
+ DWORD dwColor;
+
+#define GLD_SETUP_3D_VARS_TRIANGLES \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx); \
+ GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pTriangles; \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ GLfloat (*p4f)[4]; \
+ GLfloat (*tc)[4]; \
+ DWORD dwColor;
+
+#define GLD_SETUP_3D_VERTEX(v) \
+ p4f = VB->ObjPtr->data; \
+ pV->Position.x = p4f[##v][0]; \
+ pV->Position.y = p4f[##v][1]; \
+ pV->Position.z = p4f[##v][2];
+
+#define GLD_SETUP_SMOOTH_COLOUR_3D(v) \
+ p4f = (GLfloat (*)[4])VB->ColorPtr[0]->Ptr; \
+ pV->Diffuse = D3DCOLOR_COLORVALUE(p4f[##v][0], p4f[##v][1], p4f[##v][2], p4f[##v][3]);
+
+
+#define GLD_SETUP_GET_FLAT_COLOUR_3D(v) \
+ p4f = (GLfloat (*)[4])VB->ColorPtr[0]->Ptr; \
+ dwColor = D3DCOLOR_COLORVALUE(p4f[##v][0], p4f[##v][1], p4f[##v][2], p4f[##v][3]);
+
+#define GLD_SETUP_USE_FLAT_COLOUR_3D \
+ pV->Diffuse = dwColor;
+
+#define GLD_SETUP_TEX0_3D(v) \
+ if (VB->TexCoordPtr[0]) { \
+ tc = VB->TexCoordPtr[0]->data; \
+ pV->TexUnit0.x = tc[##v][0]; \
+ pV->TexUnit0.y = tc[##v][1]; \
+ }
+
+#define GLD_SETUP_TEX1_3D(v) \
+ if (VB->TexCoordPtr[1]) { \
+ tc = VB->TexCoordPtr[1]->data; \
+ pV->TexUnit1.x = tc[##v][0]; \
+ pV->TexUnit1.y = tc[##v][1]; \
+ }
+
+//---------------------------------------------------------------------------
+// Helper functions
+//---------------------------------------------------------------------------
+
+__inline DWORD _gldComputeFog(
+ GLcontext *ctx,
+ SWvertex *swv)
+{
+ // Full fog calculation.
+ // Based on Mesa code.
+
+ GLchan rFog, gFog, bFog;
+ GLchan fR, fG, fB;
+ const GLfloat f = swv->fog;
+ const GLfloat g = 1.0 - f;
+
+ UNCLAMPED_FLOAT_TO_CHAN(rFog, ctx->Fog.Color[RCOMP]);
+ UNCLAMPED_FLOAT_TO_CHAN(gFog, ctx->Fog.Color[GCOMP]);
+ UNCLAMPED_FLOAT_TO_CHAN(bFog, ctx->Fog.Color[BCOMP]);
+ fR = f * swv->color[0] + g * rFog;
+ fG = f * swv->color[1] + g * gFog;
+ fB = f * swv->color[2] + g * bFog;
+ return D3DCOLOR_RGBA(fR, fG, fB, swv->color[3]);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_ResetLineStipple_DX8(
+ GLcontext *ctx)
+{
+ // TODO: Fake stipple with a 32x32 texture.
+}
+
+//---------------------------------------------------------------------------
+// 2D (post-transformed) primitives
+//---------------------------------------------------------------------------
+
+void gld_Points2D_DX8(
+ GLcontext *ctx,
+ GLuint first,
+ GLuint last)
+{
+ GLD_SETUP_2D_VARS_POINTS;
+
+ unsigned i;
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ // _Size is already clamped to MaxPointSize and MinPointSize
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_POINTSIZE, *((DWORD*)&ctx->Point._Size));
+
+ if (VB->Elts) {
+ for (i=first; i<last; i++, pV++) {
+ if (VB->ClipMask[VB->Elts[i]] == 0) {
+// _swrast_Point( ctx, &verts[VB->Elts[i]] );
+ GLD_SETUP_GET_SWVERT(VB->Elts[i]);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ }
+ }
+ } else {
+ GLD_SETUP_GET_SWVERT(first);
+ for (i=first; i<last; i++, swv++, pV++) {
+ if (VB->ClipMask[i] == 0) {
+// _swrast_Point( ctx, &verts[i] );
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ }
+ }
+ }
+
+ gld->PB2d.pPoints = (BYTE*)pV;
+ gld->PB2d.nPoints += (last-first);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DFlat_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_2D_VARS_LINES;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_GET_FLAT_SPECULAR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ gld->PB2d.pLines = (BYTE*)pV;
+ gld->PB2d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DSmooth_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_2D_VARS_LINES;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ gld->PB2d.pLines = (BYTE*)pV;
+ gld->PB2d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DFlat_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DSmooth_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DFlatExtras_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v2);
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ if (bFog)
+ GLD_SETUP_GET_FLAT_FOG_COLOUR;
+ else
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_GET_FLAT_SPECULAR;
+ GLD_SETUP_GET_FLAT_LIGHTING(v2);
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DSmoothExtras_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v0);
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v0);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v1);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v2);
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DFlat_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DSmooth_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DFlatExtras_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v3);
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ if (bFog)
+ GLD_SETUP_GET_FLAT_FOG_COLOUR;
+ else
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_GET_FLAT_SPECULAR;
+ GLD_SETUP_GET_FLAT_LIGHTING(v3);
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DSmoothExtras_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v0);
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v0);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v1);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v2);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v2);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v3);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v0);
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+// 3D (pre-transformed) primitives
+//---------------------------------------------------------------------------
+
+void gld_Points3D_DX8(
+ GLcontext *ctx,
+ GLuint first,
+ GLuint last)
+{
+ GLD_SETUP_3D_VARS_POINTS
+
+ unsigned i;
+// struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ // _Size is already clamped to MaxPointSize and MinPointSize
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_POINTSIZE, *((DWORD*)&ctx->Point._Size));
+
+ if (VB->Elts) {
+ for (i=first; i<last; i++, pV++) {
+ if (VB->ClipMask[VB->Elts[i]] == 0) {
+// _swrast_Point( ctx, &verts[VB->Elts[i]] );
+// GLD_SETUP_GET_SWVERT(VB->Elts[i]);
+ GLD_SETUP_3D_VERTEX(VB->Elts[i])
+ GLD_SETUP_SMOOTH_COLOUR_3D(i)
+ GLD_SETUP_TEX0_3D(i)
+ GLD_SETUP_TEX1_3D(i)
+ }
+ }
+ } else {
+// GLD_SETUP_GET_SWVERT(first);
+ for (i=first; i<last; i++, pV++) {
+ if (VB->ClipMask[i] == 0) {
+// _swrast_Point( ctx, &verts[i] );
+ GLD_SETUP_3D_VERTEX(i)
+ GLD_SETUP_SMOOTH_COLOUR_3D(i)
+ GLD_SETUP_TEX0_3D(i)
+ GLD_SETUP_TEX1_3D(i)
+ }
+ }
+ }
+/*
+ for (i=first; i<last; i++, pV++) {
+ GLD_SETUP_3D_VERTEX(i)
+ GLD_SETUP_SMOOTH_COLOUR_3D(i)
+ GLD_SETUP_TEX0_3D(i)
+ GLD_SETUP_TEX1_3D(i)
+ }
+*/
+ gld->PB3d.pPoints = (BYTE*)pV;
+ gld->PB3d.nPoints += (last-first);
+}
+
+//---------------------------------------------------------------------------
+// Line functions
+//---------------------------------------------------------------------------
+
+void gld_Line3DFlat_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_3D_VARS_LINES
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_GET_FLAT_COLOUR_3D(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ gld->PB3d.pLines = (BYTE*)pV;
+ gld->PB3d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line3DSmooth_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_3D_VARS_LINES
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ gld->PB3d.pLines = (BYTE*)pV;
+ gld->PB3d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+// Triangle functions
+//---------------------------------------------------------------------------
+
+void gld_Triangle3DFlat_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ GLD_SETUP_GET_FLAT_COLOUR_3D(v2)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle3DSmooth_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+// Quad functions
+//---------------------------------------------------------------------------
+
+void gld_Quad3DFlat_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v3)
+ GLD_SETUP_GET_FLAT_COLOUR_3D(v3)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v3)
+ GLD_SETUP_TEX1_3D(v3)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v3)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v3)
+ GLD_SETUP_TEX1_3D(v3)
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad3DSmooth_DX8(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v3)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v3)
+ GLD_SETUP_TEX0_3D(v3)
+ GLD_SETUP_TEX1_3D(v3)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+// Vertex setup for two-sided-lighting vertex shader
+//---------------------------------------------------------------------------
+
+/*
+
+void gld_Points2DTwoside_DX8(GLcontext *ctx, GLuint first, GLuint last)
+{
+ // NOTE: Two-sided lighting does not apply to Points
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1)
+{
+ // NOTE: Two-sided lighting does not apply to Lines
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1)
+{
+ // NOTE: Two-sided lighting does not apply to Lines
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2)
+{
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+ GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles;
+ SScontext *ss = SWSETUP_CONTEXT(ctx);
+ SWvertex *swv;
+ DWORD dwSpecularColour;
+ DWORD dwFlatColour;
+ GLuint facing = 0;
+ struct vertex_buffer *VB;
+ GLchan (*vbcolor)[4];
+ GLchan (*vbspec)[4];
+
+ // Reciprocal of DepthMax
+ const float ooDepthMax = 1.0f / ctx->DepthMaxF;
+
+ // 1st vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 2nd vert
+ swv = &ss->verts[v1];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 3rd vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ gld->PBtwosidelight.pTriangles = (BYTE*)pV;
+ gld->PBtwosidelight.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DFlatTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+ GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles;
+ SScontext *ss = SWSETUP_CONTEXT(ctx);
+ SWvertex *swv;
+ DWORD dwSpecularColour;
+ DWORD dwFlatColour;
+ GLuint facing = 0;
+ struct vertex_buffer *VB;
+ GLchan (*vbcolor)[4];
+ GLchan (*vbspec)[4];
+
+ // Reciprocal of DepthMax
+ const float ooDepthMax = 1.0f / ctx->DepthMaxF;
+
+ // 1st vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 2nd vert
+ swv = &ss->verts[v1];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 3rd vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 4th vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 5th vert
+ swv = &ss->verts[v3];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 6th vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ gld->PBtwosidelight.pTriangles = (BYTE*)pV;
+ gld->PBtwosidelight.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DSmoothTwoside_DX8(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+ GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles;
+ SScontext *ss = SWSETUP_CONTEXT(ctx);
+ SWvertex *swv;
+ DWORD dwSpecularColour;
+ DWORD dwFlatColour;
+ GLuint facing = 0;
+ struct vertex_buffer *VB;
+ GLchan (*vbcolor)[4];
+ GLchan (*vbspec)[4];
+
+ // Reciprocal of DepthMax
+ const float ooDepthMax = 1.0f / ctx->DepthMaxF;
+
+ // 1st vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 2nd vert
+ swv = &ss->verts[v1];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 3rd vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 4th vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 5th vert
+ swv = &ss->verts[v3];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 6th vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ gld->PBtwosidelight.pTriangles = (BYTE*)pV;
+ gld->PBtwosidelight.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+*/
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_texture_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_texture_dx8.c
new file mode 100644
index 0000000000..282d6a130e
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_texture_dx8.c
@@ -0,0 +1,1907 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Texture / Bitmap functions
+*
+****************************************************************************/
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx8.h"
+
+#include <d3dx8tex.h>
+
+#include "texformat.h"
+#include "colormac.h"
+#include "texstore.h"
+#include "image.h"
+// #include "mem.h"
+
+//---------------------------------------------------------------------------
+
+#define GLD_FLIP_HEIGHT(y,h) (gldCtx->dwHeight - (y) - (h))
+
+//---------------------------------------------------------------------------
+// 1D texture fetch
+//---------------------------------------------------------------------------
+
+#define CHAN_SRC( t, i, j, k, sz ) \
+ ((GLchan *)(t)->Data + (i) * (sz))
+#define UBYTE_SRC( t, i, j, k, sz ) \
+ ((GLubyte *)(t)->Data + (i) * (sz))
+#define USHORT_SRC( t, i, j, k ) \
+ ((GLushort *)(t)->Data + (i))
+#define FLOAT_SRC( t, i, j, k ) \
+ ((GLfloat *)(t)->Data + (i))
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ GLchan *rgba = (GLchan *) texel;
+ rgba[RCOMP] = src[2];
+ rgba[GCOMP] = src[1];
+ rgba[BCOMP] = src[0];
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+#undef CHAN_SRC
+#undef UBYTE_SRC
+#undef USHORT_SRC
+#undef FLOAT_SRC
+
+//---------------------------------------------------------------------------
+// 2D texture fetch
+//---------------------------------------------------------------------------
+
+#define CHAN_SRC( t, i, j, k, sz ) \
+ ((GLchan *)(t)->Data + ((t)->Width * (j) + (i)) * (sz))
+#define UBYTE_SRC( t, i, j, k, sz ) \
+ ((GLubyte *)(t)->Data + ((t)->Width * (j) + (i)) * (sz))
+#define USHORT_SRC( t, i, j, k ) \
+ ((GLushort *)(t)->Data + ((t)->Width * (j) + (i)))
+#define FLOAT_SRC( t, i, j, k ) \
+ ((GLfloat *)(t)->Data + ((t)->Width * (j) + (i)))
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ GLchan *rgba = (GLchan *) texel;
+ rgba[RCOMP] = src[2];
+ rgba[GCOMP] = src[1];
+ rgba[BCOMP] = src[0];
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+#undef CHAN_SRC
+#undef UBYTE_SRC
+#undef USHORT_SRC
+#undef FLOAT_SRC
+
+//---------------------------------------------------------------------------
+// 3D texture fetch
+//---------------------------------------------------------------------------
+
+#define CHAN_SRC( t, i, j, k, sz ) \
+ (GLchan *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)) * (sz)
+#define UBYTE_SRC( t, i, j, k, sz ) \
+ ((GLubyte *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)) * (sz))
+#define USHORT_SRC( t, i, j, k ) \
+ ((GLushort *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)))
+#define FLOAT_SRC( t, i, j, k ) \
+ ((GLfloat *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)))
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ GLchan *rgba = (GLchan *) texel;
+ rgba[RCOMP] = src[2];
+ rgba[GCOMP] = src[1];
+ rgba[BCOMP] = src[0];
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+#undef CHAN_SRC
+#undef UBYTE_SRC
+#undef USHORT_SRC
+#undef FLOAT_SRC
+
+//---------------------------------------------------------------------------
+// Direct3D texture formats that have no Mesa equivalent
+//---------------------------------------------------------------------------
+
+const struct gl_texture_format _gld_texformat_X8R8G8B8 = {
+ MESA_FORMAT_ARGB8888, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+// GL_UNSIGNED_BYTE, /* Type */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 4, /* TexelBytes */
+ gld_fetch_1d_texel_X8R8G8B8, /* FetchTexel1D */
+ gld_fetch_2d_texel_X8R8G8B8, /* FetchTexel2D */
+ gld_fetch_3d_texel_X8R8G8B8, /* FetchTexel3D */
+};
+
+const struct gl_texture_format _gld_texformat_X1R5G5B5 = {
+ MESA_FORMAT_ARGB1555, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+// GL_UNSIGNED_SHORT_1_5_5_5_REV, /* Type */
+ 5, /* RedBits */
+ 5, /* GreenBits */
+ 5, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 2, /* TexelBytes */
+ gld_fetch_1d_texel_X1R5G5B5, /* FetchTexel1D */
+ gld_fetch_2d_texel_X1R5G5B5, /* FetchTexel2D */
+ gld_fetch_3d_texel_X1R5G5B5, /* FetchTexel3D */
+};
+
+const struct gl_texture_format _gld_texformat_X4R4G4B4 = {
+ MESA_FORMAT_ARGB4444, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+// GL_UNSIGNED_SHORT_4_4_4_4_REV, /* Type */
+ 4, /* RedBits */
+ 4, /* GreenBits */
+ 4, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 2, /* TexelBytes */
+ gld_fetch_1d_texel_X4R4G4B4, /* FetchTexel1D */
+ gld_fetch_2d_texel_X4R4G4B4, /* FetchTexel2D */
+ gld_fetch_3d_texel_X4R4G4B4, /* FetchTexel3D */
+};
+
+//---------------------------------------------------------------------------
+// Texture unit constants
+//---------------------------------------------------------------------------
+
+// List of possible combinations of texture environments.
+// Example: GLD_TEXENV_MODULATE_RGBA means
+// GL_MODULATE, GL_RGBA base internal format.
+#define GLD_TEXENV_DECAL_RGB 0
+#define GLD_TEXENV_DECAL_RGBA 1
+#define GLD_TEXENV_DECAL_ALPHA 2
+#define GLD_TEXENV_REPLACE_RGB 3
+#define GLD_TEXENV_REPLACE_RGBA 4
+#define GLD_TEXENV_REPLACE_ALPHA 5
+#define GLD_TEXENV_MODULATE_RGB 6
+#define GLD_TEXENV_MODULATE_RGBA 7
+#define GLD_TEXENV_MODULATE_ALPHA 8
+#define GLD_TEXENV_BLEND_RGB 9
+#define GLD_TEXENV_BLEND_RGBA 10
+#define GLD_TEXENV_BLEND_ALPHA 11
+#define GLD_TEXENV_ADD_RGB 12
+#define GLD_TEXENV_ADD_RGBA 13
+#define GLD_TEXENV_ADD_ALPHA 14
+
+// Per-stage (i.e. per-unit) texture environment
+typedef struct {
+ DWORD ColorArg1; // Colour argument 1
+ D3DTEXTUREOP ColorOp; // Colour operation
+ DWORD ColorArg2; // Colour argument 2
+ DWORD AlphaArg1; // Alpha argument 1
+ D3DTEXTUREOP AlphaOp; // Alpha operation
+ DWORD AlphaArg2; // Alpha argument 2
+} GLD_texenv;
+
+// TODO: Do we really need to set ARG1 and ARG2 every time?
+// They seem to always be TEXTURE and CURRENT respectively.
+
+// C = Colour out
+// A = Alpha out
+// Ct = Colour from Texture
+// Cf = Colour from fragment (diffuse)
+// At = Alpha from Texture
+// Af = Alpha from fragment (diffuse)
+// Cc = GL_TEXTURE_ENV_COLOUR (GL_BLEND)
+const GLD_texenv gldTexEnv[] = {
+ // DECAL_RGB: C=Ct, A=Af
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // DECAL_RGBA: C=Cf(1-At)+CtAt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_BLENDTEXTUREALPHA, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // DECAL_ALPHA: <undefined> use DECAL_RGB
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+
+ // REPLACE_RGB: C=Ct, A=Af
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // REPLACE_RGBA: C=Ct, A=At
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT},
+ // REPLACE_ALPHA: C=Cf, A=At
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT},
+
+ // MODULATE_RGB: C=CfCt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // MODULATE_RGBA: C=CfCt, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+ // MODULATE_ALPHA: C=Cf, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+
+ // BLEND_RGB: C=Cf(1-Ct)+CcCt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // BLEND_RGBA: C=Cf(1-Ct)+CcCt, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+ // BLEND_ALPHA: C=Cf, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+
+ // ADD_RGB: C=Cf+Ct, A=Af
+ {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // ADD_RGBA: C=Cf+Ct, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+ // ADD_ALPHA: C=Cf, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+};
+
+//---------------------------------------------------------------------------
+
+D3DTEXTUREADDRESS _gldConvertWrap(
+ GLenum wrap)
+{
+ return (wrap == GL_CLAMP) ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP;
+}
+
+//---------------------------------------------------------------------------
+
+D3DTEXTUREFILTERTYPE _gldConvertMagFilter(
+ GLenum magfilter)
+{
+ return (magfilter == GL_LINEAR) ? D3DTEXF_LINEAR : D3DTEXF_POINT;
+}
+
+//---------------------------------------------------------------------------
+
+void _gldConvertMinFilter(
+ GLenum minfilter,
+ D3DTEXTUREFILTERTYPE *min_filter,
+ D3DTEXTUREFILTERTYPE *mip_filter)
+{
+ switch (minfilter) {
+ case GL_NEAREST:
+ *min_filter = D3DTEXF_POINT;
+ *mip_filter = D3DTEXF_NONE;
+ break;
+ case GL_LINEAR:
+ *min_filter = D3DTEXF_LINEAR;
+ *mip_filter = D3DTEXF_NONE;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ *min_filter = D3DTEXF_POINT;
+ *mip_filter = D3DTEXF_POINT;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ *min_filter = D3DTEXF_LINEAR;
+ *mip_filter = D3DTEXF_POINT;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ *min_filter = D3DTEXF_POINT;
+ *mip_filter = D3DTEXF_LINEAR;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ *min_filter = D3DTEXF_LINEAR;
+ *mip_filter = D3DTEXF_LINEAR;
+ break;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+D3DFORMAT _gldGLFormatToD3DFormat(
+ GLenum internalFormat)
+{
+ switch (internalFormat) {
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ // LUNIMANCE != INTENSITY, but D3D doesn't have I8 textures
+ return D3DFMT_L8;
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return D3DFMT_L8;
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return D3DFMT_A8;
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ return D3DFMT_X8R8G8B8;
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ return D3DFMT_A8L8;
+ case GL_R3_G3_B2:
+ // TODO: Mesa does not support RGB332 internally
+ return D3DFMT_X4R4G4B4; //D3DFMT_R3G3B2;
+ case GL_RGB4:
+ return D3DFMT_X4R4G4B4;
+ case GL_RGB5:
+ return D3DFMT_X1R5G5B5;
+ case 3:
+ case GL_RGB:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return D3DFMT_R8G8B8;
+ case GL_RGBA4:
+ return D3DFMT_A4R4G4B4;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA2:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return D3DFMT_A8R8G8B8;
+ case GL_RGB5_A1:
+ return D3DFMT_A1R5G5B5;
+ }
+
+ // Return an acceptable default
+ return D3DFMT_A8R8G8B8;
+}
+
+//---------------------------------------------------------------------------
+
+GLenum _gldDecodeBaseFormat(
+ IDirect3DTexture8 *pTex)
+{
+ // Examine Direct3D texture and return base OpenGL internal texture format
+ // NOTE: We can't use any base format info from Mesa because D3D might have
+ // used a different texture format when we used D3DXCreateTexture().
+
+ // Base internal format is one of (Red Book p355):
+ // GL_ALPHA,
+ // GL_LUMINANCE,
+ // GL_LUMINANCE_ALPHA,
+ // GL_INTENSITY,
+ // GL_RGB,
+ // GL_RGBA
+
+ // NOTE: INTENSITY not used (not supported by Direct3D)
+ // LUMINANCE has same texture functions as RGB
+ // LUMINANCE_ALPHA has same texture functions as RGBA
+
+ // TODO: cache format instead of using GetLevelDesc()
+ D3DSURFACE_DESC desc;
+ _GLD_DX8_TEX(GetLevelDesc(pTex, 0, &desc));
+
+ switch (desc.Format) {
+ case D3DFMT_R8G8B8:
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_R5G6B5:
+ case D3DFMT_X1R5G5B5:
+ case D3DFMT_R3G3B2:
+ case D3DFMT_X4R4G4B4:
+ case D3DFMT_P8:
+ case D3DFMT_L8:
+ return GL_RGB;
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_A1R5G5B5:
+ case D3DFMT_A4R4G4B4:
+ case D3DFMT_A8R3G3B2:
+ case D3DFMT_A8P8:
+ case D3DFMT_A8L8:
+ case D3DFMT_A4L4:
+ return GL_RGBA;
+ case D3DFMT_A8:
+ return GL_ALPHA;
+ // Compressed texture formats. Need to check these...
+ case D3DFMT_DXT1:
+ return GL_RGBA;
+ case D3DFMT_DXT2:
+ return GL_RGB;
+ case D3DFMT_DXT3:
+ return GL_RGBA;
+ case D3DFMT_DXT4:
+ return GL_RGB;
+ case D3DFMT_DXT5:
+ return GL_RGBA;
+ }
+
+ // Fell through. Return arbitary default.
+ return GL_RGBA;
+}
+
+//---------------------------------------------------------------------------
+
+const struct gl_texture_format* _gldMesaFormatForD3DFormat(
+ D3DFORMAT d3dfmt)
+{
+ switch (d3dfmt) {
+ case D3DFMT_A8R8G8B8:
+ return &_mesa_texformat_argb8888;
+ case D3DFMT_R8G8B8:
+ return &_mesa_texformat_rgb888;
+ case D3DFMT_R5G6B5:
+ return &_mesa_texformat_rgb565;
+ case D3DFMT_A4R4G4B4:
+ return &_mesa_texformat_argb4444;
+ case D3DFMT_A1R5G5B5:
+ return &_mesa_texformat_argb1555;
+ case D3DFMT_A8L8:
+ return &_mesa_texformat_al88;
+ case D3DFMT_R3G3B2:
+ return &_mesa_texformat_rgb332;
+ case D3DFMT_A8:
+ return &_mesa_texformat_a8;
+ case D3DFMT_L8:
+ return &_mesa_texformat_l8;
+ case D3DFMT_X8R8G8B8:
+ return &_gld_texformat_X8R8G8B8;
+ case D3DFMT_X1R5G5B5:
+ return &_gld_texformat_X1R5G5B5;
+ case D3DFMT_X4R4G4B4:
+ return &_gld_texformat_X4R4G4B4;
+ }
+
+ // If we reach here then we've made an error somewhere else
+ // by allowing a format that is not supported.
+ assert(0);
+
+ return NULL; // Shut up compiler warning
+}
+
+//---------------------------------------------------------------------------
+// Copy* functions
+//---------------------------------------------------------------------------
+
+void gldCopyTexImage1D_DX8(
+ GLcontext *ctx,
+ GLenum target, GLint level,
+ GLenum internalFormat,
+ GLint x, GLint y,
+ GLsizei width, GLint border )
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexImage2D_DX8(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLenum internalFormat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border)
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexSubImage1D_DX8(
+ GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint x, GLint y, GLsizei width )
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexSubImage2D_DX8(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexSubImage3D_DX8(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height )
+{
+ // TODO ?
+}
+
+//---------------------------------------------------------------------------
+// Bitmap/Pixel functions
+//---------------------------------------------------------------------------
+
+#define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y))
+
+#define _GLD_FVF_IMAGE (D3DFVF_XYZRHW | D3DFVF_TEX1)
+
+typedef struct {
+ FLOAT x, y; // 2D raster coords
+ FLOAT z; // depth value
+ FLOAT rhw; // reciprocal homogenous W (always 1.0f)
+ FLOAT tu, tv; // texture coords
+} _GLD_IMAGE_VERTEX;
+
+//---------------------------------------------------------------------------
+
+HRESULT _gldDrawPixels(
+ GLcontext *ctx,
+ BOOL bChromakey, // Alpha test for glBitmap() images
+ GLint x, // GL x position
+ GLint y, // GL y position (needs flipping)
+ GLsizei width, // Width of input image
+ GLsizei height, // Height of input image
+ IDirect3DSurface8 *pImage)
+{
+ //
+ // Draw input image as texture implementing PixelZoom and clipping.
+ // Any fragment operations currently enabled will be used.
+ //
+
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ IDirect3DTexture8 *pTexture;
+ D3DSURFACE_DESC d3dsd;
+ IDirect3DSurface8 *pSurface;
+ _GLD_IMAGE_VERTEX v[4];
+ HRESULT hr;
+
+ float ZoomWidth, ZoomHeight;
+ float ScaleWidth, ScaleHeight;
+
+ // Create a texture to hold image
+ hr = D3DXCreateTexture(
+ gld->pDev,
+ width, height,
+ 1, // miplevels
+ 0, // usage
+ D3DFMT_A8R8G8B8, // format
+ D3DPOOL_MANAGED, // pool
+ &pTexture);
+ if (FAILED(hr))
+ return hr;
+
+ hr = IDirect3DTexture8_GetSurfaceLevel(pTexture, 0, &pSurface);
+ if (FAILED(hr)) {
+ IDirect3DTexture8_Release(pTexture);
+ return hr;
+ }
+
+ // Copy image into texture
+ hr = D3DXLoadSurfaceFromSurface(
+ pSurface, NULL, NULL, // Dest surface
+ pImage, NULL, NULL, // Src surface
+ D3DX_FILTER_NONE,
+ 0);
+ IDirect3DSurface8_Release(pSurface);
+ if (FAILED(hr)) {
+ IDirect3DTexture8_Release(pTexture);
+ return hr;
+ }
+
+ //
+ // Set up the quad like this (ascii-art ahead!)
+ //
+ // 3--2
+ // | |
+ // 0--1
+ //
+ //
+
+ // Set depth
+ v[0].z = v[1].z = v[2].z = v[3].z = ctx->Current.RasterPos[2];
+ // Set Reciprocal Homogenous W
+ v[0].rhw = v[1].rhw = v[2].rhw = v[3].rhw = 1.0f;
+
+ // Set texcoords
+ // Examine texture size - if different to input width and height
+ // then we'll need to munge the texcoords to fit.
+ IDirect3DTexture8_GetLevelDesc(pTexture, 0, &d3dsd);
+ ScaleWidth = (float)width / (float)d3dsd.Width;
+ ScaleHeight = (float)height / (float)d3dsd.Height;
+ v[0].tu = 0.0f; v[0].tv = 0.0f;
+ v[1].tu = ScaleWidth; v[1].tv = 0.0f;
+ v[2].tu = ScaleWidth; v[2].tv = ScaleHeight;
+ v[3].tu = 0.0f; v[3].tv = ScaleHeight;
+
+ // Set raster positions
+ ZoomWidth = (float)width * ctx->Pixel.ZoomX;
+ ZoomHeight = (float)height * ctx->Pixel.ZoomY;
+
+ v[0].x = x; v[0].y = GLD_FLIP_Y(y);
+ v[1].x = x+ZoomWidth; v[1].y = GLD_FLIP_Y(y);
+ v[2].x = x+ZoomWidth; v[2].y = GLD_FLIP_Y(y+ZoomHeight);
+ v[3].x = x; v[3].y = GLD_FLIP_Y(y+ZoomHeight);
+
+ // Draw image with full HW acceleration
+ // NOTE: Be nice to use a State Block for all this state...
+ IDirect3DDevice8_SetTexture(gld->pDev, 0, pTexture);
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_CULLMODE, D3DCULL_NONE);
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_CLIPPING, TRUE);
+ IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_MINFILTER, D3DTEXF_POINT);
+ IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
+ IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_MAGFILTER, D3DTEXF_POINT);
+ IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
+ IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
+ IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+ IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ IDirect3DDevice8_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
+ IDirect3DDevice8_SetTextureStageState(gld->pDev, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ IDirect3DDevice8_SetTextureStageState(gld->pDev, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ IDirect3DDevice8_SetVertexShader(gld->pDev, _GLD_FVF_IMAGE);
+
+ //
+ // Emulate Chromakey with an Alpha Test.
+ // [Alpha Test is more widely supported anyway]
+ //
+ if (bChromakey) {
+ // Switch on alpha testing
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_ALPHATESTENABLE, TRUE);
+ // Fragment passes is alpha is greater than reference value
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_ALPHAFUNC, D3DCMP_GREATER);
+ // Set alpha reference value between Bitmap alpha values of
+ // zero (transparent) and one (opaque).
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_ALPHAREF, 0x7f);
+ }
+
+ IDirect3DDevice8_DrawPrimitiveUP(gld->pDev, D3DPT_TRIANGLEFAN, 2, &v, sizeof(_GLD_IMAGE_VERTEX));
+
+ // Release texture
+ IDirect3DDevice8_SetTexture(gld->pDev, 0, NULL);
+ IDirect3DTexture8_Release(pTexture);
+
+ // Reset state to before we messed it up
+ FLUSH_VERTICES(ctx, _NEW_ALL);
+
+ return S_OK;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_DrawPixels_DX8(
+ GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels )
+{
+ GLD_context *gldCtx;
+ GLD_driver_dx8 *gld;
+
+ IDirect3DSurface8 *pImage;
+ HRESULT hr;
+ D3DLOCKED_RECT d3dLockedRect;
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ hr = IDirect3DDevice8_CreateImageSurface(
+ gld->pDev,
+ width,
+ height,
+ D3DFMT_A8R8G8B8,
+ &pImage);
+ if (FAILED(hr)) {
+ return;
+ }
+
+ //
+ // Use Mesa to fill in image
+ //
+
+ // Lock all of surface
+ hr = IDirect3DSurface8_LockRect(pImage, &d3dLockedRect, NULL, 0);
+ if (FAILED(hr)) {
+ IDirect3DSurface8_Release(pImage);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store directly in texture
+ _mesa_transfer_teximage(
+ ctx,
+ 2,
+ GL_RGBA,
+ &_mesa_texformat_argb8888,
+ d3dLockedRect.pBits,
+ width, height, 1, 0, 0, 0,
+ d3dLockedRect.Pitch,
+ 0, /* dstImageStride */
+ format, type, pixels, unpack);
+
+ IDirect3DSurface8_UnlockRect(pImage);
+
+ _gldDrawPixels(ctx, FALSE, x, y, width, height, pImage);
+
+ IDirect3DSurface8_Release(pImage);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_ReadPixels_DX8(
+ GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *pack,
+ GLvoid *dest)
+{
+
+ GLD_context *gldCtx;
+ GLD_driver_dx8 *gld;
+
+ IDirect3DSurface8 *pBackbuffer = NULL;
+ IDirect3DSurface8 *pNativeImage = NULL;
+ IDirect3DSurface8 *pCanonicalImage = NULL;
+
+ D3DSURFACE_DESC d3dsd;
+ RECT rcSrc; // Source rect
+ POINT ptDst; // Dest point
+ HRESULT hr;
+ D3DLOCKED_RECT d3dLockedRect;
+ struct gl_pixelstore_attrib srcPacking;
+ int i;
+ GLint DstRowStride;
+ const struct gl_texture_format *MesaFormat;
+
+ switch (format) {
+ case GL_STENCIL_INDEX:
+ case GL_DEPTH_COMPONENT:
+ return;
+ }
+
+ MesaFormat = _mesa_choose_tex_format(ctx, format, format, type);
+ DstRowStride = _mesa_image_row_stride(pack, width, format, type);
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ // Get backbuffer
+ hr = IDirect3DDevice8_GetBackBuffer(
+ gld->pDev,
+ 0, // First backbuffer
+ D3DBACKBUFFER_TYPE_MONO,
+ &pBackbuffer);
+ if (FAILED(hr))
+ return;
+
+ // Get backbuffer description
+ hr = IDirect3DSurface8_GetDesc(pBackbuffer, &d3dsd);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX8_return;
+ }
+
+ // Create a surface compatible with backbuffer
+ hr = IDirect3DDevice8_CreateImageSurface(
+ gld->pDev,
+ width,
+ height,
+ d3dsd.Format,
+ &pNativeImage);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX8_return;
+ }
+
+ // Compute source rect and dest point
+ SetRect(&rcSrc, 0, 0, width, height);
+ OffsetRect(&rcSrc, x, GLD_FLIP_HEIGHT(y, height));
+ ptDst.x = ptDst.y = 0;
+
+ // Get source pixels.
+ //
+ // This intermediate surface ensure that we can use CopyRects()
+ // instead of relying on D3DXLoadSurfaceFromSurface(), which may
+ // try and lock the backbuffer. This way seems safer.
+ //
+ hr = IDirect3DDevice8_CopyRects(
+ gld->pDev,
+ pBackbuffer,
+ &rcSrc,
+ 1,
+ pNativeImage,
+ &ptDst);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX8_return;
+ }
+
+ // Create an RGBA8888 surface
+ hr = IDirect3DDevice8_CreateImageSurface(
+ gld->pDev,
+ width,
+ height,
+ D3DFMT_A8R8G8B8,
+ &pCanonicalImage);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX8_return;
+ }
+
+ // Convert to RGBA8888
+ hr = D3DXLoadSurfaceFromSurface(
+ pCanonicalImage, // Dest surface
+ NULL, NULL, // Dest palette, RECT
+ pNativeImage, // Src surface
+ NULL, NULL, // Src palette, RECT
+ D3DX_FILTER_NONE, // Filter
+ 0); // Colourkey
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX8_return;
+ }
+
+ srcPacking.Alignment = 1;
+ srcPacking.ImageHeight = height;
+ srcPacking.LsbFirst = GL_FALSE;
+ srcPacking.RowLength = 0;
+ srcPacking.SkipImages = 0;
+ srcPacking.SkipPixels = 0;
+ srcPacking.SkipRows = 0;
+ srcPacking.SwapBytes = GL_FALSE;
+
+ // Lock all of image
+ hr = IDirect3DSurface8_LockRect(pCanonicalImage, &d3dLockedRect, NULL, 0);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX8_return;
+ }
+
+ // We need to flip the data. Yuck.
+ // Perhaps Mesa has a span packer we can use in future...
+ for (i=0; i<height; i++) {
+ BYTE *pDestRow = (BYTE*)_mesa_image_address(pack, dest, width, height, format, type, 0, i, 0);
+ BYTE *pSrcRow = (BYTE*)d3dLockedRect.pBits + (d3dLockedRect.Pitch * (height-i-1));
+ _mesa_transfer_teximage(
+ ctx,
+ 2,
+ GL_RGBA, // base format
+ MesaFormat, // dst format
+ pDestRow, // dest addr
+ width, 1, 1, 0, 0, 0, // src x,y,z & dst offsets x,y,z
+ DstRowStride, // dst row stride
+ 0, // dstImageStride
+ GL_BGRA, // src format
+ GL_UNSIGNED_BYTE, // src type
+ pSrcRow, // src addr
+ &srcPacking); // packing params of source image
+ }
+
+ IDirect3DSurface8_UnlockRect(pCanonicalImage);
+
+gld_ReadPixels_DX8_return:
+ SAFE_RELEASE_SURFACE8(pCanonicalImage);
+ SAFE_RELEASE_SURFACE8(pNativeImage);
+ SAFE_RELEASE_SURFACE8(pBackbuffer);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_CopyPixels_DX8(
+ GLcontext *ctx,
+ GLint srcx,
+ GLint srcy,
+ GLsizei width,
+ GLsizei height,
+ GLint dstx,
+ GLint dsty,
+ GLenum type)
+{
+ //
+ // NOTE: Not allowed to copy vidmem to vidmem!
+ // Therefore we use an intermediate image surface.
+ //
+
+ GLD_context *gldCtx;
+ GLD_driver_dx8 *gld;
+
+ IDirect3DSurface8 *pBackbuffer;
+ D3DSURFACE_DESC d3dsd;
+ IDirect3DSurface8 *pImage;
+ RECT rcSrc; // Source rect
+ POINT ptDst; // Dest point
+ HRESULT hr;
+
+ // Only backbuffer
+ if (type != GL_COLOR)
+ return;
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ // Get backbuffer
+ hr = IDirect3DDevice8_GetBackBuffer(
+ gld->pDev,
+ 0, // First backbuffer
+ D3DBACKBUFFER_TYPE_MONO,
+ &pBackbuffer);
+ if (FAILED(hr))
+ return;
+
+ // Get backbuffer description
+ hr = IDirect3DSurface8_GetDesc(pBackbuffer, &d3dsd);
+ if (FAILED(hr)) {
+ IDirect3DSurface8_Release(pBackbuffer);
+ return;
+ }
+
+ // Create a surface compatible with backbuffer
+ hr = IDirect3DDevice8_CreateImageSurface(
+ gld->pDev,
+ width,
+ height,
+ d3dsd.Format,
+ &pImage);
+ if (FAILED(hr)) {
+ IDirect3DSurface8_Release(pBackbuffer);
+ return;
+ }
+
+ // Compute source rect and dest point
+ SetRect(&rcSrc, 0, 0, width, height);
+ OffsetRect(&rcSrc, srcx, GLD_FLIP_HEIGHT(srcy, height));
+ ptDst.x = ptDst.y = 0;
+
+ // Get source pixels
+ hr = IDirect3DDevice8_CopyRects(
+ gld->pDev,
+ pBackbuffer,
+ &rcSrc,
+ 1,
+ pImage,
+ &ptDst);
+ IDirect3DSurface8_Release(pBackbuffer);
+ if (FAILED(hr)) {
+ IDirect3DSurface8_Release(pImage);
+ return;
+ }
+
+ _gldDrawPixels(ctx, FALSE, dstx, dsty, width, height, pImage);
+
+ IDirect3DSurface8_Release(pImage);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Bitmap_DX8(
+ GLcontext *ctx,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap)
+{
+ GLD_context *gldCtx;
+ GLD_driver_dx8 *gld;
+
+ IDirect3DSurface8 *pImage;
+ HRESULT hr;
+ D3DLOCKED_RECT d3dLockedRect;
+ BYTE *pTempBitmap;
+ D3DCOLOR clBitmapOne, clBitmapZero;
+ D3DCOLOR *pBits;
+ const GLubyte *src;
+ int i, j, k;
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ clBitmapZero = D3DCOLOR_RGBA(0,0,0,0); // NOTE: Alpha is Zero
+ clBitmapOne = D3DCOLOR_COLORVALUE(
+ ctx->Current.RasterColor[0],
+ ctx->Current.RasterColor[1],
+ ctx->Current.RasterColor[2],
+ 1.0f); // NOTE: Alpha is One
+
+ hr = IDirect3DDevice8_CreateImageSurface(
+ gld->pDev,
+ width,
+ height,
+ D3DFMT_A8R8G8B8,
+ &pImage);
+ if (FAILED(hr)) {
+ return;
+ }
+
+ // Lock all of surface
+ hr = IDirect3DSurface8_LockRect(pImage, &d3dLockedRect, NULL, 0);
+ if (FAILED(hr)) {
+ IDirect3DSurface8_Release(pImage);
+ return;
+ }
+
+ pTempBitmap = _mesa_unpack_bitmap(width, height, bitmap, unpack);
+ if (pTempBitmap == NULL) {
+ IDirect3DSurface8_Release(pImage);
+ return;
+ }
+
+ pBits = (D3DCOLOR*)d3dLockedRect.pBits;
+
+ for (i=0; i<height; i++) {
+ GLubyte byte;
+ pBits = (D3DCOLOR*)((BYTE*)d3dLockedRect.pBits + (i*d3dLockedRect.Pitch));
+ src = (const GLubyte *) _mesa_image_address(
+ &_mesa_native_packing, pTempBitmap, width, height, GL_COLOR_INDEX, GL_BITMAP,
+ 0, i, 0);
+ for (j=0; j<(width>>3); j++) {
+ byte = *src++;
+ for (k=0; k<8; k++) {
+ *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero;
+ byte <<= 1;
+ }
+ }
+ // Fill remaining bits from bitmap
+ if (width & 7) {
+ byte = *src;
+ for (k=0; k<(width & 7); k++) {
+ *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero;
+ byte <<= 1;
+ }
+ }
+ }
+
+ FREE(pTempBitmap);
+
+/*
+ // unpack image, apply transfer ops and store directly in texture
+ _mesa_transfer_teximage(
+ ctx,
+ 2,
+ GL_BITMAP,
+ &_mesa_texformat_argb8888,
+ d3dLockedRect.pBits,
+ width, height, 1, 0, 0, 0,
+ d3dLockedRect.Pitch,
+ 0, // dstImageStride
+ GL_BITMAP, GL_COLOR_INDEX, bitmap, unpack);
+*/
+ IDirect3DSurface8_UnlockRect(pImage);
+
+ _gldDrawPixels(ctx, TRUE, x, y, width, height, pImage);
+
+ IDirect3DSurface8_Release(pImage);
+}
+
+//---------------------------------------------------------------------------
+// Texture functions
+//---------------------------------------------------------------------------
+
+void _gldAllocateTexture(
+ GLcontext *ctx,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ IDirect3DTexture8 *pTex;
+ D3DFORMAT d3dFormat;
+
+ if (!tObj || !texImage)
+ return;
+
+ pTex = (IDirect3DTexture8*)tObj->DriverData;
+ if (pTex) {
+ // Decide whether we can keep existing D3D texture
+ // by examining top-level surface.
+ D3DSURFACE_DESC d3dsd;
+ _GLD_DX8_TEX(GetLevelDesc(pTex, 0, &d3dsd));
+ // Release existing texture if not compatible
+ if ((d3dsd.Width == texImage->Width) ||
+ (d3dsd.Height == texImage->Height))
+ {
+ return; // Keep the existing texture
+ }
+ tObj->DriverData = NULL;
+ _GLD_DX8_TEX(Release(pTex));
+ }
+
+ d3dFormat = _gldGLFormatToD3DFormat(texImage->IntFormat);
+ D3DXCreateTexture(
+ gld->pDev,
+ texImage->Width,
+ texImage->Height,
+ // TODO: Re-evaluate mipmapping
+ (glb.bUseMipmaps) ? D3DX_DEFAULT : 1,
+ 0, // Usage
+ d3dFormat,
+ D3DPOOL_MANAGED,
+ &pTex);
+ tObj->DriverData = pTex;
+}
+
+//---------------------------------------------------------------------------
+
+const struct gl_texture_format* gld_ChooseTextureFormat_DX8(
+ GLcontext *ctx,
+ GLint internalFormat,
+ GLenum srcFormat,
+ GLenum srcType)
+{
+ // [Based on mesa_choose_tex_format()]
+ //
+ // We will choose only texture formats that are supported
+ // by Direct3D. If the hardware doesn't support a particular
+ // texture format, then the D3DX texture calls that we use
+ // will automatically use a HW supported format.
+ //
+ // The most critical aim is to reduce copying; if we can use
+ // texture-image data directly then it will be a big performance assist.
+ //
+
+ switch (internalFormat) {
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ return &_mesa_texformat_l8; // D3DFMT_L8
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return &_mesa_texformat_l8; // D3DFMT_L8
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return &_mesa_texformat_a8; // D3DFMT_A8
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ return &_mesa_texformat_rgb565; // D3DFMT_R5G6B5
+ // Mesa will convert this for us later...
+ // return &_mesa_texformat_ci8; // D3DFMT_R5G6B5
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ return &_mesa_texformat_al88; // D3DFMT_A8L8
+ case GL_R3_G3_B2:
+ return &_mesa_texformat_rgb332; // D3DFMT_R3G3B2
+ case GL_RGB4:
+ case GL_RGBA4:
+ case GL_RGBA2:
+ return &_mesa_texformat_argb4444; // D3DFMT_A4R4G4B4
+ case 3:
+ case GL_RGB:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return &_mesa_texformat_rgb565;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return &_mesa_texformat_argb8888;
+ case GL_RGB5_A1:
+ return &_mesa_texformat_argb1555;
+ default:
+ _mesa_problem(NULL, "unexpected format in fxDDChooseTextureFormat");
+ return NULL;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+/*
+// Safer(?), slower version.
+void gld_TexImage2D_DX8(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint internalFormat,
+ GLint width,
+ GLint height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ IDirect3DTexture8 *pTex;
+ IDirect3DSurface8 *pSurface;
+ RECT rcSrcRect;
+ HRESULT hr;
+ GLint texelBytes = 4;
+ GLvoid *tempImage;
+
+ if (!tObj || !texImage)
+ return;
+
+ if (level == 0) {
+ _gldAllocateTexture(ctx, tObj, texImage);
+ }
+
+ pTex = (IDirect3DTexture8*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= IDirect3DTexture8_GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = IDirect3DTexture8_GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ tempImage = MALLOC(width * height * texelBytes);
+ if (!tempImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ IDirect3DSurface8_Release(pSurface);
+ return;
+ }
+ // unpack image, apply transfer ops and store in tempImage
+ _mesa_transfer_teximage(ctx, 2, texImage->Format,
+ &_mesa_texformat_argb8888, // dest format
+ tempImage,
+ width, height, 1, 0, 0, 0,
+ width * texelBytes,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+ SetRect(&rcSrcRect, 0, 0, width, height);
+ D3DXLoadSurfaceFromMemory(
+ pSurface,
+ NULL,
+ NULL,
+ tempImage,
+ D3DFMT_A8R8G8B8,
+ width * texelBytes,
+ NULL,
+ &rcSrcRect,
+ D3DX_FILTER_NONE,
+ 0);
+
+ FREE(tempImage);
+ IDirect3DSurface8_Release(pSurface);
+}
+*/
+
+//---------------------------------------------------------------------------
+
+// Faster, more efficient version.
+// Copies subimage straight to dest texture
+void gld_TexImage2D_DX8(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint internalFormat,
+ GLint width,
+ GLint height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ IDirect3DTexture8 *pTex;
+ IDirect3DSurface8 *pSurface;
+ HRESULT hr;
+ D3DLOCKED_RECT d3dLockedRect;
+ D3DSURFACE_DESC d3dsd;
+
+ if (!tObj || !texImage)
+ return;
+
+ // GLQUAKE FIX
+ // Test for input alpha data with non-alpha internalformat
+ if (((internalFormat==3) || (internalFormat==GL_RGB)) && (format==GL_RGBA)) {
+ // Input format has alpha, but a non-alpha format has been requested.
+ texImage->IntFormat = GL_RGBA;
+ internalFormat = GL_RGBA;
+ }
+
+ if (level == 0) {
+ _gldAllocateTexture(ctx, tObj, texImage);
+ }
+
+ pTex = (IDirect3DTexture8*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= IDirect3DTexture8_GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = IDirect3DTexture8_GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ IDirect3DSurface8_GetDesc(pSurface, &d3dsd);
+
+ // Lock all of surface
+ hr = IDirect3DSurface8_LockRect(pSurface, &d3dLockedRect, NULL, 0);
+ if (FAILED(hr)) {
+ IDirect3DSurface8_Release(pSurface);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store directly in texture
+ _mesa_transfer_teximage(
+ ctx,
+ 2,
+ texImage->Format,
+ _gldMesaFormatForD3DFormat(d3dsd.Format),
+ d3dLockedRect.pBits,
+ width, height, 1, 0, 0, 0,
+ d3dLockedRect.Pitch,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+ IDirect3DSurface8_UnlockRect(pSurface);
+ IDirect3DSurface8_Release(pSurface);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_TexImage1D_DX8(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ // A 1D texture is a 2D texture with a height of zero
+ gld_TexImage2D_DX8(ctx, target, level, internalFormat, width, 1, border, format, type, pixels, packing, texObj, texImage);
+}
+
+//---------------------------------------------------------------------------
+
+/*
+void gld_TexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage )
+{
+ GLD_GET_CONTEXT
+ IDirect3DTexture8 *pTex;
+ IDirect3DSurface8 *pSurface;
+ D3DFORMAT d3dFormat;
+ HRESULT hr;
+ GLint texelBytes = 4;
+ GLvoid *tempImage;
+ RECT rcSrcRect;
+ RECT rcDstRect;
+
+ if (!tObj || !texImage)
+ return;
+
+ pTex = (IDirect3DTexture8*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= _GLD_DX8_TEX(GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = _GLD_DX8_TEX(GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ d3dFormat = _gldGLFormatToD3DFormat(texImage->Format);
+ tempImage = MALLOC(width * height * texelBytes);
+ if (!tempImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ IDirect3DSurface8_Release(pSurface);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store in tempImage
+ _mesa_transfer_teximage(ctx, 2, texImage->Format,
+ &_mesa_texformat_argb8888, // dest format
+ tempImage,
+ width, height, 1, 0, 0, 0,
+ width * texelBytes,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+ // Source rectangle is whole of input image
+ SetRect(&rcSrcRect, 0, 0, width, height);
+
+ // Dest rectangle must be offset to dest image
+ SetRect(&rcDstRect, 0, 0, width, height);
+ OffsetRect(&rcDstRect, xoffset, yoffset);
+
+ D3DXLoadSurfaceFromMemory(
+ pSurface,
+ NULL,
+ &rcDstRect,
+ tempImage,
+ D3DFMT_A8R8G8B8,
+ width * texelBytes,
+ NULL,
+ &rcSrcRect,
+ D3DX_FILTER_NONE,
+ 0);
+
+ FREE(tempImage);
+ IDirect3DSurface8_Release(pSurface);
+}
+*/
+
+//---------------------------------------------------------------------------
+
+// Faster, more efficient version.
+// Copies subimage straight to dest texture
+void gld_TexSubImage2D_DX8( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ IDirect3DTexture8 *pTex;
+ IDirect3DSurface8 *pSurface;
+ HRESULT hr;
+ RECT rcDstRect;
+ D3DLOCKED_RECT d3dLockedRect;
+ D3DSURFACE_DESC d3dsd;
+
+ if (!tObj || !texImage)
+ return;
+
+ pTex = (IDirect3DTexture8*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= IDirect3DTexture8_GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = IDirect3DTexture8_GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ IDirect3DSurface8_GetDesc(pSurface, &d3dsd);
+
+ // Dest rectangle must be offset to dest image
+ SetRect(&rcDstRect, 0, 0, width, height);
+ OffsetRect(&rcDstRect, xoffset, yoffset);
+
+ // Lock sub-rect of surface
+ hr = IDirect3DSurface8_LockRect(pSurface, &d3dLockedRect, &rcDstRect, 0);
+ if (FAILED(hr)) {
+ IDirect3DSurface8_Release(pSurface);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store directly in texture
+ _mesa_transfer_teximage(ctx, 2, texImage->Format,
+ _gldMesaFormatForD3DFormat(d3dsd.Format),
+ d3dLockedRect.pBits,
+ width, height, 1,
+ 0, 0, 0, // NOTE: d3dLockedRect.pBits is already offset!!!
+ d3dLockedRect.Pitch,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+
+ IDirect3DSurface8_UnlockRect(pSurface);
+ IDirect3DSurface8_Release(pSurface);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_TexSubImage1D_DX8( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLsizei width,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ gld_TexSubImage2D_DX8(ctx, target, level, xoffset, 0, width, 1, format, type, pixels, packing, texObj, texImage);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_DeleteTexture_DX8(
+ GLcontext *ctx,
+ struct gl_texture_object *tObj)
+{
+ GLD_context *gld = (GLD_context*)(ctx->DriverCtx);
+
+ if (tObj) {
+ IDirect3DTexture8 *pTex = (IDirect3DTexture8*)tObj->DriverData;
+ if (pTex) {
+/* // Make sure texture is not bound to a stage before releasing it
+ for (int i=0; i<MAX_TEXTURE_UNITS; i++) {
+ if (gld->CurrentTexture[i] == pTex) {
+ gld->pDev->SetTexture(i, NULL);
+ gld->CurrentTexture[i] = NULL;
+ }
+ }*/
+ _GLD_DX8_TEX(Release(pTex));
+ tObj->DriverData = NULL;
+ }
+ }
+}
+
+//---------------------------------------------------------------------------
+
+__inline void _gldSetColorOps(
+ const GLD_driver_dx8 *gld,
+ GLuint unit,
+ DWORD ColorArg1,
+ D3DTEXTUREOP ColorOp,
+ DWORD ColorArg2)
+{
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG1, ColorArg1));
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLOROP, ColorOp));
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG2, ColorArg2));
+}
+
+//---------------------------------------------------------------------------
+
+__inline void _gldSetAlphaOps(
+ const GLD_driver_dx8 *gld,
+ GLuint unit,
+ DWORD AlphaArg1,
+ D3DTEXTUREOP AlphaOp,
+ DWORD AlphaArg2)
+{
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG1, AlphaArg1));
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAOP, AlphaOp));
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG2, AlphaArg2));
+}
+
+//---------------------------------------------------------------------------
+
+void gldUpdateTextureUnit(
+ GLcontext *ctx,
+ GLuint unit,
+ BOOL bPassThrough)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ D3DTEXTUREFILTERTYPE minfilter;
+ D3DTEXTUREFILTERTYPE mipfilter;
+ GLenum BaseFormat;
+ DWORD dwColorArg0;
+ int iTexEnv = 0;
+ GLD_texenv *pTexenv;
+
+ // NOTE: If bPassThrough is FALSE then texture stage can be
+ // disabled otherwise it must pass-through it's current fragment.
+
+ const struct gl_texture_unit *pUnit = &ctx->Texture.Unit[unit];
+ const struct gl_texture_object *tObj = pUnit->_Current;
+
+ IDirect3DTexture8 *pTex = NULL;
+ if (tObj) {
+ pTex = (IDirect3DTexture8*)tObj->DriverData;
+ }
+
+ // Enable texturing if unit is enabled and a valid D3D texture exists
+ // Mesa 5: TEXTUREn_x altered to TEXTURE_nD_BIT
+ //if (pTex && (pUnit->Enabled & (TEXTURE0_1D | TEXTURE0_2D))) {
+ if (pTex && (pUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT))) {
+ // Enable texturing
+ _GLD_DX8_DEV(SetTexture(gld->pDev, unit, pTex));
+ } else {
+ // Disable texturing, then return
+ _GLD_DX8_DEV(SetTexture(gld->pDev, unit, NULL));
+ if (bPassThrough) {
+ _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE);
+ _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE);
+ } else {
+ _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE);
+ _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE);
+ }
+ return;
+ }
+
+ // Texture parameters
+ _gldConvertMinFilter(tObj->MinFilter, &minfilter, &mipfilter);
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MINFILTER, minfilter));
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MIPFILTER, mipfilter));
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MAGFILTER, _gldConvertMagFilter(tObj->MagFilter)));
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSU, _gldConvertWrap(tObj->WrapS)));
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSV, _gldConvertWrap(tObj->WrapT)));
+
+ // Texture priority
+ _GLD_DX8_TEX(SetPriority(pTex, (DWORD)(tObj->Priority*65535.0f)));
+
+ // Texture environment
+ // TODO: Examine input texture for alpha and use specific alpha/non-alpha ops.
+ // See Page 355 of the Red Book.
+ BaseFormat = _gldDecodeBaseFormat(pTex);
+
+ switch (BaseFormat) {
+ case GL_RGB:
+ iTexEnv = 0;
+ break;
+ case GL_RGBA:
+ iTexEnv = 1;
+ break;
+ case GL_ALPHA:
+ iTexEnv = 2;
+ break;
+ }
+
+ switch (pUnit->EnvMode) {
+ case GL_DECAL:
+ iTexEnv += 0;
+ break;
+ case GL_REPLACE:
+ iTexEnv += 3;
+ break;
+ case GL_MODULATE:
+ iTexEnv += 6;
+ break;
+ case GL_BLEND:
+ // Set blend colour
+ dwColorArg0 = D3DCOLOR_COLORVALUE(pUnit->EnvColor[0], pUnit->EnvColor[1], pUnit->EnvColor[2], pUnit->EnvColor[3]);
+ _GLD_DX8_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG0, dwColorArg0));
+ iTexEnv += 9;
+ break;
+ case GL_ADD:
+ iTexEnv += 12;
+ break;
+ }
+ pTexenv = (GLD_texenv*)&gldTexEnv[iTexEnv];
+ _gldSetColorOps(gld, unit, pTexenv->ColorArg1, pTexenv->ColorOp, pTexenv->ColorArg2);
+ _gldSetAlphaOps(gld, unit, pTexenv->AlphaArg1, pTexenv->AlphaOp, pTexenv->AlphaArg2);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_TEXTURE_DX8(
+ GLcontext *ctx)
+{
+ // TODO: Support for three (ATI Radeon) or more (nVidia GeForce3) texture units
+
+ BOOL bUnit0Enabled;
+ BOOL bUnit1Enabled;
+
+ if (!ctx)
+ return; // Sanity check
+
+ if (ctx->Const.MaxTextureUnits == 1) {
+ gldUpdateTextureUnit(ctx, 0, TRUE);
+ return;
+ }
+
+ //
+ // NOTE: THE FOLLOWING RELATES TO TWO TEXTURE UNITS, AND TWO ONLY!!
+ //
+
+ // Mesa 5: Texture Units altered
+ //bUnit0Enabled = (ctx->Texture._ReallyEnabled & (TEXTURE0_1D | TEXTURE0_2D)) ? TRUE : FALSE;
+ //bUnit1Enabled = (ctx->Texture._ReallyEnabled & (TEXTURE1_1D | TEXTURE1_2D)) ? TRUE : FALSE;
+ bUnit0Enabled = (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE;
+ bUnit1Enabled = (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE;
+
+ // If Unit0 is disabled and Unit1 is enabled then we must pass-though
+ gldUpdateTextureUnit(ctx, 0, (!bUnit0Enabled && bUnit1Enabled) ? TRUE : FALSE);
+ // We can always disable the last texture unit
+ gldUpdateTextureUnit(ctx, 1, FALSE);
+
+#ifdef _DEBUG
+ {
+ // Find out whether device supports current renderstates
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+// GLD_context *gld = GLD_GET_CONTEXT(ctx);
+
+ DWORD dwPasses;
+ _GLD_DX8_DEV(ValidateDevice(gld->pDev, &dwPasses));
+// if (FAILED(hr)) {
+// gldLogError(GLDLOG_ERROR, "ValidateDevice failed", hr);
+// }
+ if (dwPasses != 1) {
+ gldLogMessage(GLDLOG_ERROR, "ValidateDevice: Can't do in one pass\n");
+ }
+ }
+#endif
+};
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_vb_d3d_render_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_vb_d3d_render_dx8.c
new file mode 100644
index 0000000000..871a651990
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_vb_d3d_render_dx8.c
@@ -0,0 +1,281 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GLDirect fastpath pipeline stage
+*
+****************************************************************************/
+
+//---------------------------------------------------------------------------
+
+//#include "../GLDirect.h"
+//#include "../gld_log.h"
+//#include "gld_dx8.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx8.h"
+
+//---------------------------------------------------------------------------
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+// #include "mem.h"
+#include "mtypes.h"
+#include "mmath.h"
+
+#include "math/m_matrix.h"
+#include "math/m_xform.h"
+
+#include "tnl/t_pipeline.h"
+
+//---------------------------------------------------------------------------
+
+__inline void _gldSetVertexShaderConstants(
+ GLcontext *ctx,
+ GLD_driver_dx8 *gld)
+{
+ D3DXMATRIX mat, matView, matProj;
+ GLfloat *pM;
+
+ // Mesa 5: Altered to a Stack
+ //pM = ctx->ModelView.m;
+ pM = ctx->ModelviewMatrixStack.Top->m;
+ matView._11 = pM[0];
+ matView._12 = pM[1];
+ matView._13 = pM[2];
+ matView._14 = pM[3];
+ matView._21 = pM[4];
+ matView._22 = pM[5];
+ matView._23 = pM[6];
+ matView._24 = pM[7];
+ matView._31 = pM[8];
+ matView._32 = pM[9];
+ matView._33 = pM[10];
+ matView._34 = pM[11];
+ matView._41 = pM[12];
+ matView._42 = pM[13];
+ matView._43 = pM[14];
+ matView._44 = pM[15];
+
+ // Mesa 5: Altered to a Stack
+ //pM = ctx->ProjectionMatrix.m;
+ pM = ctx->ProjectionMatrixStack.Top->m;
+ matProj._11 = pM[0];
+ matProj._12 = pM[1];
+ matProj._13 = pM[2];
+ matProj._14 = pM[3];
+ matProj._21 = pM[4];
+ matProj._22 = pM[5];
+ matProj._23 = pM[6];
+ matProj._24 = pM[7];
+ matProj._31 = pM[8];
+ matProj._32 = pM[9];
+ matProj._33 = pM[10];
+ matProj._34 = pM[11];
+ matProj._41 = pM[12];
+ matProj._42 = pM[13];
+ matProj._43 = pM[14];
+ matProj._44 = pM[15];
+
+ D3DXMatrixMultiply( &mat, &matView, &matProj );
+ D3DXMatrixTranspose( &mat, &mat );
+
+ _GLD_DX8_DEV(SetVertexShaderConstant(gld->pDev, 0, &mat, 4));
+}
+
+//---------------------------------------------------------------------------
+
+static GLboolean gld_d3d_render_stage_run(
+ GLcontext *ctx,
+ struct gl_pipeline_stage *stage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ TNLcontext *tnl;
+ struct vertex_buffer *VB;
+ GLuint new_inputs;
+ render_func *tab;
+ GLint pass;
+ GLD_pb_dx8 *gldPB = &gld->PB3d;
+/*
+ static int count = 0;
+ count++;
+ if (count != 2)
+ return GL_FALSE;
+*/
+ // The "check" function should disable this stage,
+ // but we'll test gld->bUseMesaTnL anyway.
+ if (gld->bUseMesaTnL) {
+ // Do nothing in this stage, but continue pipeline
+ return GL_FALSE;
+ }
+
+ tnl = TNL_CONTEXT(ctx);
+ VB = &tnl->vb;
+ new_inputs = stage->changed_inputs;
+ pass = 0;
+
+ tnl->Driver.Render.Start( ctx );
+
+#if 0
+ // For debugging: Useful to see if an app passes colour data in
+ // an unusual format.
+ switch (VB->ColorPtr[0]->Type) {
+ case GL_FLOAT:
+ ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_FLOAT\n");
+ break;
+ case GL_UNSIGNED_BYTE:
+ ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_UNSIGNED_BYTE\n");
+ break;
+ default:
+ ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: *?*\n");
+ break;
+ }
+#endif
+
+ tnl->Driver.Render.Points = gld_Points3D_DX8;
+ if (ctx->_TriangleCaps & DD_FLATSHADE) {
+ tnl->Driver.Render.Line = gld_Line3DFlat_DX8;
+ tnl->Driver.Render.Triangle = gld_Triangle3DFlat_DX8;
+ tnl->Driver.Render.Quad = gld_Quad3DFlat_DX8;
+ } else {
+ tnl->Driver.Render.Line = gld_Line3DSmooth_DX8;
+ tnl->Driver.Render.Triangle = gld_Triangle3DSmooth_DX8;
+ tnl->Driver.Render.Quad = gld_Quad3DSmooth_DX8;
+ }
+
+ _GLD_DX8_VB(Lock(gldPB->pVB, 0, 0, &gldPB->pPoints, D3DLOCK_DISCARD));
+ gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0;
+ // Allocate primitive pointers
+ // gldPB->pPoints is always first
+ gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine);
+ gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle);
+
+ ASSERT(tnl->Driver.Render.BuildVertices);
+ ASSERT(tnl->Driver.Render.PrimitiveNotify);
+ ASSERT(tnl->Driver.Render.Points);
+ ASSERT(tnl->Driver.Render.Line);
+ ASSERT(tnl->Driver.Render.Triangle);
+ ASSERT(tnl->Driver.Render.Quad);
+ ASSERT(tnl->Driver.Render.ResetLineStipple);
+ ASSERT(tnl->Driver.Render.Interp);
+ ASSERT(tnl->Driver.Render.CopyPV);
+ ASSERT(tnl->Driver.Render.ClippedLine);
+ ASSERT(tnl->Driver.Render.ClippedPolygon);
+ ASSERT(tnl->Driver.Render.Finish);
+
+ tab = (VB->Elts ? tnl->Driver.Render.PrimTabElts : tnl->Driver.Render.PrimTabVerts);
+
+ do {
+ GLuint i, length, flags = 0;
+ for (i = 0 ; !(flags & PRIM_LAST) ; i += length)
+ {
+ flags = VB->Primitive[i];
+ length= VB->PrimitiveLength[i];
+ ASSERT(length || (flags & PRIM_LAST));
+ ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1);
+ if (length)
+ tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags );
+ }
+ } while (tnl->Driver.Render.Multipass &&
+ tnl->Driver.Render.Multipass( ctx, ++pass ));
+
+ _GLD_DX8_VB(Unlock(gldPB->pVB));
+
+ _GLD_DX8_DEV(SetStreamSource(gld->pDev, 0, gldPB->pVB, gldPB->dwStride));
+
+ _GLD_DX8_DEV(SetTransform(gld->pDev, D3DTS_PROJECTION, &gld->matProjection));
+ _GLD_DX8_DEV(SetTransform(gld->pDev, D3DTS_WORLD, &gld->matModelView));
+
+ if (gldPB->nPoints) {
+ _GLD_DX8_DEV(DrawPrimitive(gld->pDev, D3DPT_POINTLIST, 0, gldPB->nPoints));
+ gldPB->nPoints = 0;
+ }
+
+ if (gldPB->nLines) {
+ _GLD_DX8_DEV(DrawPrimitive(gld->pDev, D3DPT_LINELIST, gldPB->iFirstLine, gldPB->nLines));
+ gldPB->nLines = 0;
+ }
+
+ if (gldPB->nTriangles) {
+ _GLD_DX8_DEV(DrawPrimitive(gld->pDev, D3DPT_TRIANGLELIST, gldPB->iFirstTriangle, gldPB->nTriangles));
+ gldPB->nTriangles = 0;
+ }
+
+ return GL_FALSE; /* finished the pipe */
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_d3d_render_stage_check(
+ GLcontext *ctx,
+ struct gl_pipeline_stage *stage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+ // Is this thread safe?
+ stage->active = (gld->bUseMesaTnL) ? GL_FALSE : GL_TRUE;
+ return;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_d3d_render_stage_dtr( struct gl_pipeline_stage *stage )
+{
+}
+
+//---------------------------------------------------------------------------
+
+const struct gl_pipeline_stage _gld_d3d_render_stage =
+{
+ "gld_d3d_render_stage",
+ (_NEW_BUFFERS |
+ _DD_NEW_SEPARATE_SPECULAR |
+ _DD_NEW_FLATSHADE |
+ _NEW_TEXTURE|
+ _NEW_LIGHT|
+ _NEW_POINT|
+ _NEW_FOG|
+ _DD_NEW_TRI_UNFILLED |
+ _NEW_RENDERMODE), /* re-check (new inputs, interp function) */
+ 0, /* re-run (always runs) */
+ GL_TRUE, /* active */
+ 0, 0, /* inputs (set in check_render), outputs */
+ 0, 0, /* changed_inputs, private */
+ gld_d3d_render_stage_dtr, /* destructor */
+ gld_d3d_render_stage_check, /* check */
+ gld_d3d_render_stage_run /* run */
+};
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_vb_mesa_render_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_vb_mesa_render_dx8.c
new file mode 100644
index 0000000000..083b9d4910
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_vb_mesa_render_dx8.c
@@ -0,0 +1,513 @@
+/* $Id: gld_vb_mesa_render_dx8.c,v 1.1 2004/04/20 11:13:11 alanh Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keithw@valinux.com>
+ */
+
+
+/*
+ * Render whole vertex buffers, including projection of vertices from
+ * clip space and clipping of primitives.
+ *
+ * This file makes calls to project vertices and to the point, line
+ * and triangle rasterizers via the function pointers:
+ *
+ * context->Driver.Render.*
+ *
+ */
+
+
+//---------------------------------------------------------------------------
+
+//#include "../GLDirect.h"
+//#include "../gld_log.h"
+//#include "gld_dx8.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx8.h"
+
+//---------------------------------------------------------------------------
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+// #include "mem.h"
+#include "mtypes.h"
+#include "mmath.h"
+
+#include "math/m_matrix.h"
+#include "math/m_xform.h"
+
+#include "tnl/t_pipeline.h"
+
+/**********************************************************************/
+/* Clip single primitives */
+/**********************************************************************/
+
+
+#if defined(USE_IEEE)
+#define NEGATIVE(x) (GET_FLOAT_BITS(x) & (1<<31))
+#define DIFFERENT_SIGNS(x,y) ((GET_FLOAT_BITS(x) ^ GET_FLOAT_BITS(y)) & (1<<31))
+#else
+#define NEGATIVE(x) (x < 0)
+#define DIFFERENT_SIGNS(x,y) (x * y <= 0 && x - y != 0)
+/* Could just use (x*y<0) except for the flatshading requirements.
+ * Maybe there's a better way?
+ */
+#endif
+
+
+#define W(i) coord[i][3]
+#define Z(i) coord[i][2]
+#define Y(i) coord[i][1]
+#define X(i) coord[i][0]
+#define SIZE 4
+#define TAG(x) x##_4
+#include "tnl/t_vb_cliptmp.h"
+
+
+
+/**********************************************************************/
+/* Clip and render whole begin/end objects */
+/**********************************************************************/
+
+#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED)
+#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
+#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
+
+
+/* Vertices, with the possibility of clipping.
+ */
+#define RENDER_POINTS( start, count ) \
+ tnl->Driver.Render.Points( ctx, start, count )
+
+#define RENDER_LINE( v1, v2 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2]; \
+ GLubyte ormask = c1|c2; \
+ if (!ormask) \
+ LineFunc( ctx, v1, v2 ); \
+ else if (!(c1 & c2 & 0x3f)) \
+ clip_line_4( ctx, v1, v2, ormask ); \
+} while (0)
+
+#define RENDER_TRI( v1, v2, v3 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2], c3 = mask[v3]; \
+ GLubyte ormask = c1|c2|c3; \
+ if (!ormask) \
+ TriangleFunc( ctx, v1, v2, v3 ); \
+ else if (!(c1 & c2 & c3 & 0x3f)) \
+ clip_tri_4( ctx, v1, v2, v3, ormask ); \
+} while (0)
+
+#define RENDER_QUAD( v1, v2, v3, v4 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2]; \
+ GLubyte c3 = mask[v3], c4 = mask[v4]; \
+ GLubyte ormask = c1|c2|c3|c4; \
+ if (!ormask) \
+ QuadFunc( ctx, v1, v2, v3, v4 ); \
+ else if (!(c1 & c2 & c3 & c4 & 0x3f)) \
+ clip_quad_4( ctx, v1, v2, v3, v4, ormask ); \
+} while (0)
+
+
+#define LOCAL_VARS \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ const GLuint * const elt = VB->Elts; \
+ const GLubyte *mask = VB->ClipMask; \
+ const GLuint sz = VB->ClipPtr->size; \
+ const line_func LineFunc = tnl->Driver.Render.Line; \
+ const triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
+ const quad_func QuadFunc = tnl->Driver.Render.Quad; \
+ const GLboolean stipple = ctx->Line.StippleFlag; \
+ (void) (LineFunc && TriangleFunc && QuadFunc); \
+ (void) elt; (void) mask; (void) sz; (void) stipple;
+
+#define TAG(x) clip_##x##_verts
+#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
+#define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx )
+#define RESET_OCCLUSION ctx->OcclusionResult = GL_TRUE
+#define PRESERVE_VB_DEFS
+#include "tnl/t_vb_rendertmp.h"
+
+
+
+/* Elts, with the possibility of clipping.
+ */
+#undef ELT
+#undef TAG
+#define ELT(x) elt[x]
+#define TAG(x) clip_##x##_elts
+#include "tnl/t_vb_rendertmp.h"
+
+/* TODO: do this for all primitives, verts and elts:
+ */
+static void clip_elt_triangles( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ render_func render_tris = tnl->Driver.Render.PrimTabElts[GL_TRIANGLES];
+ struct vertex_buffer *VB = &tnl->vb;
+ const GLuint * const elt = VB->Elts;
+ GLubyte *mask = VB->ClipMask;
+ GLuint last = count-2;
+ GLuint j;
+ (void) flags;
+
+ tnl->Driver.Render.PrimitiveNotify( ctx, GL_TRIANGLES );
+
+ for (j=start; j < last; j+=3 ) {
+ GLubyte c1 = mask[elt[j]];
+ GLubyte c2 = mask[elt[j+1]];
+ GLubyte c3 = mask[elt[j+2]];
+ GLubyte ormask = c1|c2|c3;
+ if (ormask) {
+ if (start < j)
+ render_tris( ctx, start, j, 0 );
+ if (!(c1&c2&c3&0x3f))
+ clip_tri_4( ctx, elt[j], elt[j+1], elt[j+2], ormask );
+ start = j+3;
+ }
+ }
+
+ if (start < j)
+ render_tris( ctx, start, j, 0 );
+}
+
+/**********************************************************************/
+/* Render whole begin/end objects */
+/**********************************************************************/
+
+#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED)
+#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
+#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
+
+
+/* Vertices, no clipping.
+ */
+#define RENDER_POINTS( start, count ) \
+ tnl->Driver.Render.Points( ctx, start, count )
+
+#define RENDER_LINE( v1, v2 ) \
+ LineFunc( ctx, v1, v2 )
+
+#define RENDER_TRI( v1, v2, v3 ) \
+ TriangleFunc( ctx, v1, v2, v3 )
+
+#define RENDER_QUAD( v1, v2, v3, v4 ) \
+ QuadFunc( ctx, v1, v2, v3, v4 )
+
+#define TAG(x) _gld_tnl_##x##_verts
+
+#define LOCAL_VARS \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ const GLuint * const elt = VB->Elts; \
+ const line_func LineFunc = tnl->Driver.Render.Line; \
+ const triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
+ const quad_func QuadFunc = tnl->Driver.Render.Quad; \
+ (void) (LineFunc && TriangleFunc && QuadFunc); \
+ (void) elt;
+
+#define RESET_STIPPLE tnl->Driver.Render.ResetLineStipple( ctx )
+#define RESET_OCCLUSION ctx->OcclusionResult = GL_TRUE
+#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
+#define RENDER_TAB_QUALIFIER
+#define PRESERVE_VB_DEFS
+#include "tnl/t_vb_rendertmp.h"
+
+
+/* Elts, no clipping.
+ */
+#undef ELT
+#define TAG(x) _gld_tnl_##x##_elts
+#define ELT(x) elt[x]
+#include "tnl/t_vb_rendertmp.h"
+
+
+/**********************************************************************/
+/* Helper functions for drivers */
+/**********************************************************************/
+/*
+void _tnl_RenderClippedPolygon( GLcontext *ctx, const GLuint *elts, GLuint n )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint *tmp = VB->Elts;
+
+ VB->Elts = (GLuint *)elts;
+ tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
+ VB->Elts = tmp;
+}
+
+void _tnl_RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->Driver.Render.Line( ctx, ii, jj );
+}
+*/
+
+
+/**********************************************************************/
+/* Clip and render whole vertex buffers */
+/**********************************************************************/
+
+points_func _gldSetupPoints[4] = {
+ gld_Points2D_DX8,
+ gld_Points2D_DX8,
+ gld_Points2D_DX8,
+ gld_Points2D_DX8
+};
+line_func _gldSetupLine[4] = {
+ gld_Line2DFlat_DX8,
+ gld_Line2DSmooth_DX8,
+ gld_Line2DFlat_DX8,
+ gld_Line2DSmooth_DX8,
+};
+triangle_func _gldSetupTriangle[4] = {
+ gld_Triangle2DFlat_DX8,
+ gld_Triangle2DSmooth_DX8,
+ gld_Triangle2DFlatExtras_DX8,
+ gld_Triangle2DSmoothExtras_DX8
+};
+quad_func _gldSetupQuad[4] = {
+ gld_Quad2DFlat_DX8,
+ gld_Quad2DSmooth_DX8,
+ gld_Quad2DFlatExtras_DX8,
+ gld_Quad2DSmoothExtras_DX8
+};
+
+//---------------------------------------------------------------------------
+
+static GLboolean _gld_mesa_render_stage_run(
+ GLcontext *ctx,
+ struct gl_pipeline_stage *stage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx8 *gld = GLD_GET_DX8_DRIVER(gldCtx);
+
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint new_inputs = stage->changed_inputs;
+ render_func *tab;
+ GLint pass = 0;
+ GLD_pb_dx8 *gldPB;
+
+ /* Allow the drivers to lock before projected verts are built so
+ * that window coordinates are guarenteed not to change before
+ * rendering.
+ */
+ ASSERT(tnl->Driver.Render.Start);
+
+ tnl->Driver.Render.Start( ctx );
+
+ // NOTE: Setting D3DRS_SOFTWAREVERTEXPROCESSING for a mixed-mode device resets
+ // stream, indices and shader to default values of NULL or 0.
+/* if ((ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) &&
+ gld->VStwosidelight.hShader &&
+ !ctx->Fog.Enabled)
+ {
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->VStwosidelight.bHardware);
+ _GLD_DX8_DEV(SetVertexShader(gld->pDev, gld->VStwosidelight.hShader));
+ gldPB = &gld->PBtwosidelight;
+ tnl->Driver.Render.Points = gld_Points2DTwoside_DX8;
+ if (ctx->_TriangleCaps & DD_FLATSHADE) {
+ tnl->Driver.Render.Line = gld_Line2DFlatTwoside_DX8;
+ tnl->Driver.Render.Triangle = gld_Triangle2DFlatTwoside_DX8;
+ tnl->Driver.Render.Quad = gld_Quad2DFlatTwoside_DX8;
+ } else {
+ tnl->Driver.Render.Line = gld_Line2DSmoothTwoside_DX8;
+ tnl->Driver.Render.Triangle = gld_Triangle2DSmoothTwoside_DX8;
+ tnl->Driver.Render.Quad = gld_Quad2DSmoothTwoside_DX8;
+ }
+ } else {*/
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, TRUE);
+ gldPB = &gld->PB2d;
+ _GLD_DX8_DEV(SetVertexShader(gld->pDev, gldPB->dwFVF));
+ tnl->Driver.Render.Points = _gldSetupPoints[gld->iSetupFunc];
+ tnl->Driver.Render.Line = _gldSetupLine[gld->iSetupFunc];
+ tnl->Driver.Render.Triangle = _gldSetupTriangle[gld->iSetupFunc];
+ tnl->Driver.Render.Quad = _gldSetupQuad[gld->iSetupFunc];
+// }
+
+ _GLD_DX8_VB(Lock(gldPB->pVB, 0, 0, &gldPB->pPoints, D3DLOCK_DISCARD));
+ gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0;
+ // Allocate primitive pointers
+ // gldPB->pPoints is always first
+ gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine);
+ gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle);
+
+ ASSERT(tnl->Driver.Render.BuildVertices);
+ ASSERT(tnl->Driver.Render.PrimitiveNotify);
+ ASSERT(tnl->Driver.Render.Points);
+ ASSERT(tnl->Driver.Render.Line);
+ ASSERT(tnl->Driver.Render.Triangle);
+ ASSERT(tnl->Driver.Render.Quad);
+ ASSERT(tnl->Driver.Render.ResetLineStipple);
+ ASSERT(tnl->Driver.Render.Interp);
+ ASSERT(tnl->Driver.Render.CopyPV);
+ ASSERT(tnl->Driver.Render.ClippedLine);
+ ASSERT(tnl->Driver.Render.ClippedPolygon);
+ ASSERT(tnl->Driver.Render.Finish);
+
+ tnl->Driver.Render.BuildVertices( ctx, 0, VB->Count, new_inputs );
+
+ if (VB->ClipOrMask) {
+ tab = VB->Elts ? clip_render_tab_elts : clip_render_tab_verts;
+ clip_render_tab_elts[GL_TRIANGLES] = clip_elt_triangles;
+ }
+ else {
+ tab = (VB->Elts ?
+ tnl->Driver.Render.PrimTabElts :
+ tnl->Driver.Render.PrimTabVerts);
+ }
+
+ do {
+ GLuint i, length, flags = 0;
+ for (i = 0 ; !(flags & PRIM_LAST) ; i += length) {
+ flags = VB->Primitive[i];
+ length= VB->PrimitiveLength[i];
+ ASSERT(length || (flags & PRIM_LAST));
+ ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1);
+ if (length)
+ tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags );
+ }
+ } while (tnl->Driver.Render.Multipass &&
+ tnl->Driver.Render.Multipass( ctx, ++pass ));
+
+
+// tnl->Driver.Render.Finish( ctx );
+
+ _GLD_DX8_VB(Unlock(gldPB->pVB));
+
+ _GLD_DX8_DEV(SetStreamSource(gld->pDev, 0, gldPB->pVB, gldPB->dwStride));
+
+ if (gldPB->nPoints) {
+ _GLD_DX8_DEV(DrawPrimitive(gld->pDev, D3DPT_POINTLIST, 0, gldPB->nPoints));
+ gldPB->nPoints = 0;
+ }
+
+ if (gldPB->nLines) {
+ _GLD_DX8_DEV(DrawPrimitive(gld->pDev, D3DPT_LINELIST, gldPB->iFirstLine, gldPB->nLines));
+ gldPB->nLines = 0;
+ }
+
+ if (gldPB->nTriangles) {
+ _GLD_DX8_DEV(DrawPrimitive(gld->pDev, D3DPT_TRIANGLELIST, gldPB->iFirstTriangle, gldPB->nTriangles));
+ gldPB->nTriangles = 0;
+ }
+
+ return GL_FALSE; /* finished the pipe */
+}
+
+
+/**********************************************************************/
+/* Render pipeline stage */
+/**********************************************************************/
+
+
+
+/* Quite a bit of work involved in finding out the inputs for the
+ * render stage.
+ */
+static void _gld_mesa_render_stage_check(
+ GLcontext *ctx,
+ struct gl_pipeline_stage *stage)
+{
+ GLuint inputs = VERT_BIT_CLIP;
+ GLuint i;
+
+ if (ctx->Visual.rgbMode) {
+ inputs |= VERT_BIT_COLOR0;
+
+ if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
+ inputs |= VERT_BIT_COLOR1; //VERT_BIT_SPEC_RGB;
+
+ //if (ctx->Texture._ReallyEnabled) {
+ for (i=0; i<ctx->Const.MaxTextureUnits; i++) {
+ if (ctx->Texture.Unit[i]._ReallyEnabled)
+ inputs |= VERT_BIT_TEX(i);
+ }
+ //}
+ } else {
+ inputs |= VERT_BIT_INDEX;
+ }
+
+ if (ctx->Point._Attenuated)
+ inputs |= VERT_BIT_POINT_SIZE;
+
+ /* How do drivers turn this off?
+ */
+ if (ctx->Fog.Enabled)
+ inputs |= VERT_BIT_FOG; // VERT_FOG_COORD;
+
+ if (ctx->_TriangleCaps & DD_TRI_UNFILLED)
+ inputs |= VERT_BIT_EDGEFLAG;
+
+ if (ctx->RenderMode==GL_FEEDBACK)
+ inputs |= VERT_BITS_TEX_ANY;
+
+ stage->inputs = inputs;
+}
+
+//---------------------------------------------------------------------------
+
+// Destructor
+static void _gld_mesa_render_stage_dtr(
+ struct gl_pipeline_stage *stage)
+{
+}
+
+//---------------------------------------------------------------------------
+
+const struct gl_pipeline_stage _gld_mesa_render_stage =
+{
+ "gld_mesa_render_stage",
+ (_NEW_BUFFERS |
+ _DD_NEW_SEPARATE_SPECULAR |
+ _DD_NEW_FLATSHADE |
+ _NEW_TEXTURE|
+ _NEW_LIGHT|
+ _NEW_POINT|
+ _NEW_FOG|
+ _DD_NEW_TRI_UNFILLED |
+ _NEW_RENDERMODE), // re-check (new inputs, interp function)
+ 0, /* re-run (always runs) */
+ GL_TRUE, /* active */
+ 0, 0, /* inputs (set in check_render), outputs */
+ 0, 0, /* changed_inputs, private */
+ _gld_mesa_render_stage_dtr, /* destructor */
+ _gld_mesa_render_stage_check, /* check */
+ _gld_mesa_render_stage_run /* run */
+};
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx8/gld_wgl_dx8.c b/src/mesa/drivers/windows/gldirect/dx8/gld_wgl_dx8.c
new file mode 100644
index 0000000000..1c7992ed55
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx8/gld_wgl_dx8.c
@@ -0,0 +1,1335 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GLDirect Direct3D 8.x WGL (WindowsGL)
+*
+****************************************************************************/
+
+#include "dglcontext.h"
+#include "gld_driver.h"
+#include "gld_dxerr8.h"
+#include "gld_dx8.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+
+// Copied from dglcontect.c
+#define GLDERR_NONE 0
+#define GLDERR_MEM 1
+#define GLDERR_DDRAW 2
+#define GLDERR_D3D 3
+#define GLDERR_BPP 4
+#define GLDERR_DDS 5
+// This external var keeps track of any error
+extern int nContextError;
+
+#define DDLOG_CRITICAL_OR_WARN DDLOG_CRITICAL
+
+extern void _gld_mesa_warning(GLcontext *, char *);
+extern void _gld_mesa_fatal(GLcontext *, char *);
+
+//---------------------------------------------------------------------------
+
+static char szColorDepthWarning[] =
+"GLDirect does not support the current desktop\n\
+color depth.\n\n\
+You may need to change the display resolution to\n\
+16 bits per pixel or higher color depth using\n\
+the Windows Display Settings control panel\n\
+before running this OpenGL application.\n";
+
+// The only depth-stencil formats currently supported by Direct3D
+// Surface Format Depth Stencil Total Bits
+// D3DFMT_D32 32 - 32
+// D3DFMT_D15S1 15 1 16
+// D3DFMT_D24S8 24 8 32
+// D3DFMT_D16 16 - 16
+// D3DFMT_D24X8 24 - 32
+// D3DFMT_D24X4S4 24 4 32
+
+// This pixel format will be used as a template when compiling the list
+// of pixel formats supported by the hardware. Many fields will be
+// filled in at runtime.
+// PFD flag defaults are upgraded to match ChoosePixelFormat() -- DaveM
+static DGL_pixelFormat pfTemplateHW =
+{
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), // Size of the data structure
+ 1, // Structure version - should be 1
+ // Flags:
+ PFD_DRAW_TO_WINDOW | // The buffer can draw to a window or device surface.
+ PFD_DRAW_TO_BITMAP | // The buffer can draw to a bitmap. (DaveM)
+ PFD_SUPPORT_GDI | // The buffer supports GDI drawing. (DaveM)
+ PFD_SUPPORT_OPENGL | // The buffer supports OpenGL drawing.
+ PFD_DOUBLEBUFFER | // The buffer is double-buffered.
+ 0, // Placeholder for easy commenting of above flags
+ PFD_TYPE_RGBA, // Pixel type RGBA.
+ 16, // Total colour bitplanes (excluding alpha bitplanes)
+ 5, 0, // Red bits, shift
+ 5, 0, // Green bits, shift
+ 5, 0, // Blue bits, shift
+ 0, 0, // Alpha bits, shift (destination alpha)
+ 0, // Accumulator bits (total)
+ 0, 0, 0, 0, // Accumulator bits: Red, Green, Blue, Alpha
+ 0, // Depth bits
+ 0, // Stencil bits
+ 0, // Number of auxiliary buffers
+ 0, // Layer type
+ 0, // Specifies the number of overlay and underlay planes.
+ 0, // Layer mask
+ 0, // Specifies the transparent color or index of an underlay plane.
+ 0 // Damage mask
+ },
+ D3DFMT_UNKNOWN, // No depth/stencil buffer
+};
+
+//---------------------------------------------------------------------------
+// Vertex Shaders
+//---------------------------------------------------------------------------
+
+// Vertex Shader Declaration
+static DWORD dwTwoSidedLightingDecl[] =
+{
+ D3DVSD_STREAM(0),
+ D3DVSD_REG(0, D3DVSDT_FLOAT3), // XYZ position
+ D3DVSD_REG(1, D3DVSDT_FLOAT3), // XYZ normal
+ D3DVSD_REG(2, D3DVSDT_D3DCOLOR), // Diffuse color
+ D3DVSD_REG(3, D3DVSDT_D3DCOLOR), // Specular color
+ D3DVSD_REG(4, D3DVSDT_FLOAT2), // 2D texture unit 0
+ D3DVSD_REG(5, D3DVSDT_FLOAT2), // 2D texture unit 1
+ D3DVSD_END()
+};
+
+// Vertex Shader for two-sided lighting
+static char *szTwoSidedLightingVS =
+// This is a test shader!
+"vs.1.0\n"
+"m4x4 oPos,v0,c0\n"
+"mov oD0,v2\n"
+"mov oD1,v3\n"
+"mov oT0,v4\n"
+"mov oT1,v5\n"
+;
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+
+typedef struct {
+ HINSTANCE hD3D8DLL; // Handle to d3d8.dll
+ FNDIRECT3DCREATE8 fnDirect3DCreate8; // Direct3DCreate8 function prototype
+ BOOL bDirect3D; // Persistant Direct3D8 exists
+ BOOL bDirect3DDevice; // Persistant Direct3DDevice8 exists
+ IDirect3D8 *pD3D; // Persistant Direct3D8
+ IDirect3DDevice8 *pDev; // Persistant Direct3DDevice8
+} GLD_dx8_globals;
+
+// These are "global" to all DX8 contexts. KeithH
+static GLD_dx8_globals dx8Globals;
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+
+BOOL gldGetDXErrorString_DX(
+ HRESULT hr,
+ char *buf,
+ int nBufSize)
+{
+ //
+ // Return a string describing the input HRESULT error code
+ //
+
+ D3DXGetErrorString(hr, buf, nBufSize);
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+static D3DMULTISAMPLE_TYPE _gldGetDeviceMultiSampleType(
+ IDirect3D8 *pD3D8,
+ D3DFORMAT SurfaceFormat,
+ D3DDEVTYPE d3dDevType,
+ BOOL Windowed)
+{
+ int i;
+ HRESULT hr;
+
+ if (glb.dwMultisample == GLDS_MULTISAMPLE_NONE)
+ return D3DMULTISAMPLE_NONE;
+
+ if (glb.dwMultisample == GLDS_MULTISAMPLE_FASTEST) {
+ // Find fastest multisample
+ for (i=2; i<17; i++) {
+ hr = IDirect3D8_CheckDeviceMultiSampleType(
+ pD3D8,
+ glb.dwAdapter,
+ d3dDevType,
+ SurfaceFormat,
+ Windowed,
+ (D3DMULTISAMPLE_TYPE)i);
+ if (SUCCEEDED(hr)) {
+ return (D3DMULTISAMPLE_TYPE)i;
+ }
+ }
+ } else {
+ // Find nicest multisample
+ for (i=16; i>1; i--) {
+ hr = IDirect3D8_CheckDeviceMultiSampleType(
+ pD3D8,
+ glb.dwAdapter,
+ d3dDevType,
+ SurfaceFormat,
+ Windowed,
+ (D3DMULTISAMPLE_TYPE)i);
+ if (SUCCEEDED(hr)) {
+ return (D3DMULTISAMPLE_TYPE)i;
+ }
+ }
+ }
+
+ // Nothing found - return default
+ return D3DMULTISAMPLE_NONE;
+}
+
+//---------------------------------------------------------------------------
+
+void _gldDestroyPrimitiveBuffer(
+ GLD_pb_dx8 *gldVB)
+{
+ SAFE_RELEASE(gldVB->pVB);
+
+ // Sanity check...
+ gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0;
+}
+
+//---------------------------------------------------------------------------
+
+HRESULT _gldCreatePrimitiveBuffer(
+ GLcontext *ctx,
+ GLD_driver_dx8 *lpCtx,
+ GLD_pb_dx8 *gldVB)
+{
+ HRESULT hResult;
+ char *szCreateVertexBufferFailed = "CreateVertexBuffer failed";
+ DWORD dwMaxVertices; // Max number of vertices in vertex buffer
+ DWORD dwVBSize; // Total size of vertex buffer
+
+ // If CVA (Compiled Vertex Array) is used by an OpenGL app, then we
+ // will need enough vertices to cater for Mesa::Const.MaxArrayLockSize.
+ // We'll use IMM_SIZE if it's larger (which it should not be).
+ dwMaxVertices = (IMM_SIZE < MAX_ARRAY_LOCK_SIZE) ? MAX_ARRAY_LOCK_SIZE : IMM_SIZE;
+
+ // Now calculate how many vertices to allow for in total
+ // 1 per point, 2 per line, 6 per quad = 9
+ dwVBSize = dwMaxVertices * 9 * gldVB->dwStride;
+
+ hResult = IDirect3DDevice8_CreateVertexBuffer(
+ lpCtx->pDev,
+ dwVBSize,
+ gldVB->dwUsage,
+ gldVB->dwFVF,
+ gldVB->dwPool,
+ &gldVB->pVB);
+ if (FAILED(hResult)) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, szCreateVertexBufferFailed);
+ return hResult;
+ }
+
+ gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0;
+ gldVB->pPoints = gldVB->pLines = gldVB->pTriangles = NULL;
+ gldVB->iFirstLine = dwMaxVertices; // Index of first line in VB
+ gldVB->iFirstTriangle = dwMaxVertices*3; // Index of first triangle in VB
+
+ return S_OK;
+}
+
+//---------------------------------------------------------------------------
+// Function: _gldCreateVertexShaders
+// Create DX8 Vertex Shaders.
+//---------------------------------------------------------------------------
+/*
+void _gldCreateVertexShaders(
+ GLD_driver_dx8 *gld)
+{
+ DWORD dwFlags;
+ LPD3DXBUFFER pVSOpcodeBuffer; // Vertex Shader opcode buffer
+ HRESULT hr;
+
+#ifdef _DEBUG
+ dwFlags = D3DXASM_DEBUG;
+#else
+ dwFlags = 0; // D3DXASM_SKIPVALIDATION;
+#endif
+
+ ddlogMessage(DDLOG_INFO, "Creating shaders...\n");
+
+ // Init the shader handle
+ gld->VStwosidelight.hShader = 0;
+
+ if (gld->d3dCaps8.MaxStreams == 0) {
+ // Lame DX8 driver doesn't support streams
+ // Not fatal, as defaults will be used
+ ddlogMessage(DDLOG_WARN, "Driver doesn't support Vertex Shaders (MaxStreams==0)\n");
+ return;
+ }
+
+ // ** THIS DISABLES VERTEX SHADER SUPPORT **
+// return;
+ // ** THIS DISABLES VERTEX SHADER SUPPORT **
+
+ //
+ // Two-sided lighting
+ //
+
+#if 0
+ //
+ // DEBUGGING: Load shader from a text file
+ //
+ {
+ LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer
+ hr = D3DXAssembleShaderFromFile(
+ "twoside.vsh",
+ dwFlags,
+ NULL, // No constants
+ &pVSOpcodeBuffer,
+ &pVSErrorBuffer);
+ if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer))
+ ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer));
+ SAFE_RELEASE(pVSErrorBuffer);
+ }
+#else
+ {
+ LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer
+ // Assemble ascii shader text into shader opcodes
+ hr = D3DXAssembleShader(
+ szTwoSidedLightingVS,
+ strlen(szTwoSidedLightingVS),
+ dwFlags,
+ NULL, // No constants
+ &pVSOpcodeBuffer,
+ &pVSErrorBuffer);
+ if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer))
+ ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer));
+ SAFE_RELEASE(pVSErrorBuffer);
+ }
+#endif
+ if (FAILED(hr)) {
+ ddlogError(DDLOG_WARN, "AssembleShader failed", hr);
+ SAFE_RELEASE(pVSOpcodeBuffer);
+ return;
+ }
+
+// This is for debugging. Remove to enable vertex shaders in HW
+#define _GLD_FORCE_SW_VS 0
+
+ if (_GLD_FORCE_SW_VS) {
+ // _GLD_FORCE_SW_VS should be disabled for Final Release
+ ddlogMessage(DDLOG_SYSTEM, "[Forcing shaders in SW]\n");
+ }
+
+ // Try and create shader in hardware.
+ // NOTE: The D3D Ref device appears to succeed when trying to
+ // create the device in hardware, but later complains
+ // when trying to set it with SetVertexShader(). Go figure.
+ if (_GLD_FORCE_SW_VS || glb.dwDriver == GLDS_DRIVER_REF) {
+ // Don't try and create a hardware shader with the Ref device
+ hr = E_FAIL; // COM error/fail result
+ } else {
+ gld->VStwosidelight.bHardware = TRUE;
+ hr = IDirect3DDevice8_CreateVertexShader(
+ gld->pDev,
+ dwTwoSidedLightingDecl,
+ pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer),
+ &gld->VStwosidelight.hShader,
+ 0);
+ }
+ if (FAILED(hr)) {
+ ddlogMessage(DDLOG_INFO, "... HW failed, trying SW...\n");
+ // Failed. Try and create shader for software processing
+ hr = IDirect3DDevice8_CreateVertexShader(
+ gld->pDev,
+ dwTwoSidedLightingDecl,
+ pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer),
+ &gld->VStwosidelight.hShader,
+ D3DUSAGE_SOFTWAREPROCESSING);
+ if (FAILED(hr)) {
+ gld->VStwosidelight.hShader = 0; // Sanity check
+ ddlogError(DDLOG_WARN, "CreateVertexShader failed", hr);
+ return;
+ }
+ // Succeeded, but for software processing
+ gld->VStwosidelight.bHardware = FALSE;
+ }
+
+ SAFE_RELEASE(pVSOpcodeBuffer);
+
+ ddlogMessage(DDLOG_INFO, "... OK\n");
+}
+
+//---------------------------------------------------------------------------
+
+void _gldDestroyVertexShaders(
+ GLD_driver_dx8 *gld)
+{
+ if (gld->VStwosidelight.hShader) {
+ IDirect3DDevice8_DeleteVertexShader(gld->pDev, gld->VStwosidelight.hShader);
+ gld->VStwosidelight.hShader = 0;
+ }
+}
+*/
+//---------------------------------------------------------------------------
+
+LPVOID lpOpaque1 = NULL;
+LPVOID lpOpaque2 = NULL;
+
+BOOL gldCreateDrawable_DX(
+ DGL_ctx *ctx,
+// BOOL bDefaultDriver,
+ BOOL bDirectDrawPersistant,
+ BOOL bPersistantBuffers)
+{
+ //
+ // bDirectDrawPersistant: applies to IDirect3D8
+ // bPersistantBuffers: applies to IDirect3DDevice8
+ //
+
+ HRESULT hResult;
+ GLD_driver_dx8 *lpCtx = NULL;
+ D3DDEVTYPE d3dDevType;
+ D3DPRESENT_PARAMETERS d3dpp;
+ D3DDISPLAYMODE d3ddm;
+ DWORD dwBehaviourFlags;
+ D3DADAPTER_IDENTIFIER8 d3dIdent;
+
+ // Error if context is NULL.
+ if (ctx == NULL)
+ return FALSE;
+
+ if (ctx->glPriv) {
+ lpCtx = ctx->glPriv;
+ // Release any existing interfaces
+ SAFE_RELEASE(lpCtx->pDev);
+ SAFE_RELEASE(lpCtx->pD3D);
+ } else {
+ lpCtx = (GLD_driver_dx8*)malloc(sizeof(GLD_driver_dx8));
+ ZeroMemory(lpCtx, sizeof(lpCtx));
+ }
+
+ d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
+ // TODO: Check this
+// if (bDefaultDriver)
+// d3dDevType = D3DDEVTYPE_REF;
+
+ // Use persistant interface if needed
+ if (bDirectDrawPersistant && dx8Globals.bDirect3D) {
+ lpCtx->pD3D = dx8Globals.pD3D;
+ IDirect3D8_AddRef(lpCtx->pD3D);
+ goto SkipDirectDrawCreate;
+ }
+
+ // Create Direct3D8 object
+ lpCtx->pD3D = dx8Globals.fnDirect3DCreate8(D3D_SDK_VERSION_DX8_SUPPORT_WIN95);
+ if (lpCtx->pD3D == NULL) {
+ MessageBox(NULL, "Unable to initialize Direct3D8", "GLDirect", MB_OK);
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D8 interface");
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Cache Direct3D interface for subsequent GLRCs
+ if (bDirectDrawPersistant && !dx8Globals.bDirect3D) {
+ dx8Globals.pD3D = lpCtx->pD3D;
+ IDirect3D8_AddRef(dx8Globals.pD3D);
+ dx8Globals.bDirect3D = TRUE;
+ }
+SkipDirectDrawCreate:
+
+ // Get the display mode so we can make a compatible backbuffer
+ hResult = IDirect3D8_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hResult)) {
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Get device caps
+ hResult = IDirect3D8_GetDeviceCaps(lpCtx->pD3D, glb.dwAdapter, d3dDevType, &lpCtx->d3dCaps8);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D8_GetDeviceCaps failed", hResult);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Check for hardware transform & lighting
+ lpCtx->bHasHWTnL = lpCtx->d3dCaps8.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE;
+
+ // If this flag is present then we can't default to Mesa
+ // SW rendering between BeginScene() and EndScene().
+ if (lpCtx->d3dCaps8.Caps2 & D3DCAPS2_NO2DDURING3DSCENE) {
+ ddlogMessage(DDLOG_WARN,
+ "Warning : No 2D allowed during 3D scene.\n");
+ }
+
+ //
+ // Create the Direct3D context
+ //
+
+ // Re-use original IDirect3DDevice if persistant buffers exist.
+ // Note that we test for persistant IDirect3D8 as well
+ // bDirectDrawPersistant == persistant IDirect3D8 (DirectDraw8 does not exist)
+ if (bDirectDrawPersistant && bPersistantBuffers && dx8Globals.pD3D && dx8Globals.pDev) {
+ lpCtx->pDev = dx8Globals.pDev;
+ IDirect3DDevice8_AddRef(dx8Globals.pDev);
+ goto skip_direct3ddevice_create;
+ }
+
+ // Clear the presentation parameters (sets all members to zero)
+ ZeroMemory(&d3dpp, sizeof(d3dpp));
+
+ // Recommended by MS; needed for MultiSample.
+ // Be careful if altering this for FullScreenBlit
+ d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+
+ d3dpp.BackBufferFormat = d3ddm.Format;
+ d3dpp.BackBufferCount = 1;
+ d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(lpCtx->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen);
+ d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData;
+ d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE;
+
+ if (ctx->bFullscreen) {
+ ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen
+ d3dpp.Windowed = FALSE;
+ d3dpp.BackBufferWidth = d3ddm.Width;
+ d3dpp.BackBufferHeight = d3ddm.Height;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
+
+ // Support for vertical retrace synchronisation.
+ // Set default presentation interval in case caps bits are missing
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ if (glb.bWaitForRetrace) {
+ if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE;
+ } else {
+ if (lpCtx->d3dCaps8.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+ }
+ } else {
+ ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages
+ d3dpp.Windowed = TRUE;
+ d3dpp.BackBufferWidth = ctx->dwWidth;
+ d3dpp.BackBufferHeight = ctx->dwHeight;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = 0;
+ // FullScreen_PresentationInterval must be default for Windowed mode
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ }
+
+ // Decide if we can use hardware TnL
+ dwBehaviourFlags = (lpCtx->bHasHWTnL) ?
+ D3DCREATE_MIXED_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING;
+ // Add flag to tell D3D to be thread-safe
+ if (glb.bMultiThreaded)
+ dwBehaviourFlags |= D3DCREATE_MULTITHREADED;
+ // Add flag to tell D3D to be FPU-safe
+ if (!glb.bFastFPU)
+ dwBehaviourFlags |= D3DCREATE_FPU_PRESERVE;
+ hResult = IDirect3D8_CreateDevice(lpCtx->pD3D,
+ glb.dwAdapter,
+ d3dDevType,
+ ctx->hWnd,
+ dwBehaviourFlags,
+ &d3dpp,
+ &lpCtx->pDev);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D8_CreateDevice failed", hResult);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ if (bDirectDrawPersistant && bPersistantBuffers && dx8Globals.pD3D) {
+ dx8Globals.pDev = lpCtx->pDev;
+ dx8Globals.bDirect3DDevice = TRUE;
+ }
+
+/*
+ // See if DDraw interfaces are available (DaveM)
+ hResult = IDirect3D8_QueryInterface(lpCtx->pDev,
+ &IID_IDirectDraw7, (LPVOID*)&lpOpaque1);
+ if (FAILED(hResult) || lpOpaque1 == NULL) {
+ ddlogMessage(DDLOG_INFO, "DirectDraw QueryInterface unavailable\n");
+ }
+
+ hResult = IDirect3DDevice8_QueryInterface(lpCtx->pDev,
+ &IID_IDirectDrawSurface7, (LPVOID*)&lpOpaque2);
+ if (FAILED(hResult) || lpOpaque2 == NULL) {
+ ddlogMessage(DDLOG_INFO, "DirectDrawSurface QueryInterface unavialable\n");
+ }
+*/
+ // Dump some useful stats
+ hResult = IDirect3D8_GetAdapterIdentifier(
+ lpCtx->pD3D,
+ glb.dwAdapter,
+ D3DENUM_NO_WHQL_LEVEL, // Avoids 1 to 2 second delay
+ &d3dIdent);
+ if (SUCCEEDED(hResult)) {
+ ddlogPrintf(DDLOG_INFO, "[Driver Description: %s]", &d3dIdent.Description);
+ ddlogPrintf(DDLOG_INFO, "[Driver file: %s %d.%d.%02d.%d]",
+ d3dIdent.Driver,
+ HIWORD(d3dIdent.DriverVersion.HighPart),
+ LOWORD(d3dIdent.DriverVersion.HighPart),
+ HIWORD(d3dIdent.DriverVersion.LowPart),
+ LOWORD(d3dIdent.DriverVersion.LowPart));
+ ddlogPrintf(DDLOG_INFO, "[VendorId: 0x%X, DeviceId: 0x%X, SubSysId: 0x%X, Revision: 0x%X]",
+ d3dIdent.VendorId, d3dIdent.DeviceId, d3dIdent.SubSysId, d3dIdent.Revision);
+ }
+
+ // Init projection matrix for D3D TnL
+ D3DXMatrixIdentity(&lpCtx->matProjection);
+ lpCtx->matModelView = lpCtx->matProjection;
+// gld->bUseMesaProjection = TRUE;
+
+skip_direct3ddevice_create:
+
+ // Create buffers to hold primitives
+ lpCtx->PB2d.dwFVF = GLD_FVF_2D_VERTEX;
+ lpCtx->PB2d.dwPool = D3DPOOL_SYSTEMMEM;
+ lpCtx->PB2d.dwStride = sizeof(GLD_2D_VERTEX);
+ lpCtx->PB2d.dwUsage = D3DUSAGE_DONOTCLIP |
+ D3DUSAGE_DYNAMIC |
+ D3DUSAGE_SOFTWAREPROCESSING |
+ D3DUSAGE_WRITEONLY;
+ hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB2d);
+ if (FAILED(hResult))
+ goto return_with_error;
+
+ lpCtx->PB3d.dwFVF = GLD_FVF_3D_VERTEX;
+ lpCtx->PB3d.dwPool = D3DPOOL_DEFAULT;
+ lpCtx->PB3d.dwStride = sizeof(GLD_3D_VERTEX);
+ lpCtx->PB3d.dwUsage = D3DUSAGE_DYNAMIC |
+ D3DUSAGE_SOFTWAREPROCESSING |
+ D3DUSAGE_WRITEONLY;
+ hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB3d);
+ if (FAILED(hResult))
+ goto return_with_error;
+
+/* // NOTE: A FVF code of zero indicates a non-FVF vertex buffer (for vertex shaders)
+ lpCtx->PBtwosidelight.dwFVF = 0; //GLD_FVF_TWOSIDED_VERTEX;
+ lpCtx->PBtwosidelight.dwPool = D3DPOOL_DEFAULT;
+ lpCtx->PBtwosidelight.dwStride = sizeof(GLD_TWOSIDED_VERTEX);
+ lpCtx->PBtwosidelight.dwUsage = D3DUSAGE_DONOTCLIP |
+ D3DUSAGE_DYNAMIC |
+ D3DUSAGE_SOFTWAREPROCESSING |
+ D3DUSAGE_WRITEONLY;
+ hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PBtwosidelight);
+ if (FAILED(hResult))
+ goto return_with_error;*/
+
+ // Now try and create the DX8 Vertex Shaders
+// _gldCreateVertexShaders(lpCtx);
+
+ // Zero the pipeline usage counters
+ lpCtx->PipelineUsage.qwMesa.QuadPart =
+// lpCtx->PipelineUsage.dwD3D2SVS.QuadPart =
+ lpCtx->PipelineUsage.qwD3DFVF.QuadPart = 0;
+
+ // Assign drawable to GL private
+ ctx->glPriv = lpCtx;
+ return TRUE;
+
+return_with_error:
+ // Clean up and bail
+
+// _gldDestroyVertexShaders(lpCtx);
+
+// _gldDestroyPrimitiveBuffer(&lpCtx->PBtwosidelight);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB3d);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB2d);
+
+ SAFE_RELEASE(lpCtx->pDev);
+ SAFE_RELEASE(lpCtx->pD3D);
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldResizeDrawable_DX(
+ DGL_ctx *ctx,
+ BOOL bDefaultDriver,
+ BOOL bPersistantInterface,
+ BOOL bPersistantBuffers)
+{
+ GLD_driver_dx8 *gld = NULL;
+ D3DDEVTYPE d3dDevType;
+ D3DPRESENT_PARAMETERS d3dpp;
+ D3DDISPLAYMODE d3ddm;
+ HRESULT hResult;
+
+ // Error if context is NULL.
+ if (ctx == NULL)
+ return FALSE;
+
+ gld = ctx->glPriv;
+ if (gld == NULL)
+ return FALSE;
+
+ if (ctx->bSceneStarted) {
+ IDirect3DDevice8_EndScene(gld->pDev);
+ ctx->bSceneStarted = FALSE;
+ }
+
+ d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
+ if (!bDefaultDriver)
+ d3dDevType = D3DDEVTYPE_REF; // Force Direct3D Reference Rasterise (software)
+
+ // Get the display mode so we can make a compatible backbuffer
+ hResult = IDirect3D8_GetAdapterDisplayMode(gld->pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hResult)) {
+ nContextError = GLDERR_D3D;
+// goto return_with_error;
+ return FALSE;
+ }
+
+ // Destroy DX8 Vertex Shaders before Reset()
+// _gldDestroyVertexShaders(gld);
+
+ // Release POOL_DEFAULT objects before Reset()
+ if (gld->PB2d.dwPool == D3DPOOL_DEFAULT)
+ _gldDestroyPrimitiveBuffer(&gld->PB2d);
+ if (gld->PB3d.dwPool == D3DPOOL_DEFAULT)
+ _gldDestroyPrimitiveBuffer(&gld->PB3d);
+// if (gld->PBtwosidelight.dwPool == D3DPOOL_DEFAULT)
+// _gldDestroyPrimitiveBuffer(&gld->PBtwosidelight);
+
+ // Clear the presentation parameters (sets all members to zero)
+ ZeroMemory(&d3dpp, sizeof(d3dpp));
+
+ // Recommended by MS; needed for MultiSample.
+ // Be careful if altering this for FullScreenBlit
+ d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+
+ d3dpp.BackBufferFormat = d3ddm.Format;
+ d3dpp.BackBufferCount = 1;
+ d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(gld->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen);
+ d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData;
+ d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE;
+
+ // TODO: Sync to refresh
+
+ if (ctx->bFullscreen) {
+ ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen
+ d3dpp.Windowed = FALSE;
+ d3dpp.BackBufferWidth = d3ddm.Width;
+ d3dpp.BackBufferHeight = d3ddm.Height;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ // Get better benchmark results? KeithH
+// d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_UNLIMITED;
+ } else {
+ ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages
+ d3dpp.Windowed = TRUE;
+ d3dpp.BackBufferWidth = ctx->dwWidth;
+ d3dpp.BackBufferHeight = ctx->dwHeight;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = 0;
+ d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ }
+ hResult = IDirect3DDevice8_Reset(gld->pDev, &d3dpp);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Reset failed", hResult);
+ return FALSE;
+ //goto cleanup_and_return_with_error;
+ }
+
+ // Explicitly Clear resized surfaces (DaveM)
+ {
+ D3DVIEWPORT8 d3dvp1, d3dvp2;
+ IDirect3DDevice8_GetViewport(gld->pDev, &d3dvp1);
+ IDirect3DDevice8_GetViewport(gld->pDev, &d3dvp2);
+ d3dvp1.X = 0;
+ d3dvp1.Y = 0;
+ d3dvp1.Width = ctx->dwWidth;
+ d3dvp1.Height = ctx->dwHeight;
+ IDirect3DDevice8_SetViewport(gld->pDev, &d3dvp1);
+ IDirect3DDevice8_Clear(gld->pDev,0,NULL,D3DCLEAR_TARGET,0,0,0);
+ IDirect3DDevice8_SetViewport(gld->pDev, &d3dvp2);
+ }
+
+ //
+ // Recreate POOL_DEFAULT objects
+ //
+ if (gld->PB2d.dwPool == D3DPOOL_DEFAULT) {
+ _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB2d);
+ }
+ if (gld->PB3d.dwPool == D3DPOOL_DEFAULT) {
+ _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB3d);
+ }
+// if (gld->PBtwosidelight.dwPool == D3DPOOL_DEFAULT) {
+// _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB2d);
+// }
+
+ // Recreate DX8 Vertex Shaders
+// _gldCreateVertexShaders(gld);
+
+ // Signal a complete state update
+ ctx->glCtx->Driver.UpdateState(ctx->glCtx, _NEW_ALL);
+
+ // Begin a new scene
+ IDirect3DDevice8_BeginScene(gld->pDev);
+ ctx->bSceneStarted = TRUE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldDestroyDrawable_DX(
+ DGL_ctx *ctx)
+{
+ GLD_driver_dx8 *lpCtx = NULL;
+
+ // Error if context is NULL.
+ if (!ctx)
+ return FALSE;
+
+ // Error if the drawable does not exist.
+ if (!ctx->glPriv)
+ return FALSE;
+
+ lpCtx = ctx->glPriv;
+
+#ifdef _DEBUG
+ // Dump out stats
+ ddlogPrintf(DDLOG_SYSTEM, "Usage: M:0x%X%X, D:0x%X%X",
+ lpCtx->PipelineUsage.qwMesa.HighPart,
+ lpCtx->PipelineUsage.qwMesa.LowPart,
+ lpCtx->PipelineUsage.qwD3DFVF.HighPart,
+ lpCtx->PipelineUsage.qwD3DFVF.LowPart);
+#endif
+
+// _gldDestroyVertexShaders(lpCtx);
+
+// _gldDestroyPrimitiveBuffer(&lpCtx->PBtwosidelight);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB3d);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB2d);
+
+ SAFE_RELEASE(lpCtx->pDev);
+ SAFE_RELEASE(lpCtx->pD3D);
+
+ // Free the private drawable data
+ free(ctx->glPriv);
+ ctx->glPriv = NULL;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldCreatePrivateGlobals_DX(void)
+{
+ ZeroMemory(&dx8Globals, sizeof(dx8Globals));
+
+ // Load d3d8.dll
+ dx8Globals.hD3D8DLL = LoadLibrary("D3D8.DLL");
+ if (dx8Globals.hD3D8DLL == NULL)
+ return FALSE;
+
+ // Now try and obtain Direct3DCreate8
+ dx8Globals.fnDirect3DCreate8 = (FNDIRECT3DCREATE8)GetProcAddress(dx8Globals.hD3D8DLL, "Direct3DCreate8");
+ if (dx8Globals.fnDirect3DCreate8 == NULL) {
+ FreeLibrary(dx8Globals.hD3D8DLL);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldDestroyPrivateGlobals_DX(void)
+{
+ if (dx8Globals.bDirect3DDevice) {
+ SAFE_RELEASE(dx8Globals.pDev);
+ dx8Globals.bDirect3DDevice = FALSE;
+ }
+ if (dx8Globals.bDirect3D) {
+ SAFE_RELEASE(dx8Globals.pD3D);
+ dx8Globals.bDirect3D = FALSE;
+ }
+
+ FreeLibrary(dx8Globals.hD3D8DLL);
+ dx8Globals.hD3D8DLL = NULL;
+ dx8Globals.fnDirect3DCreate8 = NULL;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+static void _BitsFromDisplayFormat(
+ D3DFORMAT fmt,
+ BYTE *cColorBits,
+ BYTE *cRedBits,
+ BYTE *cGreenBits,
+ BYTE *cBlueBits,
+ BYTE *cAlphaBits)
+{
+ switch (fmt) {
+ case D3DFMT_X1R5G5B5:
+ *cColorBits = 16;
+ *cRedBits = 5;
+ *cGreenBits = 5;
+ *cBlueBits = 5;
+ *cAlphaBits = 0;
+ return;
+ case D3DFMT_R5G6B5:
+ *cColorBits = 16;
+ *cRedBits = 5;
+ *cGreenBits = 6;
+ *cBlueBits = 5;
+ *cAlphaBits = 0;
+ return;
+ case D3DFMT_X8R8G8B8:
+ *cColorBits = 32;
+ *cRedBits = 8;
+ *cGreenBits = 8;
+ *cBlueBits = 8;
+ *cAlphaBits = 0;
+ return;
+ case D3DFMT_A8R8G8B8:
+ *cColorBits = 32;
+ *cRedBits = 8;
+ *cGreenBits = 8;
+ *cBlueBits = 8;
+ *cAlphaBits = 8;
+ return;
+ }
+
+ // Should not get here!
+ *cColorBits = 32;
+ *cRedBits = 8;
+ *cGreenBits = 8;
+ *cBlueBits = 8;
+ *cAlphaBits = 0;
+}
+
+//---------------------------------------------------------------------------
+
+static void _BitsFromDepthStencilFormat(
+ D3DFORMAT fmt,
+ BYTE *cDepthBits,
+ BYTE *cStencilBits)
+{
+ // NOTE: GL expects either 32 or 16 as depth bits.
+ switch (fmt) {
+ case D3DFMT_D32:
+ *cDepthBits = 32;
+ *cStencilBits = 0;
+ return;
+ case D3DFMT_D15S1:
+ *cDepthBits = 16;
+ *cStencilBits = 1;
+ return;
+ case D3DFMT_D24S8:
+ *cDepthBits = 32;
+ *cStencilBits = 8;
+ return;
+ case D3DFMT_D16:
+ *cDepthBits = 16;
+ *cStencilBits = 0;
+ return;
+ case D3DFMT_D24X8:
+ *cDepthBits = 32;
+ *cStencilBits = 0;
+ return;
+ case D3DFMT_D24X4S4:
+ *cDepthBits = 32;
+ *cStencilBits = 4;
+ return;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldBuildPixelformatList_DX(void)
+{
+ D3DDISPLAYMODE d3ddm;
+ D3DFORMAT fmt[6];
+ IDirect3D8 *pD3D = NULL;
+ HRESULT hr;
+ int nSupportedFormats = 0;
+ int i;
+ DGL_pixelFormat *pPF;
+ BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits;
+// char buf[128];
+// char cat[8];
+
+ // Direct3D (SW or HW)
+ // These are arranged so that 'best' pixelformat
+ // is higher in the list (for ChoosePixelFormat).
+ const D3DFORMAT DepthStencil[6] = {
+ D3DFMT_D15S1,
+ D3DFMT_D16,
+ D3DFMT_D24X8,
+ D3DFMT_D24X4S4,
+ D3DFMT_D24S8,
+ D3DFMT_D32,
+ };
+
+ // Dump DX version
+ ddlogMessage(GLDLOG_SYSTEM, "DirectX Version : 8.0\n");
+
+ // Release any existing pixelformat list
+ if (glb.lpPF) {
+ free(glb.lpPF);
+ }
+
+ glb.nPixelFormatCount = 0;
+ glb.lpPF = NULL;
+
+ //
+ // Pixelformats for Direct3D (SW or HW) rendering
+ //
+
+ // Get a Direct3D 8.0 interface
+ pD3D = dx8Globals.fnDirect3DCreate8(D3D_SDK_VERSION_DX8_SUPPORT_WIN95);
+ if (!pD3D) {
+ return FALSE;
+ }
+
+ // We will use the display mode format when finding compliant
+ // rendertarget/depth-stencil surfaces.
+ hr = IDirect3D8_GetAdapterDisplayMode(pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hr)) {
+ IDirect3D8_Release(pD3D);
+ return FALSE;
+ }
+
+ // Run through the possible formats and detect supported formats
+ for (i=0; i<6; i++) {
+ hr = IDirect3D8_CheckDeviceFormat(
+ pD3D,
+ glb.dwAdapter,
+ glb.dwDriver==GLDS_DRIVER_HAL ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF,
+ d3ddm.Format,
+ D3DUSAGE_DEPTHSTENCIL,
+ D3DRTYPE_SURFACE,
+ DepthStencil[i]);
+ if (FAILED(hr))
+ // A failure here is not fatal.
+ continue;
+
+ // Verify that the depth format is compatible.
+ hr = IDirect3D8_CheckDepthStencilMatch(
+ pD3D,
+ glb.dwAdapter,
+ glb.dwDriver==GLDS_DRIVER_HAL ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF,
+ d3ddm.Format,
+ d3ddm.Format,
+ DepthStencil[i]);
+ if (FAILED(hr))
+ // A failure here is not fatal, just means depth-stencil
+ // format is not compatible with this display mode.
+ continue;
+
+ fmt[nSupportedFormats++] = DepthStencil[i];
+ }
+
+ IDirect3D8_Release(pD3D);
+
+ if (nSupportedFormats == 0)
+ return FALSE; // Bail: no compliant pixelformats
+
+ // Total count of pixelformats is:
+ // (nSupportedFormats+1)*2
+ glb.lpPF = (DGL_pixelFormat *)calloc((nSupportedFormats)*2, sizeof(DGL_pixelFormat));
+ glb.nPixelFormatCount = (nSupportedFormats)*2;
+ if (glb.lpPF == NULL) {
+ glb.nPixelFormatCount = 0;
+ return FALSE;
+ }
+
+ // Get a copy of pointer that we can alter
+ pPF = glb.lpPF;
+
+ // Cache colour bits from display format
+ _BitsFromDisplayFormat(d3ddm.Format, &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits);
+
+ //
+ // Add single-buffer formats
+ //
+
+ // Single-buffer, no depth-stencil buffer
+/* memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ pPF->pfd.cDepthBits = 0;
+ pPF->pfd.cStencilBits = 0;
+ pPF->dwDriverData = D3DFMT_UNKNOWN;
+ pPF++;*/
+
+ for (i=0; i<nSupportedFormats; i++, pPF++) {
+ memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits);
+ pPF->dwDriverData = fmt[i];
+ }
+
+ //
+ // Add double-buffer formats
+ //
+
+/* memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ pPF->pfd.cDepthBits = 0;
+ pPF->pfd.cStencilBits = 0;
+ pPF->dwDriverData = D3DFMT_UNKNOWN;
+ pPF++;*/
+
+ for (i=0; i<nSupportedFormats; i++, pPF++) {
+ memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits);
+ pPF->dwDriverData = fmt[i];
+ }
+
+ // Popup warning message if non RGB color mode
+ {
+ // This is a hack. KeithH
+ HDC hdcDesktop = GetDC(NULL);
+ DWORD dwDisplayBitDepth = GetDeviceCaps(hdcDesktop, BITSPIXEL);
+ ReleaseDC(0, hdcDesktop);
+ if (dwDisplayBitDepth <= 8) {
+ ddlogPrintf(DDLOG_WARN, "Current Color Depth %d bpp is not supported", dwDisplayBitDepth);
+ MessageBox(NULL, szColorDepthWarning, "GLDirect", MB_OK | MB_ICONWARNING);
+ }
+ }
+
+ // Mark list as 'current'
+ glb.bPixelformatsDirty = FALSE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldInitialiseMesa_DX(
+ DGL_ctx *lpCtx)
+{
+ GLD_driver_dx8 *gld = NULL;
+ int MaxTextureSize, TextureLevels;
+ BOOL bSoftwareTnL;
+
+ if (lpCtx == NULL)
+ return FALSE;
+
+ gld = lpCtx->glPriv;
+ if (gld == NULL)
+ return FALSE;
+
+ if (glb.bMultitexture) {
+ lpCtx->glCtx->Const.MaxTextureUnits = gld->d3dCaps8.MaxSimultaneousTextures;
+ // Only support MAX_TEXTURE_UNITS texture units.
+ // ** If this is altered then the FVF formats must be reviewed **.
+ if (lpCtx->glCtx->Const.MaxTextureUnits > GLD_MAX_TEXTURE_UNITS_DX8)
+ lpCtx->glCtx->Const.MaxTextureUnits = GLD_MAX_TEXTURE_UNITS_DX8;
+ } else {
+ // Multitexture override
+ lpCtx->glCtx->Const.MaxTextureUnits = 1;
+ }
+
+ // max texture size
+ MaxTextureSize = min(gld->d3dCaps8.MaxTextureHeight, gld->d3dCaps8.MaxTextureWidth);
+ if (MaxTextureSize == 0)
+ MaxTextureSize = 256; // Sanity check
+
+ //
+ // HACK!!
+ if (MaxTextureSize > 1024)
+ MaxTextureSize = 1024; // HACK - CLAMP TO 1024
+ // HACK!!
+ //
+
+ // Got to set MAX_TEXTURE_SIZE as max levels.
+ // Who thought this stupid idea up? ;)
+ TextureLevels = 0;
+ // Calculate power-of-two.
+ while (MaxTextureSize) {
+ TextureLevels++;
+ MaxTextureSize >>= 1;
+ }
+ lpCtx->glCtx->Const.MaxTextureLevels = (TextureLevels) ? TextureLevels : 8;
+
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_LIGHTING, FALSE);
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_CULLMODE, D3DCULL_NONE);
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_DITHERENABLE, TRUE);
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
+
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_ZENABLE,
+ (lpCtx->lpPF->dwDriverData!=D3DFMT_UNKNOWN) ? D3DZB_TRUE : D3DZB_FALSE);
+
+ // Set the view matrix
+ {
+ D3DXMATRIX vm;
+#if 1
+ D3DXMatrixIdentity(&vm);
+#else
+ D3DXVECTOR3 Eye(0.0f, 0.0f, 0.0f);
+ D3DXVECTOR3 At(0.0f, 0.0f, -1.0f);
+ D3DXVECTOR3 Up(0.0f, 1.0f, 0.0f);
+ D3DXMatrixLookAtRH(&vm, &Eye, &At, &Up);
+ vm._31 = -vm._31;
+ vm._32 = -vm._32;
+ vm._33 = -vm._33;
+ vm._34 = -vm._34;
+#endif
+ IDirect3DDevice8_SetTransform(gld->pDev, D3DTS_VIEW, &vm);
+ }
+
+ if (gld->bHasHWTnL) {
+ if (glb.dwTnL == GLDS_TNL_DEFAULT)
+ bSoftwareTnL = FALSE; // HW TnL
+ else {
+ bSoftwareTnL = ((glb.dwTnL == GLDS_TNL_MESA) || (glb.dwTnL == GLDS_TNL_D3DSW)) ? TRUE : FALSE;
+ }
+ } else {
+ // No HW TnL, so no choice possible
+ bSoftwareTnL = TRUE;
+ }
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, bSoftwareTnL);
+
+// Dump this in a Release build as well, now.
+//#ifdef _DEBUG
+ ddlogPrintf(DDLOG_INFO, "HW TnL: %s",
+ gld->bHasHWTnL ? (bSoftwareTnL ? "Disabled" : "Enabled") : "Unavailable");
+//#endif
+
+ gldEnableExtensions_DX8(lpCtx->glCtx);
+ gldInstallPipeline_DX8(lpCtx->glCtx);
+ gldSetupDriverPointers_DX8(lpCtx->glCtx);
+
+ // Signal a complete state update
+ lpCtx->glCtx->Driver.UpdateState(lpCtx->glCtx, _NEW_ALL);
+
+ // Start a scene
+ IDirect3DDevice8_BeginScene(gld->pDev);
+ lpCtx->bSceneStarted = TRUE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldSwapBuffers_DX(
+ DGL_ctx *ctx,
+ HDC hDC,
+ HWND hWnd)
+{
+ HRESULT hr;
+ GLD_driver_dx8 *gld = NULL;
+
+ if (ctx == NULL)
+ return FALSE;
+
+ gld = ctx->glPriv;
+ if (gld == NULL)
+ return FALSE;
+
+ if (ctx->bSceneStarted) {
+ IDirect3DDevice8_EndScene(gld->pDev);
+ ctx->bSceneStarted = FALSE;
+ }
+
+ // Swap the buffers. hWnd may override the hWnd used for CreateDevice()
+ hr = IDirect3DDevice8_Present(gld->pDev, NULL, NULL, hWnd, NULL);
+
+ IDirect3DDevice8_BeginScene(gld->pDev);
+ ctx->bSceneStarted = TRUE;
+
+ return (FAILED(hr)) ? FALSE : TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldGetDisplayMode_DX(
+ DGL_ctx *ctx,
+ GLD_displayMode *glddm)
+{
+ D3DDISPLAYMODE d3ddm;
+ HRESULT hr;
+ GLD_driver_dx8 *lpCtx = NULL;
+ BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits;
+
+ if ((glddm == NULL) || (ctx == NULL))
+ return FALSE;
+
+ lpCtx = ctx->glPriv;
+ if (lpCtx == NULL)
+ return FALSE;
+
+ if (lpCtx->pD3D == NULL)
+ return FALSE;
+
+ hr = IDirect3D8_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hr))
+ return FALSE;
+
+ // Get info from the display format
+ _BitsFromDisplayFormat(d3ddm.Format,
+ &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits);
+
+ glddm->Width = d3ddm.Width;
+ glddm->Height = d3ddm.Height;
+ glddm->BPP = cColorBits;
+ glddm->Refresh = d3ddm.RefreshRate;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c
new file mode 100644
index 0000000000..96ad213f17
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_driver_dx9.c
@@ -0,0 +1,1205 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Driver interface code to Mesa
+*
+****************************************************************************/
+
+//#include <windows.h>
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx9.h"
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "array_cache/acache.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast_setup/ss_context.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+extern BOOL dglSwapBuffers(HDC hDC);
+
+// HACK: Hack the _33 member of the OpenGL perspective projection matrix
+const float _fPersp_33 = 1.6f;
+
+//---------------------------------------------------------------------------
+// Internal functions
+//---------------------------------------------------------------------------
+
+void _gld_mesa_warning(
+ __GLcontext *gc,
+ char *str)
+{
+ // Intercept Mesa's internal warning mechanism
+ gldLogPrintf(GLDLOG_WARN, "Mesa warning: %s", str);
+}
+
+//---------------------------------------------------------------------------
+
+void _gld_mesa_fatal(
+ __GLcontext *gc,
+ char *str)
+{
+ // Intercept Mesa's internal fatal-message mechanism
+ gldLogPrintf(GLDLOG_CRITICAL, "Mesa FATAL: %s", str);
+
+ // Mesa calls abort(0) here.
+ ddlogClose();
+ exit(0);
+}
+
+//---------------------------------------------------------------------------
+
+D3DSTENCILOP _gldConvertStencilOp(
+ GLenum StencilOp)
+{
+ // Used by Stencil: pass, fail and zfail
+
+ switch (StencilOp) {
+ case GL_KEEP:
+ return D3DSTENCILOP_KEEP;
+ case GL_ZERO:
+ return D3DSTENCILOP_ZERO;
+ case GL_REPLACE:
+ return D3DSTENCILOP_REPLACE;
+ case GL_INCR:
+ return D3DSTENCILOP_INCRSAT;
+ case GL_DECR:
+ return D3DSTENCILOP_DECRSAT;
+ case GL_INVERT:
+ return D3DSTENCILOP_INVERT;
+ case GL_INCR_WRAP_EXT: // GL_EXT_stencil_wrap
+ return D3DSTENCILOP_INCR;
+ case GL_DECR_WRAP_EXT: // GL_EXT_stencil_wrap
+ return D3DSTENCILOP_DECR;
+ }
+
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "_gldConvertStencilOp: Unknown StencilOp\n");
+#endif
+
+ return D3DSTENCILOP_KEEP;
+}
+
+//---------------------------------------------------------------------------
+
+D3DCMPFUNC _gldConvertCompareFunc(
+ GLenum CmpFunc)
+{
+ // Used for Alpha func, depth func and stencil func.
+
+ switch (CmpFunc) {
+ case GL_NEVER:
+ return D3DCMP_NEVER;
+ case GL_LESS:
+ return D3DCMP_LESS;
+ case GL_EQUAL:
+ return D3DCMP_EQUAL;
+ case GL_LEQUAL:
+ return D3DCMP_LESSEQUAL;
+ case GL_GREATER:
+ return D3DCMP_GREATER;
+ case GL_NOTEQUAL:
+ return D3DCMP_NOTEQUAL;
+ case GL_GEQUAL:
+ return D3DCMP_GREATEREQUAL;
+ case GL_ALWAYS:
+ return D3DCMP_ALWAYS;
+ };
+
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "_gldConvertCompareFunc: Unknown CompareFunc\n");
+#endif
+
+ return D3DCMP_ALWAYS;
+}
+
+//---------------------------------------------------------------------------
+
+D3DBLEND _gldConvertBlendFunc(
+ GLenum blend,
+ GLenum DefaultBlend)
+{
+ switch (blend) {
+ case GL_ZERO:
+ return D3DBLEND_ZERO;
+ case GL_ONE:
+ return D3DBLEND_ONE;
+ case GL_DST_COLOR:
+ return D3DBLEND_DESTCOLOR;
+ case GL_SRC_COLOR:
+ return D3DBLEND_SRCCOLOR;
+ case GL_ONE_MINUS_DST_COLOR:
+ return D3DBLEND_INVDESTCOLOR;
+ case GL_ONE_MINUS_SRC_COLOR:
+ return D3DBLEND_INVSRCCOLOR;
+ case GL_SRC_ALPHA:
+ return D3DBLEND_SRCALPHA;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ return D3DBLEND_INVSRCALPHA;
+ case GL_DST_ALPHA:
+ return D3DBLEND_DESTALPHA;
+ case GL_ONE_MINUS_DST_ALPHA:
+ return D3DBLEND_INVDESTALPHA;
+ case GL_SRC_ALPHA_SATURATE:
+ return D3DBLEND_SRCALPHASAT;
+ }
+
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "_gldConvertBlendFunc: Unknown BlendFunc\n");
+#endif
+
+ return DefaultBlend;
+}
+
+//---------------------------------------------------------------------------
+// Misc. functions
+//---------------------------------------------------------------------------
+
+void gld_Noop_DX9(
+ GLcontext *ctx)
+{
+#ifdef _DEBUG
+ gldLogMessage(GLDLOG_ERROR, "gld_Noop called!\n");
+#endif
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Error_DX9(
+ GLcontext *ctx)
+{
+#ifdef _DEBUG
+ // Quite useless.
+// gldLogMessage(GLDLOG_ERROR, "ctx->Driver.Error called!\n");
+#endif
+}
+
+//---------------------------------------------------------------------------
+// Required Mesa functions
+//---------------------------------------------------------------------------
+
+static GLboolean gld_set_draw_buffer_DX9(
+ GLcontext *ctx,
+ GLenum mode)
+{
+ (void) ctx;
+ if ((mode==GL_FRONT_LEFT) || (mode == GL_BACK_LEFT)) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_set_read_buffer_DX9(
+ GLcontext *ctx,
+ GLframebuffer *buffer,
+ GLenum mode)
+{
+ /* separate read buffer not supported */
+/*
+ ASSERT(buffer == ctx->DrawBuffer);
+ ASSERT(mode == GL_FRONT_LEFT);
+*/
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Clear_DX9(
+ GLcontext *ctx,
+ GLbitfield mask,
+ GLboolean all,
+ GLint x,
+ GLint y,
+ GLint width,
+ GLint height)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ DWORD dwFlags = 0;
+ D3DCOLOR Color = 0;
+ float Z = 0.0f;
+ DWORD Stencil = 0;
+ D3DRECT d3dClearRect;
+
+ // TODO: Colourmask
+ const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
+
+ if (!gld->pDev)
+ return;
+
+ if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) {
+ GLubyte col[4];
+ CLAMPED_FLOAT_TO_UBYTE(col[0], ctx->Color.ClearColor[0]);
+ CLAMPED_FLOAT_TO_UBYTE(col[1], ctx->Color.ClearColor[1]);
+ CLAMPED_FLOAT_TO_UBYTE(col[2], ctx->Color.ClearColor[2]);
+ CLAMPED_FLOAT_TO_UBYTE(col[3], ctx->Color.ClearColor[3]);
+ dwFlags |= D3DCLEAR_TARGET;
+ Color = D3DCOLOR_RGBA(col[0], col[1], col[2], col[3]);
+ }
+
+ if (mask & DD_DEPTH_BIT) {
+ // D3D8 will fail the Clear call if we try and clear a
+ // depth buffer and we haven't created one.
+ // Also, some apps try and clear a depth buffer,
+ // when a depth buffer hasn't been requested by the app.
+ if (ctx->Visual.depthBits == 0) {
+ mask &= ~DD_DEPTH_BIT; // Remove depth bit from mask
+ } else {
+ dwFlags |= D3DCLEAR_ZBUFFER;
+ Z = ctx->Depth.Clear;
+ }
+ }
+
+ if (mask & DD_STENCIL_BIT) {
+ if (ctx->Visual.stencilBits == 0) {
+ // No stencil bits in depth buffer
+ mask &= ~DD_STENCIL_BIT; // Remove stencil bit from mask
+ } else {
+ dwFlags |= D3DCLEAR_STENCIL;
+ Stencil = ctx->Stencil.Clear;
+ }
+ }
+
+ // Some apps do really weird things with the rect, such as Quake3.
+ if ((x < 0) || (y < 0) || (width <= 0) || (height <= 0)) {
+ all = GL_TRUE;
+ }
+
+ if (!all) {
+ // Calculate clear subrect
+ d3dClearRect.x1 = x;
+ d3dClearRect.y1 = gldCtx->dwHeight - (y + height);
+ d3dClearRect.x2 = x + width;
+ d3dClearRect.y2 = d3dClearRect.y1 + height;
+// gldLogPrintf(GLDLOG_INFO, "Rect %d,%d %d,%d", x,y,width,height);
+ }
+
+ // dwFlags will be zero if there's nothing to clear
+ if (dwFlags) {
+ _GLD_DX9_DEV(Clear(
+ gld->pDev,
+ all ? 0 : 1,
+ all ? NULL : &d3dClearRect,
+ dwFlags,
+ Color, Z, Stencil));
+ }
+
+ if (mask & DD_ACCUM_BIT) {
+ // Clear accumulation buffer
+ }
+}
+
+//---------------------------------------------------------------------------
+
+// Mesa 5: Parameter change
+static void gld_buffer_size_DX9(
+// GLcontext *ctx,
+ GLframebuffer *fb,
+ GLuint *width,
+ GLuint *height)
+{
+// GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+
+ *width = fb->Width; // gldCtx->dwWidth;
+ *height = fb->Height; // gldCtx->dwHeight;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_Finish_DX9(
+ GLcontext *ctx)
+{
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_Flush_DX9(
+ GLcontext *ctx)
+{
+ GLD_context *gld = GLD_GET_CONTEXT(ctx);
+
+ // TODO: Detect apps that glFlush() then SwapBuffers() ?
+
+ if (gld->EmulateSingle) {
+ // Emulating a single-buffered context.
+ // [Direct3D doesn't allow rendering to front buffer]
+ dglSwapBuffers(gld->hDC);
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_STENCIL(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ // Two-sided stencil. New for Mesa 5
+ const GLuint uiFace = 0UL;
+
+ struct gl_stencil_attrib *pStencil = &ctx->Stencil;
+
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILENABLE, pStencil->Enabled ? TRUE : FALSE));
+ if (pStencil->Enabled) {
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILFUNC, _gldConvertCompareFunc(pStencil->Function[uiFace])));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILREF, pStencil->Ref[uiFace]));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILMASK, pStencil->ValueMask[uiFace]));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILWRITEMASK, pStencil->WriteMask[uiFace]));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILFAIL, _gldConvertStencilOp(pStencil->FailFunc[uiFace])));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILZFAIL, _gldConvertStencilOp(pStencil->ZFailFunc[uiFace])));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_STENCILPASS, _gldConvertStencilOp(pStencil->ZPassFunc[uiFace])));
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_COLOR(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ DWORD dwFlags = 0;
+ D3DBLEND src;
+ D3DBLEND dest;
+
+ // Alpha func
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ALPHAFUNC, _gldConvertCompareFunc(ctx->Color.AlphaFunc)));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ALPHAREF, (DWORD)ctx->Color.AlphaRef));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ALPHATESTENABLE, ctx->Color.AlphaEnabled));
+
+ // Blend func
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ALPHABLENDENABLE, ctx->Color.BlendEnabled));
+ src = _gldConvertBlendFunc(ctx->Color.BlendSrcRGB, GL_ONE);
+ dest = _gldConvertBlendFunc(ctx->Color.BlendDstRGB, GL_ZERO);
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SRCBLEND, src));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_DESTBLEND, dest));
+
+ // Color mask
+ if (ctx->Color.ColorMask[0]) dwFlags |= D3DCOLORWRITEENABLE_RED;
+ if (ctx->Color.ColorMask[1]) dwFlags |= D3DCOLORWRITEENABLE_GREEN;
+ if (ctx->Color.ColorMask[2]) dwFlags |= D3DCOLORWRITEENABLE_BLUE;
+ if (ctx->Color.ColorMask[3]) dwFlags |= D3DCOLORWRITEENABLE_ALPHA;
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_COLORWRITEENABLE, dwFlags));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_DEPTH(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ZENABLE, ctx->Depth.Test ? D3DZB_TRUE : D3DZB_FALSE));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ZFUNC, _gldConvertCompareFunc(ctx->Depth.Func)));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_ZWRITEENABLE, ctx->Depth.Mask ? TRUE : FALSE));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_POLYGON(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ D3DFILLMODE d3dFillMode = D3DFILL_SOLID;
+ D3DCULL d3dCullMode = D3DCULL_NONE;
+ float fOffset = 0; // Changed from int to float for DX9
+
+ // Fillmode
+ switch (ctx->Polygon.FrontMode) {
+ case GL_POINT:
+ d3dFillMode = D3DFILL_POINT;
+ break;
+ case GL_LINE:
+ d3dFillMode = D3DFILL_WIREFRAME;
+ break;
+ case GL_FILL:
+ d3dFillMode = D3DFILL_SOLID;
+ break;
+ }
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FILLMODE, d3dFillMode));
+
+ if (ctx->Polygon.CullFlag) {
+ switch (ctx->Polygon.CullFaceMode) {
+ case GL_BACK:
+ if (ctx->Polygon.FrontFace == GL_CCW)
+ d3dCullMode = D3DCULL_CW;
+ else
+ d3dCullMode = D3DCULL_CCW;
+ break;
+ case GL_FRONT:
+ if (ctx->Polygon.FrontFace == GL_CCW)
+ d3dCullMode = D3DCULL_CCW;
+ else
+ d3dCullMode = D3DCULL_CW;
+ break;
+ case GL_FRONT_AND_BACK:
+ d3dCullMode = D3DCULL_NONE;
+ break;
+ default:
+ break;
+ }
+ } else {
+ d3dCullMode = D3DCULL_NONE;
+ }
+// d3dCullMode = D3DCULL_NONE; // FOR DEBUGGING
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_CULLMODE, d3dCullMode));
+
+ // Polygon offset
+ // ZBIAS ranges from 0 to 16 and can only move towards the viewer
+ // Mesa5: ctx->Polygon._OffsetAny removed
+ if (ctx->Polygon.OffsetFill) {
+ fOffset = ctx->Polygon.OffsetUnits;
+// if (iOffset < 0.0f)
+// iOffset = -iOffset;
+// else
+// iOffset = 0.0f; // D3D can't push away
+ }
+ // NOTE: SetRenderState() required a DWORD, so need to cast
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_DEPTHBIAS, *((DWORD*)&fOffset)));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_FOG(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ D3DCOLOR d3dFogColour;
+ D3DFOGMODE d3dFogMode = D3DFOG_LINEAR;
+
+ // TODO: Fog is calculated seperately in the Mesa pipeline
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGENABLE, FALSE));
+ return;
+
+ // Fog enable
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGENABLE, ctx->Fog.Enabled));
+ if (!ctx->Fog.Enabled) {
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGTABLEMODE, D3DFOG_NONE));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGVERTEXMODE, D3DFOG_NONE));
+ return; // If disabled, don't bother setting any fog state
+ }
+
+ // Fog colour
+ d3dFogColour = D3DCOLOR_COLORVALUE( ctx->Fog.Color[0],
+ ctx->Fog.Color[1],
+ ctx->Fog.Color[2],
+ ctx->Fog.Color[3]);
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGCOLOR, d3dFogColour));
+
+ // Fog density
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGDENSITY, *((DWORD*) (&ctx->Fog.Density))));
+
+ // Fog start
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGSTART, *((DWORD*) (&ctx->Fog.Start))));
+
+ // Fog end
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGEND, *((DWORD*) (&ctx->Fog.End))));
+
+ // Fog mode
+ switch (ctx->Fog.Mode) {
+ case GL_LINEAR:
+ d3dFogMode = D3DFOG_LINEAR;
+ break;
+ case GL_EXP:
+ d3dFogMode = D3DFOG_EXP;
+ break;
+ case GL_EXP2:
+ d3dFogMode = D3DFOG_EXP2;
+ break;
+ }
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGTABLEMODE, d3dFogMode));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_FOGVERTEXMODE, D3DFOG_NONE));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_LIGHT(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+ DWORD dwSpecularEnable;
+
+ // Shademode
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SHADEMODE, (ctx->Light.ShadeModel == GL_SMOOTH) ? D3DSHADE_GOURAUD : D3DSHADE_FLAT));
+
+ // Separate specular colour
+ if (ctx->Light.Enabled)
+ dwSpecularEnable = (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) ? TRUE: FALSE;
+ else
+ dwSpecularEnable = FALSE;
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SPECULARENABLE, dwSpecularEnable));
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_MODELVIEW(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ D3DMATRIX m;
+ //GLfloat *pM = ctx->ModelView.m;
+ // Mesa5: Model-view is now a stack
+ GLfloat *pM = ctx->ModelviewMatrixStack.Top->m;
+ m._11 = pM[0];
+ m._12 = pM[1];
+ m._13 = pM[2];
+ m._14 = pM[3];
+ m._21 = pM[4];
+ m._22 = pM[5];
+ m._23 = pM[6];
+ m._24 = pM[7];
+ m._31 = pM[8];
+ m._32 = pM[9];
+ m._33 = pM[10];
+ m._34 = pM[11];
+ m._41 = pM[12];
+ m._42 = pM[13];
+ m._43 = pM[14];
+ m._44 = pM[15];
+
+ gld->matModelView = m;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_PROJECTION(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ D3DMATRIX m;
+ //GLfloat *pM = ctx->ProjectionMatrix.m;
+ // Mesa 5: Now a stack
+ GLfloat *pM = ctx->ProjectionMatrixStack.Top->m;
+ m._11 = pM[0];
+ m._12 = pM[1];
+ m._13 = pM[2];
+ m._14 = pM[3];
+
+ m._21 = pM[4];
+ m._22 = pM[5];
+ m._23 = pM[6];
+ m._24 = pM[7];
+
+ m._31 = pM[8];
+ m._32 = pM[9];
+ m._33 = pM[10] / _fPersp_33; // / 1.6f;
+ m._34 = pM[11];
+
+ m._41 = pM[12];
+ m._42 = pM[13];
+ m._43 = pM[14] / 2.0f;
+ m._44 = pM[15];
+
+ gld->matProjection = m;
+}
+
+//---------------------------------------------------------------------------
+/*
+void gldFrustumHook_DX9(
+ GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top,
+ GLdouble nearval,
+ GLdouble farval)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ // Pass values on to Mesa first (in case we mess with them)
+ _mesa_Frustum(left, right, bottom, top, nearval, farval);
+
+ _fPersp_33 = farval / (nearval - farval);
+
+// ddlogPrintf(GLDLOG_SYSTEM, "Frustum: %f", farval/nearval);
+}
+
+//---------------------------------------------------------------------------
+
+void gldOrthoHook_DX9(
+ GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top,
+ GLdouble nearval,
+ GLdouble farval)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ // Pass values on to Mesa first (in case we mess with them)
+ _mesa_Ortho(left, right, bottom, top, nearval, farval);
+
+ _fPersp_33 = 1.6f;
+
+// ddlogPrintf(GLDLOG_SYSTEM, "Ortho: %f", farval/nearval);
+}
+*/
+//---------------------------------------------------------------------------
+
+void gld_NEW_VIEWPORT(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ D3DVIEWPORT9 d3dvp;
+// GLint x, y;
+// GLsizei w, h;
+
+ // Set depth range
+ _GLD_DX9_DEV(GetViewport(gld->pDev, &d3dvp));
+ // D3D can't do Quake1/Quake2 z-trick
+ if (ctx->Viewport.Near <= ctx->Viewport.Far) {
+ d3dvp.MinZ = ctx->Viewport.Near;
+ d3dvp.MaxZ = ctx->Viewport.Far;
+ } else {
+ d3dvp.MinZ = ctx->Viewport.Far;
+ d3dvp.MaxZ = ctx->Viewport.Near;
+ }
+/* x = ctx->Viewport.X;
+ y = ctx->Viewport.Y;
+ w = ctx->Viewport.Width;
+ h = ctx->Viewport.Height;
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (w > gldCtx->dwWidth) w = gldCtx->dwWidth;
+ if (h > gldCtx->dwHeight) h = gldCtx->dwHeight;
+ // Ditto for D3D viewport dimensions
+ if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x;
+ if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y;
+ d3dvp.X = x;
+ d3dvp.Y = gldCtx->dwHeight - (y + h);
+ d3dvp.Width = w;
+ d3dvp.Height = h;*/
+ _GLD_DX9_DEV(SetViewport(gld->pDev, &d3dvp));
+
+// gld->fFlipWindowY = (float)gldCtx->dwHeight;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_SCISSOR(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ // Bail if IHV driver cannot scissor
+ if (!gld->bCanScissor)
+ return;
+
+ // Set scissor rect
+ if (ctx->Scissor.Enabled) {
+ RECT rcRect;
+ // Keep in mind that RECT's need an extra row and column
+ rcRect.left = ctx->Scissor.X;
+ rcRect.right = ctx->Scissor.X + ctx->Scissor.Width; // + 1;
+ rcRect.top = gldCtx->dwHeight - (ctx->Scissor.Y + ctx->Scissor.Height);
+ rcRect.bottom = rcRect.top + ctx->Scissor.Height;
+ IDirect3DDevice9_SetScissorRect(gld->pDev, &rcRect);
+ }
+
+ // Enable/disable scissor as required
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SCISSORTESTENABLE, ctx->Scissor.Enabled));
+}
+
+//---------------------------------------------------------------------------
+
+__inline BOOL _gldAnyEvalEnabled(
+ GLcontext *ctx)
+{
+ struct gl_eval_attrib *eval = &ctx->Eval;
+
+ if ((eval->AutoNormal) ||
+ (eval->Map1Color4) ||
+ (eval->Map1Index) ||
+ (eval->Map1Normal) ||
+ (eval->Map1TextureCoord1) ||
+ (eval->Map1TextureCoord2) ||
+ (eval->Map1TextureCoord3) ||
+ (eval->Map1TextureCoord4) ||
+ (eval->Map1Vertex3) ||
+ (eval->Map1Vertex4) ||
+ (eval->Map2Color4) ||
+ (eval->Map2Index) ||
+ (eval->Map2Normal) ||
+ (eval->Map2TextureCoord1) ||
+ (eval->Map2TextureCoord2) ||
+ (eval->Map2TextureCoord3) ||
+ (eval->Map2TextureCoord4) ||
+ (eval->Map2Vertex3) ||
+ (eval->Map2Vertex4)
+ )
+ return TRUE;
+
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL _gldChooseInternalPipeline(
+ GLcontext *ctx,
+ GLD_driver_dx9 *gld)
+{
+// return TRUE; // DEBUGGING: ALWAYS USE MESA
+// return FALSE; // DEBUGGING: ALWAYS USE D3D
+
+ if ((glb.dwTnL == GLDS_TNL_MESA) || (gld->bHasHWTnL == FALSE))
+ {
+ gld->PipelineUsage.qwMesa.QuadPart++;
+ return TRUE; // Force Mesa TnL
+ }
+
+ if ((ctx->Light.Enabled) ||
+ (1) ||
+ (ctx->Texture._TexGenEnabled) ||
+ (ctx->Texture._TexMatEnabled) ||
+// (ctx->Transform._AnyClip) ||
+ (ctx->Scissor.Enabled) ||
+ _gldAnyEvalEnabled(ctx) // Put this last so we can early-out
+ )
+ {
+ gld->PipelineUsage.qwMesa.QuadPart++;
+ return TRUE;
+ }
+
+ gld->PipelineUsage.qwD3DFVF.QuadPart++;
+ return FALSE;
+
+/* // Force Mesa pipeline?
+ if (glb.dwTnL == GLDS_TNL_MESA) {
+ gld->PipelineUsage.dwMesa.QuadPart++;
+ return GLD_PIPELINE_MESA;
+ }
+
+ // Test for functionality not exposed in the D3D pathways
+ if ((ctx->Texture._GenFlags)) {
+ gld->PipelineUsage.dwMesa.QuadPart++;
+ return GLD_PIPELINE_MESA;
+ }
+
+ // Now decide if vertex shader can be used.
+ // If two sided lighting is enabled then we must either
+ // use Mesa TnL or the vertex shader
+ if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
+ if (gld->VStwosidelight.hShader && !ctx->Fog.Enabled) {
+ // Use Vertex Shader
+ gld->PipelineUsage.dwD3D2SVS.QuadPart++;
+ return GLD_PIPELINE_D3D_VS_TWOSIDE;
+ } else {
+ // Use Mesa TnL
+ gld->PipelineUsage.dwMesa.QuadPart++;
+ return GLD_PIPELINE_MESA;
+ }
+ }
+
+ // Must be D3D fixed-function pipeline
+ gld->PipelineUsage.dwD3DFVF.QuadPart++;
+ return GLD_PIPELINE_D3D_FVF;
+*/
+}
+
+//---------------------------------------------------------------------------
+
+void gld_update_state_DX9(
+ GLcontext *ctx,
+ GLuint new_state)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLD_pb_dx9 *gldPB;
+
+ if (!gld || !gld->pDev)
+ return;
+
+ _swsetup_InvalidateState( ctx, new_state );
+ _ac_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+
+ // SetupIndex will be used in the pipelines for choosing setup function
+ if ((ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE | DD_SEPARATE_SPECULAR)) ||
+ (ctx->Fog.Enabled))
+ {
+ if (ctx->_TriangleCaps & DD_FLATSHADE)
+ gld->iSetupFunc = GLD_SI_FLAT_EXTRAS;
+ else
+ gld->iSetupFunc = GLD_SI_SMOOTH_EXTRAS;
+ } else {
+ if (ctx->_TriangleCaps & DD_FLATSHADE)
+ gld->iSetupFunc = GLD_SI_FLAT; // Setup flat shade + texture
+ else
+ gld->iSetupFunc = GLD_SI_SMOOTH; // Setup smooth shade + texture
+ }
+
+ gld->bUseMesaTnL = _gldChooseInternalPipeline(ctx, gld);
+ if (gld->bUseMesaTnL) {
+ gldPB = &gld->PB2d;
+ _GLD_DX9_DEV(SetSoftwareVertexProcessing(gld->pDev, TRUE));
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_CLIPPING, FALSE));
+ _GLD_DX9_DEV(SetVertexShader(gld->pDev, NULL));
+ _GLD_DX9_DEV(SetFVF(gld->pDev, gldPB->dwFVF));
+ } else {
+ gldPB = &gld->PB3d;
+ _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_CLIPPING, TRUE));
+// if (gld->TnLPipeline == GLD_PIPELINE_D3D_VS_TWOSIDE) {
+// _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->VStwosidelight.bHardware));
+// _GLD_DX9_DEV(SetVertexShader(gld->pDev, gld->VStwosidelight.hShader));
+// } else {
+// _GLD_DX9_DEV(SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->bHasHWTnL));
+ _GLD_DX9_DEV(SetSoftwareVertexProcessing(gld->pDev, !gld->bHasHWTnL));
+ _GLD_DX9_DEV(SetVertexShader(gld->pDev, NULL));
+ _GLD_DX9_DEV(SetFVF(gld->pDev, gldPB->dwFVF));
+// }
+ }
+
+#define _GLD_TEST_STATE(a) \
+ if (new_state & (a)) { \
+ gld##a(ctx); \
+ new_state &= ~(a); \
+ }
+
+#define _GLD_TEST_STATE_DX9(a) \
+ if (new_state & (a)) { \
+ gld##a##_DX9(ctx); \
+ new_state &= ~(a); \
+ }
+
+#define _GLD_IGNORE_STATE(a) new_state &= ~(a);
+
+// if (!gld->bUseMesaTnL) {
+ // Not required if Mesa is doing the TnL.
+ // Problem: If gld->bUseMesaTnL is TRUE when these are signaled,
+ // then we'll miss updating the D3D TnL pipeline.
+ // Therefore, don't test for gld->bUseMesaTnL
+ _GLD_TEST_STATE(_NEW_MODELVIEW);
+ _GLD_TEST_STATE(_NEW_PROJECTION);
+// }
+
+ _GLD_TEST_STATE_DX9(_NEW_TEXTURE); // extern, so guard with _DX9
+ _GLD_TEST_STATE(_NEW_COLOR);
+ _GLD_TEST_STATE(_NEW_DEPTH);
+ _GLD_TEST_STATE(_NEW_POLYGON);
+ _GLD_TEST_STATE(_NEW_STENCIL);
+ _GLD_TEST_STATE(_NEW_FOG);
+ _GLD_TEST_STATE(_NEW_LIGHT);
+ _GLD_TEST_STATE(_NEW_VIEWPORT);
+
+ _GLD_IGNORE_STATE(_NEW_TRANSFORM);
+
+ // Scissor Test: New for DX9
+ _GLD_TEST_STATE(_NEW_SCISSOR);
+
+// Stubs for future use.
+/* _GLD_TEST_STATE(_NEW_TEXTURE_MATRIX);
+ _GLD_TEST_STATE(_NEW_COLOR_MATRIX);
+ _GLD_TEST_STATE(_NEW_ACCUM);
+ _GLD_TEST_STATE(_NEW_EVAL);
+ _GLD_TEST_STATE(_NEW_HINT);
+ _GLD_TEST_STATE(_NEW_LINE);
+ _GLD_TEST_STATE(_NEW_PIXEL);
+ _GLD_TEST_STATE(_NEW_POINT);
+ _GLD_TEST_STATE(_NEW_POLYGONSTIPPLE);
+ _GLD_TEST_STATE(_NEW_PACKUNPACK);
+ _GLD_TEST_STATE(_NEW_ARRAY);
+ _GLD_TEST_STATE(_NEW_RENDERMODE);
+ _GLD_TEST_STATE(_NEW_BUFFERS);
+ _GLD_TEST_STATE(_NEW_MULTISAMPLE);
+*/
+
+// For debugging.
+#if 0
+#define _GLD_TEST_UNHANDLED_STATE(a) \
+ if (new_state & (a)) { \
+ gldLogMessage(GLDLOG_ERROR, "Unhandled " #a "\n"); \
+ }
+ _GLD_TEST_UNHANDLED_STATE(_NEW_TEXTURE_MATRIX);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_COLOR_MATRIX);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_ACCUM);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_EVAL);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_HINT);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_LINE);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_PIXEL);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_POINT);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_POLYGONSTIPPLE);
+// _GLD_TEST_UNHANDLED_STATE(_NEW_SCISSOR);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_PACKUNPACK);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_ARRAY);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_RENDERMODE);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_BUFFERS);
+ _GLD_TEST_UNHANDLED_STATE(_NEW_MULTISAMPLE);
+#undef _GLD_UNHANDLED_STATE
+#endif
+
+#undef _GLD_TEST_STATE
+}
+
+//---------------------------------------------------------------------------
+// Viewport
+//---------------------------------------------------------------------------
+
+void gld_Viewport_DX9(
+ GLcontext *ctx,
+ GLint x,
+ GLint y,
+ GLsizei w,
+ GLsizei h)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ D3DVIEWPORT9 d3dvp;
+
+ if (!gld || !gld->pDev)
+ return;
+
+ // This is a hack. When the app is minimized, Mesa passes
+ // w=1 and h=1 for viewport dimensions. Without this test
+ // we get a GPF in gld_wgl_resize_buffers().
+ if ((w==1) && (h==1))
+ return;
+
+ // Call ResizeBuffersMESA. This function will early-out
+ // if no resize is needed.
+ //ctx->Driver.ResizeBuffersMESA(ctx);
+ // Mesa 5: Changed parameters
+ ctx->Driver.ResizeBuffers(gldCtx->glBuffer);
+
+#if 0
+ ddlogPrintf(GLDLOG_SYSTEM, ">> Viewport x=%d y=%d w=%d h=%d", x,y,w,h);
+#endif
+
+ // ** D3D viewport must not be outside the render target surface **
+ // Sanity check the GL viewport dimensions
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (w > gldCtx->dwWidth) w = gldCtx->dwWidth;
+ if (h > gldCtx->dwHeight) h = gldCtx->dwHeight;
+ // Ditto for D3D viewport dimensions
+ if (w+x > gldCtx->dwWidth) w = gldCtx->dwWidth-x;
+ if (h+y > gldCtx->dwHeight) h = gldCtx->dwHeight-y;
+
+ d3dvp.X = x;
+ d3dvp.Y = gldCtx->dwHeight - (y + h);
+ d3dvp.Width = w;
+ d3dvp.Height = h;
+ if (ctx->Viewport.Near <= ctx->Viewport.Far) {
+ d3dvp.MinZ = ctx->Viewport.Near;
+ d3dvp.MaxZ = ctx->Viewport.Far;
+ } else {
+ d3dvp.MinZ = ctx->Viewport.Far;
+ d3dvp.MaxZ = ctx->Viewport.Near;
+ }
+
+ // TODO: DEBUGGING
+// d3dvp.MinZ = 0.0f;
+// d3dvp.MaxZ = 1.0f;
+
+ _GLD_DX9_DEV(SetViewport(gld->pDev, &d3dvp));
+
+}
+
+//---------------------------------------------------------------------------
+
+extern BOOL dglWglResizeBuffers(GLcontext *ctx, BOOL bDefaultDriver);
+
+// Mesa 5: Parameter change
+void gldResizeBuffers_DX9(
+// GLcontext *ctx)
+ GLframebuffer *fb)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ dglWglResizeBuffers(ctx, TRUE);
+}
+
+//---------------------------------------------------------------------------
+#ifdef _DEBUG
+// This is only for debugging.
+// To use, plug into ctx->Driver.Enable pointer below.
+void gld_Enable(
+ GLcontext *ctx,
+ GLenum e,
+ GLboolean b)
+{
+ char buf[1024];
+ sprintf(buf, "Enable: %s (%s)\n", _mesa_lookup_enum_by_nr(e), b?"TRUE":"FALSE");
+ ddlogMessage(DDLOG_SYSTEM, buf);
+}
+#endif
+//---------------------------------------------------------------------------
+// Driver pointer setup
+//---------------------------------------------------------------------------
+
+extern const GLubyte* _gldGetStringGeneric(GLcontext*, GLenum);
+
+void gldSetupDriverPointers_DX9(
+ GLcontext *ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ // Mandatory functions
+ ctx->Driver.GetString = _gldGetStringGeneric;
+ ctx->Driver.UpdateState = gld_update_state_DX9;
+ ctx->Driver.Clear = gld_Clear_DX9;
+ ctx->Driver.DrawBuffer = gld_set_draw_buffer_DX9;
+ ctx->Driver.GetBufferSize = gld_buffer_size_DX9;
+ ctx->Driver.Finish = gld_Finish_DX9;
+ ctx->Driver.Flush = gld_Flush_DX9;
+ ctx->Driver.Error = gld_Error_DX9;
+
+ // Hardware accumulation buffer
+ ctx->Driver.Accum = NULL; // TODO: gld_Accum;
+
+ // Bitmap functions
+ ctx->Driver.CopyPixels = gld_CopyPixels_DX9;
+ ctx->Driver.DrawPixels = gld_DrawPixels_DX9;
+ ctx->Driver.ReadPixels = gld_ReadPixels_DX9;
+ ctx->Driver.Bitmap = gld_Bitmap_DX9;
+
+ // Buffer resize
+ ctx->Driver.ResizeBuffers = gldResizeBuffers_DX9;
+
+ // Texture image functions
+ ctx->Driver.ChooseTextureFormat = gld_ChooseTextureFormat_DX9;
+ ctx->Driver.TexImage1D = gld_TexImage1D_DX9;
+ ctx->Driver.TexImage2D = gld_TexImage2D_DX9;
+ ctx->Driver.TexImage3D = _mesa_store_teximage3d;
+ ctx->Driver.TexSubImage1D = gld_TexSubImage1D_DX9;
+ ctx->Driver.TexSubImage2D = gld_TexSubImage2D_DX9;
+ ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
+
+ ctx->Driver.CopyTexImage1D = gldCopyTexImage1D_DX9; //NULL;
+ ctx->Driver.CopyTexImage2D = gldCopyTexImage2D_DX9; //NULL;
+ ctx->Driver.CopyTexSubImage1D = gldCopyTexSubImage1D_DX9; //NULL;
+ ctx->Driver.CopyTexSubImage2D = gldCopyTexSubImage2D_DX9; //NULL;
+ ctx->Driver.CopyTexSubImage3D = gldCopyTexSubImage3D_DX9;
+ ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
+
+ // Texture object functions
+ ctx->Driver.BindTexture = NULL;
+ ctx->Driver.CreateTexture = NULL; // Not yet implemented by Mesa!;
+ ctx->Driver.DeleteTexture = gld_DeleteTexture_DX9;
+ ctx->Driver.PrioritizeTexture = NULL;
+
+ // Imaging functionality
+ ctx->Driver.CopyColorTable = NULL;
+ ctx->Driver.CopyColorSubTable = NULL;
+ ctx->Driver.CopyConvolutionFilter1D = NULL;
+ ctx->Driver.CopyConvolutionFilter2D = NULL;
+
+ // State changing functions
+ ctx->Driver.AlphaFunc = NULL; //gld_AlphaFunc;
+ ctx->Driver.BlendFunc = NULL; //gld_BlendFunc;
+ ctx->Driver.ClearColor = NULL; //gld_ClearColor;
+ ctx->Driver.ClearDepth = NULL; //gld_ClearDepth;
+ ctx->Driver.ClearStencil = NULL; //gld_ClearStencil;
+ ctx->Driver.ColorMask = NULL; //gld_ColorMask;
+ ctx->Driver.CullFace = NULL; //gld_CullFace;
+ ctx->Driver.ClipPlane = NULL; //gld_ClipPlane;
+ ctx->Driver.FrontFace = NULL; //gld_FrontFace;
+ ctx->Driver.DepthFunc = NULL; //gld_DepthFunc;
+ ctx->Driver.DepthMask = NULL; //gld_DepthMask;
+ ctx->Driver.DepthRange = NULL;
+ ctx->Driver.Enable = NULL; //gld_Enable;
+ ctx->Driver.Fogfv = NULL; //gld_Fogfv;
+ ctx->Driver.Hint = NULL; //gld_Hint;
+ ctx->Driver.Lightfv = NULL; //gld_Lightfv;
+ ctx->Driver.LightModelfv = NULL; //gld_LightModelfv;
+ ctx->Driver.LineStipple = NULL; //gld_LineStipple;
+ ctx->Driver.LineWidth = NULL; //gld_LineWidth;
+ ctx->Driver.LogicOpcode = NULL; //gld_LogicOpcode;
+ ctx->Driver.PointParameterfv = NULL; //gld_PointParameterfv;
+ ctx->Driver.PointSize = NULL; //gld_PointSize;
+ ctx->Driver.PolygonMode = NULL; //gld_PolygonMode;
+ ctx->Driver.PolygonOffset = NULL; //gld_PolygonOffset;
+ ctx->Driver.PolygonStipple = NULL; //gld_PolygonStipple;
+ ctx->Driver.RenderMode = NULL; //gld_RenderMode;
+ ctx->Driver.Scissor = NULL; //gld_Scissor;
+ ctx->Driver.ShadeModel = NULL; //gld_ShadeModel;
+ ctx->Driver.StencilFunc = NULL; //gld_StencilFunc;
+ ctx->Driver.StencilMask = NULL; //gld_StencilMask;
+ ctx->Driver.StencilOp = NULL; //gld_StencilOp;
+ ctx->Driver.TexGen = NULL; //gld_TexGen;
+ ctx->Driver.TexEnv = NULL;
+ ctx->Driver.TexParameter = NULL;
+ ctx->Driver.TextureMatrix = NULL; //gld_TextureMatrix;
+ ctx->Driver.Viewport = gld_Viewport_DX9;
+
+ _swsetup_Wakeup(ctx);
+
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+ tnl->Driver.Render.ResetLineStipple = gld_ResetLineStipple_DX9;
+ tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
+ tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine;
+
+ // Hook into glFrustum() and glOrtho()
+// ctx->Exec->Frustum = gldFrustumHook_DX9;
+// ctx->Exec->Ortho = gldOrthoHook_DX9;
+
+}
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_dx9.h b/src/mesa/drivers/windows/gldirect/dx9/gld_dx9.h
new file mode 100644
index 0000000000..aec40ac9dd
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_dx9.h
@@ -0,0 +1,327 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GLDirect Direct3D 9.0 header file
+*
+****************************************************************************/
+
+#ifndef _GLD_DX9_H
+#define _GLD_DX9_H
+
+//---------------------------------------------------------------------------
+// Windows includes
+//---------------------------------------------------------------------------
+
+//#ifndef STRICT
+//#define STRICT
+//#endif
+
+//#define WIN32_LEAN_AND_MEAN
+//#include <windows.h>
+#include <d3d9.h>
+#include <d3dx9.h>
+
+// MS screwed up with the DX8.1 SDK - there's no compile-time
+// method of compiling for 8.0 via the 8.1 SDK unless you
+// "make sure you don't use any 8.1 interfaces".
+// We CAN use 8.1 D3DX static functions, though - just not new 8.1 interfaces.
+//
+// D3D_SDK_VERSION is 120 for 8.0 (supported by Windows 95).
+// D3D_SDK_VERSION is 220 for 8.1 (NOT supported by Windows 95).
+//
+//#define D3D_SDK_VERSION_DX9_SUPPORT_WIN95 120
+//#define D3D_SDK_VERSION_DX91 220
+
+// Typedef for obtaining function from d3d8.dll
+typedef IDirect3D9* (WINAPI *FNDIRECT3DCREATE9) (UINT);
+
+
+//---------------------------------------------------------------------------
+// Defines
+//---------------------------------------------------------------------------
+
+#ifdef _DEBUG
+#define _GLD_TEST_HRESULT(h) \
+{ \
+ HRESULT _hr = (h); \
+ if (FAILED(_hr)) { \
+ gldLogError(GLDLOG_ERROR, #h, _hr); \
+ } \
+}
+#define _GLD_DX9(func) _GLD_TEST_HRESULT(IDirect3D9_##func##)
+#define _GLD_DX9_DEV(func) _GLD_TEST_HRESULT(IDirect3DDevice9_##func##)
+#define _GLD_DX9_VB(func) _GLD_TEST_HRESULT(IDirect3DVertexBuffer9_##func##)
+#define _GLD_DX9_TEX(func) _GLD_TEST_HRESULT(IDirect3DTexture9_##func##)
+#else
+#define _GLD_DX9(func) IDirect3D9_##func
+#define _GLD_DX9_DEV(func) IDirect3DDevice9_##func
+#define _GLD_DX9_VB(func) IDirect3DVertexBuffer9_##func
+#define _GLD_DX9_TEX(func) IDirect3DTexture9_##func
+#endif
+
+#define SAFE_RELEASE(p) \
+{ \
+ if (p) { \
+ (p)->lpVtbl->Release(p); \
+ (p) = NULL; \
+ } \
+}
+
+#define SAFE_RELEASE_VB9(p) \
+{ \
+ if (p) { \
+ IDirect3DVertexBuffer9_Release((p)); \
+ (p) = NULL; \
+ } \
+}
+
+#define SAFE_RELEASE_SURFACE9(p) \
+{ \
+ if (p) { \
+ IDirect3DSurface9_Release((p)); \
+ (p) = NULL; \
+ } \
+}
+
+// Setup index.
+enum {
+ GLD_SI_FLAT = 0,
+ GLD_SI_SMOOTH = 1,
+ GLD_SI_FLAT_EXTRAS = 2,
+ GLD_SI_SMOOTH_EXTRAS = 3,
+};
+/*
+// Internal pipeline
+typedef enum {
+ GLD_PIPELINE_MESA = 0, // Mesa pipeline
+ GLD_PIPELINE_D3D_FVF = 1, // Direct3D Fixed-function pipeline
+ GLD_PIPELINE_D3D_VS_TWOSIDE = 2 // Direct3D two-sided-lighting vertex shader
+} GLD_tnl_pipeline;
+*/
+//---------------------------------------------------------------------------
+// Vertex definitions for Fixed-Function pipeline
+//---------------------------------------------------------------------------
+
+//
+// NOTE: If the number of texture units is altered then most of
+// the texture code will need to be revised.
+//
+
+#define GLD_MAX_TEXTURE_UNITS_DX9 2
+
+//
+// 2D vertex transformed by Mesa
+//
+#define GLD_FVF_2D_VERTEX ( D3DFVF_XYZRHW | \
+ D3DFVF_DIFFUSE | \
+ D3DFVF_SPECULAR | \
+ D3DFVF_TEX2)
+typedef struct {
+ FLOAT x, y; // 2D raster coords
+ FLOAT sz; // Screen Z (depth)
+ FLOAT rhw; // Reciprocal homogenous W
+ DWORD diffuse; // Diffuse colour
+ DWORD specular; // For separate-specular support
+ FLOAT t0_u, t0_v; // 1st set of texture coords
+ FLOAT t1_u, t1_v; // 2nd set of texture coords
+} GLD_2D_VERTEX;
+
+
+//
+// 3D vertex transformed by Direct3D
+//
+#define GLD_FVF_3D_VERTEX ( D3DFVF_XYZ | \
+ D3DFVF_DIFFUSE | \
+ D3DFVF_TEX2)
+
+typedef struct {
+ D3DXVECTOR3 Position; // XYZ Vector in object space
+ D3DCOLOR Diffuse; // Diffuse colour
+ D3DXVECTOR2 TexUnit0; // Texture unit 0
+ D3DXVECTOR2 TexUnit1; // Texture unit 1
+} GLD_3D_VERTEX;
+
+//---------------------------------------------------------------------------
+// Vertex Shaders
+//---------------------------------------------------------------------------
+/*
+// DX8 Vertex Shader
+typedef struct {
+ DWORD hShader; // If NULL, shader is invalid and cannot be used
+ BOOL bHardware; // If TRUE then shader was created for hardware,
+ // otherwise shader was created for software.
+} GLD_vertexShader;
+*/
+//---------------------------------------------------------------------------
+// Structs
+//---------------------------------------------------------------------------
+
+// This keeps a count of how many times we choose each individual internal
+// pathway. Useful for seeing if a certain pathway was ever used by an app, and
+// how much each pathway is biased.
+// Zero the members at context creation and dump stats at context deletion.
+typedef struct {
+ // Note: DWORD is probably too small
+ ULARGE_INTEGER qwMesa; // Mesa TnL pipeline
+ ULARGE_INTEGER qwD3DFVF; // Direct3D Fixed-Function pipeline
+// ULARGE_INTEGER dwD3D2SVS; // Direct3D Two-Sided Vertex Shader pipeline
+} GLD_pipeline_usage;
+
+// GLDirect Primitive Buffer (points, lines, triangles and quads)
+typedef struct {
+ // Data for IDirect3DDevice9::CreateVertexBuffer()
+ DWORD dwStride; // Stride of vertex
+ DWORD dwUsage; // Usage flags
+ DWORD dwFVF; // Direct3D Flexible Vertex Format
+ DWORD dwPool; // Pool flags
+
+ IDirect3DVertexBuffer9 *pVB; // Holds points, lines, tris and quads.
+
+ // Point list is assumed to be at start of buffer
+ DWORD iFirstLine; // Index of start of line list
+ DWORD iFirstTriangle; // Index of start of triangle list
+
+ BYTE *pPoints; // Pointer to next free point
+ BYTE *pLines; // Pointer to next free line
+ BYTE *pTriangles; // Pointer to next free triangle
+
+ DWORD nPoints; // Number of points ready to render
+ DWORD nLines; // Number of lines ready to render
+ DWORD nTriangles; // Number of triangles ready to render
+} GLD_pb_dx9;
+
+// GLDirect DX9 driver data
+typedef struct {
+ // GLDirect vars
+ BOOL bDoublebuffer; // Doublebuffer (otherwise single-buffered)
+ BOOL bDepthStencil; // Depth buffer needed (stencil optional)
+ D3DFORMAT RenderFormat; // Format of back/front buffer
+ D3DFORMAT DepthFormat; // Format of depth/stencil
+// float fFlipWindowY; // Value for flipping viewport Y coord
+
+ // Direct3D vars
+ D3DCAPS9 d3dCaps9;
+ BOOL bHasHWTnL; // Device has Hardware Transform/Light?
+ IDirect3D9 *pD3D; // Base Direct3D9 interface
+ IDirect3DDevice9 *pDev; // Direct3D9 Device interface
+ GLD_pb_dx9 PB2d; // Vertices transformed by Mesa
+ GLD_pb_dx9 PB3d; // Vertices transformed by Direct3D
+ D3DPRIMITIVETYPE d3dpt; // Current Direct3D primitive type
+ D3DXMATRIX matProjection; // Projection matrix for D3D TnL
+ D3DXMATRIX matModelView; // Model/View matrix for D3D TnL
+ int iSetupFunc; // Which setup functions to use
+ BOOL bUseMesaTnL; // Whether to use Mesa or D3D for TnL
+
+ // Direct3D vars for two-sided lighting
+// GLD_vertexShader VStwosidelight; // Vertex Shader for two-sided lighting
+// D3DXMATRIX matWorldViewProj;// World/View/Projection matrix for shaders
+
+
+// GLD_tnl_pipeline TnLPipeline; // Index of current internal pipeline
+ GLD_pipeline_usage PipelineUsage;
+
+ BOOL bCanScissor; // Scissor test - new for DX9
+} GLD_driver_dx9;
+
+#define GLD_GET_DX9_DRIVER(c) (GLD_driver_dx9*)(c)->glPriv
+
+//---------------------------------------------------------------------------
+// Function prototypes
+//---------------------------------------------------------------------------
+
+PROC gldGetProcAddress_DX9(LPCSTR a);
+void gldEnableExtensions_DX9(GLcontext *ctx);
+void gldInstallPipeline_DX9(GLcontext *ctx);
+void gldSetupDriverPointers_DX9(GLcontext *ctx);
+//void gldResizeBuffers_DX9(GLcontext *ctx);
+void gldResizeBuffers_DX9(GLframebuffer *fb);
+
+
+// Texture functions
+
+void gldCopyTexImage1D_DX9(GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
+void gldCopyTexImage2D_DX9(GLcontext *ctx, GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+void gldCopyTexSubImage1D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width );
+void gldCopyTexSubImage2D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height );
+void gldCopyTexSubImage3D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height );
+
+void gld_NEW_TEXTURE_DX9(GLcontext *ctx);
+void gld_DrawPixels_DX9(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels);
+void gld_ReadPixels_DX9(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, const struct gl_pixelstore_attrib *unpack, GLvoid *dest);
+void gld_CopyPixels_DX9(GLcontext *ctx, GLint srcx, GLint srcy, GLsizei width, GLsizei height, GLint dstx, GLint dsty, GLenum type);
+void gld_Bitmap_DX9(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap);
+const struct gl_texture_format* gld_ChooseTextureFormat_DX9(GLcontext *ctx, GLint internalFormat, GLenum srcFormat, GLenum srcType);
+void gld_TexImage2D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint height, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *tObj, struct gl_texture_image *texImage);
+void gld_TexImage1D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint internalFormat, GLint width, GLint border, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage );
+void gld_TexSubImage2D_DX9( GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage );
+void gld_TexSubImage1D_DX9(GLcontext *ctx, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels, const struct gl_pixelstore_attrib *packing, struct gl_texture_object *texObj, struct gl_texture_image *texImage);
+void gld_DeleteTexture_DX9(GLcontext *ctx, struct gl_texture_object *tObj);
+void gld_ResetLineStipple_DX9(GLcontext *ctx);
+
+// 2D primitive functions
+
+void gld_Points2D_DX9(GLcontext *ctx, GLuint first, GLuint last);
+
+void gld_Line2DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Line2DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1);
+
+void gld_Triangle2DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DFlatExtras_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DSmoothExtras_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+
+void gld_Quad2DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DFlatExtras_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DSmoothExtras_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+
+// 3D primitive functions
+
+void gld_Points3D_DX9(GLcontext *ctx, GLuint first, GLuint last);
+void gld_Line3DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Triangle3DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Quad3DFlat_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Line3DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Triangle3DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Quad3DSmooth_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+
+// Primitive functions for Two-sided-lighting Vertex Shader
+
+void gld_Points2DTwoside_DX9(GLcontext *ctx, GLuint first, GLuint last);
+void gld_Line2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Line2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1);
+void gld_Triangle2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Triangle2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2);
+void gld_Quad2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+void gld_Quad2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+
+#endif
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_dxerr9.h b/src/mesa/drivers/windows/gldirect/dx9/gld_dxerr9.h
new file mode 100644
index 0000000000..1d6b7b1c76
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_dxerr9.h
@@ -0,0 +1,77 @@
+/*==========================================================================;
+ *
+ *
+ * File: dxerr9.h
+ * Content: DirectX Error Library Include File
+ *
+ ****************************************************************************/
+
+#ifndef _GLD_DXERR9_H_
+#define _GLD_DXERR9_H_
+
+
+#include <d3d9.h>
+
+//
+// DXGetErrorString9
+//
+// Desc: Converts an DirectX HRESULT to a string
+//
+// Args: HRESULT hr Can be any error code from
+// DPLAY D3D8 D3DX8 DMUSIC DSOUND
+//
+// Return: Converted string
+//
+const char* __stdcall DXGetErrorString9A(HRESULT hr);
+const WCHAR* __stdcall DXGetErrorString9W(HRESULT hr);
+
+#ifdef UNICODE
+ #define DXGetErrorString9 DXGetErrorString9W
+#else
+ #define DXGetErrorString9 DXGetErrorString9A
+#endif
+
+
+//
+// DXTrace
+//
+// Desc: Outputs a formatted error message to the debug stream
+//
+// Args: CHAR* strFile The current file, typically passed in using the
+// __FILE__ macro.
+// DWORD dwLine The current line number, typically passed in using the
+// __LINE__ macro.
+// HRESULT hr An HRESULT that will be traced to the debug stream.
+// CHAR* strMsg A string that will be traced to the debug stream (may be NULL)
+// BOOL bPopMsgBox If TRUE, then a message box will popup also containing the passed info.
+//
+// Return: The hr that was passed in.
+//
+//HRESULT __stdcall DXTraceA( char* strFile, DWORD dwLine, HRESULT hr, char* strMsg, BOOL bPopMsgBox = FALSE );
+//HRESULT __stdcall DXTraceW( char* strFile, DWORD dwLine, HRESULT hr, WCHAR* strMsg, BOOL bPopMsgBox = FALSE );
+HRESULT __stdcall DXTraceA( char* strFile, DWORD dwLine, HRESULT hr, char* strMsg, BOOL bPopMsgBox);
+HRESULT __stdcall DXTraceW( char* strFile, DWORD dwLine, HRESULT hr, WCHAR* strMsg, BOOL bPopMsgBox);
+
+#ifdef UNICODE
+ #define DXTrace DXTraceW
+#else
+ #define DXTrace DXTraceA
+#endif
+
+
+//
+// Helper macros
+//
+#if defined(DEBUG) | defined(_DEBUG)
+ #define DXTRACE_MSG(str) DXTrace( __FILE__, (DWORD)__LINE__, 0, str, FALSE )
+ #define DXTRACE_ERR(str,hr) DXTrace( __FILE__, (DWORD)__LINE__, hr, str, TRUE )
+ #define DXTRACE_ERR_NOMSGBOX(str,hr) DXTrace( __FILE__, (DWORD)__LINE__, hr, str, FALSE )
+#else
+ #define DXTRACE_MSG(str) (0L)
+ #define DXTRACE_ERR(str,hr) (hr)
+ #define DXTRACE_ERR_NOMSGBOX(str,hr) (hr)
+#endif
+
+
+#endif
+
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_ext_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_ext_dx9.c
new file mode 100644
index 0000000000..a542806d2f
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_ext_dx9.c
@@ -0,0 +1,344 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GL extensions
+*
+****************************************************************************/
+
+//#include "../GLDirect.h"
+//#include "../gld_log.h"
+//#include "../gld_settings.h"
+
+#include <windows.h>
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glext.h>
+
+//#include "ddlog.h"
+//#include "gld_dx8.h"
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "array_cache/acache.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast_setup/ss_context.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+#include "dglcontext.h"
+#include "extensions.h"
+
+// For some reason this is not defined in an above header...
+extern void _mesa_enable_imaging_extensions(GLcontext *ctx);
+
+//---------------------------------------------------------------------------
+// Hack for the SGIS_multitexture extension that was removed from Mesa
+// NOTE: SGIS_multitexture enums also clash with GL_SGIX_async_pixel
+
+ // NOTE: Quake2 ran *slower* with this enabled, so I've
+ // disabled it for now.
+ // To enable, uncomment:
+ // _mesa_add_extension(ctx, GL_TRUE, szGL_SGIS_multitexture, 0);
+
+//---------------------------------------------------------------------------
+
+enum {
+ /* Quake2 GL_SGIS_multitexture */
+ GL_SELECTED_TEXTURE_SGIS = 0x835B,
+ GL_SELECTED_TEXTURE_COORD_SET_SGIS = 0x835C,
+ GL_MAX_TEXTURES_SGIS = 0x835D,
+ GL_TEXTURE0_SGIS = 0x835E,
+ GL_TEXTURE1_SGIS = 0x835F,
+ GL_TEXTURE2_SGIS = 0x8360,
+ GL_TEXTURE3_SGIS = 0x8361,
+ GL_TEXTURE_COORD_SET_SOURCE_SGIS = 0x8363,
+};
+
+//---------------------------------------------------------------------------
+
+void APIENTRY gldSelectTextureSGIS(
+ GLenum target)
+{
+ GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS);
+ glActiveTextureARB(ARB_target);
+}
+
+//---------------------------------------------------------------------------
+
+void APIENTRY gldMTexCoord2fSGIS(
+ GLenum target,
+ GLfloat s,
+ GLfloat t)
+{
+ GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS);
+ glMultiTexCoord2fARB(ARB_target, s, t);
+}
+
+//---------------------------------------------------------------------------
+
+void APIENTRY gldMTexCoord2fvSGIS(
+ GLenum target,
+ const GLfloat *v)
+{
+ GLenum ARB_target = GL_TEXTURE0_ARB + (target - GL_TEXTURE0_SGIS);
+ glMultiTexCoord2fvARB(ARB_target, v);
+}
+
+//---------------------------------------------------------------------------
+// Extensions
+//---------------------------------------------------------------------------
+
+typedef struct {
+ PROC proc;
+ char *name;
+} GLD_extension;
+
+GLD_extension GLD_extList[] = {
+#ifdef GL_EXT_polygon_offset
+ { (PROC)glPolygonOffsetEXT, "glPolygonOffsetEXT" },
+#endif
+ { (PROC)glBlendEquationEXT, "glBlendEquationEXT" },
+ { (PROC)glBlendColorEXT, "glBlendColorExt" },
+ { (PROC)glVertexPointerEXT, "glVertexPointerEXT" },
+ { (PROC)glNormalPointerEXT, "glNormalPointerEXT" },
+ { (PROC)glColorPointerEXT, "glColorPointerEXT" },
+ { (PROC)glIndexPointerEXT, "glIndexPointerEXT" },
+ { (PROC)glTexCoordPointerEXT, "glTexCoordPointer" },
+ { (PROC)glEdgeFlagPointerEXT, "glEdgeFlagPointerEXT" },
+ { (PROC)glGetPointervEXT, "glGetPointervEXT" },
+ { (PROC)glArrayElementEXT, "glArrayElementEXT" },
+ { (PROC)glDrawArraysEXT, "glDrawArrayEXT" },
+ { (PROC)glAreTexturesResidentEXT, "glAreTexturesResidentEXT" },
+ { (PROC)glBindTextureEXT, "glBindTextureEXT" },
+ { (PROC)glDeleteTexturesEXT, "glDeleteTexturesEXT" },
+ { (PROC)glGenTexturesEXT, "glGenTexturesEXT" },
+ { (PROC)glIsTextureEXT, "glIsTextureEXT" },
+ { (PROC)glPrioritizeTexturesEXT, "glPrioritizeTexturesEXT" },
+ { (PROC)glCopyTexSubImage3DEXT, "glCopyTexSubImage3DEXT" },
+ { (PROC)glTexImage3DEXT, "glTexImage3DEXT" },
+ { (PROC)glTexSubImage3DEXT, "glTexSubImage3DEXT" },
+ { (PROC)glPointParameterfEXT, "glPointParameterfEXT" },
+ { (PROC)glPointParameterfvEXT, "glPointParameterfvEXT" },
+
+ { (PROC)glLockArraysEXT, "glLockArraysEXT" },
+ { (PROC)glUnlockArraysEXT, "glUnlockArraysEXT" },
+ { NULL, "\0" }
+};
+
+GLD_extension GLD_multitexList[] = {
+/*
+ { (PROC)glMultiTexCoord1dSGIS, "glMTexCoord1dSGIS" },
+ { (PROC)glMultiTexCoord1dvSGIS, "glMTexCoord1dvSGIS" },
+ { (PROC)glMultiTexCoord1fSGIS, "glMTexCoord1fSGIS" },
+ { (PROC)glMultiTexCoord1fvSGIS, "glMTexCoord1fvSGIS" },
+ { (PROC)glMultiTexCoord1iSGIS, "glMTexCoord1iSGIS" },
+ { (PROC)glMultiTexCoord1ivSGIS, "glMTexCoord1ivSGIS" },
+ { (PROC)glMultiTexCoord1sSGIS, "glMTexCoord1sSGIS" },
+ { (PROC)glMultiTexCoord1svSGIS, "glMTexCoord1svSGIS" },
+ { (PROC)glMultiTexCoord2dSGIS, "glMTexCoord2dSGIS" },
+ { (PROC)glMultiTexCoord2dvSGIS, "glMTexCoord2dvSGIS" },
+ { (PROC)glMultiTexCoord2fSGIS, "glMTexCoord2fSGIS" },
+ { (PROC)glMultiTexCoord2fvSGIS, "glMTexCoord2fvSGIS" },
+ { (PROC)glMultiTexCoord2iSGIS, "glMTexCoord2iSGIS" },
+ { (PROC)glMultiTexCoord2ivSGIS, "glMTexCoord2ivSGIS" },
+ { (PROC)glMultiTexCoord2sSGIS, "glMTexCoord2sSGIS" },
+ { (PROC)glMultiTexCoord2svSGIS, "glMTexCoord2svSGIS" },
+ { (PROC)glMultiTexCoord3dSGIS, "glMTexCoord3dSGIS" },
+ { (PROC)glMultiTexCoord3dvSGIS, "glMTexCoord3dvSGIS" },
+ { (PROC)glMultiTexCoord3fSGIS, "glMTexCoord3fSGIS" },
+ { (PROC)glMultiTexCoord3fvSGIS, "glMTexCoord3fvSGIS" },
+ { (PROC)glMultiTexCoord3iSGIS, "glMTexCoord3iSGIS" },
+ { (PROC)glMultiTexCoord3ivSGIS, "glMTexCoord3ivSGIS" },
+ { (PROC)glMultiTexCoord3sSGIS, "glMTexCoord3sSGIS" },
+ { (PROC)glMultiTexCoord3svSGIS, "glMTexCoord3svSGIS" },
+ { (PROC)glMultiTexCoord4dSGIS, "glMTexCoord4dSGIS" },
+ { (PROC)glMultiTexCoord4dvSGIS, "glMTexCoord4dvSGIS" },
+ { (PROC)glMultiTexCoord4fSGIS, "glMTexCoord4fSGIS" },
+ { (PROC)glMultiTexCoord4fvSGIS, "glMTexCoord4fvSGIS" },
+ { (PROC)glMultiTexCoord4iSGIS, "glMTexCoord4iSGIS" },
+ { (PROC)glMultiTexCoord4ivSGIS, "glMTexCoord4ivSGIS" },
+ { (PROC)glMultiTexCoord4sSGIS, "glMTexCoord4sSGIS" },
+ { (PROC)glMultiTexCoord4svSGIS, "glMTexCoord4svSGIS" },
+ { (PROC)glMultiTexCoordPointerSGIS, "glMTexCoordPointerSGIS" },
+ { (PROC)glSelectTextureSGIS, "glSelectTextureSGIS" },
+ { (PROC)glSelectTextureCoordSetSGIS, "glSelectTextureCoordSetSGIS" },
+*/
+ { (PROC)glActiveTextureARB, "glActiveTextureARB" },
+ { (PROC)glClientActiveTextureARB, "glClientActiveTextureARB" },
+ { (PROC)glMultiTexCoord1dARB, "glMultiTexCoord1dARB" },
+ { (PROC)glMultiTexCoord1dvARB, "glMultiTexCoord1dvARB" },
+ { (PROC)glMultiTexCoord1fARB, "glMultiTexCoord1fARB" },
+ { (PROC)glMultiTexCoord1fvARB, "glMultiTexCoord1fvARB" },
+ { (PROC)glMultiTexCoord1iARB, "glMultiTexCoord1iARB" },
+ { (PROC)glMultiTexCoord1ivARB, "glMultiTexCoord1ivARB" },
+ { (PROC)glMultiTexCoord1sARB, "glMultiTexCoord1sARB" },
+ { (PROC)glMultiTexCoord1svARB, "glMultiTexCoord1svARB" },
+ { (PROC)glMultiTexCoord2dARB, "glMultiTexCoord2dARB" },
+ { (PROC)glMultiTexCoord2dvARB, "glMultiTexCoord2dvARB" },
+ { (PROC)glMultiTexCoord2fARB, "glMultiTexCoord2fARB" },
+ { (PROC)glMultiTexCoord2fvARB, "glMultiTexCoord2fvARB" },
+ { (PROC)glMultiTexCoord2iARB, "glMultiTexCoord2iARB" },
+ { (PROC)glMultiTexCoord2ivARB, "glMultiTexCoord2ivARB" },
+ { (PROC)glMultiTexCoord2sARB, "glMultiTexCoord2sARB" },
+ { (PROC)glMultiTexCoord2svARB, "glMultiTexCoord2svARB" },
+ { (PROC)glMultiTexCoord3dARB, "glMultiTexCoord3dARB" },
+ { (PROC)glMultiTexCoord3dvARB, "glMultiTexCoord3dvARB" },
+ { (PROC)glMultiTexCoord3fARB, "glMultiTexCoord3fARB" },
+ { (PROC)glMultiTexCoord3fvARB, "glMultiTexCoord3fvARB" },
+ { (PROC)glMultiTexCoord3iARB, "glMultiTexCoord3iARB" },
+ { (PROC)glMultiTexCoord3ivARB, "glMultiTexCoord3ivARB" },
+ { (PROC)glMultiTexCoord3sARB, "glMultiTexCoord3sARB" },
+ { (PROC)glMultiTexCoord3svARB, "glMultiTexCoord3svARB" },
+ { (PROC)glMultiTexCoord4dARB, "glMultiTexCoord4dARB" },
+ { (PROC)glMultiTexCoord4dvARB, "glMultiTexCoord4dvARB" },
+ { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4fARB" },
+ { (PROC)glMultiTexCoord4fvARB, "glMultiTexCoord4fvARB" },
+ { (PROC)glMultiTexCoord4iARB, "glMultiTexCoord4iARB" },
+ { (PROC)glMultiTexCoord4ivARB, "glMultiTexCoord4ivARB" },
+ { (PROC)glMultiTexCoord4sARB, "glMultiTexCoord4sARB" },
+ { (PROC)glMultiTexCoord4svARB, "glMultiTexCoord4svARB" },
+
+ // Descent3 doesn't use correct string, hence this hack
+ { (PROC)glMultiTexCoord4fARB, "glMultiTexCoord4f" },
+
+ // Quake2 SGIS multitexture
+ { (PROC)gldSelectTextureSGIS, "glSelectTextureSGIS" },
+ { (PROC)gldMTexCoord2fSGIS, "glMTexCoord2fSGIS" },
+ { (PROC)gldMTexCoord2fvSGIS, "glMTexCoord2fvSGIS" },
+
+ { NULL, "\0" }
+};
+
+//---------------------------------------------------------------------------
+
+PROC gldGetProcAddress_DX(
+ LPCSTR a)
+{
+ int i;
+ PROC proc = NULL;
+
+ for (i=0; GLD_extList[i].proc; i++) {
+ if (!strcmp(a, GLD_extList[i].name)) {
+ proc = GLD_extList[i].proc;
+ break;
+ }
+ }
+
+ if (glb.bMultitexture) {
+ for (i=0; GLD_multitexList[i].proc; i++) {
+ if (!strcmp(a, GLD_multitexList[i].name)) {
+ proc = GLD_multitexList[i].proc;
+ break;
+ }
+ }
+ }
+
+ gldLogPrintf(GLDLOG_INFO, "GetProcAddress: %s (%s)", a, proc ? "OK" : "Failed");
+
+ return proc;
+}
+
+//---------------------------------------------------------------------------
+
+void gldEnableExtensions_DX9(
+ GLcontext *ctx)
+{
+ GLuint i;
+
+ // Mesa enables some extensions by default.
+ // This table decides which ones we want to switch off again.
+
+ // NOTE: GL_EXT_compiled_vertex_array appears broken.
+
+ const char *gld_disable_extensions[] = {
+// "GL_ARB_transpose_matrix",
+// "GL_EXT_compiled_vertex_array",
+// "GL_EXT_polygon_offset",
+// "GL_EXT_rescale_normal",
+ "GL_EXT_texture3D",
+// "GL_NV_texgen_reflection",
+ NULL
+ };
+
+ const char *gld_multitex_extensions[] = {
+ "GL_ARB_multitexture", // Quake 3
+ NULL
+ };
+
+ // Quake 2 engines
+ const char *szGL_SGIS_multitexture = "GL_SGIS_multitexture";
+
+ const char *gld_enable_extensions[] = {
+ "GL_EXT_texture_env_add", // Quake 3
+ "GL_ARB_texture_env_add", // Quake 3
+ NULL
+ };
+
+ for (i=0; gld_disable_extensions[i]; i++) {
+ _mesa_disable_extension(ctx, gld_disable_extensions[i]);
+ }
+
+ for (i=0; gld_enable_extensions[i]; i++) {
+ _mesa_enable_extension(ctx, gld_enable_extensions[i]);
+ }
+
+ if (glb.bMultitexture) {
+ for (i=0; gld_multitex_extensions[i]; i++) {
+ _mesa_enable_extension(ctx, gld_multitex_extensions[i]);
+ }
+
+ // GL_SGIS_multitexture
+ // NOTE: Quake2 ran *slower* with this enabled, so I've
+ // disabled it for now.
+ // Fair bit slower on GeForce256,
+ // Much slower on 3dfx Voodoo5 5500.
+// _mesa_add_extension(ctx, GL_TRUE, szGL_SGIS_multitexture, 0);
+
+ }
+
+ _mesa_enable_imaging_extensions(ctx);
+ _mesa_enable_1_3_extensions(ctx);
+ _mesa_enable_1_4_extensions(ctx);
+}
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_pipeline_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_pipeline_dx9.c
new file mode 100644
index 0000000000..c69ad26dfe
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_pipeline_dx9.c
@@ -0,0 +1,77 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Mesa transformation pipeline with GLDirect fastpath
+*
+****************************************************************************/
+
+//#include "../GLDirect.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx9.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+//---------------------------------------------------------------------------
+
+extern struct gl_pipeline_stage _gld_d3d_render_stage;
+extern struct gl_pipeline_stage _gld_mesa_render_stage;
+
+static const struct gl_pipeline_stage *gld_pipeline[] = {
+ &_gld_d3d_render_stage, // Direct3D TnL
+ &_tnl_vertex_transform_stage,
+ &_tnl_normal_transform_stage,
+ &_tnl_lighting_stage,
+ &_tnl_fog_coordinate_stage, /* TODO: Omit fog stage. ??? */
+ &_tnl_texgen_stage,
+ &_tnl_texture_transform_stage,
+ &_tnl_point_attenuation_stage,
+ &_gld_mesa_render_stage, // Mesa TnL, D3D rendering
+ 0,
+};
+
+//---------------------------------------------------------------------------
+
+void gldInstallPipeline_DX9(
+ GLcontext *ctx)
+{
+ // Remove any existing pipeline stages,
+ // then install GLDirect pipeline stages.
+
+ _tnl_destroy_pipeline(ctx);
+ _tnl_install_pipeline(ctx, gld_pipeline);
+}
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c
new file mode 100644
index 0000000000..6edbe702a7
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_primitive_dx9.c
@@ -0,0 +1,1446 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Primitive (points/lines/tris/quads) rendering
+*
+****************************************************************************/
+
+//#include "../GLDirect.h"
+
+//#include "gld_dx8.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx9.h"
+
+#include "glheader.h"
+#include "context.h"
+#include "colormac.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "array_cache/acache.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast_setup/ss_context.h"
+#include "swrast/s_context.h"
+#include "swrast/s_depth.h"
+#include "swrast/s_lines.h"
+#include "swrast/s_triangle.h"
+#include "swrast/s_trispan.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+// Disable compiler complaints about unreferenced local variables
+#pragma warning (disable:4101)
+
+//---------------------------------------------------------------------------
+// Helper defines for primitives
+//---------------------------------------------------------------------------
+
+//static const float ooZ = 1.0f / 65536.0f; // One over Z
+
+#define GLD_COLOUR (D3DCOLOR_RGBA(swv->color[0], swv->color[1], swv->color[2], swv->color[3]))
+#define GLD_SPECULAR (D3DCOLOR_RGBA(swv->specular[0], swv->specular[1], swv->specular[2], swv->specular[3]))
+#define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y))
+
+//---------------------------------------------------------------------------
+// 2D vertex setup
+//---------------------------------------------------------------------------
+
+#define GLD_SETUP_2D_VARS_POINTS \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \
+ GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pPoints; \
+ SScontext *ss = SWSETUP_CONTEXT(ctx); \
+ SWvertex *swv; \
+ DWORD dwSpecularColour; \
+ DWORD dwFlatColour
+
+#define GLD_SETUP_2D_VARS_LINES \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \
+ GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pLines; \
+ SScontext *ss = SWSETUP_CONTEXT(ctx); \
+ SWvertex *swv; \
+ DWORD dwSpecularColour; \
+ DWORD dwFlatColour
+
+#define GLD_SETUP_2D_VARS_TRIANGLES \
+ BOOL bFog = ctx->Fog.Enabled; \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \
+ GLD_2D_VERTEX *pV = (GLD_2D_VERTEX*)gld->PB2d.pTriangles; \
+ SScontext *ss = SWSETUP_CONTEXT(ctx); \
+ SWvertex *swv; \
+ DWORD dwSpecularColour; \
+ DWORD dwFlatColour; \
+ GLuint facing = 0; \
+ struct vertex_buffer *VB; \
+ GLchan (*vbcolor)[4]; \
+ GLchan (*vbspec)[4]
+
+#define GLD_SETUP_GET_SWVERT(s) \
+ swv = &ss->verts[##s]
+
+#define GLD_SETUP_2D_VERTEX \
+ pV->x = swv->win[0]; \
+ pV->y = GLD_FLIP_Y(swv->win[1]); \
+ pV->rhw = swv->win[3]
+
+#define GLD_SETUP_SMOOTH_COLOUR \
+ pV->diffuse = GLD_COLOUR
+
+#define GLD_SETUP_GET_FLAT_COLOUR \
+ dwFlatColour = GLD_COLOUR
+#define GLD_SETUP_GET_FLAT_FOG_COLOUR \
+ dwFlatColour = _gldComputeFog(ctx, swv)
+
+#define GLD_SETUP_USE_FLAT_COLOUR \
+ pV->diffuse = dwFlatColour
+
+#define GLD_SETUP_GET_FLAT_SPECULAR \
+ dwSpecularColour= GLD_SPECULAR
+
+#define GLD_SETUP_USE_FLAT_SPECULAR \
+ pV->specular = dwSpecularColour
+
+#define GLD_SETUP_DEPTH \
+ pV->sz = swv->win[2] / ctx->DepthMaxF
+// pV->z = swv->win[2] * ooZ;
+
+#define GLD_SETUP_SPECULAR \
+ pV->specular = GLD_SPECULAR
+
+#define GLD_SETUP_FOG \
+ pV->diffuse = _gldComputeFog(ctx, swv)
+
+#define GLD_SETUP_TEX0 \
+ pV->t0_u = swv->texcoord[0][0]; \
+ pV->t0_v = swv->texcoord[0][1]
+
+#define GLD_SETUP_TEX1 \
+ pV->t1_u = swv->texcoord[1][0]; \
+ pV->t1_v = swv->texcoord[1][1]
+
+#define GLD_SETUP_LIGHTING(v) \
+ if (facing == 1) { \
+ pV->diffuse = D3DCOLOR_RGBA(vbcolor[##v][0], vbcolor[##v][1], vbcolor[##v][2], vbcolor[##v][3]); \
+ if (vbspec) { \
+ pV->specular = D3DCOLOR_RGBA(vbspec[##v][0], vbspec[##v][1], vbspec[##v][2], vbspec[##v][3]); \
+ } \
+ } else { \
+ if (bFog) \
+ GLD_SETUP_FOG; \
+ else \
+ GLD_SETUP_SMOOTH_COLOUR; \
+ GLD_SETUP_SPECULAR; \
+ }
+
+#define GLD_SETUP_GET_FLAT_LIGHTING(v) \
+ if (facing == 1) { \
+ dwFlatColour = D3DCOLOR_RGBA(vbcolor[##v][0], vbcolor[##v][1], vbcolor[##v][2], vbcolor[##v][3]); \
+ if (vbspec) { \
+ dwSpecularColour = D3DCOLOR_RGBA(vbspec[##v][0], vbspec[##v][1], vbspec[##v][2], vbspec[##v][3]); \
+ } \
+ }
+
+#define GLD_SETUP_TWOSIDED_LIGHTING \
+ /* Two-sided lighting */ \
+ if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) { \
+ SWvertex *verts = SWSETUP_CONTEXT(ctx)->verts; \
+ SWvertex *v[3]; \
+ GLfloat ex,ey,fx,fy,cc; \
+ /* Get vars for later */ \
+ VB = &TNL_CONTEXT(ctx)->vb; \
+ vbcolor = (GLchan (*)[4])VB->ColorPtr[1]->Ptr; \
+ if (VB->SecondaryColorPtr[1]) { \
+ vbspec = (GLchan (*)[4])VB->SecondaryColorPtr[1]->Ptr; \
+ } else { \
+ vbspec = NULL; \
+ } \
+ v[0] = &verts[v0]; \
+ v[1] = &verts[v1]; \
+ v[2] = &verts[v2]; \
+ ex = v[0]->win[0] - v[2]->win[0]; \
+ ey = v[0]->win[1] - v[2]->win[1]; \
+ fx = v[1]->win[0] - v[2]->win[0]; \
+ fy = v[1]->win[1] - v[2]->win[1]; \
+ cc = ex*fy - ey*fx; \
+ facing = (cc < 0.0) ^ ctx->Polygon._FrontBit; \
+ }
+
+//---------------------------------------------------------------------------
+// 3D vertex setup
+//---------------------------------------------------------------------------
+
+#define GLD_SETUP_3D_VARS_POINTS \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \
+ GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pPoints; \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ GLfloat (*p4f)[4]; \
+ GLfloat (*tc)[4]; \
+ DWORD dwColor;
+
+#define GLD_SETUP_3D_VARS_LINES \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \
+ GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pLines; \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ GLfloat (*p4f)[4]; \
+ GLfloat (*tc)[4]; \
+ DWORD dwColor;
+
+#define GLD_SETUP_3D_VARS_TRIANGLES \
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx); \
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx); \
+ GLD_3D_VERTEX *pV = (GLD_3D_VERTEX*)gld->PB3d.pTriangles; \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ GLfloat (*p4f)[4]; \
+ GLfloat (*tc)[4]; \
+ DWORD dwColor;
+
+#define GLD_SETUP_3D_VERTEX(v) \
+ p4f = VB->ObjPtr->data; \
+ pV->Position.x = p4f[##v][0]; \
+ pV->Position.y = p4f[##v][1]; \
+ pV->Position.z = p4f[##v][2];
+
+#define GLD_SETUP_SMOOTH_COLOUR_3D(v) \
+ p4f = (GLfloat (*)[4])VB->ColorPtr[0]->Ptr; \
+ pV->Diffuse = D3DCOLOR_COLORVALUE(p4f[##v][0], p4f[##v][1], p4f[##v][2], p4f[##v][3]);
+
+
+#define GLD_SETUP_GET_FLAT_COLOUR_3D(v) \
+ p4f = (GLfloat (*)[4])VB->ColorPtr[0]->Ptr; \
+ dwColor = D3DCOLOR_COLORVALUE(p4f[##v][0], p4f[##v][1], p4f[##v][2], p4f[##v][3]);
+
+#define GLD_SETUP_USE_FLAT_COLOUR_3D \
+ pV->Diffuse = dwColor;
+
+#define GLD_SETUP_TEX0_3D(v) \
+ if (VB->TexCoordPtr[0]) { \
+ tc = VB->TexCoordPtr[0]->data; \
+ pV->TexUnit0.x = tc[##v][0]; \
+ pV->TexUnit0.y = tc[##v][1]; \
+ }
+
+#define GLD_SETUP_TEX1_3D(v) \
+ if (VB->TexCoordPtr[1]) { \
+ tc = VB->TexCoordPtr[1]->data; \
+ pV->TexUnit1.x = tc[##v][0]; \
+ pV->TexUnit1.y = tc[##v][1]; \
+ }
+
+//---------------------------------------------------------------------------
+// Helper functions
+//---------------------------------------------------------------------------
+
+__inline DWORD _gldComputeFog(
+ GLcontext *ctx,
+ SWvertex *swv)
+{
+ // Full fog calculation.
+ // Based on Mesa code.
+
+ GLchan rFog, gFog, bFog;
+ GLchan fR, fG, fB;
+ const GLfloat f = swv->fog;
+ const GLfloat g = 1.0 - f;
+
+ UNCLAMPED_FLOAT_TO_CHAN(rFog, ctx->Fog.Color[RCOMP]);
+ UNCLAMPED_FLOAT_TO_CHAN(gFog, ctx->Fog.Color[GCOMP]);
+ UNCLAMPED_FLOAT_TO_CHAN(bFog, ctx->Fog.Color[BCOMP]);
+ fR = f * swv->color[0] + g * rFog;
+ fG = f * swv->color[1] + g * gFog;
+ fB = f * swv->color[2] + g * bFog;
+ return D3DCOLOR_RGBA(fR, fG, fB, swv->color[3]);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_ResetLineStipple_DX9(
+ GLcontext *ctx)
+{
+ // TODO: Fake stipple with a 32x32 texture.
+}
+
+//---------------------------------------------------------------------------
+// 2D (post-transformed) primitives
+//---------------------------------------------------------------------------
+
+void gld_Points2D_DX9(
+ GLcontext *ctx,
+ GLuint first,
+ GLuint last)
+{
+ GLD_SETUP_2D_VARS_POINTS;
+
+ unsigned i;
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ // _Size is already clamped to MaxPointSize and MinPointSize
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_POINTSIZE, *((DWORD*)&ctx->Point._Size));
+
+ if (VB->Elts) {
+ for (i=first; i<last; i++, pV++) {
+ if (VB->ClipMask[VB->Elts[i]] == 0) {
+// _swrast_Point( ctx, &verts[VB->Elts[i]] );
+ GLD_SETUP_GET_SWVERT(VB->Elts[i]);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ }
+ }
+ } else {
+ GLD_SETUP_GET_SWVERT(first);
+ for (i=first; i<last; i++, swv++, pV++) {
+ if (VB->ClipMask[i] == 0) {
+// _swrast_Point( ctx, &verts[i] );
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ }
+ }
+ }
+
+ gld->PB2d.pPoints = (BYTE*)pV;
+ gld->PB2d.nPoints += (last-first);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DFlat_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_2D_VARS_LINES;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_GET_FLAT_SPECULAR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ gld->PB2d.pLines = (BYTE*)pV;
+ gld->PB2d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DSmooth_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_2D_VARS_LINES;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_SPECULAR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ gld->PB2d.pLines = (BYTE*)pV;
+ gld->PB2d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DFlat_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DSmooth_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DFlatExtras_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v2);
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ if (bFog)
+ GLD_SETUP_GET_FLAT_FOG_COLOUR;
+ else
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_GET_FLAT_SPECULAR;
+ GLD_SETUP_GET_FLAT_LIGHTING(v2);
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DSmoothExtras_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v0);
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v0);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v1);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v2);
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DFlat_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DSmooth_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_SMOOTH_COLOUR;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DFlatExtras_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v3);
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ if (bFog)
+ GLD_SETUP_GET_FLAT_FOG_COLOUR;
+ else
+ GLD_SETUP_GET_FLAT_COLOUR;
+ GLD_SETUP_GET_FLAT_SPECULAR;
+ GLD_SETUP_GET_FLAT_LIGHTING(v3);
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_USE_FLAT_COLOUR;
+ GLD_SETUP_USE_FLAT_SPECULAR;
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DSmoothExtras_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_2D_VARS_TRIANGLES;
+
+ GLD_SETUP_TWOSIDED_LIGHTING(v0);
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v0);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v1);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v1);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v2);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v2);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v2);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v3);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v3);
+ pV++;
+
+ GLD_SETUP_GET_SWVERT(v0);
+ GLD_SETUP_2D_VERTEX;
+ GLD_SETUP_DEPTH;
+ GLD_SETUP_TEX0;
+ GLD_SETUP_TEX1;
+ GLD_SETUP_LIGHTING(v0);
+ pV++;
+
+ gld->PB2d.pTriangles = (BYTE*)pV;
+ gld->PB2d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+// 3D (pre-transformed) primitives
+//---------------------------------------------------------------------------
+
+void gld_Points3D_DX9(
+ GLcontext *ctx,
+ GLuint first,
+ GLuint last)
+{
+ GLD_SETUP_3D_VARS_POINTS
+
+ unsigned i;
+// struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ // _Size is already clamped to MaxPointSize and MinPointSize
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_POINTSIZE, *((DWORD*)&ctx->Point._Size));
+
+ if (VB->Elts) {
+ for (i=first; i<last; i++, pV++) {
+ if (VB->ClipMask[VB->Elts[i]] == 0) {
+// _swrast_Point( ctx, &verts[VB->Elts[i]] );
+// GLD_SETUP_GET_SWVERT(VB->Elts[i]);
+ GLD_SETUP_3D_VERTEX(VB->Elts[i])
+ GLD_SETUP_SMOOTH_COLOUR_3D(i)
+ GLD_SETUP_TEX0_3D(i)
+ GLD_SETUP_TEX1_3D(i)
+ }
+ }
+ } else {
+// GLD_SETUP_GET_SWVERT(first);
+ for (i=first; i<last; i++, pV++) {
+ if (VB->ClipMask[i] == 0) {
+// _swrast_Point( ctx, &verts[i] );
+ GLD_SETUP_3D_VERTEX(i)
+ GLD_SETUP_SMOOTH_COLOUR_3D(i)
+ GLD_SETUP_TEX0_3D(i)
+ GLD_SETUP_TEX1_3D(i)
+ }
+ }
+ }
+/*
+ for (i=first; i<last; i++, pV++) {
+ GLD_SETUP_3D_VERTEX(i)
+ GLD_SETUP_SMOOTH_COLOUR_3D(i)
+ GLD_SETUP_TEX0_3D(i)
+ GLD_SETUP_TEX1_3D(i)
+ }
+*/
+ gld->PB3d.pPoints = (BYTE*)pV;
+ gld->PB3d.nPoints += (last-first);
+}
+
+//---------------------------------------------------------------------------
+// Line functions
+//---------------------------------------------------------------------------
+
+void gld_Line3DFlat_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_3D_VARS_LINES
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_GET_FLAT_COLOUR_3D(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ gld->PB3d.pLines = (BYTE*)pV;
+ gld->PB3d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line3DSmooth_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1)
+{
+ GLD_SETUP_3D_VARS_LINES
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ gld->PB3d.pLines = (BYTE*)pV;
+ gld->PB3d.nLines++;
+}
+
+//---------------------------------------------------------------------------
+// Triangle functions
+//---------------------------------------------------------------------------
+
+void gld_Triangle3DFlat_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ GLD_SETUP_GET_FLAT_COLOUR_3D(v2)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle3DSmooth_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+// Quad functions
+//---------------------------------------------------------------------------
+
+void gld_Quad3DFlat_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v3)
+ GLD_SETUP_GET_FLAT_COLOUR_3D(v3)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v3)
+ GLD_SETUP_TEX1_3D(v3)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v3)
+ GLD_SETUP_USE_FLAT_COLOUR_3D
+ GLD_SETUP_TEX0_3D(v3)
+ GLD_SETUP_TEX1_3D(v3)
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad3DSmooth_DX9(
+ GLcontext *ctx,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLD_SETUP_3D_VARS_TRIANGLES
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v1)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v1)
+ GLD_SETUP_TEX0_3D(v1)
+ GLD_SETUP_TEX1_3D(v1)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v2)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v2)
+ GLD_SETUP_TEX0_3D(v2)
+ GLD_SETUP_TEX1_3D(v2)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v3)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v3)
+ GLD_SETUP_TEX0_3D(v3)
+ GLD_SETUP_TEX1_3D(v3)
+ pV++;
+
+ GLD_SETUP_3D_VERTEX(v0)
+ GLD_SETUP_SMOOTH_COLOUR_3D(v0)
+ GLD_SETUP_TEX0_3D(v0)
+ GLD_SETUP_TEX1_3D(v0)
+ pV++;
+
+ gld->PB3d.pTriangles = (BYTE*)pV;
+ gld->PB3d.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+// Vertex setup for two-sided-lighting vertex shader
+//---------------------------------------------------------------------------
+
+/*
+
+void gld_Points2DTwoside_DX9(GLcontext *ctx, GLuint first, GLuint last)
+{
+ // NOTE: Two-sided lighting does not apply to Points
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1)
+{
+ // NOTE: Two-sided lighting does not apply to Lines
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Line2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1)
+{
+ // NOTE: Two-sided lighting does not apply to Lines
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2)
+{
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Triangle2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+ GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles;
+ SScontext *ss = SWSETUP_CONTEXT(ctx);
+ SWvertex *swv;
+ DWORD dwSpecularColour;
+ DWORD dwFlatColour;
+ GLuint facing = 0;
+ struct vertex_buffer *VB;
+ GLchan (*vbcolor)[4];
+ GLchan (*vbspec)[4];
+
+ // Reciprocal of DepthMax
+ const float ooDepthMax = 1.0f / ctx->DepthMaxF;
+
+ // 1st vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 2nd vert
+ swv = &ss->verts[v1];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 3rd vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ gld->PBtwosidelight.pTriangles = (BYTE*)pV;
+ gld->PBtwosidelight.nTriangles++;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DFlatTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+ GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles;
+ SScontext *ss = SWSETUP_CONTEXT(ctx);
+ SWvertex *swv;
+ DWORD dwSpecularColour;
+ DWORD dwFlatColour;
+ GLuint facing = 0;
+ struct vertex_buffer *VB;
+ GLchan (*vbcolor)[4];
+ GLchan (*vbspec)[4];
+
+ // Reciprocal of DepthMax
+ const float ooDepthMax = 1.0f / ctx->DepthMaxF;
+
+ // 1st vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 2nd vert
+ swv = &ss->verts[v1];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 3rd vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 4th vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 5th vert
+ swv = &ss->verts[v3];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 6th vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ gld->PBtwosidelight.pTriangles = (BYTE*)pV;
+ gld->PBtwosidelight.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Quad2DSmoothTwoside_DX9(GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+ GLD_TWOSIDED_VERTEX *pV = (GLD_TWOSIDED_VERTEX*)gld->PBtwosidelight.pTriangles;
+ SScontext *ss = SWSETUP_CONTEXT(ctx);
+ SWvertex *swv;
+ DWORD dwSpecularColour;
+ DWORD dwFlatColour;
+ GLuint facing = 0;
+ struct vertex_buffer *VB;
+ GLchan (*vbcolor)[4];
+ GLchan (*vbspec)[4];
+
+ // Reciprocal of DepthMax
+ const float ooDepthMax = 1.0f / ctx->DepthMaxF;
+
+ // 1st vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 2nd vert
+ swv = &ss->verts[v1];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 3rd vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 4th vert
+ swv = &ss->verts[v2];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 5th vert
+ swv = &ss->verts[v3];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ // 6th vert
+ swv = &ss->verts[v0];
+ pV->Position.x = swv->win[0];
+ pV->Position.y = GLD_FLIP_Y(swv->win[1]);
+ pV->Position.z = swv->win[2] * ooDepthMax;
+ pV->Position.w = swv->win[3];
+ pV->TexUnit0.x = swv->texcoord[0][0];
+ pV->TexUnit0.y = swv->texcoord[0][1];
+ pV->TexUnit1.x = swv->texcoord[1][0];
+ pV->TexUnit1.y = swv->texcoord[1][1];
+ pV->FrontDiffuse = GLD_COLOUR;
+ pV->FrontSpecular = GLD_SPECULAR;
+ pV++;
+
+ gld->PBtwosidelight.pTriangles = (BYTE*)pV;
+ gld->PBtwosidelight.nTriangles += 2;
+}
+
+//---------------------------------------------------------------------------
+
+*/
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_texture_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_texture_dx9.c
new file mode 100644
index 0000000000..ad2f4aab6f
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_texture_dx9.c
@@ -0,0 +1,1965 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Texture / Bitmap functions
+*
+****************************************************************************/
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx9.h"
+
+#include <d3dx9tex.h>
+
+#include "texformat.h"
+#include "colormac.h"
+#include "texstore.h"
+#include "image.h"
+// #include "mem.h"
+
+//---------------------------------------------------------------------------
+
+#define GLD_FLIP_HEIGHT(y,h) (gldCtx->dwHeight - (y) - (h))
+
+//---------------------------------------------------------------------------
+// 1D texture fetch
+//---------------------------------------------------------------------------
+
+#define CHAN_SRC( t, i, j, k, sz ) \
+ ((GLchan *)(t)->Data + (i) * (sz))
+#define UBYTE_SRC( t, i, j, k, sz ) \
+ ((GLubyte *)(t)->Data + (i) * (sz))
+#define USHORT_SRC( t, i, j, k ) \
+ ((GLushort *)(t)->Data + (i))
+#define FLOAT_SRC( t, i, j, k ) \
+ ((GLfloat *)(t)->Data + (i))
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ GLchan *rgba = (GLchan *) texel;
+ rgba[RCOMP] = src[2];
+ rgba[GCOMP] = src[1];
+ rgba[BCOMP] = src[0];
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_1d_texel_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+#undef CHAN_SRC
+#undef UBYTE_SRC
+#undef USHORT_SRC
+#undef FLOAT_SRC
+
+//---------------------------------------------------------------------------
+// 2D texture fetch
+//---------------------------------------------------------------------------
+
+#define CHAN_SRC( t, i, j, k, sz ) \
+ ((GLchan *)(t)->Data + ((t)->Width * (j) + (i)) * (sz))
+#define UBYTE_SRC( t, i, j, k, sz ) \
+ ((GLubyte *)(t)->Data + ((t)->Width * (j) + (i)) * (sz))
+#define USHORT_SRC( t, i, j, k ) \
+ ((GLushort *)(t)->Data + ((t)->Width * (j) + (i)))
+#define FLOAT_SRC( t, i, j, k ) \
+ ((GLfloat *)(t)->Data + ((t)->Width * (j) + (i)))
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ GLchan *rgba = (GLchan *) texel;
+ rgba[RCOMP] = src[2];
+ rgba[GCOMP] = src[1];
+ rgba[BCOMP] = src[0];
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_2d_texel_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+#undef CHAN_SRC
+#undef UBYTE_SRC
+#undef USHORT_SRC
+#undef FLOAT_SRC
+
+//---------------------------------------------------------------------------
+// 3D texture fetch
+//---------------------------------------------------------------------------
+
+#define CHAN_SRC( t, i, j, k, sz ) \
+ (GLchan *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)) * (sz)
+#define UBYTE_SRC( t, i, j, k, sz ) \
+ ((GLubyte *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)) * (sz))
+#define USHORT_SRC( t, i, j, k ) \
+ ((GLushort *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)))
+#define FLOAT_SRC( t, i, j, k ) \
+ ((GLfloat *)(t)->Data + (((t)->Height * (k) + (j)) * \
+ (t)->Width + (i)))
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_X8R8G8B8(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLchan *src = CHAN_SRC( texImage, i, j, k, 4 );
+ GLchan *rgba = (GLchan *) texel;
+ rgba[RCOMP] = src[2];
+ rgba[GCOMP] = src[1];
+ rgba[BCOMP] = src[0];
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_X1R5G5B5(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 10) & 0xf8) * 255 / 0xf8 );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 5) & 0xf8) * 255 / 0xf8 );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf8) * 255 / 0xf8 );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_fetch_3d_texel_X4R4G4B4(
+ const struct gl_texture_image *texImage,
+ GLint i, GLint j, GLint k, GLvoid *texel )
+{
+ const GLushort *src = USHORT_SRC( texImage, i, j, k );
+ GLchan *rgba = (GLchan *) texel; GLushort s = *src;
+ rgba[RCOMP] = UBYTE_TO_CHAN( ((s >> 8) & 0xf) * 255 / 0xf );
+ rgba[GCOMP] = UBYTE_TO_CHAN( ((s >> 4) & 0xf) * 255 / 0xf );
+ rgba[BCOMP] = UBYTE_TO_CHAN( ((s ) & 0xf) * 255 / 0xf );
+ rgba[ACOMP] = CHAN_MAX;
+}
+
+//---------------------------------------------------------------------------
+
+#undef CHAN_SRC
+#undef UBYTE_SRC
+#undef USHORT_SRC
+#undef FLOAT_SRC
+
+//---------------------------------------------------------------------------
+// Direct3D texture formats that have no Mesa equivalent
+//---------------------------------------------------------------------------
+
+const struct gl_texture_format _gld_texformat_X8R8G8B8 = {
+ MESA_FORMAT_ARGB8888, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+// GL_UNSIGNED_BYTE, /* Type */
+ 8, /* RedBits */
+ 8, /* GreenBits */
+ 8, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 4, /* TexelBytes */
+ gld_fetch_1d_texel_X8R8G8B8, /* FetchTexel1D */
+ gld_fetch_2d_texel_X8R8G8B8, /* FetchTexel2D */
+ gld_fetch_3d_texel_X8R8G8B8, /* FetchTexel3D */
+};
+
+const struct gl_texture_format _gld_texformat_X1R5G5B5 = {
+ MESA_FORMAT_ARGB1555, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+// GL_UNSIGNED_SHORT_1_5_5_5_REV, /* Type */
+ 5, /* RedBits */
+ 5, /* GreenBits */
+ 5, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 2, /* TexelBytes */
+ gld_fetch_1d_texel_X1R5G5B5, /* FetchTexel1D */
+ gld_fetch_2d_texel_X1R5G5B5, /* FetchTexel2D */
+ gld_fetch_3d_texel_X1R5G5B5, /* FetchTexel3D */
+};
+
+const struct gl_texture_format _gld_texformat_X4R4G4B4 = {
+ MESA_FORMAT_ARGB4444, /* MesaFormat */
+ GL_RGBA, /* BaseFormat */
+// GL_UNSIGNED_SHORT_4_4_4_4_REV, /* Type */
+ 4, /* RedBits */
+ 4, /* GreenBits */
+ 4, /* BlueBits */
+ 0, /* AlphaBits */
+ 0, /* LuminanceBits */
+ 0, /* IntensityBits */
+ 0, /* IndexBits */
+ 0, /* DepthBits */
+ 2, /* TexelBytes */
+ gld_fetch_1d_texel_X4R4G4B4, /* FetchTexel1D */
+ gld_fetch_2d_texel_X4R4G4B4, /* FetchTexel2D */
+ gld_fetch_3d_texel_X4R4G4B4, /* FetchTexel3D */
+};
+
+//---------------------------------------------------------------------------
+// Texture unit constants
+//---------------------------------------------------------------------------
+
+// List of possible combinations of texture environments.
+// Example: GLD_TEXENV_MODULATE_RGBA means
+// GL_MODULATE, GL_RGBA base internal format.
+#define GLD_TEXENV_DECAL_RGB 0
+#define GLD_TEXENV_DECAL_RGBA 1
+#define GLD_TEXENV_DECAL_ALPHA 2
+#define GLD_TEXENV_REPLACE_RGB 3
+#define GLD_TEXENV_REPLACE_RGBA 4
+#define GLD_TEXENV_REPLACE_ALPHA 5
+#define GLD_TEXENV_MODULATE_RGB 6
+#define GLD_TEXENV_MODULATE_RGBA 7
+#define GLD_TEXENV_MODULATE_ALPHA 8
+#define GLD_TEXENV_BLEND_RGB 9
+#define GLD_TEXENV_BLEND_RGBA 10
+#define GLD_TEXENV_BLEND_ALPHA 11
+#define GLD_TEXENV_ADD_RGB 12
+#define GLD_TEXENV_ADD_RGBA 13
+#define GLD_TEXENV_ADD_ALPHA 14
+
+// Per-stage (i.e. per-unit) texture environment
+typedef struct {
+ DWORD ColorArg1; // Colour argument 1
+ D3DTEXTUREOP ColorOp; // Colour operation
+ DWORD ColorArg2; // Colour argument 2
+ DWORD AlphaArg1; // Alpha argument 1
+ D3DTEXTUREOP AlphaOp; // Alpha operation
+ DWORD AlphaArg2; // Alpha argument 2
+} GLD_texenv;
+
+// TODO: Do we really need to set ARG1 and ARG2 every time?
+// They seem to always be TEXTURE and CURRENT respectively.
+
+// C = Colour out
+// A = Alpha out
+// Ct = Colour from Texture
+// Cf = Colour from fragment (diffuse)
+// At = Alpha from Texture
+// Af = Alpha from fragment (diffuse)
+// Cc = GL_TEXTURE_ENV_COLOUR (GL_BLEND)
+const GLD_texenv gldTexEnv[] = {
+ // DECAL_RGB: C=Ct, A=Af
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // DECAL_RGBA: C=Cf(1-At)+CtAt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_BLENDTEXTUREALPHA, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // DECAL_ALPHA: <undefined> use DECAL_RGB
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+
+ // REPLACE_RGB: C=Ct, A=Af
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // REPLACE_RGBA: C=Ct, A=At
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT},
+ // REPLACE_ALPHA: C=Cf, A=At
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG1, D3DTA_CURRENT},
+
+ // MODULATE_RGB: C=CfCt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // MODULATE_RGBA: C=CfCt, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+ // MODULATE_ALPHA: C=Cf, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+
+ // BLEND_RGB: C=Cf(1-Ct)+CcCt, A=Af
+ {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // BLEND_RGBA: C=Cf(1-Ct)+CcCt, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_LERP, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+ // BLEND_ALPHA: C=Cf, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+
+ // ADD_RGB: C=Cf+Ct, A=Af
+ {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT},
+ // ADD_RGBA: C=Cf+Ct, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_ADD, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+ // ADD_ALPHA: C=Cf, A=AfAt
+ {D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_CURRENT,
+ D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT},
+};
+
+//---------------------------------------------------------------------------
+
+D3DTEXTUREADDRESS _gldConvertWrap(
+ GLenum wrap)
+{
+ return (wrap == GL_CLAMP) ? D3DTADDRESS_CLAMP : D3DTADDRESS_WRAP;
+}
+
+//---------------------------------------------------------------------------
+
+D3DTEXTUREFILTERTYPE _gldConvertMagFilter(
+ GLenum magfilter)
+{
+ return (magfilter == GL_LINEAR) ? D3DTEXF_LINEAR : D3DTEXF_POINT;
+}
+
+//---------------------------------------------------------------------------
+
+void _gldConvertMinFilter(
+ GLenum minfilter,
+ D3DTEXTUREFILTERTYPE *min_filter,
+ D3DTEXTUREFILTERTYPE *mip_filter)
+{
+ switch (minfilter) {
+ case GL_NEAREST:
+ *min_filter = D3DTEXF_POINT;
+ *mip_filter = D3DTEXF_NONE;
+ break;
+ case GL_LINEAR:
+ *min_filter = D3DTEXF_LINEAR;
+ *mip_filter = D3DTEXF_NONE;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ *min_filter = D3DTEXF_POINT;
+ *mip_filter = D3DTEXF_POINT;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ *min_filter = D3DTEXF_LINEAR;
+ *mip_filter = D3DTEXF_POINT;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ *min_filter = D3DTEXF_POINT;
+ *mip_filter = D3DTEXF_LINEAR;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ *min_filter = D3DTEXF_LINEAR;
+ *mip_filter = D3DTEXF_LINEAR;
+ break;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+D3DFORMAT _gldGLFormatToD3DFormat(
+ GLenum internalFormat)
+{
+ switch (internalFormat) {
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ // LUNIMANCE != INTENSITY, but D3D doesn't have I8 textures
+ return D3DFMT_L8;
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return D3DFMT_L8;
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return D3DFMT_A8;
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ return D3DFMT_X8R8G8B8;
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ return D3DFMT_A8L8;
+ case GL_R3_G3_B2:
+ // TODO: Mesa does not support RGB332 internally
+ return D3DFMT_X4R4G4B4; //D3DFMT_R3G3B2;
+ case GL_RGB4:
+ return D3DFMT_X4R4G4B4;
+ case GL_RGB5:
+ return D3DFMT_X1R5G5B5;
+ case 3:
+ case GL_RGB:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return D3DFMT_R8G8B8;
+ case GL_RGBA4:
+ return D3DFMT_A4R4G4B4;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA2:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return D3DFMT_A8R8G8B8;
+ case GL_RGB5_A1:
+ return D3DFMT_A1R5G5B5;
+ }
+
+ // Return an acceptable default
+ return D3DFMT_A8R8G8B8;
+}
+
+//---------------------------------------------------------------------------
+
+GLenum _gldDecodeBaseFormat(
+ IDirect3DTexture9 *pTex)
+{
+ // Examine Direct3D texture and return base OpenGL internal texture format
+ // NOTE: We can't use any base format info from Mesa because D3D might have
+ // used a different texture format when we used D3DXCreateTexture().
+
+ // Base internal format is one of (Red Book p355):
+ // GL_ALPHA,
+ // GL_LUMINANCE,
+ // GL_LUMINANCE_ALPHA,
+ // GL_INTENSITY,
+ // GL_RGB,
+ // GL_RGBA
+
+ // NOTE: INTENSITY not used (not supported by Direct3D)
+ // LUMINANCE has same texture functions as RGB
+ // LUMINANCE_ALPHA has same texture functions as RGBA
+
+ // TODO: cache format instead of using GetLevelDesc()
+ D3DSURFACE_DESC desc;
+ _GLD_DX9_TEX(GetLevelDesc(pTex, 0, &desc));
+
+ switch (desc.Format) {
+ case D3DFMT_R8G8B8:
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_R5G6B5:
+ case D3DFMT_X1R5G5B5:
+ case D3DFMT_R3G3B2:
+ case D3DFMT_X4R4G4B4:
+ case D3DFMT_P8:
+ case D3DFMT_L8:
+ return GL_RGB;
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_A1R5G5B5:
+ case D3DFMT_A4R4G4B4:
+ case D3DFMT_A8R3G3B2:
+ case D3DFMT_A8P8:
+ case D3DFMT_A8L8:
+ case D3DFMT_A4L4:
+ return GL_RGBA;
+ case D3DFMT_A8:
+ return GL_ALPHA;
+ // Compressed texture formats. Need to check these...
+ case D3DFMT_DXT1:
+ return GL_RGBA;
+ case D3DFMT_DXT2:
+ return GL_RGB;
+ case D3DFMT_DXT3:
+ return GL_RGBA;
+ case D3DFMT_DXT4:
+ return GL_RGB;
+ case D3DFMT_DXT5:
+ return GL_RGBA;
+ }
+
+ // Fell through. Return arbitary default.
+ return GL_RGBA;
+}
+
+//---------------------------------------------------------------------------
+
+const struct gl_texture_format* _gldMesaFormatForD3DFormat(
+ D3DFORMAT d3dfmt)
+{
+ switch (d3dfmt) {
+ case D3DFMT_A8R8G8B8:
+ return &_mesa_texformat_argb8888;
+ case D3DFMT_R8G8B8:
+ return &_mesa_texformat_rgb888;
+ case D3DFMT_R5G6B5:
+ return &_mesa_texformat_rgb565;
+ case D3DFMT_A4R4G4B4:
+ return &_mesa_texformat_argb4444;
+ case D3DFMT_A1R5G5B5:
+ return &_mesa_texformat_argb1555;
+ case D3DFMT_A8L8:
+ return &_mesa_texformat_al88;
+ case D3DFMT_R3G3B2:
+ return &_mesa_texformat_rgb332;
+ case D3DFMT_A8:
+ return &_mesa_texformat_a8;
+ case D3DFMT_L8:
+ return &_mesa_texformat_l8;
+ case D3DFMT_X8R8G8B8:
+ return &_gld_texformat_X8R8G8B8;
+ case D3DFMT_X1R5G5B5:
+ return &_gld_texformat_X1R5G5B5;
+ case D3DFMT_X4R4G4B4:
+ return &_gld_texformat_X4R4G4B4;
+ }
+
+ // If we reach here then we've made an error somewhere else
+ // by allowing a format that is not supported.
+ assert(0);
+
+ return NULL; // Shut up compiler warning
+}
+
+//---------------------------------------------------------------------------
+// Copy* functions
+//---------------------------------------------------------------------------
+
+void gldCopyTexImage1D_DX9(
+ GLcontext *ctx,
+ GLenum target, GLint level,
+ GLenum internalFormat,
+ GLint x, GLint y,
+ GLsizei width, GLint border )
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexImage2D_DX9(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLenum internalFormat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border)
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexSubImage1D_DX9(
+ GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint x, GLint y, GLsizei width )
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexSubImage2D_DX9(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ // TODO
+}
+
+//---------------------------------------------------------------------------
+
+void gldCopyTexSubImage3D_DX9(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height )
+{
+ // TODO ?
+}
+
+//---------------------------------------------------------------------------
+// Bitmap/Pixel functions
+//---------------------------------------------------------------------------
+
+#define GLD_FLIP_Y(y) (gldCtx->dwHeight - (y))
+
+#define _GLD_FVF_IMAGE (D3DFVF_XYZRHW | D3DFVF_TEX1)
+
+typedef struct {
+ FLOAT x, y; // 2D raster coords
+ FLOAT z; // depth value
+ FLOAT rhw; // reciprocal homogenous W (always 1.0f)
+ FLOAT tu, tv; // texture coords
+} _GLD_IMAGE_VERTEX;
+
+//---------------------------------------------------------------------------
+
+HRESULT _gldDrawPixels(
+ GLcontext *ctx,
+ BOOL bChromakey, // Alpha test for glBitmap() images
+ GLint x, // GL x position
+ GLint y, // GL y position (needs flipping)
+ GLsizei width, // Width of input image
+ GLsizei height, // Height of input image
+ IDirect3DSurface9 *pImage)
+{
+ //
+ // Draw input image as texture implementing PixelZoom and clipping.
+ // Any fragment operations currently enabled will be used.
+ //
+
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ IDirect3DTexture9 *pTexture;
+ D3DSURFACE_DESC d3dsd;
+ IDirect3DSurface9 *pSurface;
+ _GLD_IMAGE_VERTEX v[4];
+ HRESULT hr;
+
+ float ZoomWidth, ZoomHeight;
+ float ScaleWidth, ScaleHeight;
+
+ // Create a texture to hold image
+ hr = D3DXCreateTexture(
+ gld->pDev,
+ width, height,
+ 1, // miplevels
+ 0, // usage
+ D3DFMT_A8R8G8B8, // format
+ D3DPOOL_MANAGED, // pool
+ &pTexture);
+ if (FAILED(hr))
+ return hr;
+
+ hr = IDirect3DTexture9_GetSurfaceLevel(pTexture, 0, &pSurface);
+ if (FAILED(hr)) {
+ IDirect3DTexture9_Release(pTexture);
+ return hr;
+ }
+
+ // Copy image into texture
+ hr = D3DXLoadSurfaceFromSurface(
+ pSurface, NULL, NULL, // Dest surface
+ pImage, NULL, NULL, // Src surface
+ D3DX_FILTER_NONE,
+ 0);
+ IDirect3DSurface9_Release(pSurface);
+ if (FAILED(hr)) {
+ IDirect3DTexture9_Release(pTexture);
+ return hr;
+ }
+
+ //
+ // Set up the quad like this (ascii-art ahead!)
+ //
+ // 3--2
+ // | |
+ // 0--1
+ //
+ //
+
+ // Set depth
+ v[0].z = v[1].z = v[2].z = v[3].z = ctx->Current.RasterPos[2];
+ // Set Reciprocal Homogenous W
+ v[0].rhw = v[1].rhw = v[2].rhw = v[3].rhw = 1.0f;
+
+ // Set texcoords
+ // Examine texture size - if different to input width and height
+ // then we'll need to munge the texcoords to fit.
+ IDirect3DTexture9_GetLevelDesc(pTexture, 0, &d3dsd);
+ ScaleWidth = (float)width / (float)d3dsd.Width;
+ ScaleHeight = (float)height / (float)d3dsd.Height;
+ v[0].tu = 0.0f; v[0].tv = 0.0f;
+ v[1].tu = ScaleWidth; v[1].tv = 0.0f;
+ v[2].tu = ScaleWidth; v[2].tv = ScaleHeight;
+ v[3].tu = 0.0f; v[3].tv = ScaleHeight;
+
+ // Set raster positions
+ ZoomWidth = (float)width * ctx->Pixel.ZoomX;
+ ZoomHeight = (float)height * ctx->Pixel.ZoomY;
+
+ v[0].x = x; v[0].y = GLD_FLIP_Y(y);
+ v[1].x = x+ZoomWidth; v[1].y = GLD_FLIP_Y(y);
+ v[2].x = x+ZoomWidth; v[2].y = GLD_FLIP_Y(y+ZoomHeight);
+ v[3].x = x; v[3].y = GLD_FLIP_Y(y+ZoomHeight);
+
+ // Draw image with full HW acceleration
+ // NOTE: Be nice to use a State Block for all this state...
+ IDirect3DDevice9_SetTexture(gld->pDev, 0, pTexture);
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_CULLMODE, D3DCULL_NONE);
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_CLIPPING, TRUE);
+
+// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_MINFILTER, D3DTEXF_POINT);
+// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
+// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_MAGFILTER, D3DTEXF_POINT);
+// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
+// IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
+ IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
+ IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
+ IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
+ IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+ IDirect3DDevice9_SetSamplerState(gld->pDev, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+
+ IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+ IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ IDirect3DDevice9_SetTextureStageState(gld->pDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
+ IDirect3DDevice9_SetTextureStageState(gld->pDev, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ IDirect3DDevice9_SetTextureStageState(gld->pDev, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+
+ IDirect3DDevice9_SetVertexShader(gld->pDev, NULL);
+ IDirect3DDevice9_SetFVF(gld->pDev, _GLD_FVF_IMAGE);
+
+ //
+ // Emulate Chromakey with an Alpha Test.
+ // [Alpha Test is more widely supported anyway]
+ //
+ if (bChromakey) {
+ // Switch on alpha testing
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ALPHATESTENABLE, TRUE);
+ // Fragment passes is alpha is greater than reference value
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ALPHAFUNC, D3DCMP_GREATER);
+ // Set alpha reference value between Bitmap alpha values of
+ // zero (transparent) and one (opaque).
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ALPHAREF, 0x7f);
+ }
+
+ IDirect3DDevice9_DrawPrimitiveUP(gld->pDev, D3DPT_TRIANGLEFAN, 2, &v, sizeof(_GLD_IMAGE_VERTEX));
+
+ // Release texture
+ IDirect3DDevice9_SetTexture(gld->pDev, 0, NULL);
+ IDirect3DTexture9_Release(pTexture);
+
+ // Reset state to before we messed it up
+ FLUSH_VERTICES(ctx, _NEW_ALL);
+
+ return S_OK;
+}
+
+//---------------------------------------------------------------------------
+
+void gld_DrawPixels_DX9(
+ GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels )
+{
+ GLD_context *gldCtx;
+ GLD_driver_dx9 *gld;
+
+ IDirect3DSurface9 *pImage;
+ HRESULT hr;
+ D3DLOCKED_RECT d3dLockedRect;
+
+ // Mesa does not currently handle this format.
+ if (format == GL_BGR)
+ return;
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ hr = IDirect3DDevice9_CreateOffscreenPlainSurface(
+ gld->pDev,
+ width,
+ height,
+ D3DFMT_A8R8G8B8,
+ D3DPOOL_SCRATCH,
+ &pImage,
+ NULL);
+ if (FAILED(hr)) {
+ return;
+ }
+
+ //
+ // Use Mesa to fill in image
+ //
+
+ // Lock all of surface
+ hr = IDirect3DSurface9_LockRect(pImage, &d3dLockedRect, NULL, 0);
+ if (FAILED(hr)) {
+ IDirect3DSurface9_Release(pImage);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store directly in texture
+ _mesa_transfer_teximage(
+ ctx,
+ 2,
+ GL_RGBA,
+ &_mesa_texformat_argb8888,
+ d3dLockedRect.pBits,
+ width, height, 1, 0, 0, 0,
+ d3dLockedRect.Pitch,
+ 0, /* dstImageStride */
+ format, type, pixels, unpack);
+
+ IDirect3DSurface9_UnlockRect(pImage);
+
+ _gldDrawPixels(ctx, FALSE, x, y, width, height, pImage);
+
+ IDirect3DSurface9_Release(pImage);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_ReadPixels_DX9(
+ GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *pack,
+ GLvoid *dest)
+{
+
+ GLD_context *gldCtx;
+ GLD_driver_dx9 *gld;
+
+ IDirect3DSurface9 *pBackbuffer = NULL;
+ IDirect3DSurface9 *pNativeImage = NULL;
+ IDirect3DSurface9 *pCanonicalImage = NULL;
+
+ D3DSURFACE_DESC d3dsd;
+ RECT rcSrc; // Source rect
+ POINT ptDst; // Dest point
+ HRESULT hr;
+ D3DLOCKED_RECT d3dLockedRect;
+ struct gl_pixelstore_attrib srcPacking;
+ int i;
+ GLint DstRowStride;
+ const struct gl_texture_format *MesaFormat;
+
+ switch (format) {
+ case GL_STENCIL_INDEX:
+ case GL_DEPTH_COMPONENT:
+ return;
+ }
+
+ MesaFormat = _mesa_choose_tex_format(ctx, format, format, type);
+ DstRowStride = _mesa_image_row_stride(pack, width, format, type);
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ // Get backbuffer
+ hr = IDirect3DDevice9_GetBackBuffer(
+ gld->pDev,
+ 0, // First swapchain
+ 0, // First backbuffer
+ D3DBACKBUFFER_TYPE_MONO,
+ &pBackbuffer);
+ if (FAILED(hr))
+ return;
+
+ // Get backbuffer description
+ hr = IDirect3DSurface9_GetDesc(pBackbuffer, &d3dsd);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX9_return;
+ }
+
+ // Create a surface compatible with backbuffer
+ hr = IDirect3DDevice9_CreateOffscreenPlainSurface(
+ gld->pDev,
+ width,
+ height,
+ d3dsd.Format,
+ D3DPOOL_SCRATCH,
+ &pNativeImage,
+ NULL);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX9_return;
+ }
+
+ // Compute source rect and dest point
+ SetRect(&rcSrc, 0, 0, width, height);
+ OffsetRect(&rcSrc, x, GLD_FLIP_HEIGHT(y, height));
+ ptDst.x = ptDst.y = 0;
+
+ // Get source pixels.
+ //
+ // This intermediate surface ensure that we can use CopyRects()
+ // instead of relying on D3DXLoadSurfaceFromSurface(), which may
+ // try and lock the backbuffer. This way seems safer.
+ //
+ // CopyRects has been removed for DX9.
+ //
+/* hr = IDirect3DDevice9_CopyRects(
+ gld->pDev,
+ pBackbuffer,
+ &rcSrc,
+ 1,
+ pNativeImage,
+ &ptDst);*/
+ hr = D3DXLoadSurfaceFromSurface(
+ pNativeImage, // Dest surface
+ NULL, // Dest palette
+ &rcSrc, // Dest rect
+ pBackbuffer, // Src surface
+ NULL, // Src palette
+ &rcSrc, // Src rect
+ D3DX_FILTER_NONE, // Filter
+ 0 // Colorkey (0=no colorkey)
+ );
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX9_return;
+ }
+
+ // Create an RGBA8888 surface
+ hr = IDirect3DDevice9_CreateOffscreenPlainSurface(
+ gld->pDev,
+ width,
+ height,
+ D3DFMT_A8R8G8B8,
+ D3DPOOL_SCRATCH,
+ &pCanonicalImage,
+ NULL);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX9_return;
+ }
+
+ // Convert to RGBA8888
+ hr = D3DXLoadSurfaceFromSurface(
+ pCanonicalImage, // Dest surface
+ NULL, NULL, // Dest palette, RECT
+ pNativeImage, // Src surface
+ NULL, NULL, // Src palette, RECT
+ D3DX_FILTER_NONE, // Filter
+ 0); // Colourkey
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX9_return;
+ }
+
+ srcPacking.Alignment = 1;
+ srcPacking.ImageHeight = height;
+ srcPacking.LsbFirst = GL_FALSE;
+ srcPacking.RowLength = 0;
+ srcPacking.SkipImages = 0;
+ srcPacking.SkipPixels = 0;
+ srcPacking.SkipRows = 0;
+ srcPacking.SwapBytes = GL_FALSE;
+
+ // Lock all of image
+ hr = IDirect3DSurface9_LockRect(pCanonicalImage, &d3dLockedRect, NULL, 0);
+ if (FAILED(hr)) {
+ goto gld_ReadPixels_DX9_return;
+ }
+
+ // We need to flip the data. Yuck.
+ // Perhaps Mesa has a span packer we can use in future...
+ for (i=0; i<height; i++) {
+ BYTE *pDestRow = (BYTE*)_mesa_image_address(pack, dest, width, height, format, type, 0, i, 0);
+ BYTE *pSrcRow = (BYTE*)d3dLockedRect.pBits + (d3dLockedRect.Pitch * (height-i-1));
+ _mesa_transfer_teximage(
+ ctx,
+ 2,
+ GL_RGBA, // base format
+ MesaFormat, // dst format
+ pDestRow, // dest addr
+ width, 1, 1, 0, 0, 0, // src x,y,z & dst offsets x,y,z
+ DstRowStride, // dst row stride
+ 0, // dstImageStride
+ GL_BGRA, // src format
+ GL_UNSIGNED_BYTE, // src type
+ pSrcRow, // src addr
+ &srcPacking); // packing params of source image
+ }
+
+ IDirect3DSurface9_UnlockRect(pCanonicalImage);
+
+gld_ReadPixels_DX9_return:
+ SAFE_RELEASE_SURFACE9(pCanonicalImage);
+ SAFE_RELEASE_SURFACE9(pNativeImage);
+ SAFE_RELEASE_SURFACE9(pBackbuffer);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_CopyPixels_DX9(
+ GLcontext *ctx,
+ GLint srcx,
+ GLint srcy,
+ GLsizei width,
+ GLsizei height,
+ GLint dstx,
+ GLint dsty,
+ GLenum type)
+{
+ //
+ // NOTE: Not allowed to copy vidmem to vidmem!
+ // Therefore we use an intermediate image surface.
+ //
+
+ GLD_context *gldCtx;
+ GLD_driver_dx9 *gld;
+
+ IDirect3DSurface9 *pBackbuffer;
+ D3DSURFACE_DESC d3dsd;
+ IDirect3DSurface9 *pImage;
+ RECT rcSrc; // Source rect
+ POINT ptDst; // Dest point
+ HRESULT hr;
+
+ // Only backbuffer
+ if (type != GL_COLOR)
+ return;
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ // Get backbuffer
+ hr = IDirect3DDevice9_GetBackBuffer(
+ gld->pDev,
+ 0, // First swapchain
+ 0, // First backbuffer
+ D3DBACKBUFFER_TYPE_MONO,
+ &pBackbuffer);
+ if (FAILED(hr))
+ return;
+
+ // Get backbuffer description
+ hr = IDirect3DSurface9_GetDesc(pBackbuffer, &d3dsd);
+ if (FAILED(hr)) {
+ IDirect3DSurface9_Release(pBackbuffer);
+ return;
+ }
+
+ // Create a surface compatible with backbuffer
+ hr = IDirect3DDevice9_CreateOffscreenPlainSurface(
+ gld->pDev,
+ width,
+ height,
+ d3dsd.Format,
+ D3DPOOL_SCRATCH,
+ &pImage,
+ NULL);
+ if (FAILED(hr)) {
+ IDirect3DSurface9_Release(pBackbuffer);
+ return;
+ }
+
+ // Compute source rect and dest point
+ SetRect(&rcSrc, 0, 0, width, height);
+ OffsetRect(&rcSrc, srcx, GLD_FLIP_HEIGHT(srcy, height));
+ ptDst.x = ptDst.y = 0;
+
+ // Get source pixels
+/* hr = IDirect3DDevice8_CopyRects(
+ gld->pDev,
+ pBackbuffer,
+ &rcSrc,
+ 1,
+ pImage,
+ &ptDst);*/
+ hr = D3DXLoadSurfaceFromSurface(
+ pImage, // Dest surface
+ NULL, // Dest palette
+ &rcSrc, // Dest rect
+ pBackbuffer, // Src surface
+ NULL, // Src palette
+ &rcSrc, // Src rect
+ D3DX_FILTER_NONE, // Filter
+ 0 // Colorkey (0=no colorkey)
+ );
+ IDirect3DSurface9_Release(pBackbuffer);
+ if (FAILED(hr)) {
+ IDirect3DSurface9_Release(pImage);
+ return;
+ }
+
+ _gldDrawPixels(ctx, FALSE, dstx, dsty, width, height, pImage);
+
+ IDirect3DSurface9_Release(pImage);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_Bitmap_DX9(
+ GLcontext *ctx,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap)
+{
+ GLD_context *gldCtx;
+ GLD_driver_dx9 *gld;
+
+ IDirect3DSurface9 *pImage;
+ HRESULT hr;
+ D3DLOCKED_RECT d3dLockedRect;
+ BYTE *pTempBitmap;
+ D3DCOLOR clBitmapOne, clBitmapZero;
+ D3DCOLOR *pBits;
+ const GLubyte *src;
+ int i, j, k;
+
+ gldCtx = GLD_GET_CONTEXT(ctx);
+ gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ // A NULL bitmap is valid, but merely advances the raster position
+ if ((bitmap == NULL) || (width == 0) || (height == 0))
+ return;
+
+ clBitmapZero = D3DCOLOR_RGBA(0,0,0,0); // NOTE: Alpha is Zero
+ clBitmapOne = D3DCOLOR_COLORVALUE(
+ ctx->Current.RasterColor[0],
+ ctx->Current.RasterColor[1],
+ ctx->Current.RasterColor[2],
+ 1.0f); // NOTE: Alpha is One
+
+ hr = IDirect3DDevice9_CreateOffscreenPlainSurface(
+ gld->pDev,
+ width,
+ height,
+ D3DFMT_A8R8G8B8,
+ D3DPOOL_SCRATCH,
+ &pImage,
+ NULL);
+ if (FAILED(hr)) {
+ return;
+ }
+
+ // Lock all of surface
+ hr = IDirect3DSurface9_LockRect(pImage, &d3dLockedRect, NULL, 0);
+ if (FAILED(hr)) {
+ IDirect3DSurface9_Release(pImage);
+ return;
+ }
+
+ pTempBitmap = _mesa_unpack_bitmap(width, height, bitmap, unpack);
+ if (pTempBitmap == NULL) {
+ IDirect3DSurface9_Release(pImage);
+ return;
+ }
+
+ pBits = (D3DCOLOR*)d3dLockedRect.pBits;
+
+ for (i=0; i<height; i++) {
+ GLubyte byte;
+ pBits = (D3DCOLOR*)((BYTE*)d3dLockedRect.pBits + (i*d3dLockedRect.Pitch));
+ src = (const GLubyte *) _mesa_image_address(
+ &_mesa_native_packing, pTempBitmap, width, height, GL_COLOR_INDEX, GL_BITMAP,
+ 0, i, 0);
+ for (j=0; j<(width>>3); j++) {
+ byte = *src++;
+ for (k=0; k<8; k++) {
+ *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero;
+ byte <<= 1;
+ }
+ }
+ // Fill remaining bits from bitmap
+ if (width & 7) {
+ byte = *src;
+ for (k=0; k<(width & 7); k++) {
+ *pBits++ = (byte & 128) ? clBitmapOne : clBitmapZero;
+ byte <<= 1;
+ }
+ }
+ }
+
+ FREE(pTempBitmap);
+
+/*
+ // unpack image, apply transfer ops and store directly in texture
+ _mesa_transfer_teximage(
+ ctx,
+ 2,
+ GL_BITMAP,
+ &_mesa_texformat_argb8888,
+ d3dLockedRect.pBits,
+ width, height, 1, 0, 0, 0,
+ d3dLockedRect.Pitch,
+ 0, // dstImageStride
+ GL_BITMAP, GL_COLOR_INDEX, bitmap, unpack);
+*/
+ IDirect3DSurface9_UnlockRect(pImage);
+
+ _gldDrawPixels(ctx, TRUE, x, y, width, height, pImage);
+
+ IDirect3DSurface9_Release(pImage);
+}
+
+//---------------------------------------------------------------------------
+// Texture functions
+//---------------------------------------------------------------------------
+
+void _gldAllocateTexture(
+ GLcontext *ctx,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ IDirect3DTexture9 *pTex;
+ D3DFORMAT d3dFormat;
+
+ if (!tObj || !texImage)
+ return;
+
+ pTex = (IDirect3DTexture9*)tObj->DriverData;
+ if (pTex) {
+ // Decide whether we can keep existing D3D texture
+ // by examining top-level surface.
+ D3DSURFACE_DESC d3dsd;
+ _GLD_DX9_TEX(GetLevelDesc(pTex, 0, &d3dsd));
+ // Release existing texture if not compatible
+ if ((d3dsd.Width == texImage->Width) ||
+ (d3dsd.Height == texImage->Height))
+ {
+ return; // Keep the existing texture
+ }
+ tObj->DriverData = NULL;
+ _GLD_DX9_TEX(Release(pTex));
+ }
+
+ d3dFormat = _gldGLFormatToD3DFormat(texImage->IntFormat);
+ D3DXCreateTexture(
+ gld->pDev,
+ texImage->Width,
+ texImage->Height,
+ // TODO: Re-evaluate mipmapping
+ (glb.bUseMipmaps) ? D3DX_DEFAULT : 1,
+ 0, // Usage
+ d3dFormat,
+ D3DPOOL_MANAGED,
+ &pTex);
+ tObj->DriverData = pTex;
+}
+
+//---------------------------------------------------------------------------
+
+const struct gl_texture_format* gld_ChooseTextureFormat_DX9(
+ GLcontext *ctx,
+ GLint internalFormat,
+ GLenum srcFormat,
+ GLenum srcType)
+{
+ // [Based on mesa_choose_tex_format()]
+ //
+ // We will choose only texture formats that are supported
+ // by Direct3D. If the hardware doesn't support a particular
+ // texture format, then the D3DX texture calls that we use
+ // will automatically use a HW supported format.
+ //
+ // The most critical aim is to reduce copying; if we can use
+ // texture-image data directly then it will be a big performance assist.
+ //
+
+ switch (internalFormat) {
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ return &_mesa_texformat_l8; // D3DFMT_L8
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return &_mesa_texformat_l8; // D3DFMT_L8
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return &_mesa_texformat_a8; // D3DFMT_A8
+ case GL_COLOR_INDEX:
+ case GL_COLOR_INDEX1_EXT:
+ case GL_COLOR_INDEX2_EXT:
+ case GL_COLOR_INDEX4_EXT:
+ case GL_COLOR_INDEX8_EXT:
+ case GL_COLOR_INDEX12_EXT:
+ case GL_COLOR_INDEX16_EXT:
+ return &_mesa_texformat_rgb565; // D3DFMT_R5G6B5
+ // Mesa will convert this for us later...
+ // return &_mesa_texformat_ci8; // D3DFMT_R5G6B5
+ case 2:
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE4_ALPHA4:
+ case GL_LUMINANCE6_ALPHA2:
+ case GL_LUMINANCE8_ALPHA8:
+ case GL_LUMINANCE12_ALPHA4:
+ case GL_LUMINANCE12_ALPHA12:
+ case GL_LUMINANCE16_ALPHA16:
+ return &_mesa_texformat_al88; // D3DFMT_A8L8
+ case GL_R3_G3_B2:
+ return &_mesa_texformat_rgb332; // D3DFMT_R3G3B2
+ case GL_RGB4:
+ case GL_RGBA4:
+ case GL_RGBA2:
+ return &_mesa_texformat_argb4444; // D3DFMT_A4R4G4B4
+ case 3:
+ case GL_RGB:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return &_mesa_texformat_rgb565;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return &_mesa_texformat_argb8888;
+ case GL_RGB5_A1:
+ return &_mesa_texformat_argb1555;
+ default:
+ _mesa_problem(NULL, "unexpected format in fxDDChooseTextureFormat");
+ return NULL;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+/*
+// Safer(?), slower version.
+void gld_TexImage2D_DX9(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint internalFormat,
+ GLint width,
+ GLint height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ IDirect3DTexture9 *pTex;
+ IDirect3DSurface9 *pSurface;
+ RECT rcSrcRect;
+ HRESULT hr;
+ GLint texelBytes = 4;
+ GLvoid *tempImage;
+
+ if (!tObj || !texImage)
+ return;
+
+ if (level == 0) {
+ _gldAllocateTexture(ctx, tObj, texImage);
+ }
+
+ pTex = (IDirect3DTexture9*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= IDirect3DTexture9_GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = IDirect3DTexture9_GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ tempImage = MALLOC(width * height * texelBytes);
+ if (!tempImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ IDirect3DSurface9_Release(pSurface);
+ return;
+ }
+ // unpack image, apply transfer ops and store in tempImage
+ _mesa_transfer_teximage(ctx, 2, texImage->Format,
+ &_mesa_texformat_argb8888, // dest format
+ tempImage,
+ width, height, 1, 0, 0, 0,
+ width * texelBytes,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+ SetRect(&rcSrcRect, 0, 0, width, height);
+ D3DXLoadSurfaceFromMemory(
+ pSurface,
+ NULL,
+ NULL,
+ tempImage,
+ D3DFMT_A8R8G8B8,
+ width * texelBytes,
+ NULL,
+ &rcSrcRect,
+ D3DX_FILTER_NONE,
+ 0);
+
+ FREE(tempImage);
+ IDirect3DSurface9_Release(pSurface);
+}
+*/
+
+//---------------------------------------------------------------------------
+
+// Faster, more efficient version.
+// Copies subimage straight to dest texture
+void gld_TexImage2D_DX9(
+ GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint internalFormat,
+ GLint width,
+ GLint height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ IDirect3DTexture9 *pTex;
+ IDirect3DSurface9 *pSurface;
+ HRESULT hr;
+ D3DLOCKED_RECT d3dLockedRect;
+ D3DSURFACE_DESC d3dsd;
+
+ if (!tObj || !texImage)
+ return;
+
+ // GLQUAKE FIX
+ // Test for input alpha data with non-alpha internalformat
+ if (((internalFormat==3) || (internalFormat==GL_RGB)) && (format==GL_RGBA)) {
+ // Input format has alpha, but a non-alpha format has been requested.
+ texImage->IntFormat = GL_RGBA;
+ internalFormat = GL_RGBA;
+ }
+
+ if (level == 0) {
+ _gldAllocateTexture(ctx, tObj, texImage);
+ }
+
+ pTex = (IDirect3DTexture9*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= IDirect3DTexture9_GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = IDirect3DTexture9_GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ IDirect3DSurface9_GetDesc(pSurface, &d3dsd);
+
+ // Lock all of surface
+ hr = IDirect3DSurface9_LockRect(pSurface, &d3dLockedRect, NULL, 0);
+ if (FAILED(hr)) {
+ IDirect3DSurface9_Release(pSurface);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store directly in texture
+ _mesa_transfer_teximage(
+ ctx,
+ 2,
+ texImage->Format,
+ _gldMesaFormatForD3DFormat(d3dsd.Format),
+ d3dLockedRect.pBits,
+ width, height, 1, 0, 0, 0,
+ d3dLockedRect.Pitch,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+ IDirect3DSurface9_UnlockRect(pSurface);
+ IDirect3DSurface9_Release(pSurface);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_TexImage1D_DX9(GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ // A 1D texture is a 2D texture with a height of zero
+ gld_TexImage2D_DX9(ctx, target, level, internalFormat, width, 1, border, format, type, pixels, packing, texObj, texImage);
+}
+
+//---------------------------------------------------------------------------
+
+/*
+void gld_TexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage )
+{
+ GLD_GET_CONTEXT
+ IDirect3DTexture9 *pTex;
+ IDirect3DSurface9 *pSurface;
+ D3DFORMAT d3dFormat;
+ HRESULT hr;
+ GLint texelBytes = 4;
+ GLvoid *tempImage;
+ RECT rcSrcRect;
+ RECT rcDstRect;
+
+ if (!tObj || !texImage)
+ return;
+
+ pTex = (IDirect3DTexture9*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= _GLD_DX9_TEX(GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = _GLD_DX9_TEX(GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ d3dFormat = _gldGLFormatToD3DFormat(texImage->Format);
+ tempImage = MALLOC(width * height * texelBytes);
+ if (!tempImage) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+ IDirect3DSurface9_Release(pSurface);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store in tempImage
+ _mesa_transfer_teximage(ctx, 2, texImage->Format,
+ &_mesa_texformat_argb8888, // dest format
+ tempImage,
+ width, height, 1, 0, 0, 0,
+ width * texelBytes,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+ // Source rectangle is whole of input image
+ SetRect(&rcSrcRect, 0, 0, width, height);
+
+ // Dest rectangle must be offset to dest image
+ SetRect(&rcDstRect, 0, 0, width, height);
+ OffsetRect(&rcDstRect, xoffset, yoffset);
+
+ D3DXLoadSurfaceFromMemory(
+ pSurface,
+ NULL,
+ &rcDstRect,
+ tempImage,
+ D3DFMT_A8R8G8B8,
+ width * texelBytes,
+ NULL,
+ &rcSrcRect,
+ D3DX_FILTER_NONE,
+ 0);
+
+ FREE(tempImage);
+ IDirect3DSurface9_Release(pSurface);
+}
+*/
+
+//---------------------------------------------------------------------------
+
+// Faster, more efficient version.
+// Copies subimage straight to dest texture
+void gld_TexSubImage2D_DX9( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *tObj,
+ struct gl_texture_image *texImage )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ IDirect3DTexture9 *pTex;
+ IDirect3DSurface9 *pSurface;
+ HRESULT hr;
+ RECT rcDstRect;
+ D3DLOCKED_RECT d3dLockedRect;
+ D3DSURFACE_DESC d3dsd;
+
+ if (!tObj || !texImage)
+ return;
+
+ pTex = (IDirect3DTexture9*)tObj->DriverData;
+ if (!pTex)
+ return; // Texture has not been created
+ if (level >= IDirect3DTexture9_GetLevelCount(pTex))
+ return; // Level does not exist
+ hr = IDirect3DTexture9_GetSurfaceLevel(pTex, level, &pSurface);
+ if (FAILED(hr))
+ return; // Surface level doesn't exist (or just a plain error)
+
+ IDirect3DSurface9_GetDesc(pSurface, &d3dsd);
+
+ // Dest rectangle must be offset to dest image
+ SetRect(&rcDstRect, 0, 0, width, height);
+ OffsetRect(&rcDstRect, xoffset, yoffset);
+
+ // Lock sub-rect of surface
+ hr = IDirect3DSurface9_LockRect(pSurface, &d3dLockedRect, &rcDstRect, 0);
+ if (FAILED(hr)) {
+ IDirect3DSurface9_Release(pSurface);
+ return;
+ }
+
+ // unpack image, apply transfer ops and store directly in texture
+ _mesa_transfer_teximage(ctx, 2, texImage->Format,
+ _gldMesaFormatForD3DFormat(d3dsd.Format),
+ d3dLockedRect.pBits,
+ width, height, 1,
+ 0, 0, 0, // NOTE: d3dLockedRect.pBits is already offset!!!
+ d3dLockedRect.Pitch,
+ 0, // dstImageStride
+ format, type, pixels, packing);
+
+
+ IDirect3DSurface9_UnlockRect(pSurface);
+ IDirect3DSurface9_Release(pSurface);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_TexSubImage1D_DX9( GLcontext *ctx, GLenum target, GLint level,
+ GLint xoffset, GLsizei width,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ gld_TexSubImage2D_DX9(ctx, target, level, xoffset, 0, width, 1, format, type, pixels, packing, texObj, texImage);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_DeleteTexture_DX9(
+ GLcontext *ctx,
+ struct gl_texture_object *tObj)
+{
+ GLD_context *gld = (GLD_context*)(ctx->DriverCtx);
+
+ if (tObj) {
+ IDirect3DTexture9 *pTex = (IDirect3DTexture9*)tObj->DriverData;
+ if (pTex) {
+/* // Make sure texture is not bound to a stage before releasing it
+ for (int i=0; i<MAX_TEXTURE_UNITS; i++) {
+ if (gld->CurrentTexture[i] == pTex) {
+ gld->pDev->SetTexture(i, NULL);
+ gld->CurrentTexture[i] = NULL;
+ }
+ }*/
+ _GLD_DX9_TEX(Release(pTex));
+ tObj->DriverData = NULL;
+ }
+ }
+}
+
+//---------------------------------------------------------------------------
+
+__inline void _gldSetColorOps(
+ const GLD_driver_dx9 *gld,
+ GLuint unit,
+ DWORD ColorArg1,
+ D3DTEXTUREOP ColorOp,
+ DWORD ColorArg2)
+{
+ _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG1, ColorArg1));
+ _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLOROP, ColorOp));
+ _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG2, ColorArg2));
+}
+
+//---------------------------------------------------------------------------
+
+__inline void _gldSetAlphaOps(
+ const GLD_driver_dx9 *gld,
+ GLuint unit,
+ DWORD AlphaArg1,
+ D3DTEXTUREOP AlphaOp,
+ DWORD AlphaArg2)
+{
+ _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG1, AlphaArg1));
+ _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAOP, AlphaOp));
+ _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ALPHAARG2, AlphaArg2));
+}
+
+//---------------------------------------------------------------------------
+
+void gldUpdateTextureUnit(
+ GLcontext *ctx,
+ GLuint unit,
+ BOOL bPassThrough)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ D3DTEXTUREFILTERTYPE minfilter;
+ D3DTEXTUREFILTERTYPE mipfilter;
+ GLenum BaseFormat;
+ DWORD dwColorArg0;
+ int iTexEnv = 0;
+ GLD_texenv *pTexenv;
+
+ // NOTE: If bPassThrough is FALSE then texture stage can be
+ // disabled otherwise it must pass-through it's current fragment.
+
+ const struct gl_texture_unit *pUnit = &ctx->Texture.Unit[unit];
+ const struct gl_texture_object *tObj = pUnit->_Current;
+
+ IDirect3DTexture9 *pTex = NULL;
+ if (tObj) {
+ pTex = (IDirect3DTexture9*)tObj->DriverData;
+ }
+
+ // Enable texturing if unit is enabled and a valid D3D texture exists
+ // Mesa 5: TEXTUREn_x altered to TEXTURE_nD_BIT
+ //if (pTex && (pUnit->Enabled & (TEXTURE0_1D | TEXTURE0_2D))) {
+ if (pTex && (pUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT))) {
+ // Enable texturing
+ _GLD_DX9_DEV(SetTexture(gld->pDev, unit, pTex));
+ } else {
+ // Disable texturing, then return
+ _GLD_DX9_DEV(SetTexture(gld->pDev, unit, NULL));
+ if (bPassThrough) {
+ _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE);
+ _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_SELECTARG2, D3DTA_DIFFUSE);
+ } else {
+ _gldSetColorOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE);
+ _gldSetAlphaOps(gld, unit, D3DTA_TEXTURE, D3DTOP_DISABLE, D3DTA_DIFFUSE);
+ }
+ return;
+ }
+
+ // Texture parameters
+ _gldConvertMinFilter(tObj->MinFilter, &minfilter, &mipfilter);
+// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MINFILTER, minfilter));
+// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MIPFILTER, mipfilter));
+// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_MAGFILTER, _gldConvertMagFilter(tObj->MagFilter)));
+// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSU, _gldConvertWrap(tObj->WrapS)));
+// _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_ADDRESSV, _gldConvertWrap(tObj->WrapT)));
+ _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_MINFILTER, minfilter));
+ _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_MIPFILTER, mipfilter));
+ _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_MAGFILTER, _gldConvertMagFilter(tObj->MagFilter)));
+ _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_ADDRESSU, _gldConvertWrap(tObj->WrapS)));
+ _GLD_DX9_DEV(SetSamplerState(gld->pDev, unit, D3DSAMP_ADDRESSV, _gldConvertWrap(tObj->WrapT)));
+
+ // Texture priority
+ _GLD_DX9_TEX(SetPriority(pTex, (DWORD)(tObj->Priority*65535.0f)));
+
+ // Texture environment
+ // TODO: Examine input texture for alpha and use specific alpha/non-alpha ops.
+ // See Page 355 of the Red Book.
+ BaseFormat = _gldDecodeBaseFormat(pTex);
+
+ switch (BaseFormat) {
+ case GL_RGB:
+ iTexEnv = 0;
+ break;
+ case GL_RGBA:
+ iTexEnv = 1;
+ break;
+ case GL_ALPHA:
+ iTexEnv = 2;
+ break;
+ }
+
+ switch (pUnit->EnvMode) {
+ case GL_DECAL:
+ iTexEnv += 0;
+ break;
+ case GL_REPLACE:
+ iTexEnv += 3;
+ break;
+ case GL_MODULATE:
+ iTexEnv += 6;
+ break;
+ case GL_BLEND:
+ // Set blend colour
+ dwColorArg0 = D3DCOLOR_COLORVALUE(pUnit->EnvColor[0], pUnit->EnvColor[1], pUnit->EnvColor[2], pUnit->EnvColor[3]);
+ _GLD_DX9_DEV(SetTextureStageState(gld->pDev, unit, D3DTSS_COLORARG0, dwColorArg0));
+ iTexEnv += 9;
+ break;
+ case GL_ADD:
+ iTexEnv += 12;
+ break;
+ }
+ pTexenv = (GLD_texenv*)&gldTexEnv[iTexEnv];
+ _gldSetColorOps(gld, unit, pTexenv->ColorArg1, pTexenv->ColorOp, pTexenv->ColorArg2);
+ _gldSetAlphaOps(gld, unit, pTexenv->AlphaArg1, pTexenv->AlphaOp, pTexenv->AlphaArg2);
+}
+
+//---------------------------------------------------------------------------
+
+void gld_NEW_TEXTURE_DX9(
+ GLcontext *ctx)
+{
+ // TODO: Support for three (ATI Radeon) or more (nVidia GeForce3) texture units
+
+ BOOL bUnit0Enabled;
+ BOOL bUnit1Enabled;
+
+ if (!ctx)
+ return; // Sanity check
+
+ if (ctx->Const.MaxTextureUnits == 1) {
+ gldUpdateTextureUnit(ctx, 0, TRUE);
+ return;
+ }
+
+ //
+ // NOTE: THE FOLLOWING RELATES TO TWO TEXTURE UNITS, AND TWO ONLY!!
+ //
+
+ // Mesa 5: Texture Units altered
+ //bUnit0Enabled = (ctx->Texture._ReallyEnabled & (TEXTURE0_1D | TEXTURE0_2D)) ? TRUE : FALSE;
+ //bUnit1Enabled = (ctx->Texture._ReallyEnabled & (TEXTURE1_1D | TEXTURE1_2D)) ? TRUE : FALSE;
+ bUnit0Enabled = (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE;
+ bUnit1Enabled = (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) ? TRUE : FALSE;
+
+ // If Unit0 is disabled and Unit1 is enabled then we must pass-though
+ gldUpdateTextureUnit(ctx, 0, (!bUnit0Enabled && bUnit1Enabled) ? TRUE : FALSE);
+ // We can always disable the last texture unit
+ gldUpdateTextureUnit(ctx, 1, FALSE);
+
+#ifdef _DEBUG
+#if 0
+ {
+ // Find out whether device supports current renderstates
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+// GLD_context *gld = GLD_GET_CONTEXT(ctx);
+
+ DWORD dwPasses;
+ _GLD_DX9_DEV(ValidateDevice(gld->pDev, &dwPasses));
+// if (FAILED(hr)) {
+// gldLogError(GLDLOG_ERROR, "ValidateDevice failed", hr);
+// }
+ if (dwPasses != 1) {
+ gldLogMessage(GLDLOG_ERROR, "ValidateDevice: Can't do in one pass\n");
+ }
+ }
+#endif
+#endif
+};
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_vb_d3d_render_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_vb_d3d_render_dx9.c
new file mode 100644
index 0000000000..30650d6f9a
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_vb_d3d_render_dx9.c
@@ -0,0 +1,281 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GLDirect fastpath pipeline stage
+*
+****************************************************************************/
+
+//---------------------------------------------------------------------------
+
+//#include "../GLDirect.h"
+//#include "../gld_log.h"
+//#include "gld_dx8.h"
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx9.h"
+
+//---------------------------------------------------------------------------
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+// #include "mem.h"
+#include "mtypes.h"
+#include "mmath.h"
+
+#include "math/m_matrix.h"
+#include "math/m_xform.h"
+
+#include "tnl/t_pipeline.h"
+
+//---------------------------------------------------------------------------
+
+__inline void _gldSetVertexShaderConstants(
+ GLcontext *ctx,
+ GLD_driver_dx9 *gld)
+{
+ D3DXMATRIX mat, matView, matProj;
+ GLfloat *pM;
+
+ // Mesa 5: Altered to a Stack
+ //pM = ctx->ModelView.m;
+ pM = ctx->ModelviewMatrixStack.Top->m;
+ matView._11 = pM[0];
+ matView._12 = pM[1];
+ matView._13 = pM[2];
+ matView._14 = pM[3];
+ matView._21 = pM[4];
+ matView._22 = pM[5];
+ matView._23 = pM[6];
+ matView._24 = pM[7];
+ matView._31 = pM[8];
+ matView._32 = pM[9];
+ matView._33 = pM[10];
+ matView._34 = pM[11];
+ matView._41 = pM[12];
+ matView._42 = pM[13];
+ matView._43 = pM[14];
+ matView._44 = pM[15];
+
+ // Mesa 5: Altered to a Stack
+ //pM = ctx->ProjectionMatrix.m;
+ pM = ctx->ProjectionMatrixStack.Top->m;
+ matProj._11 = pM[0];
+ matProj._12 = pM[1];
+ matProj._13 = pM[2];
+ matProj._14 = pM[3];
+ matProj._21 = pM[4];
+ matProj._22 = pM[5];
+ matProj._23 = pM[6];
+ matProj._24 = pM[7];
+ matProj._31 = pM[8];
+ matProj._32 = pM[9];
+ matProj._33 = pM[10];
+ matProj._34 = pM[11];
+ matProj._41 = pM[12];
+ matProj._42 = pM[13];
+ matProj._43 = pM[14];
+ matProj._44 = pM[15];
+
+ D3DXMatrixMultiply( &mat, &matView, &matProj );
+ D3DXMatrixTranspose( &mat, &mat );
+
+ _GLD_DX9_DEV(SetVertexShaderConstantF(gld->pDev, 0, (float*)&mat, 4));
+}
+
+//---------------------------------------------------------------------------
+
+static GLboolean gld_d3d_render_stage_run(
+ GLcontext *ctx,
+ struct gl_pipeline_stage *stage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ TNLcontext *tnl;
+ struct vertex_buffer *VB;
+ GLuint new_inputs;
+ render_func *tab;
+ GLint pass;
+ GLD_pb_dx9 *gldPB = &gld->PB3d;
+/*
+ static int count = 0;
+ count++;
+ if (count != 2)
+ return GL_FALSE;
+*/
+ // The "check" function should disable this stage,
+ // but we'll test gld->bUseMesaTnL anyway.
+ if (gld->bUseMesaTnL) {
+ // Do nothing in this stage, but continue pipeline
+ return GL_FALSE;
+ }
+
+ tnl = TNL_CONTEXT(ctx);
+ VB = &tnl->vb;
+ new_inputs = stage->changed_inputs;
+ pass = 0;
+
+ tnl->Driver.Render.Start( ctx );
+
+#if 0
+ // For debugging: Useful to see if an app passes colour data in
+ // an unusual format.
+ switch (VB->ColorPtr[0]->Type) {
+ case GL_FLOAT:
+ ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_FLOAT\n");
+ break;
+ case GL_UNSIGNED_BYTE:
+ ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: GL_UNSIGNED_BYTE\n");
+ break;
+ default:
+ ddlogMessage(GLDLOG_SYSTEM, "ColorPtr: *?*\n");
+ break;
+ }
+#endif
+
+ tnl->Driver.Render.Points = gld_Points3D_DX9;
+ if (ctx->_TriangleCaps & DD_FLATSHADE) {
+ tnl->Driver.Render.Line = gld_Line3DFlat_DX9;
+ tnl->Driver.Render.Triangle = gld_Triangle3DFlat_DX9;
+ tnl->Driver.Render.Quad = gld_Quad3DFlat_DX9;
+ } else {
+ tnl->Driver.Render.Line = gld_Line3DSmooth_DX9;
+ tnl->Driver.Render.Triangle = gld_Triangle3DSmooth_DX9;
+ tnl->Driver.Render.Quad = gld_Quad3DSmooth_DX9;
+ }
+
+ _GLD_DX9_VB(Lock(gldPB->pVB, 0, 0, &gldPB->pPoints, D3DLOCK_DISCARD));
+ gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0;
+ // Allocate primitive pointers
+ // gldPB->pPoints is always first
+ gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine);
+ gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle);
+
+ ASSERT(tnl->Driver.Render.BuildVertices);
+ ASSERT(tnl->Driver.Render.PrimitiveNotify);
+ ASSERT(tnl->Driver.Render.Points);
+ ASSERT(tnl->Driver.Render.Line);
+ ASSERT(tnl->Driver.Render.Triangle);
+ ASSERT(tnl->Driver.Render.Quad);
+ ASSERT(tnl->Driver.Render.ResetLineStipple);
+ ASSERT(tnl->Driver.Render.Interp);
+ ASSERT(tnl->Driver.Render.CopyPV);
+ ASSERT(tnl->Driver.Render.ClippedLine);
+ ASSERT(tnl->Driver.Render.ClippedPolygon);
+ ASSERT(tnl->Driver.Render.Finish);
+
+ tab = (VB->Elts ? tnl->Driver.Render.PrimTabElts : tnl->Driver.Render.PrimTabVerts);
+
+ do {
+ GLuint i, length, flags = 0;
+ for (i = 0 ; !(flags & PRIM_LAST) ; i += length)
+ {
+ flags = VB->Primitive[i];
+ length= VB->PrimitiveLength[i];
+ ASSERT(length || (flags & PRIM_LAST));
+ ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1);
+ if (length)
+ tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags );
+ }
+ } while (tnl->Driver.Render.Multipass &&
+ tnl->Driver.Render.Multipass( ctx, ++pass ));
+
+ _GLD_DX9_VB(Unlock(gldPB->pVB));
+
+ _GLD_DX9_DEV(SetStreamSource(gld->pDev, 0, gldPB->pVB, 0, gldPB->dwStride));
+
+ _GLD_DX9_DEV(SetTransform(gld->pDev, D3DTS_PROJECTION, &gld->matProjection));
+ _GLD_DX9_DEV(SetTransform(gld->pDev, D3DTS_WORLD, &gld->matModelView));
+
+ if (gldPB->nPoints) {
+ _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_POINTLIST, 0, gldPB->nPoints));
+ gldPB->nPoints = 0;
+ }
+
+ if (gldPB->nLines) {
+ _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_LINELIST, gldPB->iFirstLine, gldPB->nLines));
+ gldPB->nLines = 0;
+ }
+
+ if (gldPB->nTriangles) {
+ _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_TRIANGLELIST, gldPB->iFirstTriangle, gldPB->nTriangles));
+ gldPB->nTriangles = 0;
+ }
+
+ return GL_FALSE; /* finished the pipe */
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_d3d_render_stage_check(
+ GLcontext *ctx,
+ struct gl_pipeline_stage *stage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+ // Is this thread safe?
+ stage->active = (gld->bUseMesaTnL) ? GL_FALSE : GL_TRUE;
+ return;
+}
+
+//---------------------------------------------------------------------------
+
+static void gld_d3d_render_stage_dtr( struct gl_pipeline_stage *stage )
+{
+}
+
+//---------------------------------------------------------------------------
+
+const struct gl_pipeline_stage _gld_d3d_render_stage =
+{
+ "gld_d3d_render_stage",
+ (_NEW_BUFFERS |
+ _DD_NEW_SEPARATE_SPECULAR |
+ _DD_NEW_FLATSHADE |
+ _NEW_TEXTURE|
+ _NEW_LIGHT|
+ _NEW_POINT|
+ _NEW_FOG|
+ _DD_NEW_TRI_UNFILLED |
+ _NEW_RENDERMODE), /* re-check (new inputs, interp function) */
+ 0, /* re-run (always runs) */
+ GL_TRUE, /* active */
+ 0, 0, /* inputs (set in check_render), outputs */
+ 0, 0, /* changed_inputs, private */
+ gld_d3d_render_stage_dtr, /* destructor */
+ gld_d3d_render_stage_check, /* check */
+ gld_d3d_render_stage_run /* run */
+};
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_vb_mesa_render_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_vb_mesa_render_dx9.c
new file mode 100644
index 0000000000..10e994c3c8
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_vb_mesa_render_dx9.c
@@ -0,0 +1,510 @@
+/* $Id: gld_vb_mesa_render_dx9.c,v 1.1 2004/04/20 11:13:11 alanh Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keithw@valinux.com>
+ */
+
+
+/*
+ * Render whole vertex buffers, including projection of vertices from
+ * clip space and clipping of primitives.
+ *
+ * This file makes calls to project vertices and to the point, line
+ * and triangle rasterizers via the function pointers:
+ *
+ * context->Driver.Render.*
+ *
+ */
+
+
+//---------------------------------------------------------------------------
+
+#include "dglcontext.h"
+#include "ddlog.h"
+#include "gld_dx9.h"
+
+//---------------------------------------------------------------------------
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "mmath.h"
+
+#include "math/m_matrix.h"
+#include "math/m_xform.h"
+
+#include "tnl/t_pipeline.h"
+
+/**********************************************************************/
+/* Clip single primitives */
+/**********************************************************************/
+
+
+#if defined(USE_IEEE)
+#define NEGATIVE(x) (GET_FLOAT_BITS(x) & (1<<31))
+#define DIFFERENT_SIGNS(x,y) ((GET_FLOAT_BITS(x) ^ GET_FLOAT_BITS(y)) & (1<<31))
+#else
+#define NEGATIVE(x) (x < 0)
+#define DIFFERENT_SIGNS(x,y) (x * y <= 0 && x - y != 0)
+/* Could just use (x*y<0) except for the flatshading requirements.
+ * Maybe there's a better way?
+ */
+#endif
+
+
+#define W(i) coord[i][3]
+#define Z(i) coord[i][2]
+#define Y(i) coord[i][1]
+#define X(i) coord[i][0]
+#define SIZE 4
+#define TAG(x) x##_4
+#include "tnl/t_vb_cliptmp.h"
+
+
+
+/**********************************************************************/
+/* Clip and render whole begin/end objects */
+/**********************************************************************/
+
+#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED)
+#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
+#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
+
+
+/* Vertices, with the possibility of clipping.
+ */
+#define RENDER_POINTS( start, count ) \
+ tnl->Driver.Render.Points( ctx, start, count )
+
+#define RENDER_LINE( v1, v2 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2]; \
+ GLubyte ormask = c1|c2; \
+ if (!ormask) \
+ LineFunc( ctx, v1, v2 ); \
+ else if (!(c1 & c2 & 0x3f)) \
+ clip_line_4( ctx, v1, v2, ormask ); \
+} while (0)
+
+#define RENDER_TRI( v1, v2, v3 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2], c3 = mask[v3]; \
+ GLubyte ormask = c1|c2|c3; \
+ if (!ormask) \
+ TriangleFunc( ctx, v1, v2, v3 ); \
+ else if (!(c1 & c2 & c3 & 0x3f)) \
+ clip_tri_4( ctx, v1, v2, v3, ormask ); \
+} while (0)
+
+#define RENDER_QUAD( v1, v2, v3, v4 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2]; \
+ GLubyte c3 = mask[v3], c4 = mask[v4]; \
+ GLubyte ormask = c1|c2|c3|c4; \
+ if (!ormask) \
+ QuadFunc( ctx, v1, v2, v3, v4 ); \
+ else if (!(c1 & c2 & c3 & c4 & 0x3f)) \
+ clip_quad_4( ctx, v1, v2, v3, v4, ormask ); \
+} while (0)
+
+
+#define LOCAL_VARS \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ const GLuint * const elt = VB->Elts; \
+ const GLubyte *mask = VB->ClipMask; \
+ const GLuint sz = VB->ClipPtr->size; \
+ const line_func LineFunc = tnl->Driver.Render.Line; \
+ const triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
+ const quad_func QuadFunc = tnl->Driver.Render.Quad; \
+ const GLboolean stipple = ctx->Line.StippleFlag; \
+ (void) (LineFunc && TriangleFunc && QuadFunc); \
+ (void) elt; (void) mask; (void) sz; (void) stipple;
+
+#define TAG(x) clip_##x##_verts
+#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
+#define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx )
+#define RESET_OCCLUSION ctx->OcclusionResult = GL_TRUE
+#define PRESERVE_VB_DEFS
+#include "tnl/t_vb_rendertmp.h"
+
+
+
+/* Elts, with the possibility of clipping.
+ */
+#undef ELT
+#undef TAG
+#define ELT(x) elt[x]
+#define TAG(x) clip_##x##_elts
+#include "tnl/t_vb_rendertmp.h"
+
+/* TODO: do this for all primitives, verts and elts:
+ */
+static void clip_elt_triangles( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ render_func render_tris = tnl->Driver.Render.PrimTabElts[GL_TRIANGLES];
+ struct vertex_buffer *VB = &tnl->vb;
+ const GLuint * const elt = VB->Elts;
+ GLubyte *mask = VB->ClipMask;
+ GLuint last = count-2;
+ GLuint j;
+ (void) flags;
+
+ tnl->Driver.Render.PrimitiveNotify( ctx, GL_TRIANGLES );
+
+ for (j=start; j < last; j+=3 ) {
+ GLubyte c1 = mask[elt[j]];
+ GLubyte c2 = mask[elt[j+1]];
+ GLubyte c3 = mask[elt[j+2]];
+ GLubyte ormask = c1|c2|c3;
+ if (ormask) {
+ if (start < j)
+ render_tris( ctx, start, j, 0 );
+ if (!(c1&c2&c3&0x3f))
+ clip_tri_4( ctx, elt[j], elt[j+1], elt[j+2], ormask );
+ start = j+3;
+ }
+ }
+
+ if (start < j)
+ render_tris( ctx, start, j, 0 );
+}
+
+/**********************************************************************/
+/* Render whole begin/end objects */
+/**********************************************************************/
+
+#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED)
+#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
+#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
+
+
+/* Vertices, no clipping.
+ */
+#define RENDER_POINTS( start, count ) \
+ tnl->Driver.Render.Points( ctx, start, count )
+
+#define RENDER_LINE( v1, v2 ) \
+ LineFunc( ctx, v1, v2 )
+
+#define RENDER_TRI( v1, v2, v3 ) \
+ TriangleFunc( ctx, v1, v2, v3 )
+
+#define RENDER_QUAD( v1, v2, v3, v4 ) \
+ QuadFunc( ctx, v1, v2, v3, v4 )
+
+#define TAG(x) _gld_tnl_##x##_verts
+
+#define LOCAL_VARS \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ const GLuint * const elt = VB->Elts; \
+ const line_func LineFunc = tnl->Driver.Render.Line; \
+ const triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
+ const quad_func QuadFunc = tnl->Driver.Render.Quad; \
+ (void) (LineFunc && TriangleFunc && QuadFunc); \
+ (void) elt;
+
+#define RESET_STIPPLE tnl->Driver.Render.ResetLineStipple( ctx )
+#define RESET_OCCLUSION ctx->OcclusionResult = GL_TRUE
+#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
+#define RENDER_TAB_QUALIFIER
+#define PRESERVE_VB_DEFS
+#include "tnl/t_vb_rendertmp.h"
+
+
+/* Elts, no clipping.
+ */
+#undef ELT
+#define TAG(x) _gld_tnl_##x##_elts
+#define ELT(x) elt[x]
+#include "tnl/t_vb_rendertmp.h"
+
+
+/**********************************************************************/
+/* Helper functions for drivers */
+/**********************************************************************/
+/*
+void _tnl_RenderClippedPolygon( GLcontext *ctx, const GLuint *elts, GLuint n )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint *tmp = VB->Elts;
+
+ VB->Elts = (GLuint *)elts;
+ tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
+ VB->Elts = tmp;
+}
+
+void _tnl_RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->Driver.Render.Line( ctx, ii, jj );
+}
+*/
+
+
+/**********************************************************************/
+/* Clip and render whole vertex buffers */
+/**********************************************************************/
+
+points_func _gldSetupPoints[4] = {
+ gld_Points2D_DX9,
+ gld_Points2D_DX9,
+ gld_Points2D_DX9,
+ gld_Points2D_DX9
+};
+line_func _gldSetupLine[4] = {
+ gld_Line2DFlat_DX9,
+ gld_Line2DSmooth_DX9,
+ gld_Line2DFlat_DX9,
+ gld_Line2DSmooth_DX9,
+};
+triangle_func _gldSetupTriangle[4] = {
+ gld_Triangle2DFlat_DX9,
+ gld_Triangle2DSmooth_DX9,
+ gld_Triangle2DFlatExtras_DX9,
+ gld_Triangle2DSmoothExtras_DX9
+};
+quad_func _gldSetupQuad[4] = {
+ gld_Quad2DFlat_DX9,
+ gld_Quad2DSmooth_DX9,
+ gld_Quad2DFlatExtras_DX9,
+ gld_Quad2DSmoothExtras_DX9
+};
+
+//---------------------------------------------------------------------------
+
+static GLboolean _gld_mesa_render_stage_run(
+ GLcontext *ctx,
+ struct gl_pipeline_stage *stage)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ GLD_driver_dx9 *gld = GLD_GET_DX9_DRIVER(gldCtx);
+
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint new_inputs = stage->changed_inputs;
+ render_func *tab;
+ GLint pass = 0;
+ GLD_pb_dx9 *gldPB;
+
+ /* Allow the drivers to lock before projected verts are built so
+ * that window coordinates are guarenteed not to change before
+ * rendering.
+ */
+ ASSERT(tnl->Driver.Render.Start);
+
+ tnl->Driver.Render.Start( ctx );
+
+ // NOTE: Setting D3DRS_SOFTWAREVERTEXPROCESSING for a mixed-mode device resets
+ // stream, indices and shader to default values of NULL or 0.
+/* if ((ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) &&
+ gld->VStwosidelight.hShader &&
+ !ctx->Fog.Enabled)
+ {
+ IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, !gld->VStwosidelight.bHardware);
+ _GLD_DX9_DEV(SetVertexShader(gld->pDev, gld->VStwosidelight.hShader));
+ gldPB = &gld->PBtwosidelight;
+ tnl->Driver.Render.Points = gld_Points2DTwoside_DX9;
+ if (ctx->_TriangleCaps & DD_FLATSHADE) {
+ tnl->Driver.Render.Line = gld_Line2DFlatTwoside_DX9;
+ tnl->Driver.Render.Triangle = gld_Triangle2DFlatTwoside_DX9;
+ tnl->Driver.Render.Quad = gld_Quad2DFlatTwoside_DX9;
+ } else {
+ tnl->Driver.Render.Line = gld_Line2DSmoothTwoside_DX9;
+ tnl->Driver.Render.Triangle = gld_Triangle2DSmoothTwoside_DX9;
+ tnl->Driver.Render.Quad = gld_Quad2DSmoothTwoside_DX9;
+ }
+ } else {*/
+// IDirect3DDevice8_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, TRUE);
+ IDirect3DDevice9_SetSoftwareVertexProcessing(gld->pDev, TRUE);
+ gldPB = &gld->PB2d;
+ _GLD_DX9_DEV(SetVertexShader(gld->pDev, NULL));
+ _GLD_DX9_DEV(SetFVF(gld->pDev, gldPB->dwFVF));
+ tnl->Driver.Render.Points = _gldSetupPoints[gld->iSetupFunc];
+ tnl->Driver.Render.Line = _gldSetupLine[gld->iSetupFunc];
+ tnl->Driver.Render.Triangle = _gldSetupTriangle[gld->iSetupFunc];
+ tnl->Driver.Render.Quad = _gldSetupQuad[gld->iSetupFunc];
+// }
+
+ _GLD_DX9_VB(Lock(gldPB->pVB, 0, 0, &gldPB->pPoints, D3DLOCK_DISCARD));
+ gldPB->nPoints = gldPB->nLines = gldPB->nTriangles = 0;
+ // Allocate primitive pointers
+ // gldPB->pPoints is always first
+ gldPB->pLines = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstLine);
+ gldPB->pTriangles = gldPB->pPoints + (gldPB->dwStride * gldPB->iFirstTriangle);
+
+ ASSERT(tnl->Driver.Render.BuildVertices);
+ ASSERT(tnl->Driver.Render.PrimitiveNotify);
+ ASSERT(tnl->Driver.Render.Points);
+ ASSERT(tnl->Driver.Render.Line);
+ ASSERT(tnl->Driver.Render.Triangle);
+ ASSERT(tnl->Driver.Render.Quad);
+ ASSERT(tnl->Driver.Render.ResetLineStipple);
+ ASSERT(tnl->Driver.Render.Interp);
+ ASSERT(tnl->Driver.Render.CopyPV);
+ ASSERT(tnl->Driver.Render.ClippedLine);
+ ASSERT(tnl->Driver.Render.ClippedPolygon);
+ ASSERT(tnl->Driver.Render.Finish);
+
+ tnl->Driver.Render.BuildVertices( ctx, 0, VB->Count, new_inputs );
+
+ if (VB->ClipOrMask) {
+ tab = VB->Elts ? clip_render_tab_elts : clip_render_tab_verts;
+ clip_render_tab_elts[GL_TRIANGLES] = clip_elt_triangles;
+ }
+ else {
+ tab = (VB->Elts ?
+ tnl->Driver.Render.PrimTabElts :
+ tnl->Driver.Render.PrimTabVerts);
+ }
+
+ do {
+ GLuint i, length, flags = 0;
+ for (i = 0 ; !(flags & PRIM_LAST) ; i += length) {
+ flags = VB->Primitive[i];
+ length= VB->PrimitiveLength[i];
+ ASSERT(length || (flags & PRIM_LAST));
+ ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1);
+ if (length)
+ tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags );
+ }
+ } while (tnl->Driver.Render.Multipass &&
+ tnl->Driver.Render.Multipass( ctx, ++pass ));
+
+
+// tnl->Driver.Render.Finish( ctx );
+
+ _GLD_DX9_VB(Unlock(gldPB->pVB));
+
+ _GLD_DX9_DEV(SetStreamSource(gld->pDev, 0, gldPB->pVB, 0, gldPB->dwStride));
+
+ if (gldPB->nPoints) {
+ _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_POINTLIST, 0, gldPB->nPoints));
+ gldPB->nPoints = 0;
+ }
+
+ if (gldPB->nLines) {
+ _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_LINELIST, gldPB->iFirstLine, gldPB->nLines));
+ gldPB->nLines = 0;
+ }
+
+ if (gldPB->nTriangles) {
+ _GLD_DX9_DEV(DrawPrimitive(gld->pDev, D3DPT_TRIANGLELIST, gldPB->iFirstTriangle, gldPB->nTriangles));
+ gldPB->nTriangles = 0;
+ }
+
+ return GL_FALSE; /* finished the pipe */
+}
+
+
+/**********************************************************************/
+/* Render pipeline stage */
+/**********************************************************************/
+
+
+
+/* Quite a bit of work involved in finding out the inputs for the
+ * render stage.
+ */
+static void _gld_mesa_render_stage_check(
+ GLcontext *ctx,
+ struct gl_pipeline_stage *stage)
+{
+ GLuint inputs = VERT_BIT_CLIP;
+ GLuint i;
+
+ if (ctx->Visual.rgbMode) {
+ inputs |= VERT_BIT_COLOR0;
+
+ if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
+ inputs |= VERT_BIT_COLOR1; //VERT_BIT_SPEC_RGB;
+
+ //if (ctx->Texture._ReallyEnabled) {
+ for (i=0; i<ctx->Const.MaxTextureUnits; i++) {
+ if (ctx->Texture.Unit[i]._ReallyEnabled)
+ inputs |= VERT_BIT_TEX(i);
+ }
+ //}
+ } else {
+ inputs |= VERT_BIT_INDEX;
+ }
+
+ if (ctx->Point._Attenuated)
+ inputs |= VERT_BIT_POINT_SIZE;
+
+ /* How do drivers turn this off?
+ */
+ if (ctx->Fog.Enabled)
+ inputs |= VERT_BIT_FOG; // VERT_FOG_COORD;
+
+ if (ctx->_TriangleCaps & DD_TRI_UNFILLED)
+ inputs |= VERT_BIT_EDGEFLAG;
+
+ if (ctx->RenderMode==GL_FEEDBACK)
+ inputs |= VERT_BITS_TEX_ANY;
+
+ stage->inputs = inputs;
+}
+
+//---------------------------------------------------------------------------
+
+// Destructor
+static void _gld_mesa_render_stage_dtr(
+ struct gl_pipeline_stage *stage)
+{
+}
+
+//---------------------------------------------------------------------------
+
+const struct gl_pipeline_stage _gld_mesa_render_stage =
+{
+ "gld_mesa_render_stage",
+ (_NEW_BUFFERS |
+ _DD_NEW_SEPARATE_SPECULAR |
+ _DD_NEW_FLATSHADE |
+ _NEW_TEXTURE|
+ _NEW_LIGHT|
+ _NEW_POINT|
+ _NEW_FOG|
+ _DD_NEW_TRI_UNFILLED |
+ _NEW_RENDERMODE), // re-check (new inputs, interp function)
+ 0, /* re-run (always runs) */
+ GL_TRUE, /* active */
+ 0, 0, /* inputs (set in check_render), outputs */
+ 0, 0, /* changed_inputs, private */
+ _gld_mesa_render_stage_dtr, /* destructor */
+ _gld_mesa_render_stage_check, /* check */
+ _gld_mesa_render_stage_run /* run */
+};
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c b/src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c
new file mode 100644
index 0000000000..86c4e30555
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/dx9/gld_wgl_dx9.c
@@ -0,0 +1,1345 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: GLDirect Direct3D 8.x WGL (WindowsGL)
+*
+****************************************************************************/
+
+#include "dglcontext.h"
+#include "gld_driver.h"
+#include "gld_dxerr9.h"
+#include "gld_dx9.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+
+// Copied from dglcontect.c
+#define GLDERR_NONE 0
+#define GLDERR_MEM 1
+#define GLDERR_DDRAW 2
+#define GLDERR_D3D 3
+#define GLDERR_BPP 4
+#define GLDERR_DDS 5
+// This external var keeps track of any error
+extern int nContextError;
+
+#define DDLOG_CRITICAL_OR_WARN DDLOG_CRITICAL
+
+extern void _gld_mesa_warning(GLcontext *, char *);
+extern void _gld_mesa_fatal(GLcontext *, char *);
+
+//---------------------------------------------------------------------------
+
+static char szColorDepthWarning[] =
+"GLDirect does not support the current desktop\n\
+color depth.\n\n\
+You may need to change the display resolution to\n\
+16 bits per pixel or higher color depth using\n\
+the Windows Display Settings control panel\n\
+before running this OpenGL application.\n";
+
+// The only depth-stencil formats currently supported by Direct3D
+// Surface Format Depth Stencil Total Bits
+// D3DFMT_D32 32 - 32
+// D3DFMT_D15S1 15 1 16
+// D3DFMT_D24S8 24 8 32
+// D3DFMT_D16 16 - 16
+// D3DFMT_D24X8 24 - 32
+// D3DFMT_D24X4S4 24 4 32
+
+// This pixel format will be used as a template when compiling the list
+// of pixel formats supported by the hardware. Many fields will be
+// filled in at runtime.
+// PFD flag defaults are upgraded to match ChoosePixelFormat() -- DaveM
+static DGL_pixelFormat pfTemplateHW =
+{
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), // Size of the data structure
+ 1, // Structure version - should be 1
+ // Flags:
+ PFD_DRAW_TO_WINDOW | // The buffer can draw to a window or device surface.
+ PFD_DRAW_TO_BITMAP | // The buffer can draw to a bitmap. (DaveM)
+ PFD_SUPPORT_GDI | // The buffer supports GDI drawing. (DaveM)
+ PFD_SUPPORT_OPENGL | // The buffer supports OpenGL drawing.
+ PFD_DOUBLEBUFFER | // The buffer is double-buffered.
+ 0, // Placeholder for easy commenting of above flags
+ PFD_TYPE_RGBA, // Pixel type RGBA.
+ 16, // Total colour bitplanes (excluding alpha bitplanes)
+ 5, 0, // Red bits, shift
+ 5, 0, // Green bits, shift
+ 5, 0, // Blue bits, shift
+ 0, 0, // Alpha bits, shift (destination alpha)
+ 0, // Accumulator bits (total)
+ 0, 0, 0, 0, // Accumulator bits: Red, Green, Blue, Alpha
+ 0, // Depth bits
+ 0, // Stencil bits
+ 0, // Number of auxiliary buffers
+ 0, // Layer type
+ 0, // Specifies the number of overlay and underlay planes.
+ 0, // Layer mask
+ 0, // Specifies the transparent color or index of an underlay plane.
+ 0 // Damage mask
+ },
+ D3DFMT_UNKNOWN, // No depth/stencil buffer
+};
+
+//---------------------------------------------------------------------------
+// Vertex Shaders
+//---------------------------------------------------------------------------
+/*
+// Vertex Shader Declaration
+static DWORD dwTwoSidedLightingDecl[] =
+{
+ D3DVSD_STREAM(0),
+ D3DVSD_REG(0, D3DVSDT_FLOAT3), // XYZ position
+ D3DVSD_REG(1, D3DVSDT_FLOAT3), // XYZ normal
+ D3DVSD_REG(2, D3DVSDT_D3DCOLOR), // Diffuse color
+ D3DVSD_REG(3, D3DVSDT_D3DCOLOR), // Specular color
+ D3DVSD_REG(4, D3DVSDT_FLOAT2), // 2D texture unit 0
+ D3DVSD_REG(5, D3DVSDT_FLOAT2), // 2D texture unit 1
+ D3DVSD_END()
+};
+
+// Vertex Shader for two-sided lighting
+static char *szTwoSidedLightingVS =
+// This is a test shader!
+"vs.1.0\n"
+"m4x4 oPos,v0,c0\n"
+"mov oD0,v2\n"
+"mov oD1,v3\n"
+"mov oT0,v4\n"
+"mov oT1,v5\n"
+;
+*/
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+
+typedef struct {
+ HINSTANCE hD3D9DLL; // Handle to d3d9.dll
+ FNDIRECT3DCREATE9 fnDirect3DCreate9; // Direct3DCreate9 function prototype
+ BOOL bDirect3D; // Persistant Direct3D9 exists
+ BOOL bDirect3DDevice; // Persistant Direct3DDevice9 exists
+ IDirect3D9 *pD3D; // Persistant Direct3D9
+ IDirect3DDevice9 *pDev; // Persistant Direct3DDevice9
+} GLD_dx9_globals;
+
+// These are "global" to all DX9 contexts. KeithH
+static GLD_dx9_globals dx9Globals;
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+
+BOOL gldGetDXErrorString_DX(
+ HRESULT hr,
+ char *buf,
+ int nBufSize)
+{
+ //
+ // Return a string describing the input HRESULT error code
+ //
+
+ const char *pStr = DXGetErrorString9(hr);
+
+ if (pStr == NULL)
+ return FALSE;
+
+ if (strlen(pStr) > nBufSize)
+ strncpy(buf, pStr, nBufSize);
+ else
+ strcpy(buf, pStr);
+
+// D3DXGetErrorString(hr, buf, nBufSize);
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+static D3DMULTISAMPLE_TYPE _gldGetDeviceMultiSampleType(
+ IDirect3D9 *pD3D9,
+ D3DFORMAT SurfaceFormat,
+ D3DDEVTYPE d3dDevType,
+ BOOL Windowed)
+{
+ int i;
+ HRESULT hr;
+
+ if (glb.dwMultisample == GLDS_MULTISAMPLE_NONE)
+ return D3DMULTISAMPLE_NONE;
+
+ if (glb.dwMultisample == GLDS_MULTISAMPLE_FASTEST) {
+ // Find fastest multisample
+ for (i=2; i<17; i++) {
+ hr = IDirect3D9_CheckDeviceMultiSampleType(
+ pD3D9,
+ glb.dwAdapter,
+ d3dDevType,
+ SurfaceFormat,
+ Windowed,
+ (D3DMULTISAMPLE_TYPE)i,
+ NULL);
+ if (SUCCEEDED(hr)) {
+ return (D3DMULTISAMPLE_TYPE)i;
+ }
+ }
+ } else {
+ // Find nicest multisample
+ for (i=16; i>1; i--) {
+ hr = IDirect3D9_CheckDeviceMultiSampleType(
+ pD3D9,
+ glb.dwAdapter,
+ d3dDevType,
+ SurfaceFormat,
+ Windowed,
+ (D3DMULTISAMPLE_TYPE)i,
+ NULL);
+ if (SUCCEEDED(hr)) {
+ return (D3DMULTISAMPLE_TYPE)i;
+ }
+ }
+ }
+
+ // Nothing found - return default
+ return D3DMULTISAMPLE_NONE;
+}
+
+//---------------------------------------------------------------------------
+
+void _gldDestroyPrimitiveBuffer(
+ GLD_pb_dx9 *gldVB)
+{
+ SAFE_RELEASE(gldVB->pVB);
+
+ // Sanity check...
+ gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0;
+}
+
+//---------------------------------------------------------------------------
+
+HRESULT _gldCreatePrimitiveBuffer(
+ GLcontext *ctx,
+ GLD_driver_dx9 *lpCtx,
+ GLD_pb_dx9 *gldVB)
+{
+ HRESULT hResult;
+ char *szCreateVertexBufferFailed = "CreateVertexBuffer failed";
+ DWORD dwMaxVertices; // Max number of vertices in vertex buffer
+ DWORD dwVBSize; // Total size of vertex buffer
+
+ // If CVA (Compiled Vertex Array) is used by an OpenGL app, then we
+ // will need enough vertices to cater for Mesa::Const.MaxArrayLockSize.
+ // We'll use IMM_SIZE if it's larger (which it should not be).
+ dwMaxVertices = (IMM_SIZE < MAX_ARRAY_LOCK_SIZE) ? MAX_ARRAY_LOCK_SIZE : IMM_SIZE;
+
+ // Now calculate how many vertices to allow for in total
+ // 1 per point, 2 per line, 6 per quad = 9
+ dwVBSize = dwMaxVertices * 9 * gldVB->dwStride;
+
+ hResult = IDirect3DDevice9_CreateVertexBuffer(
+ lpCtx->pDev,
+ dwVBSize,
+ gldVB->dwUsage,
+ gldVB->dwFVF,
+ gldVB->dwPool,
+ &gldVB->pVB,
+ NULL);
+ if (FAILED(hResult)) {
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, szCreateVertexBufferFailed);
+ return hResult;
+ }
+
+ gldVB->nLines = gldVB->nPoints = gldVB->nTriangles = 0;
+ gldVB->pPoints = gldVB->pLines = gldVB->pTriangles = NULL;
+ gldVB->iFirstLine = dwMaxVertices; // Index of first line in VB
+ gldVB->iFirstTriangle = dwMaxVertices*3; // Index of first triangle in VB
+
+ return S_OK;
+}
+
+//---------------------------------------------------------------------------
+// Function: _gldCreateVertexShaders
+// Create DX9 Vertex Shaders.
+//---------------------------------------------------------------------------
+/*
+void _gldCreateVertexShaders(
+ GLD_driver_dx9 *gld)
+{
+ DWORD dwFlags;
+ LPD3DXBUFFER pVSOpcodeBuffer; // Vertex Shader opcode buffer
+ HRESULT hr;
+
+#ifdef _DEBUG
+ dwFlags = D3DXASM_DEBUG;
+#else
+ dwFlags = 0; // D3DXASM_SKIPVALIDATION;
+#endif
+
+ ddlogMessage(DDLOG_INFO, "Creating shaders...\n");
+
+ // Init the shader handle
+ gld->VStwosidelight.hShader = 0;
+
+ if (gld->d3dCaps8.MaxStreams == 0) {
+ // Lame DX8 driver doesn't support streams
+ // Not fatal, as defaults will be used
+ ddlogMessage(DDLOG_WARN, "Driver doesn't support Vertex Shaders (MaxStreams==0)\n");
+ return;
+ }
+
+ // ** THIS DISABLES VERTEX SHADER SUPPORT **
+// return;
+ // ** THIS DISABLES VERTEX SHADER SUPPORT **
+
+ //
+ // Two-sided lighting
+ //
+
+#if 0
+ //
+ // DEBUGGING: Load shader from a text file
+ //
+ {
+ LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer
+ hr = D3DXAssembleShaderFromFile(
+ "twoside.vsh",
+ dwFlags,
+ NULL, // No constants
+ &pVSOpcodeBuffer,
+ &pVSErrorBuffer);
+ if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer))
+ ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer));
+ SAFE_RELEASE(pVSErrorBuffer);
+ }
+#else
+ {
+ LPD3DXBUFFER pVSErrorBuffer; // Vertex Shader error buffer
+ // Assemble ascii shader text into shader opcodes
+ hr = D3DXAssembleShader(
+ szTwoSidedLightingVS,
+ strlen(szTwoSidedLightingVS),
+ dwFlags,
+ NULL, // No constants
+ &pVSOpcodeBuffer,
+ &pVSErrorBuffer);
+ if (pVSErrorBuffer && pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer))
+ ddlogMessage(DDLOG_INFO, pVSErrorBuffer->lpVtbl->GetBufferPointer(pVSErrorBuffer));
+ SAFE_RELEASE(pVSErrorBuffer);
+ }
+#endif
+ if (FAILED(hr)) {
+ ddlogError(DDLOG_WARN, "AssembleShader failed", hr);
+ SAFE_RELEASE(pVSOpcodeBuffer);
+ return;
+ }
+
+// This is for debugging. Remove to enable vertex shaders in HW
+#define _GLD_FORCE_SW_VS 0
+
+ if (_GLD_FORCE_SW_VS) {
+ // _GLD_FORCE_SW_VS should be disabled for Final Release
+ ddlogMessage(DDLOG_SYSTEM, "[Forcing shaders in SW]\n");
+ }
+
+ // Try and create shader in hardware.
+ // NOTE: The D3D Ref device appears to succeed when trying to
+ // create the device in hardware, but later complains
+ // when trying to set it with SetVertexShader(). Go figure.
+ if (_GLD_FORCE_SW_VS || glb.dwDriver == GLDS_DRIVER_REF) {
+ // Don't try and create a hardware shader with the Ref device
+ hr = E_FAIL; // COM error/fail result
+ } else {
+ gld->VStwosidelight.bHardware = TRUE;
+ hr = IDirect3DDevice8_CreateVertexShader(
+ gld->pDev,
+ dwTwoSidedLightingDecl,
+ pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer),
+ &gld->VStwosidelight.hShader,
+ 0);
+ }
+ if (FAILED(hr)) {
+ ddlogMessage(DDLOG_INFO, "... HW failed, trying SW...\n");
+ // Failed. Try and create shader for software processing
+ hr = IDirect3DDevice8_CreateVertexShader(
+ gld->pDev,
+ dwTwoSidedLightingDecl,
+ pVSOpcodeBuffer->lpVtbl->GetBufferPointer(pVSOpcodeBuffer),
+ &gld->VStwosidelight.hShader,
+ D3DUSAGE_SOFTWAREPROCESSING);
+ if (FAILED(hr)) {
+ gld->VStwosidelight.hShader = 0; // Sanity check
+ ddlogError(DDLOG_WARN, "CreateVertexShader failed", hr);
+ return;
+ }
+ // Succeeded, but for software processing
+ gld->VStwosidelight.bHardware = FALSE;
+ }
+
+ SAFE_RELEASE(pVSOpcodeBuffer);
+
+ ddlogMessage(DDLOG_INFO, "... OK\n");
+}
+
+//---------------------------------------------------------------------------
+
+void _gldDestroyVertexShaders(
+ GLD_driver_dx9 *gld)
+{
+ if (gld->VStwosidelight.hShader) {
+ IDirect3DDevice8_DeleteVertexShader(gld->pDev, gld->VStwosidelight.hShader);
+ gld->VStwosidelight.hShader = 0;
+ }
+}
+*/
+//---------------------------------------------------------------------------
+
+BOOL gldCreateDrawable_DX(
+ DGL_ctx *ctx,
+// BOOL bDefaultDriver,
+ BOOL bDirectDrawPersistant,
+ BOOL bPersistantBuffers)
+{
+ //
+ // bDirectDrawPersistant: applies to IDirect3D9
+ // bPersistantBuffers: applies to IDirect3DDevice9
+ //
+
+ HRESULT hResult;
+ GLD_driver_dx9 *lpCtx = NULL;
+ D3DDEVTYPE d3dDevType;
+ D3DPRESENT_PARAMETERS d3dpp;
+ D3DDISPLAYMODE d3ddm;
+ DWORD dwBehaviourFlags;
+ D3DADAPTER_IDENTIFIER9 d3dIdent;
+
+ // Error if context is NULL.
+ if (ctx == NULL)
+ return FALSE;
+
+ if (ctx->glPriv) {
+ lpCtx = ctx->glPriv;
+ // Release any existing interfaces
+ SAFE_RELEASE(lpCtx->pDev);
+ SAFE_RELEASE(lpCtx->pD3D);
+ } else {
+ lpCtx = (GLD_driver_dx9*)malloc(sizeof(GLD_driver_dx9));
+ ZeroMemory(lpCtx, sizeof(lpCtx));
+ }
+
+ d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
+ // TODO: Check this
+// if (bDefaultDriver)
+// d3dDevType = D3DDEVTYPE_REF;
+
+ // Use persistant interface if needed
+ if (bDirectDrawPersistant && dx9Globals.bDirect3D) {
+ lpCtx->pD3D = dx9Globals.pD3D;
+ IDirect3D9_AddRef(lpCtx->pD3D);
+ goto SkipDirectDrawCreate;
+ }
+
+ // Create Direct3D9 object
+ lpCtx->pD3D = dx9Globals.fnDirect3DCreate9(D3D_SDK_VERSION);
+ if (lpCtx->pD3D == NULL) {
+ MessageBox(NULL, "Unable to initialize Direct3D9", "GLDirect", MB_OK);
+ ddlogMessage(DDLOG_CRITICAL_OR_WARN, "Unable to create Direct3D9 interface");
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Cache Direct3D interface for subsequent GLRCs
+ if (bDirectDrawPersistant && !dx9Globals.bDirect3D) {
+ dx9Globals.pD3D = lpCtx->pD3D;
+ IDirect3D9_AddRef(dx9Globals.pD3D);
+ dx9Globals.bDirect3D = TRUE;
+ }
+SkipDirectDrawCreate:
+
+ // Get the display mode so we can make a compatible backbuffer
+ hResult = IDirect3D9_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hResult)) {
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Get device caps
+ hResult = IDirect3D9_GetDeviceCaps(lpCtx->pD3D, glb.dwAdapter, d3dDevType, &lpCtx->d3dCaps9);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D9_GetDeviceCaps failed", hResult);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ // Check for hardware transform & lighting
+ lpCtx->bHasHWTnL = lpCtx->d3dCaps9.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ? TRUE : FALSE;
+
+/*
+ //
+ // GONE FOR DX9?
+ //
+ // If this flag is present then we can't default to Mesa
+ // SW rendering between BeginScene() and EndScene().
+ if (lpCtx->d3dCaps9.Caps2 & D3DCAPS2_NO2DDURING3DSCENE) {
+ ddlogMessage(DDLOG_WARN,
+ "Warning : No 2D allowed during 3D scene.\n");
+ }
+*/
+
+ //
+ // Create the Direct3D context
+ //
+
+ // Re-use original IDirect3DDevice if persistant buffers exist.
+ // Note that we test for persistant IDirect3D9 as well
+ // bDirectDrawPersistant == persistant IDirect3D9 (DirectDraw9 does not exist)
+ if (bDirectDrawPersistant && bPersistantBuffers && dx9Globals.pD3D && dx9Globals.pDev) {
+ lpCtx->pDev = dx9Globals.pDev;
+ IDirect3DDevice9_AddRef(dx9Globals.pDev);
+ goto skip_direct3ddevice_create;
+ }
+
+ // Clear the presentation parameters (sets all members to zero)
+ ZeroMemory(&d3dpp, sizeof(d3dpp));
+
+ // Recommended by MS; needed for MultiSample.
+ // Be careful if altering this for FullScreenBlit
+ d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+
+ d3dpp.BackBufferFormat = d3ddm.Format;
+ d3dpp.BackBufferCount = 2; //1;
+ d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(lpCtx->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen);
+ d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData;
+ d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE;
+
+ if (ctx->bFullscreen) {
+ ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen
+ d3dpp.Windowed = FALSE;
+ d3dpp.BackBufferWidth = d3ddm.Width;
+ d3dpp.BackBufferHeight = d3ddm.Height;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
+
+ // Support for vertical retrace synchronisation.
+ // Set default presentation interval in case caps bits are missing
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ if (glb.bWaitForRetrace) {
+ if (lpCtx->d3dCaps9.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
+ } else {
+ if (lpCtx->d3dCaps9.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+ }
+ } else {
+ ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages
+ d3dpp.Windowed = TRUE;
+ d3dpp.BackBufferWidth = ctx->dwWidth;
+ d3dpp.BackBufferHeight = ctx->dwHeight;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = 0;
+ // PresentationInterval Windowed mode is optional now in DX9 (DaveM)
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ if (glb.bWaitForRetrace) {
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
+ } else {
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+ }
+ }
+
+ // Decide if we can use hardware TnL
+ dwBehaviourFlags = (lpCtx->bHasHWTnL) ?
+ D3DCREATE_MIXED_VERTEXPROCESSING : D3DCREATE_SOFTWARE_VERTEXPROCESSING;
+ // Add flag to tell D3D to be thread-safe
+ if (glb.bMultiThreaded)
+ dwBehaviourFlags |= D3DCREATE_MULTITHREADED;
+ // Add flag to tell D3D to be FPU-safe
+ if (!glb.bFastFPU)
+ dwBehaviourFlags |= D3DCREATE_FPU_PRESERVE;
+ hResult = IDirect3D9_CreateDevice(lpCtx->pD3D,
+ glb.dwAdapter,
+ d3dDevType,
+ ctx->hWnd,
+ dwBehaviourFlags,
+ &d3dpp,
+ &lpCtx->pDev);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "IDirect3D9_CreateDevice failed", hResult);
+ nContextError = GLDERR_D3D;
+ goto return_with_error;
+ }
+
+ if (bDirectDrawPersistant && bPersistantBuffers && dx9Globals.pD3D) {
+ dx9Globals.pDev = lpCtx->pDev;
+ dx9Globals.bDirect3DDevice = TRUE;
+ }
+
+ // Dump some useful stats
+ hResult = IDirect3D9_GetAdapterIdentifier(
+ lpCtx->pD3D,
+ glb.dwAdapter,
+ 0, // No WHQL detection (avoid few seconds delay)
+ &d3dIdent);
+ if (SUCCEEDED(hResult)) {
+ ddlogPrintf(DDLOG_INFO, "[Driver Description: %s]", &d3dIdent.Description);
+ ddlogPrintf(DDLOG_INFO, "[Driver file: %s %d.%d.%02d.%d]",
+ d3dIdent.Driver,
+ HIWORD(d3dIdent.DriverVersion.HighPart),
+ LOWORD(d3dIdent.DriverVersion.HighPart),
+ HIWORD(d3dIdent.DriverVersion.LowPart),
+ LOWORD(d3dIdent.DriverVersion.LowPart));
+ ddlogPrintf(DDLOG_INFO, "[VendorId: 0x%X, DeviceId: 0x%X, SubSysId: 0x%X, Revision: 0x%X]",
+ d3dIdent.VendorId, d3dIdent.DeviceId, d3dIdent.SubSysId, d3dIdent.Revision);
+ }
+
+ // Test to see if IHV driver exposes Scissor Test (new for DX9)
+ lpCtx->bCanScissor = lpCtx->d3dCaps9.RasterCaps & D3DPRASTERCAPS_SCISSORTEST;
+ ddlogPrintf(DDLOG_INFO, "Can Scissor: %s", lpCtx->bCanScissor ? "Yes" : "No");
+
+ // Init projection matrix for D3D TnL
+ D3DXMatrixIdentity(&lpCtx->matProjection);
+ lpCtx->matModelView = lpCtx->matProjection;
+// gld->bUseMesaProjection = TRUE;
+
+skip_direct3ddevice_create:
+
+ // Create buffers to hold primitives
+ lpCtx->PB2d.dwFVF = GLD_FVF_2D_VERTEX;
+ lpCtx->PB2d.dwPool = D3DPOOL_SYSTEMMEM;
+ lpCtx->PB2d.dwStride = sizeof(GLD_2D_VERTEX);
+ lpCtx->PB2d.dwUsage = D3DUSAGE_DONOTCLIP |
+ D3DUSAGE_DYNAMIC |
+ D3DUSAGE_SOFTWAREPROCESSING |
+ D3DUSAGE_WRITEONLY;
+ hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB2d);
+ if (FAILED(hResult))
+ goto return_with_error;
+
+ lpCtx->PB3d.dwFVF = GLD_FVF_3D_VERTEX;
+ lpCtx->PB3d.dwPool = D3DPOOL_DEFAULT;
+ lpCtx->PB3d.dwStride = sizeof(GLD_3D_VERTEX);
+ lpCtx->PB3d.dwUsage = D3DUSAGE_DYNAMIC |
+//DaveM D3DUSAGE_SOFTWAREPROCESSING |
+ D3DUSAGE_WRITEONLY;
+ hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PB3d);
+ if (FAILED(hResult))
+ goto return_with_error;
+
+/* // NOTE: A FVF code of zero indicates a non-FVF vertex buffer (for vertex shaders)
+ lpCtx->PBtwosidelight.dwFVF = 0; //GLD_FVF_TWOSIDED_VERTEX;
+ lpCtx->PBtwosidelight.dwPool = D3DPOOL_DEFAULT;
+ lpCtx->PBtwosidelight.dwStride = sizeof(GLD_TWOSIDED_VERTEX);
+ lpCtx->PBtwosidelight.dwUsage = D3DUSAGE_DONOTCLIP |
+ D3DUSAGE_DYNAMIC |
+ D3DUSAGE_SOFTWAREPROCESSING |
+ D3DUSAGE_WRITEONLY;
+ hResult = _gldCreatePrimitiveBuffer(ctx->glCtx, lpCtx, &lpCtx->PBtwosidelight);
+ if (FAILED(hResult))
+ goto return_with_error;*/
+
+ // Now try and create the DX9 Vertex Shaders
+// _gldCreateVertexShaders(lpCtx);
+
+ // Zero the pipeline usage counters
+ lpCtx->PipelineUsage.qwMesa.QuadPart =
+// lpCtx->PipelineUsage.dwD3D2SVS.QuadPart =
+ lpCtx->PipelineUsage.qwD3DFVF.QuadPart = 0;
+
+ // Assign drawable to GL private
+ ctx->glPriv = lpCtx;
+ return TRUE;
+
+return_with_error:
+ // Clean up and bail
+
+// _gldDestroyVertexShaders(lpCtx);
+
+// _gldDestroyPrimitiveBuffer(&lpCtx->PBtwosidelight);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB3d);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB2d);
+
+ SAFE_RELEASE(lpCtx->pDev);
+ SAFE_RELEASE(lpCtx->pD3D);
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldResizeDrawable_DX(
+ DGL_ctx *ctx,
+ BOOL bDefaultDriver,
+ BOOL bPersistantInterface,
+ BOOL bPersistantBuffers)
+{
+ GLD_driver_dx9 *gld = NULL;
+ D3DDEVTYPE d3dDevType;
+ D3DPRESENT_PARAMETERS d3dpp;
+ D3DDISPLAYMODE d3ddm;
+ HRESULT hResult;
+
+ // Error if context is NULL.
+ if (ctx == NULL)
+ return FALSE;
+
+ gld = ctx->glPriv;
+ if (gld == NULL)
+ return FALSE;
+
+ if (ctx->bSceneStarted) {
+ IDirect3DDevice9_EndScene(gld->pDev);
+ ctx->bSceneStarted = FALSE;
+ }
+
+ d3dDevType = (glb.dwDriver == GLDS_DRIVER_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
+ if (!bDefaultDriver)
+ d3dDevType = D3DDEVTYPE_REF; // Force Direct3D Reference Rasterise (software)
+
+ // Get the display mode so we can make a compatible backbuffer
+ hResult = IDirect3D9_GetAdapterDisplayMode(gld->pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hResult)) {
+ nContextError = GLDERR_D3D;
+// goto return_with_error;
+ return FALSE;
+ }
+
+ // Destroy DX9 Vertex Shaders before Reset()
+// _gldDestroyVertexShaders(gld);
+
+ // Release POOL_DEFAULT objects before Reset()
+ if (gld->PB2d.dwPool == D3DPOOL_DEFAULT)
+ _gldDestroyPrimitiveBuffer(&gld->PB2d);
+ if (gld->PB3d.dwPool == D3DPOOL_DEFAULT)
+ _gldDestroyPrimitiveBuffer(&gld->PB3d);
+// if (gld->PBtwosidelight.dwPool == D3DPOOL_DEFAULT)
+// _gldDestroyPrimitiveBuffer(&gld->PBtwosidelight);
+
+ // Clear the presentation parameters (sets all members to zero)
+ ZeroMemory(&d3dpp, sizeof(d3dpp));
+
+ // Recommended by MS; needed for MultiSample.
+ // Be careful if altering this for FullScreenBlit
+ d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
+
+ d3dpp.BackBufferFormat = d3ddm.Format;
+ d3dpp.BackBufferCount = 1;
+ d3dpp.MultiSampleType = _gldGetDeviceMultiSampleType(gld->pD3D, d3ddm.Format, d3dDevType, !ctx->bFullscreen);
+ d3dpp.AutoDepthStencilFormat = ctx->lpPF->dwDriverData;
+ d3dpp.EnableAutoDepthStencil = (d3dpp.AutoDepthStencilFormat == D3DFMT_UNKNOWN) ? FALSE : TRUE;
+
+ // TODO: Sync to refresh
+
+ if (ctx->bFullscreen) {
+ ddlogWarnOption(FALSE); // Don't popup any messages in fullscreen
+ d3dpp.Windowed = FALSE;
+ d3dpp.BackBufferWidth = d3ddm.Width;
+ d3dpp.BackBufferHeight = d3ddm.Height;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ // Get better benchmark results? KeithH
+// d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_UNLIMITED;
+ } else {
+ ddlogWarnOption(glb.bMessageBoxWarnings); // OK to popup messages
+ d3dpp.Windowed = TRUE;
+ d3dpp.BackBufferWidth = ctx->dwWidth;
+ d3dpp.BackBufferHeight = ctx->dwHeight;
+ d3dpp.hDeviceWindow = ctx->hWnd;
+ d3dpp.FullScreen_RefreshRateInHz = 0;
+ d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ }
+ hResult = IDirect3DDevice9_Reset(gld->pDev, &d3dpp);
+ if (FAILED(hResult)) {
+ ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Reset failed", hResult);
+ return FALSE;
+ //goto cleanup_and_return_with_error;
+ }
+
+ //
+ // Recreate POOL_DEFAULT objects
+ //
+ if (gld->PB2d.dwPool == D3DPOOL_DEFAULT) {
+ _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB2d);
+ }
+ if (gld->PB3d.dwPool == D3DPOOL_DEFAULT) {
+ _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB3d);
+ }
+// if (gld->PBtwosidelight.dwPool == D3DPOOL_DEFAULT) {
+// _gldCreatePrimitiveBuffer(ctx->glCtx, gld, &gld->PB2d);
+// }
+
+ // Recreate DX9 Vertex Shaders
+// _gldCreateVertexShaders(gld);
+
+ // Signal a complete state update
+ ctx->glCtx->Driver.UpdateState(ctx->glCtx, _NEW_ALL);
+
+ // Begin a new scene
+ IDirect3DDevice9_BeginScene(gld->pDev);
+ ctx->bSceneStarted = TRUE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldDestroyDrawable_DX(
+ DGL_ctx *ctx)
+{
+ GLD_driver_dx9 *lpCtx = NULL;
+
+ // Error if context is NULL.
+ if (!ctx)
+ return FALSE;
+
+ // Error if the drawable does not exist.
+ if (!ctx->glPriv)
+ return FALSE;
+
+ lpCtx = ctx->glPriv;
+
+#ifdef _DEBUG
+ // Dump out stats
+ ddlogPrintf(DDLOG_SYSTEM, "Usage: M:0x%X%X, D:0x%X%X",
+ lpCtx->PipelineUsage.qwMesa.HighPart,
+ lpCtx->PipelineUsage.qwMesa.LowPart,
+ lpCtx->PipelineUsage.qwD3DFVF.HighPart,
+ lpCtx->PipelineUsage.qwD3DFVF.LowPart);
+#endif
+
+// _gldDestroyVertexShaders(lpCtx);
+
+// _gldDestroyPrimitiveBuffer(&lpCtx->PBtwosidelight);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB3d);
+ _gldDestroyPrimitiveBuffer(&lpCtx->PB2d);
+
+ SAFE_RELEASE(lpCtx->pDev);
+ SAFE_RELEASE(lpCtx->pD3D);
+
+ // Free the private drawable data
+ free(ctx->glPriv);
+ ctx->glPriv = NULL;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldCreatePrivateGlobals_DX(void)
+{
+ ZeroMemory(&dx9Globals, sizeof(dx9Globals));
+
+ // Load d3d9.dll
+ dx9Globals.hD3D9DLL = LoadLibrary("D3D9.DLL");
+ if (dx9Globals.hD3D9DLL == NULL)
+ return FALSE;
+
+ // Now try and obtain Direct3DCreate9
+ dx9Globals.fnDirect3DCreate9 = (FNDIRECT3DCREATE9)GetProcAddress(dx9Globals.hD3D9DLL, "Direct3DCreate9");
+ if (dx9Globals.fnDirect3DCreate9 == NULL) {
+ FreeLibrary(dx9Globals.hD3D9DLL);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldDestroyPrivateGlobals_DX(void)
+{
+ if (dx9Globals.bDirect3DDevice) {
+ SAFE_RELEASE(dx9Globals.pDev);
+ dx9Globals.bDirect3DDevice = FALSE;
+ }
+ if (dx9Globals.bDirect3D) {
+ SAFE_RELEASE(dx9Globals.pD3D);
+ dx9Globals.bDirect3D = FALSE;
+ }
+
+ FreeLibrary(dx9Globals.hD3D9DLL);
+ dx9Globals.hD3D9DLL = NULL;
+ dx9Globals.fnDirect3DCreate9 = NULL;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+static void _BitsFromDisplayFormat(
+ D3DFORMAT fmt,
+ BYTE *cColorBits,
+ BYTE *cRedBits,
+ BYTE *cGreenBits,
+ BYTE *cBlueBits,
+ BYTE *cAlphaBits)
+{
+ switch (fmt) {
+ case D3DFMT_X1R5G5B5:
+ *cColorBits = 16;
+ *cRedBits = 5;
+ *cGreenBits = 5;
+ *cBlueBits = 5;
+ *cAlphaBits = 0;
+ return;
+ case D3DFMT_R5G6B5:
+ *cColorBits = 16;
+ *cRedBits = 5;
+ *cGreenBits = 6;
+ *cBlueBits = 5;
+ *cAlphaBits = 0;
+ return;
+ case D3DFMT_X8R8G8B8:
+ *cColorBits = 32;
+ *cRedBits = 8;
+ *cGreenBits = 8;
+ *cBlueBits = 8;
+ *cAlphaBits = 0;
+ return;
+ case D3DFMT_A8R8G8B8:
+ *cColorBits = 32;
+ *cRedBits = 8;
+ *cGreenBits = 8;
+ *cBlueBits = 8;
+ *cAlphaBits = 8;
+ return;
+ }
+
+ // Should not get here!
+ *cColorBits = 32;
+ *cRedBits = 8;
+ *cGreenBits = 8;
+ *cBlueBits = 8;
+ *cAlphaBits = 0;
+}
+
+//---------------------------------------------------------------------------
+
+static void _BitsFromDepthStencilFormat(
+ D3DFORMAT fmt,
+ BYTE *cDepthBits,
+ BYTE *cStencilBits)
+{
+ // NOTE: GL expects either 32 or 16 as depth bits.
+ switch (fmt) {
+ case D3DFMT_D32:
+ *cDepthBits = 32;
+ *cStencilBits = 0;
+ return;
+ case D3DFMT_D15S1:
+ *cDepthBits = 16;
+ *cStencilBits = 1;
+ return;
+ case D3DFMT_D24S8:
+ *cDepthBits = 32;
+ *cStencilBits = 8;
+ return;
+ case D3DFMT_D16:
+ *cDepthBits = 16;
+ *cStencilBits = 0;
+ return;
+ case D3DFMT_D24X8:
+ *cDepthBits = 32;
+ *cStencilBits = 0;
+ return;
+ case D3DFMT_D24X4S4:
+ *cDepthBits = 32;
+ *cStencilBits = 4;
+ return;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldBuildPixelformatList_DX(void)
+{
+ D3DDISPLAYMODE d3ddm;
+ D3DFORMAT fmt[6];
+ IDirect3D9 *pD3D = NULL;
+ HRESULT hr;
+ int nSupportedFormats = 0;
+ int i;
+ DGL_pixelFormat *pPF;
+ BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits;
+// char buf[128];
+// char cat[8];
+
+ // Direct3D (SW or HW)
+ // These are arranged so that 'best' pixelformat
+ // is higher in the list (for ChoosePixelFormat).
+ const D3DFORMAT DepthStencil[6] = {
+// New order: increaing Z, then increasing stencil
+ D3DFMT_D15S1,
+ D3DFMT_D16,
+ D3DFMT_D24X4S4,
+ D3DFMT_D24X8,
+ D3DFMT_D24S8,
+ D3DFMT_D32,
+ };
+
+ // Dump DX version
+ ddlogMessage(GLDLOG_SYSTEM, "DirectX Version : 9.0\n");
+
+ // Release any existing pixelformat list
+ if (glb.lpPF) {
+ free(glb.lpPF);
+ }
+
+ glb.nPixelFormatCount = 0;
+ glb.lpPF = NULL;
+
+ //
+ // Pixelformats for Direct3D (SW or HW) rendering
+ //
+
+ // Get a Direct3D 9.0 interface
+ pD3D = dx9Globals.fnDirect3DCreate9(D3D_SDK_VERSION);
+ if (!pD3D) {
+ return FALSE;
+ }
+
+ // We will use the display mode format when finding compliant
+ // rendertarget/depth-stencil surfaces.
+ hr = IDirect3D9_GetAdapterDisplayMode(pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hr)) {
+ IDirect3D9_Release(pD3D);
+ return FALSE;
+ }
+
+ // Run through the possible formats and detect supported formats
+ for (i=0; i<6; i++) {
+ hr = IDirect3D9_CheckDeviceFormat(
+ pD3D,
+ glb.dwAdapter,
+ glb.dwDriver==GLDS_DRIVER_HAL ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF,
+ d3ddm.Format,
+ D3DUSAGE_DEPTHSTENCIL,
+ D3DRTYPE_SURFACE,
+ DepthStencil[i]);
+ if (FAILED(hr))
+ // A failure here is not fatal.
+ continue;
+
+ // Verify that the depth format is compatible.
+ hr = IDirect3D9_CheckDepthStencilMatch(
+ pD3D,
+ glb.dwAdapter,
+ glb.dwDriver==GLDS_DRIVER_HAL ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF,
+ d3ddm.Format,
+ d3ddm.Format,
+ DepthStencil[i]);
+ if (FAILED(hr))
+ // A failure here is not fatal, just means depth-stencil
+ // format is not compatible with this display mode.
+ continue;
+
+ fmt[nSupportedFormats++] = DepthStencil[i];
+ }
+
+ IDirect3D9_Release(pD3D);
+
+ if (nSupportedFormats == 0)
+ return FALSE; // Bail: no compliant pixelformats
+
+ // Total count of pixelformats is:
+ // (nSupportedFormats+1)*2
+ // UPDATED: nSupportedFormats*2
+ glb.lpPF = (DGL_pixelFormat *)calloc(nSupportedFormats*2, sizeof(DGL_pixelFormat));
+ glb.nPixelFormatCount = nSupportedFormats*2;
+ if (glb.lpPF == NULL) {
+ glb.nPixelFormatCount = 0;
+ return FALSE;
+ }
+
+ // Get a copy of pointer that we can alter
+ pPF = glb.lpPF;
+
+ // Cache colour bits from display format
+ _BitsFromDisplayFormat(d3ddm.Format, &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits);
+
+ //
+ // Add single-buffer formats
+ //
+/*
+ // NOTE: No longer returning pixelformats that don't contain depth
+ // Single-buffer, no depth-stencil buffer
+ memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ pPF->pfd.cDepthBits = 0;
+ pPF->pfd.cStencilBits = 0;
+ pPF->dwDriverData = D3DFMT_UNKNOWN;
+ pPF++;
+*/
+ for (i=0; i<nSupportedFormats; i++, pPF++) {
+ memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits);
+ pPF->dwDriverData = fmt[i];
+ }
+
+ //
+ // Add double-buffer formats
+ //
+
+ // NOTE: No longer returning pixelformats that don't contain depth
+/*
+ memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ pPF->pfd.cDepthBits = 0;
+ pPF->pfd.cStencilBits = 0;
+ pPF->dwDriverData = D3DFMT_UNKNOWN;
+ pPF++;
+*/
+ for (i=0; i<nSupportedFormats; i++, pPF++) {
+ memcpy(pPF, &pfTemplateHW, sizeof(DGL_pixelFormat));
+ pPF->pfd.cColorBits = cColorBits;
+ pPF->pfd.cRedBits = cRedBits;
+ pPF->pfd.cGreenBits = cGreenBits;
+ pPF->pfd.cBlueBits = cBlueBits;
+ pPF->pfd.cAlphaBits = cAlphaBits;
+ _BitsFromDepthStencilFormat(fmt[i], &pPF->pfd.cDepthBits, &pPF->pfd.cStencilBits);
+ pPF->dwDriverData = fmt[i];
+ }
+
+ // Popup warning message if non RGB color mode
+ {
+ // This is a hack. KeithH
+ HDC hdcDesktop = GetDC(NULL);
+ DWORD dwDisplayBitDepth = GetDeviceCaps(hdcDesktop, BITSPIXEL);
+ ReleaseDC(0, hdcDesktop);
+ if (dwDisplayBitDepth <= 8) {
+ ddlogPrintf(DDLOG_WARN, "Current Color Depth %d bpp is not supported", dwDisplayBitDepth);
+ MessageBox(NULL, szColorDepthWarning, "GLDirect", MB_OK | MB_ICONWARNING);
+ }
+ }
+
+ // Mark list as 'current'
+ glb.bPixelformatsDirty = FALSE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldInitialiseMesa_DX(
+ DGL_ctx *lpCtx)
+{
+ GLD_driver_dx9 *gld = NULL;
+ int MaxTextureSize, TextureLevels;
+ BOOL bSoftwareTnL;
+
+ if (lpCtx == NULL)
+ return FALSE;
+
+ gld = lpCtx->glPriv;
+ if (gld == NULL)
+ return FALSE;
+
+ if (glb.bMultitexture) {
+ lpCtx->glCtx->Const.MaxTextureUnits = gld->d3dCaps9.MaxSimultaneousTextures;
+ // Only support MAX_TEXTURE_UNITS texture units.
+ // ** If this is altered then the FVF formats must be reviewed **.
+ if (lpCtx->glCtx->Const.MaxTextureUnits > GLD_MAX_TEXTURE_UNITS_DX9)
+ lpCtx->glCtx->Const.MaxTextureUnits = GLD_MAX_TEXTURE_UNITS_DX9;
+ } else {
+ // Multitexture override
+ lpCtx->glCtx->Const.MaxTextureUnits = 1;
+ }
+
+ // max texture size
+ MaxTextureSize = min(gld->d3dCaps9.MaxTextureHeight, gld->d3dCaps9.MaxTextureWidth);
+ if (MaxTextureSize == 0)
+ MaxTextureSize = 256; // Sanity check
+
+ //
+ // HACK!!
+ if (MaxTextureSize > 1024)
+ MaxTextureSize = 1024; // HACK - CLAMP TO 1024
+ // HACK!!
+ //
+
+ // Got to set MAX_TEXTURE_SIZE as max levels.
+ // Who thought this stupid idea up? ;)
+ TextureLevels = 0;
+ // Calculate power-of-two.
+ while (MaxTextureSize) {
+ TextureLevels++;
+ MaxTextureSize >>= 1;
+ }
+ lpCtx->glCtx->Const.MaxTextureLevels = (TextureLevels) ? TextureLevels : 8;
+
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_LIGHTING, FALSE);
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_CULLMODE, D3DCULL_NONE);
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_DITHERENABLE, TRUE);
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
+
+ IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_ZENABLE,
+ (lpCtx->lpPF->dwDriverData!=D3DFMT_UNKNOWN) ? D3DZB_TRUE : D3DZB_FALSE);
+
+ // Set the view matrix
+ {
+ D3DXMATRIX vm;
+#if 1
+ D3DXMatrixIdentity(&vm);
+#else
+ D3DXVECTOR3 Eye(0.0f, 0.0f, 0.0f);
+ D3DXVECTOR3 At(0.0f, 0.0f, -1.0f);
+ D3DXVECTOR3 Up(0.0f, 1.0f, 0.0f);
+ D3DXMatrixLookAtRH(&vm, &Eye, &At, &Up);
+ vm._31 = -vm._31;
+ vm._32 = -vm._32;
+ vm._33 = -vm._33;
+ vm._34 = -vm._34;
+#endif
+ IDirect3DDevice9_SetTransform(gld->pDev, D3DTS_VIEW, &vm);
+ }
+
+ if (gld->bHasHWTnL) {
+ if (glb.dwTnL == GLDS_TNL_DEFAULT)
+ bSoftwareTnL = FALSE; // HW TnL
+ else {
+ bSoftwareTnL = ((glb.dwTnL == GLDS_TNL_MESA) || (glb.dwTnL == GLDS_TNL_D3DSW)) ? TRUE : FALSE;
+ }
+ } else {
+ // No HW TnL, so no choice possible
+ bSoftwareTnL = TRUE;
+ }
+// IDirect3DDevice9_SetRenderState(gld->pDev, D3DRS_SOFTWAREVERTEXPROCESSING, bSoftwareTnL);
+ IDirect3DDevice9_SetSoftwareVertexProcessing(gld->pDev, bSoftwareTnL);
+
+// Dump this in a Release build as well, now.
+//#ifdef _DEBUG
+ ddlogPrintf(DDLOG_INFO, "HW TnL: %s",
+ gld->bHasHWTnL ? (bSoftwareTnL ? "Disabled" : "Enabled") : "Unavailable");
+//#endif
+
+ gldEnableExtensions_DX9(lpCtx->glCtx);
+ gldInstallPipeline_DX9(lpCtx->glCtx);
+ gldSetupDriverPointers_DX9(lpCtx->glCtx);
+
+ // Signal a complete state update
+ lpCtx->glCtx->Driver.UpdateState(lpCtx->glCtx, _NEW_ALL);
+
+ // Start a scene
+ IDirect3DDevice9_BeginScene(gld->pDev);
+ lpCtx->bSceneStarted = TRUE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldSwapBuffers_DX(
+ DGL_ctx *ctx,
+ HDC hDC,
+ HWND hWnd)
+{
+ HRESULT hr;
+ GLD_driver_dx9 *gld = NULL;
+
+ if (ctx == NULL)
+ return FALSE;
+
+ gld = ctx->glPriv;
+ if (gld == NULL)
+ return FALSE;
+
+ if (ctx->bSceneStarted) {
+ IDirect3DDevice9_EndScene(gld->pDev);
+ ctx->bSceneStarted = FALSE;
+ }
+
+ // Swap the buffers. hWnd may override the hWnd used for CreateDevice()
+ hr = IDirect3DDevice9_Present(gld->pDev, NULL, NULL, hWnd, NULL);
+
+exit_swap:
+
+ IDirect3DDevice9_BeginScene(gld->pDev);
+ ctx->bSceneStarted = TRUE;
+
+// Debugging code
+#ifdef _DEBUG
+// ddlogMessage(GLDLOG_WARN, "SwapBuffers\n");
+#endif
+
+ return (FAILED(hr)) ? FALSE : TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldGetDisplayMode_DX(
+ DGL_ctx *ctx,
+ GLD_displayMode *glddm)
+{
+ D3DDISPLAYMODE d3ddm;
+ HRESULT hr;
+ GLD_driver_dx9 *lpCtx = NULL;
+ BYTE cColorBits, cRedBits, cGreenBits, cBlueBits, cAlphaBits;
+
+ if ((glddm == NULL) || (ctx == NULL))
+ return FALSE;
+
+ lpCtx = ctx->glPriv;
+ if (lpCtx == NULL)
+ return FALSE;
+
+ if (lpCtx->pD3D == NULL)
+ return FALSE;
+
+ hr = IDirect3D9_GetAdapterDisplayMode(lpCtx->pD3D, glb.dwAdapter, &d3ddm);
+ if (FAILED(hr))
+ return FALSE;
+
+ // Get info from the display format
+ _BitsFromDisplayFormat(d3ddm.Format,
+ &cColorBits, &cRedBits, &cGreenBits, &cBlueBits, &cAlphaBits);
+
+ glddm->Width = d3ddm.Width;
+ glddm->Height = d3ddm.Height;
+ glddm->BPP = cColorBits;
+ glddm->Refresh = d3ddm.RefreshRate;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
diff --git a/src/mesa/drivers/windows/gldirect/gld_debug_clip.c b/src/mesa/drivers/windows/gldirect/gld_debug_clip.c
new file mode 100644
index 0000000000..1eb19ca84b
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/gld_debug_clip.c
@@ -0,0 +1,40 @@
+/* $Id: gld_debug_clip.c,v 1.1 2004/04/20 11:13:11 alanh Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifdef DEBUG /* This code only used for debugging */
+
+// Stub to enable Mesa to build. KeithH
+#pragma message("NOTE: Using gld_debug_clip.c HACK")
+
+void _math_test_all_cliptest_functions( char *description )
+{
+}
+
+
+#endif /* DEBUG */
diff --git a/src/mesa/drivers/windows/gldirect/gld_debug_norm.c b/src/mesa/drivers/windows/gldirect/gld_debug_norm.c
new file mode 100644
index 0000000000..00c428bd26
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/gld_debug_norm.c
@@ -0,0 +1,40 @@
+/* $Id: gld_debug_norm.c,v 1.1 2004/04/20 11:13:11 alanh Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifdef DEBUG /* This code only used for debugging */
+
+// Stub to enable Mesa to build. KeithH
+#pragma message("NOTE: Using gld_debug_norm.c HACK")
+
+void _math_test_all_normal_transform_functions( char *description )
+{
+}
+
+
+#endif /* DEBUG */
diff --git a/src/mesa/drivers/windows/gldirect/gld_debug_xform.c b/src/mesa/drivers/windows/gldirect/gld_debug_xform.c
new file mode 100644
index 0000000000..d6e64b8ffd
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/gld_debug_xform.c
@@ -0,0 +1,42 @@
+/* $Id: gld_debug_xform.c,v 1.1 2004/04/20 11:13:11 alanh Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.5
+ *
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Updated for P6 architecture by Gareth Hughes.
+ */
+
+
+#ifdef DEBUG /* This code only used for debugging */
+
+// Stub to enable Mesa to build. KeithH
+#pragma message("NOTE: Using gld_debug_xform.c HACK")
+
+void _math_test_all_transform_functions( char *description )
+{
+}
+
+
+#endif /* DEBUG */
diff --git a/src/mesa/drivers/windows/gldirect/gld_dispatch.c b/src/mesa/drivers/windows/gldirect/gld_dispatch.c
new file mode 100644
index 0000000000..e05d767e30
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/gld_dispatch.c
@@ -0,0 +1,73 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Thread-aware dispatch table.
+*
+****************************************************************************/
+
+#include "glheader.h"
+#include "glapi.h"
+#include "glapitable.h"
+#include "mtypes.h"
+#include "context.h"
+
+#define KEYWORD1
+#define KEYWORD2 GLAPIENTRY
+#if defined(USE_MGL_NAMESPACE)
+ #define NAME(func) mgl##func
+#else
+ #define NAME(func) gl##func
+#endif
+
+#if 0
+// Altered these to get the dispatch table from
+// the current context of the calling thread.
+#define DISPATCH(FUNC, ARGS, MESSAGE) \
+ GET_CURRENT_CONTEXT(gc); \
+ (gc->CurrentDispatch->FUNC) ARGS
+#define RETURN_DISPATCH(FUNC, ARGS, MESSAGE) \
+ GET_CURRENT_CONTEXT(gc); \
+ return (gc->CurrentDispatch->FUNC) ARGS
+#else // #if 0
+#define DISPATCH(FUNC, ARGS, MESSAGE) \
+ GET_CURRENT_CONTEXT(gc); \
+ (_glapi_Dispatch->FUNC) ARGS
+#define RETURN_DISPATCH(FUNC, ARGS, MESSAGE) \
+ GET_CURRENT_CONTEXT(gc); \
+ return (_glapi_Dispatch->FUNC) ARGS
+#endif // #if 0
+
+#ifndef GLAPIENTRY
+#define GLAPIENTRY
+#endif
+
+#include "glapitemp.h"
diff --git a/src/mesa/drivers/windows/gldirect/gld_driver.c b/src/mesa/drivers/windows/gldirect/gld_driver.c
new file mode 100644
index 0000000000..f7c575614b
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/gld_driver.c
@@ -0,0 +1,279 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Driver functions and interfaces
+*
+****************************************************************************/
+
+#define STRICT
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include "gld_driver.h"
+#include "ddlog.h"
+#include "glheader.h"
+
+// For glGetString().
+#include "common_x86_asm.h"
+
+//---------------------------------------------------------------------------
+
+static char *szDriverError = "Driver used before initialisation!";
+
+// This holds our dynamically created OpenGL renderer string.
+// 256 chars should be plenty - remember that some apps display this.
+static char _gldRendererString[256];
+
+static char *szVendor = "SciTech Software, Inc.";
+
+//---------------------------------------------------------------------------
+
+extern BOOL gldGetDXErrorString_DX(HRESULT hr, char *buf, int nBufSize);
+
+extern BOOL gldCreateDrawable_MesaSW(DGL_ctx *ctx, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+extern BOOL gldResizeDrawable_MesaSW(DGL_ctx *ctx, BOOL bDefaultDriver, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+extern BOOL gldDestroyDrawable_MesaSW(DGL_ctx *ctx);
+extern BOOL gldCreatePrivateGlobals_MesaSW(void);
+extern BOOL gldDestroyPrivateGlobals_MesaSW(void);
+extern BOOL gldBuildPixelformatList_MesaSW(void);
+extern BOOL gldInitialiseMesa_MesaSW(DGL_ctx *ctx);
+extern BOOL gldSwapBuffers_MesaSW(DGL_ctx *ctx, HDC hDC, HWND hWnd);
+extern PROC gldGetProcAddress_MesaSW(LPCSTR a);
+extern BOOL gldGetDisplayMode_MesaSW(DGL_ctx *ctx, GLD_displayMode *glddm);
+
+extern BOOL gldCreateDrawable_DX(DGL_ctx *ctx, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+extern BOOL gldResizeDrawable_DX(DGL_ctx *ctx, BOOL bDefaultDriver, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+extern BOOL gldDestroyDrawable_DX(DGL_ctx *ctx);
+extern BOOL gldCreatePrivateGlobals_DX(void);
+extern BOOL gldDestroyPrivateGlobals_DX(void);
+extern BOOL gldBuildPixelformatList_DX(void);
+extern BOOL gldInitialiseMesa_DX(DGL_ctx *ctx);
+extern BOOL gldSwapBuffers_DX(DGL_ctx *ctx, HDC hDC, HWND hWnd);
+extern PROC gldGetProcAddress_DX(LPCSTR a);
+extern BOOL gldGetDisplayMode_DX(DGL_ctx *ctx, GLD_displayMode *glddm);
+
+//---------------------------------------------------------------------------
+// NOP functions. Called if proper driver functions are not set.
+//---------------------------------------------------------------------------
+
+static BOOL _gldDriverError(void)
+{
+ ddlogMessage(DDLOG_CRITICAL, szDriverError);
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _GetDXErrorString_ERROR(
+ HRESULT hr,
+ char *buf,
+ int nBufSize)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _CreateDrawable_ERROR(
+ DGL_ctx *ctx,
+ BOOL bPersistantInterface,
+ BOOL bPersistantBuffers)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _ResizeDrawable_ERROR(
+ DGL_ctx *ctx,
+ BOOL bDefaultDriver,
+ BOOL bPersistantInterface,
+ BOOL bPersistantBuffers)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _DestroyDrawable_ERROR(
+ DGL_ctx *ctx)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _CreatePrivateGlobals_ERROR(void)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _DestroyPrivateGlobals_ERROR(void)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _BuildPixelformatList_ERROR(void)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+
+static BOOL _InitialiseMesa_ERROR(
+ DGL_ctx *ctx)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _SwapBuffers_ERROR(
+ DGL_ctx *ctx,
+ HDC hDC,
+ HWND hWnd)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+
+static PROC _GetProcAddress_ERROR(
+ LPCSTR a)
+{
+ _gldDriverError();
+ return NULL;
+}
+
+//---------------------------------------------------------------------------
+
+static BOOL _GetDisplayMode_ERROR(
+ DGL_ctx *ctx,
+ GLD_displayMode *glddm)
+{
+ return _gldDriverError();
+}
+
+//---------------------------------------------------------------------------
+// Functions useful to all drivers
+//---------------------------------------------------------------------------
+
+const GLubyte* _gldGetStringGeneric(
+ GLcontext *ctx,
+ GLenum name)
+{
+ if (!ctx)
+ return NULL;
+
+ switch (name) {
+ case GL_RENDERER:
+ sprintf(_gldRendererString, "GLDirect 4.0 %s%s%s%s (%s %s)",
+ _mesa_x86_cpu_features ? "/x86" : "",
+ cpu_has_mmx ? "/MMX" : "",
+ cpu_has_3dnow ? "/3DNow!" : "",
+ cpu_has_xmm ? "/SSE" : "",
+ __DATE__, __TIME__);
+ return (const GLubyte *) _gldRendererString;
+ case GL_VENDOR:
+ return (const GLubyte *) szVendor;
+ default:
+ return NULL;
+ }
+}
+
+//---------------------------------------------------------------------------
+// Global driver function pointers, initially set to functions that
+// will report an error when called.
+//---------------------------------------------------------------------------
+
+GLD_driver _gldDriver = {
+ _GetDXErrorString_ERROR,
+ _CreateDrawable_ERROR,
+ _ResizeDrawable_ERROR,
+ _DestroyDrawable_ERROR,
+ _CreatePrivateGlobals_ERROR,
+ _DestroyPrivateGlobals_ERROR,
+ _BuildPixelformatList_ERROR,
+ _InitialiseMesa_ERROR,
+ _SwapBuffers_ERROR,
+ _GetProcAddress_ERROR,
+ _GetDisplayMode_ERROR
+};
+
+//---------------------------------------------------------------------------
+// Init function. Should be called as soon as regkeys/ini-settings are read.
+//---------------------------------------------------------------------------
+
+BOOL gldInitDriverPointers(
+ DWORD dwDriver)
+{
+ _gldDriver.GetDXErrorString = gldGetDXErrorString_DX;
+
+ if (dwDriver == GLDS_DRIVER_MESA_SW) {
+ // Mesa Software driver
+ _gldDriver.CreateDrawable = gldCreateDrawable_MesaSW;
+ _gldDriver.ResizeDrawable = gldResizeDrawable_MesaSW;
+ _gldDriver.DestroyDrawable = gldDestroyDrawable_MesaSW;
+ _gldDriver.CreatePrivateGlobals = gldCreatePrivateGlobals_MesaSW;
+ _gldDriver.DestroyPrivateGlobals = gldDestroyPrivateGlobals_MesaSW;
+ _gldDriver.BuildPixelformatList = gldBuildPixelformatList_MesaSW;
+ _gldDriver.InitialiseMesa = gldInitialiseMesa_MesaSW;
+ _gldDriver.SwapBuffers = gldSwapBuffers_MesaSW;
+ _gldDriver.wglGetProcAddress = gldGetProcAddress_MesaSW;
+ _gldDriver.GetDisplayMode = gldGetDisplayMode_MesaSW;
+ return TRUE;
+ }
+
+ if ((dwDriver == GLDS_DRIVER_REF) || (dwDriver == GLDS_DRIVER_HAL)) {
+ // Direct3D driver, either HW or SW
+ _gldDriver.CreateDrawable = gldCreateDrawable_DX;
+ _gldDriver.ResizeDrawable = gldResizeDrawable_DX;
+ _gldDriver.DestroyDrawable = gldDestroyDrawable_DX;
+ _gldDriver.CreatePrivateGlobals = gldCreatePrivateGlobals_DX;
+ _gldDriver.DestroyPrivateGlobals = gldDestroyPrivateGlobals_DX;
+ _gldDriver.BuildPixelformatList = gldBuildPixelformatList_DX;
+ _gldDriver.InitialiseMesa = gldInitialiseMesa_DX;
+ _gldDriver.SwapBuffers = gldSwapBuffers_DX;
+ _gldDriver.wglGetProcAddress = gldGetProcAddress_DX;
+ _gldDriver.GetDisplayMode = gldGetDisplayMode_DX;
+ return TRUE;
+ };
+
+ return FALSE;
+}
+
+//---------------------------------------------------------------------------
diff --git a/src/mesa/drivers/windows/gldirect/gld_driver.h b/src/mesa/drivers/windows/gldirect/gld_driver.h
new file mode 100644
index 0000000000..01a46a8325
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/gld_driver.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Driver functions and interfaces
+*
+****************************************************************************/
+
+#ifndef _GLD_DRIVER_H
+#define _GLD_DRIVER_H
+
+// This file is only useful is we're using the new GLD3 WGL code.
+#ifdef _USE_GLD3_WGL
+
+#include "dglcontext.h"
+
+// Same as DX8 D3DDISPLAYMODE
+typedef struct {
+ DWORD Width;
+ DWORD Height;
+ DWORD Refresh;
+ DWORD BPP;
+} GLD_displayMode;
+
+typedef struct {
+ // Returns a string for a given HRESULT error code.
+ BOOL (*GetDXErrorString)(HRESULT hr, char *buf, int nBufSize);
+
+ // Driver functions for managing drawables.
+ // Functions must respect persistant buffers / persistant interface.
+ // NOTE: Persistant interface is: DirectDraw, pre-DX8; Direct3D, DX8 and above.
+ BOOL (*CreateDrawable)(DGL_ctx *ctx, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+ BOOL (*ResizeDrawable)(DGL_ctx *ctx, BOOL bDefaultDriver, BOOL bPersistantInterface, BOOL bPersistantBuffers);
+ BOOL (*DestroyDrawable)(DGL_ctx *ctx);
+
+ // Create/Destroy private globals belonging to driver
+ BOOL (*CreatePrivateGlobals)(void);
+ BOOL (*DestroyPrivateGlobals)(void);
+
+ // Build pixelformat list
+ BOOL (*BuildPixelformatList)(void);
+
+ // Initialise Mesa's driver pointers
+ BOOL (*InitialiseMesa)(DGL_ctx *ctx);
+
+ // Swap buffers
+ BOOL (*SwapBuffers)(DGL_ctx *ctx, HDC hDC, HWND hWnd);
+
+ // wglGetProcAddress()
+ PROC (*wglGetProcAddress)(LPCSTR a);
+
+ BOOL (*GetDisplayMode)(DGL_ctx *ctx, GLD_displayMode *glddm);
+} GLD_driver;
+
+extern GLD_driver _gldDriver;
+
+BOOL gldInitDriverPointers(DWORD dwDriver);
+const GLubyte* _gldGetStringGeneric(GLcontext *ctx, GLenum name);
+
+#endif // _USE_GLD3_WGL
+
+#endif // _GLD_DRIVER_H
diff --git a/src/mesa/drivers/windows/gldirect/gldirect.rc b/src/mesa/drivers/windows/gldirect/gldirect.rc
new file mode 100644
index 0000000000..ba09631538
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/gldirect.rc
@@ -0,0 +1,43 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: Windows Resource Compiler
+* Environment: Windows 95
+*
+****************************************************************************/
+
+#ifndef WORKSHOP_INVOKED
+ #include <windows.h>
+#endif
+
+#define FILE_DESCRIPTION "SciTech GLDirect"
+#define ORIG_FILENAME "opengl32.dll"
+#define FILE_TYPE VFT_DLL
+
+#include "gldirect/gldver.ver"
diff --git a/src/mesa/drivers/windows/gldirect/gldlame8.c b/src/mesa/drivers/windows/gldirect/gldlame8.c
new file mode 100644
index 0000000000..5ac519c174
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/gldlame8.c
@@ -0,0 +1,181 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: GLDirect utility for determining lame boards/drivers.
+*
+****************************************************************************/
+
+#define STRICT
+#define WIN32_LEAN_AND_MEAN
+#include <d3d8.h>
+
+/*
+Ack. Broken out from gldlame.c because of broken D3D headers. KeithH
+*/
+
+/****************************************************************************
+REMARKS:
+Scans list of DirectDraw devices for specific device IDs.
+****************************************************************************/
+
+#define VENDORID_ATI 0x1002
+
+static DWORD devATIRagePro[] = {
+ 0x4742, // 3D RAGE PRO BGA AGP 1X/2X
+ 0x4744, // 3D RAGE PRO BGA AGP 1X only
+ 0x4749, // 3D RAGE PRO BGA PCI 33 MHz
+ 0x4750, // 3D RAGE PRO PQFP PCI 33 MHz
+ 0x4751, // 3D RAGE PRO PQFP PCI 33 MHz limited 3D
+ 0x4C42, // 3D RAGE LT PRO BGA-312 AGP 133 MHz
+ 0x4C44, // 3D RAGE LT PRO BGA-312 AGP 66 MHz
+ 0x4C49, // 3D RAGE LT PRO BGA-312 PCI 33 MHz
+ 0x4C50, // 3D RAGE LT PRO BGA-256 PCI 33 MHz
+ 0x4C51, // 3D RAGE LT PRO BGA-256 PCI 33 MHz limited 3D
+};
+
+static DWORD devATIRageIIplus[] = {
+ 0x4755, // 3D RAGE II+
+ 0x4756, // 3D RAGE IIC PQFP PCI
+ 0x4757, // 3D RAGE IIC BGA AGP
+ 0x475A, // 3D RAGE IIC PQFP AGP
+ 0x4C47, // 3D RAGE LT-G
+};
+
+static __inline BOOL IsDevice(
+ DWORD *lpDeviceIdList,
+ DWORD dwDeviceId,
+ int count)
+{
+ int i;
+
+ for (i=0; i<count; i++)
+ if (dwDeviceId == lpDeviceIdList[i])
+ return TRUE;
+
+ return FALSE;
+}
+
+/****************************************************************************
+REMARKS:
+Test the Direct3D8 device for "lameness" with respect to GLDirect.
+This is done on per-chipset basis, as in GLD CAD driver (DGLCONTEXT.C).
+If bTestForWHQL is set then the device is tested to see if it is
+certified, and bIsWHQL is set to indicate TRUE or FALSE. Otherwise bIsWHQL
+is not set. [WHQL = Windows Hardware Quality Labs]
+
+NOTE: There is a one- or two-second time penalty incurred in determining
+ the WHQL certification date.
+****************************************************************************/
+BOOL IsThisD3D8Lame(
+ IDirect3D8 *pD3D,
+ DWORD dwAdapter,
+ BOOL bTestForWHQL,
+ BOOL *bIsWHQL)
+{
+ DWORD dwFlags = bTestForWHQL ? 0 : D3DENUM_NO_WHQL_LEVEL;
+ D3DADAPTER_IDENTIFIER8 d3dai;
+ HRESULT hr;
+
+ hr = IDirect3D8_GetAdapterIdentifier(pD3D, dwAdapter, dwFlags, &d3dai);
+ if (FAILED(hr))
+ return TRUE; // Definitely lame if adapter details can't be obtained!
+
+ if (bTestForWHQL) {
+ *bIsWHQL = d3dai.WHQLLevel ? TRUE : FALSE;
+ }
+
+ // Vendor 1: ATI
+ if (d3dai.VendorId == VENDORID_ATI) {
+ // Test A: ATI Rage PRO
+ if (IsDevice(devATIRagePro, d3dai.DeviceId, sizeof(devATIRagePro)))
+ return TRUE; // bad mipmapping
+ // Test B: ATI Rage II+
+ if (IsDevice(devATIRageIIplus, d3dai.DeviceId, sizeof(devATIRageIIplus)))
+ return TRUE; // bad HW alpha testing
+ }
+
+ return FALSE;
+}
+
+/****************************************************************************
+REMARKS:
+Test the Direct3DDevice8 device for "lameness" with respect to GLDirect.
+This is done by querying for particular caps, as in GLD CPL (CPLMAIN.CPP).
+****************************************************************************/
+BOOL IsThisD3D8DeviceLame(
+ IDirect3DDevice8 *pDev)
+{
+ D3DCAPS8 d3dCaps;
+ HRESULT hr;
+
+ hr = IDirect3DDevice8_GetDeviceCaps(pDev, &d3dCaps);
+ if (FAILED(hr))
+ return TRUE;
+
+ // Test 1: Perspective-correct textures
+ // Any card that cannot do perspective-textures is *exceptionally* lame.
+ if (!(d3dCaps.TextureCaps & D3DPTEXTURECAPS_PERSPECTIVE)) {
+ return TRUE; // Lame!
+ }
+
+ // Test 2: Bilinear filtering
+ if (!(d3dCaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR)) {
+ return TRUE; // Lame!
+ }
+
+ // Test 3: Mipmapping
+ if (!(d3dCaps.TextureCaps & D3DPTEXTURECAPS_MIPMAP)) {
+ return TRUE; // Lame!
+ }
+
+ // Test 4: Depth-test modes (?)
+
+ // Test 5: Blend Modes -- Based on DX7 D3DIM MTEXTURE.CPP caps test
+
+ // Accept devices that can do multipass, alpha blending
+ if( !((d3dCaps.DestBlendCaps & D3DPBLENDCAPS_INVSRCALPHA) &&
+ (d3dCaps.SrcBlendCaps & D3DPBLENDCAPS_SRCALPHA)) )
+ return TRUE;
+
+ // Accept devices that can do multipass, color blending
+ if( !((d3dCaps.DestBlendCaps & D3DPBLENDCAPS_SRCCOLOR) &&
+ (d3dCaps.SrcBlendCaps & D3DPBLENDCAPS_ZERO)) )
+ return TRUE;
+
+ // Accept devices that really support multiple textures.
+ if( !((d3dCaps.MaxTextureBlendStages > 1 ) &&
+ (d3dCaps.MaxSimultaneousTextures > 1 ) &&
+ (d3dCaps.TextureOpCaps & D3DTEXOPCAPS_MODULATE )) )
+ return TRUE;
+
+ return FALSE; // Not lame
+}
diff --git a/src/mesa/drivers/windows/gldirect/mesasw/colors.h b/src/mesa/drivers/windows/gldirect/mesasw/colors.h
new file mode 100644
index 0000000000..17371a96cc
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/mesasw/colors.h
@@ -0,0 +1,523 @@
+/* File name : colors.h
+ * Version : 2.3
+ *
+ * Header file for display driver for Mesa 2.3 under
+ * Windows95 and WindowsNT
+ * This file defines macros and global variables needed
+ * for converting color format
+ *
+ * Copyright (C) 1996- Li Wei
+ * Address : Institute of Artificial Intelligence
+ * : & Robotics
+ * : Xi'an Jiaotong University
+ * Email : liwei@aiar.xjtu.edu.cn
+ * Web page : http://sun.aiar.xjtu.edu.cn
+ *
+ * This file and its associations are partially based on the
+ * Windows NT driver for Mesa, written by Mark Leaming
+ * (mark@rsinc.com).
+ */
+
+/* $Log: ddcolors.h 1997/6/14 by Li Wei(liwei@aiar.xjtu.edu.cn)
+ * Macros for pixel format defined
+ */
+
+/*
+ * $Log: colors.h,v $
+ * Revision 1.1 2004/04/20 11:13:11 alanh
+ * add SciTech's GLDirect driver for Windows.
+ *
+ * This code is donated to Mesa which allows the usage of
+ * a Direct3D layer (DX7, DX8, DX9 or complete software fallback).
+ *
+ * No build system exists for this code yet, that will come.....
+ *
+ * Revision 1.1.1.1 1999/08/19 00:55:42 jtg
+ * Imported sources
+ *
+ * Revision 1.2 1999/01/03 03:08:57 brianp
+ * Ted Jump's changes
+ *
+ * Revision 1.1 1999/01/03 03:08:12 brianp
+ * Initial revision
+ *
+ * Revision 2.0.2 1997/4/30 15:58:00 CST by Li Wei(liwei@aiar.xjtu.edu.cn)
+ * Add LUTs need for dithering
+ */
+
+/*
+ * $Log: colors.h,v $
+ * Revision 1.1 2004/04/20 11:13:11 alanh
+ * add SciTech's GLDirect driver for Windows.
+ *
+ * This code is donated to Mesa which allows the usage of
+ * a Direct3D layer (DX7, DX8, DX9 or complete software fallback).
+ *
+ * No build system exists for this code yet, that will come.....
+ *
+ * Revision 1.1.1.1 1999/08/19 00:55:42 jtg
+ * Imported sources
+ *
+ * Revision 1.2 1999/01/03 03:08:57 brianp
+ * Ted Jump's changes
+ *
+ * Revision 1.1 1999/01/03 03:08:12 brianp
+ * Initial revision
+ *
+ * Revision 2.0.1 1997/4/29 15:52:00 CST by Li Wei(liwei@aiar.xjtu.edu.cn)
+ * Add BGR8 Macro
+ */
+
+/*
+ * $Log: colors.h,v $
+ * Revision 1.1 2004/04/20 11:13:11 alanh
+ * add SciTech's GLDirect driver for Windows.
+ *
+ * This code is donated to Mesa which allows the usage of
+ * a Direct3D layer (DX7, DX8, DX9 or complete software fallback).
+ *
+ * No build system exists for this code yet, that will come.....
+ *
+ * Revision 1.1.1.1 1999/08/19 00:55:42 jtg
+ * Imported sources
+ *
+ * Revision 1.2 1999/01/03 03:08:57 brianp
+ * Ted Jump's changes
+ *
+ * Revision 1.1 1999/01/03 03:08:12 brianp
+ * Initial revision
+ *
+ * Revision 2.0 1996/11/15 10:55:00 CST by Li Wei(liwei@aiar.xjtu.edu.cn)
+ * Initial revision
+ */
+/* Values for wmesa->pixelformat: */
+
+#define PF_8A8B8G8R 3 /* 32-bit TrueColor: 8-A, 8-B, 8-G, 8-R */
+#define PF_8R8G8B 4 /* 32-bit TrueColor: 8-R, 8-G, 8-B */
+#define PF_5R6G5B 5 /* 16-bit TrueColor: 5-R, 6-G, 5-B bits */
+#define PF_DITHER8 6 /* Dithered RGB using a lookup table */
+#define PF_LOOKUP 7 /* Undithered RGB using a lookup table */
+#define PF_GRAYSCALE 10 /* Grayscale or StaticGray */
+#define PF_BADFORMAT 11
+#define PF_INDEX8 12
+
+char ColorMap16[] = {
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
+0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,
+0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,
+0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,
+0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,
+0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
+0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,
+0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
+0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,
+0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,
+0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,
+0x1A,0x1A,0x1A,0x1A,0x1A,0x1A,0x1A,0x1A,
+0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,
+0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,
+0x1D,0x1D,0x1D,0x1D,0x1D,0x1D,0x1D,0x1D,
+0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,
+0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F};
+
+#define BGR8(r,g,b) (unsigned)(((BYTE)(b & 0xc0 | (g & 0xe0)>>2 | (r & 0xe0)>>5)))
+#ifdef DDRAW
+#define BGR16(r,g,b) ((WORD)(((BYTE)(ColorMap16[b]) | ((BYTE)(g&0xfc) << 3)) | (((WORD)(BYTE)(ColorMap16[r])) << 11)))
+#else
+#define BGR16(r,g,b) ((WORD)(((BYTE)(ColorMap16[b]) | ((BYTE)(ColorMap16[g]) << 5)) | (((WORD)(BYTE)(ColorMap16[r])) << 10)))
+#endif
+#define BGR24(r,g,b) (unsigned long)(((DWORD)(((BYTE)(b)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(r))<<16))) << 8)
+#define BGR32(r,g,b) (unsigned long)((DWORD)(((BYTE)(b)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(r))<<16)))
+
+
+
+/*
+ * If pixelformat==PF_8A8B8G8R:
+ */
+#define PACK_8A8B8G8R( R, G, B, A ) \
+ ( ((A) << 24) | ((B) << 16) | ((G) << 8) | (R) )
+
+
+/*
+ * If pixelformat==PF_8R8G8B:
+ */
+#define PACK_8R8G8B( R, G, B) ( ((R) << 16) | ((G) << 8) | (B) )
+
+
+/*
+ * If pixelformat==PF_5R6G5B:
+ */
+
+
+#ifdef DDRAW
+#define PACK_5R6G5B( R, G, B) ((WORD)(((BYTE)(ColorMap16[B]) | ((BYTE)(G&0xfc) << 3)) | (((WORD)(BYTE)(ColorMap16[R])) << 11)))
+#else
+#define PACK_5R6G5B( R, G, B) ((WORD)(((BYTE)(ColorMap16[B]) | ((BYTE)(ColorMap16[G]) << 5)) | (((WORD)(BYTE)(ColorMap16[R])) << 10)))
+#endif
+/*----------------------------------------------------------------------------
+
+Division lookup tables. These tables compute 0-255 divided by 51 and
+modulo 51. These tables could approximate gamma correction.
+
+*/
+
+char unsigned const aDividedBy51Rounded[256] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+};
+
+char unsigned const aDividedBy51[256] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5,
+};
+
+char unsigned const aModulo51[256] =
+{
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 0, 1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 0, 1, 2, 3,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 0,
+};
+
+/*----------------------------------------------------------------------------
+
+Multiplication LUTs. These compute 0-5 times 6 and 36.
+
+*/
+
+char unsigned const aTimes6[6] =
+{
+ 0, 6, 12, 18, 24, 30
+};
+
+char unsigned const aTimes36[6] =
+{
+ 0, 36, 72, 108, 144, 180
+};
+
+
+/*----------------------------------------------------------------------------
+
+Dither matrices for 8 bit to 2.6 bit halftones.
+
+*/
+
+char unsigned const aHalftone16x16[256] =
+{
+ 0, 44, 9, 41, 3, 46, 12, 43, 1, 44, 10, 41, 3, 46, 12, 43,
+ 34, 16, 25, 19, 37, 18, 28, 21, 35, 16, 26, 19, 37, 18, 28, 21,
+ 38, 6, 47, 3, 40, 9, 50, 6, 38, 7, 47, 4, 40, 9, 49, 6,
+ 22, 28, 13, 31, 25, 31, 15, 34, 22, 29, 13, 32, 24, 31, 15, 34,
+ 2, 46, 12, 43, 1, 45, 10, 42, 2, 45, 11, 42, 1, 45, 11, 42,
+ 37, 18, 27, 21, 35, 17, 26, 20, 36, 17, 27, 20, 36, 17, 26, 20,
+ 40, 8, 49, 5, 38, 7, 48, 4, 39, 8, 48, 5, 39, 7, 48, 4,
+ 24, 30, 15, 33, 23, 29, 13, 32, 23, 30, 14, 33, 23, 29, 14, 32,
+ 2, 46, 12, 43, 0, 44, 10, 41, 3, 47, 12, 44, 0, 44, 10, 41,
+ 37, 18, 27, 21, 35, 16, 25, 19, 37, 19, 28, 22, 35, 16, 25, 19,
+ 40, 9, 49, 5, 38, 7, 47, 4, 40, 9, 50, 6, 38, 6, 47, 3,
+ 24, 30, 15, 34, 22, 29, 13, 32, 25, 31, 15, 34, 22, 28, 13, 31,
+ 1, 45, 11, 42, 2, 46, 11, 42, 1, 45, 10, 41, 2, 46, 11, 43,
+ 36, 17, 26, 20, 36, 17, 27, 21, 35, 16, 26, 20, 36, 18, 27, 21,
+ 39, 8, 48, 4, 39, 8, 49, 5, 38, 7, 48, 4, 39, 8, 49, 5,
+ 23, 29, 14, 33, 24, 30, 14, 33, 23, 29, 13, 32, 24, 30, 14, 33,
+};
+
+char unsigned const aHalftone8x8[64] =
+{
+ 0, 38, 9, 47, 2, 40, 11, 50,
+ 25, 12, 35, 22, 27, 15, 37, 24,
+ 6, 44, 3, 41, 8, 47, 5, 43,
+ 31, 19, 28, 15, 34, 21, 31, 18,
+ 1, 39, 11, 49, 0, 39, 10, 48,
+ 27, 14, 36, 23, 26, 13, 35, 23,
+ 7, 46, 4, 43, 7, 45, 3, 42,
+ 33, 20, 30, 17, 32, 19, 29, 16,
+};
+
+char unsigned const aHalftone4x4_1[16] =
+{
+ 0, 25, 6, 31,
+ 38, 12, 44, 19,
+ 9, 35, 3, 28,
+ 47, 22, 41, 15
+};
+
+char unsigned const aHalftone4x4_2[16] =
+{
+ 41, 3, 9, 28,
+ 35, 15, 22, 47,
+ 6, 25, 38, 0,
+ 19, 44, 31, 12
+};
+
+/***************************************************************************
+ aWinGHalftoneTranslation
+
+ Translates a 2.6 bit-per-pixel halftoned representation into the
+ slightly rearranged WinG Halftone Palette.
+*/
+
+char unsigned const aWinGHalftoneTranslation[216] =
+{
+ 0,
+ 29,
+ 30,
+ 31,
+ 32,
+ 249,
+ 33,
+ 34,
+ 35,
+ 36,
+ 37,
+ 38,
+ 39,
+ 40,
+ 41,
+ 42,
+ 43,
+ 44,
+ 45,
+ 46,
+ 47,
+ 48,
+ 49,
+ 50,
+ 51,
+ 52,
+ 53,
+ 54,
+ 55,
+ 56,
+ 250,
+ 250,
+ 57,
+ 58,
+ 59,
+ 251,
+ 60,
+ 61,
+ 62,
+ 63,
+ 64,
+ 65,
+ 66,
+ 67,
+ 68,
+ 69,
+ 70,
+ 71,
+ 72,
+ 73,
+ 74,
+ 75,
+ 76,
+ 77,
+ 78,
+ 79,
+ 80,
+ 81,
+ 82,
+ 83,
+ 84,
+ 85,
+ 86,
+ 87,
+ 88,
+ 89,
+ 250,
+ 90,
+ 91,
+ 92,
+ 93,
+ 94,
+ 95,
+ 96,
+ 97,
+ 98,
+ 99,
+ 100,
+ 101,
+ 102,
+ 103,
+ 104,
+ 105,
+ 106,
+ 107,
+ 108,
+ 109,
+ 110,
+ 111,
+ 227,
+ 112,
+ 113,
+ 114,
+ 115,
+ 116,
+ 117,
+ 118,
+ 119,
+ 151,
+ 120,
+ 121,
+ 122,
+ 123,
+ 124,
+ 228,
+ 125,
+ 126,
+ 229,
+ 133,
+ 162,
+ 135,
+ 131,
+ 132,
+ 137,
+ 166,
+ 134,
+ 140,
+ 130,
+ 136,
+ 143,
+ 138,
+ 139,
+ 174,
+ 141,
+ 142,
+ 177,
+ 129,
+ 144,
+ 145,
+ 146,
+ 147,
+ 148,
+ 149,
+ 150,
+ 157,
+ 152,
+ 153,
+ 154,
+ 155,
+ 156,
+ 192,
+ 158,
+ 159,
+ 160,
+ 161,
+ 196,
+ 163,
+ 164,
+ 165,
+ 127,
+ 199,
+ 167,
+ 168,
+ 169,
+ 170,
+ 171,
+ 172,
+ 173,
+ 207,
+ 175,
+ 176,
+ 210,
+ 178,
+ 179,
+ 180,
+ 181,
+ 182,
+ 183,
+ 184,
+ 185,
+ 186,
+ 187,
+ 188,
+ 189,
+ 190,
+ 191,
+ 224,
+ 193,
+ 194,
+ 195,
+ 252,
+ 252,
+ 197,
+ 198,
+ 128,
+ 253,
+ 252,
+ 200,
+ 201,
+ 202,
+ 203,
+ 204,
+ 205,
+ 206,
+ 230,
+ 208,
+ 209,
+ 231,
+ 211,
+ 212,
+ 213,
+ 214,
+ 215,
+ 216,
+ 217,
+ 218,
+ 219,
+ 220,
+ 221,
+ 222,
+ 254,
+ 223,
+ 232,
+ 225,
+ 226,
+ 255,
+}; \ No newline at end of file
diff --git a/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c b/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c
new file mode 100644
index 0000000000..ed58e35301
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/mesasw/gld_wgl_mesasw.c
@@ -0,0 +1,1718 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x/2000/XP/XBox (Win32)
+*
+* Description: Mesa Software WGL (WindowsGL)
+*
+****************************************************************************/
+
+#include <windows.h>
+#define GL_GLEXT_PROTOTYPES
+#include <GL/gl.h>
+#include <GL/glext.h>
+
+#include "glheader.h"
+#include "colors.h"
+#include "context.h"
+#include "colormac.h"
+#include "dd.h"
+#include "depth.h"
+#include "extensions.h"
+#include "macros.h"
+#include "matrix.h"
+// #include "mem.h"
+#include "mmath.h"
+#include "mtypes.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "array_cache/acache.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast/s_context.h"
+#include "swrast/s_depth.h"
+#include "swrast/s_lines.h"
+#include "swrast/s_triangle.h"
+#include "swrast/s_trispan.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+#include "dglcontext.h"
+#include "gld_driver.h"
+
+//---------------------------------------------------------------------------
+//---------------------------------------------------------------------------
+
+DGL_pixelFormat pfTemplateMesaSW =
+{
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), // Size of the data structure
+ 1, // Structure version - should be 1
+ // Flags:
+ PFD_DRAW_TO_WINDOW | // The buffer can draw to a window or device surface.
+ PFD_DRAW_TO_BITMAP | // The buffer can draw to a bitmap. (DaveM)
+ PFD_SUPPORT_GDI | // The buffer supports GDI drawing. (DaveM)
+ PFD_SUPPORT_OPENGL | // The buffer supports OpenGL drawing.
+ PFD_DOUBLEBUFFER | // The buffer is double-buffered.
+ 0, // Placeholder for easy commenting of above flags
+ PFD_TYPE_RGBA, // Pixel type RGBA.
+ 32, // Total colour bitplanes (excluding alpha bitplanes)
+ 8, 0, // Red bits, shift
+ 8, 8, // Green bits, shift
+ 8, 16, // Blue bits, shift
+ 8, 24, // Alpha bits, shift (destination alpha)
+ 64, // Accumulator bits (total)
+ 16, 16, 16, 16, // Accumulator bits: Red, Green, Blue, Alpha
+ 16, // Depth bits
+ 8, // Stencil bits
+ 0, // Number of auxiliary buffers
+ 0, // Layer type
+ 0, // Specifies the number of overlay and underlay planes.
+ 0, // Layer mask
+ 0, // Specifies the transparent color or index of an underlay plane.
+ 0 // Damage mask
+ },
+ 0, // Unused
+};
+
+//---------------------------------------------------------------------------
+// Extensions
+//---------------------------------------------------------------------------
+
+typedef struct {
+ PROC proc;
+ char *name;
+} GLD_extension;
+
+static GLD_extension GLD_extList[] = {
+#ifdef GL_EXT_polygon_offset
+ { (PROC)glPolygonOffsetEXT, "glPolygonOffsetEXT" },
+#endif
+ { (PROC)glBlendEquationEXT, "glBlendEquationEXT" },
+ { (PROC)glBlendColorEXT, "glBlendColorExt" },
+ { (PROC)glVertexPointerEXT, "glVertexPointerEXT" },
+ { (PROC)glNormalPointerEXT, "glNormalPointerEXT" },
+ { (PROC)glColorPointerEXT, "glColorPointerEXT" },
+ { (PROC)glIndexPointerEXT, "glIndexPointerEXT" },
+ { (PROC)glTexCoordPointerEXT, "glTexCoordPointer" },
+ { (PROC)glEdgeFlagPointerEXT, "glEdgeFlagPointerEXT" },
+ { (PROC)glGetPointervEXT, "glGetPointervEXT" },
+ { (PROC)glArrayElementEXT, "glArrayElementEXT" },
+ { (PROC)glDrawArraysEXT, "glDrawArrayEXT" },
+ { (PROC)glAreTexturesResidentEXT, "glAreTexturesResidentEXT" },
+ { (PROC)glBindTextureEXT, "glBindTextureEXT" },
+ { (PROC)glDeleteTexturesEXT, "glDeleteTexturesEXT" },
+ { (PROC)glGenTexturesEXT, "glGenTexturesEXT" },
+ { (PROC)glIsTextureEXT, "glIsTextureEXT" },
+ { (PROC)glPrioritizeTexturesEXT, "glPrioritizeTexturesEXT" },
+ { (PROC)glCopyTexSubImage3DEXT, "glCopyTexSubImage3DEXT" },
+ { (PROC)glTexImage3DEXT, "glTexImage3DEXT" },
+ { (PROC)glTexSubImage3DEXT, "glTexSubImage3DEXT" },
+ { (PROC)glPointParameterfEXT, "glPointParameterfEXT" },
+ { (PROC)glPointParameterfvEXT, "glPointParameterfvEXT" },
+ { (PROC)glLockArraysEXT, "glLockArraysEXT" },
+ { (PROC)glUnlockArraysEXT, "glUnlockArraysEXT" },
+ { NULL, "\0" }
+};
+
+//---------------------------------------------------------------------------
+// WMesa Internal Functions
+//---------------------------------------------------------------------------
+
+#define PAGE_FILE 0xffffffff
+
+#define REDBITS 0x03
+#define REDSHIFT 0x00
+#define GREENBITS 0x03
+#define GREENSHIFT 0x03
+#define BLUEBITS 0x02
+#define BLUESHIFT 0x06
+
+typedef struct _dibSection {
+ HDC hDC;
+ HANDLE hFileMap;
+ BOOL fFlushed;
+ LPVOID base;
+} WMDIBSECTION, *PWMDIBSECTION;
+
+typedef struct wmesa_context {
+ HWND Window;
+ HDC hDC;
+ HPALETTE hPalette;
+ HPALETTE hOldPalette;
+ HPEN hPen;
+ HPEN hOldPen;
+ HCURSOR hOldCursor;
+ COLORREF crColor;
+ // 3D projection stuff
+ RECT drawRect;
+ UINT uiDIBoffset;
+ // OpenGL stuff
+ HPALETTE hGLPalette;
+ GLuint width;
+ GLuint height;
+ GLuint ScanWidth;
+ GLboolean db_flag; //* double buffered?
+ GLboolean rgb_flag; //* RGB mode?
+ GLboolean dither_flag; //* use dither when 256 color mode for RGB?
+ GLuint depth; //* bits per pixel (1, 8, 24, etc)
+ ULONG pixel; // current color index or RGBA pixel value
+ ULONG clearpixel; //* pixel for clearing the color buffers
+ PBYTE ScreenMem; // WinG memory
+ BITMAPINFO *IndexFormat;
+ HPALETTE hPal; // Current Palette
+ HPALETTE hPalHalfTone;
+
+
+ WMDIBSECTION dib;
+ BITMAPINFO bmi;
+ HBITMAP hbmDIB;
+ HBITMAP hOldBitmap;
+ HBITMAP Old_Compat_BM;
+ HBITMAP Compat_BM; // Bitmap for double buffering
+ PBYTE pbPixels;
+ int nColors;
+ BYTE cColorBits;
+ int pixelformat;
+
+ RECT rectOffScreen;
+ RECT rectSurface;
+// HWND hwnd;
+ DWORD pitch;
+ PBYTE addrOffScreen;
+
+ // We always double-buffer, for performance reasons, but
+ // we need to know which of SwapBuffers() or glFlush() to
+ // handle. If we're emulating, then we update on Flush(),
+ // otherwise we update on SwapBufers(). KeithH
+ BOOL bEmulateSingleBuffer;
+} WMesaContext, *PWMC;
+
+#define GLD_GET_WMESA_DRIVER(c) (WMesaContext*)(c)->glPriv
+
+// TODO:
+GLint stereo_flag = 0 ;
+
+/* If we are double-buffering, we want to get the DC for the
+ * off-screen DIB, otherwise the DC for the window.
+ */
+#define DD_GETDC ((Current->db_flag) ? Current->dib.hDC : Current->hDC )
+#define DD_RELEASEDC
+
+#define FLIP(Y) (Current->height-(Y)-1)
+
+struct DISPLAY_OPTIONS {
+ int stereo;
+ int fullScreen;
+ int mode;
+ int bpp;
+};
+
+struct DISPLAY_OPTIONS displayOptions;
+
+//---------------------------------------------------------------------------
+
+static unsigned char threeto8[8] = {
+ 0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377
+};
+
+static unsigned char twoto8[4] = {
+ 0, 0x55, 0xaa, 0xff
+};
+
+static unsigned char oneto8[2] = {
+ 0, 255
+};
+
+//---------------------------------------------------------------------------
+
+BYTE DITHER_RGB_2_8BIT( int red, int green, int blue, int pixel, int scanline)
+{
+ char unsigned redtemp, greentemp, bluetemp, paletteindex;
+
+ //*** now, look up each value in the halftone matrix
+ //*** using an 8x8 ordered dither.
+ redtemp = aDividedBy51[red]
+ + (aModulo51[red] > aHalftone8x8[(pixel%8)*8
+ + scanline%8]);
+ greentemp = aDividedBy51[(char unsigned)green]
+ + (aModulo51[green] > aHalftone8x8[
+ (pixel%8)*8 + scanline%8]);
+ bluetemp = aDividedBy51[(char unsigned)blue]
+ + (aModulo51[blue] > aHalftone8x8[
+ (pixel%8)*8 +scanline%8]);
+
+ //*** recombine the halftoned rgb values into a palette index
+ paletteindex =
+ redtemp + aTimes6[greentemp] + aTimes36[bluetemp];
+
+ //*** and translate through the wing halftone palette
+ //*** translation vector to give the correct value.
+ return aWinGHalftoneTranslation[paletteindex];
+}
+
+//---------------------------------------------------------------------------
+
+static unsigned char componentFromIndex(UCHAR i, UINT nbits, UINT shift)
+{
+ unsigned char val;
+
+ val = i >> shift;
+ switch (nbits) {
+
+ case 1:
+ val &= 0x1;
+ return oneto8[val];
+
+ case 2:
+ val &= 0x3;
+ return twoto8[val];
+
+ case 3:
+ val &= 0x7;
+ return threeto8[val];
+
+ default:
+ return 0;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+
+void wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b)
+{
+ WMesaContext *Current = pwc;
+
+ // Test for invalid scanline parameter. KeithH
+ if ((iScanLine < 0) || (iScanLine >= pwc->height))
+ return;
+
+ if (Current->db_flag) {
+ LPBYTE lpb = pwc->pbPixels;
+ UINT nBypp = pwc->cColorBits >> 3;
+ UINT nOffset = iPixel % nBypp;
+
+ lpb += pwc->ScanWidth * iScanLine;
+ lpb += iPixel * nBypp;
+
+ if(nBypp == 1){
+ if(pwc->dither_flag)
+ *lpb = DITHER_RGB_2_8BIT(r,g,b,iScanLine,iPixel);
+ else
+ *lpb = BGR8(r,g,b);
+ }
+ else if(nBypp == 2)
+ *((LPWORD)lpb) = BGR16(r,g,b);
+ else if (nBypp == 3)
+ *((LPDWORD)lpb) = BGR24(r,g,b);
+ else if (nBypp == 4)
+ *((LPDWORD)lpb) = BGR32(r,g,b);
+ }
+ else{
+ SetPixel(Current->hDC, iPixel, iScanLine, RGB(r,g,b));
+ }
+}
+
+//---------------------------------------------------------------------------
+
+void wmCreateDIBSection(
+ HDC hDC,
+ PWMC pwc, // handle of device context
+ CONST BITMAPINFO *pbmi, // bitmap size, format, and color data
+ UINT iUsage // color data type indicator: RGB values or palette indices
+ )
+{
+ DWORD dwSize = 0;
+ DWORD dwScanWidth;
+ UINT nBypp = pwc->cColorBits / 8;
+ HDC hic;
+
+ dwScanWidth = (((pwc->ScanWidth * nBypp)+ 3) & ~3);
+
+ pwc->ScanWidth =pwc->pitch = dwScanWidth;
+
+ if (stereo_flag)
+ pwc->ScanWidth = 2* pwc->pitch;
+
+ dwSize = sizeof(BITMAPINFO) + (dwScanWidth * pwc->height);
+
+ pwc->dib.hFileMap = CreateFileMapping((HANDLE)PAGE_FILE,
+ NULL,
+ PAGE_READWRITE | SEC_COMMIT,
+ 0,
+ dwSize,
+ NULL);
+
+ if (!pwc->dib.hFileMap)
+ return;
+
+ pwc->dib.base = MapViewOfFile(pwc->dib.hFileMap,
+ FILE_MAP_ALL_ACCESS,
+ 0,
+ 0,
+ 0);
+
+ if(!pwc->dib.base){
+ CloseHandle(pwc->dib.hFileMap);
+ return;
+ }
+
+
+ CopyMemory(pwc->dib.base, pbmi, sizeof(BITMAPINFO));
+
+ hic = CreateIC("display", NULL, NULL, NULL);
+ pwc->dib.hDC = CreateCompatibleDC(hic);
+
+
+ pwc->hbmDIB = CreateDIBSection(hic,
+ &(pwc->bmi),
+ (iUsage ? DIB_PAL_COLORS : DIB_RGB_COLORS),
+ &(pwc->pbPixels),
+ pwc->dib.hFileMap,
+ 0);
+ pwc->ScreenMem = pwc->addrOffScreen = pwc->pbPixels;
+ pwc->hOldBitmap = SelectObject(pwc->dib.hDC, pwc->hbmDIB);
+
+ DeleteDC(hic);
+
+ return;
+
+}
+
+//---------------------------------------------------------------------------
+
+void wmCreatePalette( PWMC pwdc )
+{
+ /* Create a compressed and re-expanded 3:3:2 palette */
+ int i;
+ LOGPALETTE *pPal;
+ BYTE rb, rs, gb, gs, bb, bs;
+
+ pwdc->nColors = 0x100;
+
+ pPal = (PLOGPALETTE)malloc(sizeof(LOGPALETTE) +
+ pwdc->nColors * sizeof(PALETTEENTRY));
+ memset( pPal, 0, sizeof(LOGPALETTE) + pwdc->nColors * sizeof(PALETTEENTRY) );
+
+ pPal->palVersion = 0x300;
+
+ rb = REDBITS;
+ rs = REDSHIFT;
+ gb = GREENBITS;
+ gs = GREENSHIFT;
+ bb = BLUEBITS;
+ bs = BLUESHIFT;
+
+ if (pwdc->db_flag) {
+
+ /* Need to make two palettes: one for the screen DC and one for the DIB. */
+ pPal->palNumEntries = pwdc->nColors;
+ for (i = 0; i < pwdc->nColors; i++) {
+ pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs );
+ pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs );
+ pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs );
+ pPal->palPalEntry[i].peFlags = 0;
+ }
+ pwdc->hGLPalette = CreatePalette( pPal );
+ pwdc->hPalette = CreatePalette( pPal );
+ }
+
+ else {
+ pPal->palNumEntries = pwdc->nColors;
+ for (i = 0; i < pwdc->nColors; i++) {
+ pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs );
+ pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs );
+ pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs );
+ pPal->palPalEntry[i].peFlags = 0;
+ }
+ pwdc->hGLPalette = CreatePalette( pPal );
+ }
+
+ free(pPal);
+
+}
+
+//---------------------------------------------------------------------------
+
+/* This function sets the color table of a DIB section
+ * to match that of the destination DC
+ */
+BOOL wmSetDibColors(PWMC pwc)
+{
+ RGBQUAD *pColTab, *pRGB;
+ PALETTEENTRY *pPal, *pPE;
+ int i, nColors;
+ BOOL bRet=TRUE;
+ DWORD dwErr=0;
+
+ /* Build a color table in the DIB that maps to the
+ * selected palette in the DC.
+ */
+ nColors = 1 << pwc->cColorBits;
+ pPal = (PALETTEENTRY *)malloc( nColors * sizeof(PALETTEENTRY));
+ memset( pPal, 0, nColors * sizeof(PALETTEENTRY) );
+ GetPaletteEntries( pwc->hGLPalette, 0, nColors, pPal );
+ pColTab = (RGBQUAD *)malloc( nColors * sizeof(RGBQUAD));
+ for (i = 0, pRGB = pColTab, pPE = pPal; i < nColors; i++, pRGB++, pPE++) {
+ pRGB->rgbRed = pPE->peRed;
+ pRGB->rgbGreen = pPE->peGreen;
+ pRGB->rgbBlue = pPE->peBlue;
+ }
+ if(pwc->db_flag)
+ bRet = SetDIBColorTable(pwc->dib.hDC, 0, nColors, pColTab );
+
+ if(!bRet)
+ dwErr = GetLastError();
+
+ free( pColTab );
+ free( pPal );
+
+ return bRet;
+}
+
+//---------------------------------------------------------------------------
+
+static void wmSetPixelFormat( PWMC wc, HDC hDC)
+{
+ if(wc->rgb_flag)
+ wc->cColorBits = GetDeviceCaps(hDC, BITSPIXEL);
+ else
+ wc->cColorBits = 8;
+ switch(wc->cColorBits){
+ case 8:
+ if(wc->dither_flag != GL_TRUE)
+ wc->pixelformat = PF_INDEX8;
+ else
+ wc->pixelformat = PF_DITHER8;
+ break;
+ case 16:
+ wc->pixelformat = PF_5R6G5B;
+ break;
+ case 32:
+ wc->pixelformat = PF_8R8G8B;
+ break;
+ default:
+ wc->pixelformat = PF_BADFORMAT;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+/*
+ * This function creates the DIB section that is used for combined
+ * GL and GDI calls
+ */
+BOOL wmCreateBackingStore(PWMC pwc, long lxSize, long lySize)
+{
+ HDC hdc = pwc->hDC;
+ LPBITMAPINFO pbmi = &(pwc->bmi);
+ int iUsage;
+
+ pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ pbmi->bmiHeader.biWidth = lxSize;
+ pbmi->bmiHeader.biHeight= -lySize;
+ pbmi->bmiHeader.biPlanes = 1;
+ if(pwc->rgb_flag)
+ pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwc->hDC, BITSPIXEL);
+ else
+ pbmi->bmiHeader.biBitCount = 8;
+ pbmi->bmiHeader.biCompression = BI_RGB;
+ pbmi->bmiHeader.biSizeImage = 0;
+ pbmi->bmiHeader.biXPelsPerMeter = 0;
+ pbmi->bmiHeader.biYPelsPerMeter = 0;
+ pbmi->bmiHeader.biClrUsed = 0;
+ pbmi->bmiHeader.biClrImportant = 0;
+
+ iUsage = (pbmi->bmiHeader.biBitCount <= 8) ? DIB_PAL_COLORS : DIB_RGB_COLORS;
+
+ pwc->cColorBits = pbmi->bmiHeader.biBitCount;
+ pwc->ScanWidth = pwc->pitch = lxSize;
+ pwc->width = lxSize;
+ pwc->height = lySize;
+
+ wmCreateDIBSection(hdc, pwc, pbmi, iUsage);
+
+ if ((iUsage == DIB_PAL_COLORS) && !(pwc->hGLPalette)) {
+ wmCreatePalette( pwc );
+ wmSetDibColors( pwc );
+ }
+ wmSetPixelFormat(pwc, pwc->hDC);
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+/*
+ * Free up the dib section that was created
+ */
+BOOL wmDeleteBackingStore(PWMC pwc)
+{
+ SelectObject(pwc->dib.hDC, pwc->hOldBitmap);
+ DeleteDC(pwc->dib.hDC);
+ DeleteObject(pwc->hbmDIB);
+ UnmapViewOfFile(pwc->dib.base);
+ CloseHandle(pwc->dib.hFileMap);
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+/*
+ * Blit memory DC to screen DC
+ */
+BOOL wmFlush(PWMC pwc, HDC hDC)
+{
+ BOOL bRet = 0;
+ DWORD dwErr = 0;
+
+// Now using bEmulateSingleBuffer in the calling function. KeithH
+
+// if(pwc->db_flag){
+ bRet = BitBlt(hDC, 0, 0, pwc->width, pwc->height,
+ pwc->dib.hDC, 0, 0, SRCCOPY);
+// }
+
+ return bRet;
+
+}
+
+//---------------------------------------------------------------------------
+// Support Functions
+//---------------------------------------------------------------------------
+
+static void flush(GLcontext* ctx)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+/*
+ if((Current->rgb_flag &&!(Current->db_flag))
+ ||(!Current->rgb_flag))
+ {
+ wmFlush(Current, Current->hDC);
+ }
+*/
+ // Only flush if we're not in double-buffer mode. KeithH
+ // The demo fractal.c calls glutSwapBuffers() then glFlush()!
+ if (Current->bEmulateSingleBuffer) {
+ wmFlush(Current, Current->hDC);
+ }
+}
+
+
+//---------------------------------------------------------------------------
+
+
+/*
+ * Set the color index used to clear the color buffer.
+ */
+static void clear_index(GLcontext* ctx, GLuint index)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ Current->clearpixel = index;
+}
+
+
+
+//---------------------------------------------------------------------------
+
+/*
+ * Set the color used to clear the color buffer.
+ */
+//static void clear_color( GLcontext* ctx, const GLchan color[4] )
+// Changed for Mesa 5.x. KeithH
+static void clear_color(
+ GLcontext* ctx,
+ const GLfloat color[4])
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLubyte col[4];
+ CLAMPED_FLOAT_TO_UBYTE(col[0], color[0]);
+ CLAMPED_FLOAT_TO_UBYTE(col[1], color[1]);
+ CLAMPED_FLOAT_TO_UBYTE(col[2], color[2]);
+ Current->clearpixel = RGB(col[0], col[1], col[2]);
+}
+
+
+//---------------------------------------------------------------------------
+
+
+/*
+ * Clear the specified region of the color buffer using the clear color
+ * or index as specified by one of the two functions above.
+ *
+ * This procedure clears either the front and/or the back COLOR buffers.
+ * Only the "left" buffer is cleared since we are not stereo.
+ * Clearing of the other non-color buffers is left to the swrast.
+ * We also only clear the color buffers if the color masks are all 1's.
+ * Otherwise, we let swrast do it.
+ */
+
+static clear(GLcontext* ctx, GLbitfield mask,
+ GLboolean all, GLint x, GLint y, GLint width, GLint height)
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ DWORD dwColor;
+ WORD wColor;
+ BYTE bColor;
+ LPDWORD lpdw = (LPDWORD)Current->pbPixels;
+ LPWORD lpw = (LPWORD)Current->pbPixels;
+ LPBYTE lpb = Current->pbPixels;
+ int lines;
+ const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
+
+ if (all){
+ x=y=0;
+ width=Current->width;
+ height=Current->height;
+ }
+
+
+ /* sanity check - can't have right(stereo) buffers */
+ assert((mask & (DD_FRONT_RIGHT_BIT | DD_BACK_RIGHT_BIT)) == 0);
+
+ /* clear alpha */
+ if ((mask & (DD_FRONT_LEFT_BIT | DD_BACK_RIGHT_BIT)) &&
+ ctx->DrawBuffer->UseSoftwareAlphaBuffers &&
+ ctx->Color.ColorMask[ACOMP]) {
+ _mesa_clear_alpha_buffers( ctx );
+ }
+
+ if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) {
+ if (mask & DD_BACK_LEFT_BIT) {
+ /* Double-buffering - clear back buffer */
+ UINT nBypp = Current->cColorBits / 8;
+ int i = 0;
+ int iSize = 0;
+
+ assert(Current->db_flag==GL_TRUE); /* we'd better be double buffer */
+ if(nBypp ==1 ){
+ iSize = Current->width/4;
+ bColor = BGR8(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ wColor = MAKEWORD(bColor,bColor);
+ dwColor = MAKELONG(wColor, wColor);
+ }
+ if(nBypp == 2){
+ iSize = Current->width / 2;
+ wColor = BGR16(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ dwColor = MAKELONG(wColor, wColor);
+ }
+ else if(nBypp == 4){
+ iSize = Current->width;
+ dwColor = BGR32(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ }
+
+ /* clear a line */
+ while(i < iSize){
+ *lpdw = dwColor;
+ lpdw++;
+ i++;
+ }
+
+ /* This is the 24bit case */
+ if (nBypp == 3) {
+ iSize = Current->width *3/4;
+ dwColor = BGR24(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ while(i < iSize){
+ *lpdw = dwColor;
+ lpb += nBypp;
+ lpdw = (LPDWORD)lpb;
+ i++;
+ }
+ }
+
+ i = 0;
+ if (stereo_flag)
+ lines = height /2;
+ else
+ lines = height;
+ /* copy cleared line to other lines in buffer */
+ do {
+ memcpy(lpb, Current->pbPixels, iSize*4);
+ lpb += Current->ScanWidth;
+ i++;
+ }
+ while (i<lines-1);
+ mask &= ~DD_BACK_LEFT_BIT;
+ } /* double-buffer */
+
+ if (mask & DD_FRONT_LEFT_BIT) {
+ /* single-buffer */
+ HDC DC=DD_GETDC;
+ HPEN Pen=CreatePen(PS_SOLID,1,Current->clearpixel);
+ HBRUSH Brush=CreateSolidBrush(Current->clearpixel);
+ HPEN Old_Pen=SelectObject(DC,Pen);
+ HBRUSH Old_Brush=SelectObject(DC,Brush);
+ Rectangle(DC,x,y,x+width,y+height);
+ SelectObject(DC,Old_Pen);
+ SelectObject(DC,Old_Brush);
+ DeleteObject(Pen);
+ DeleteObject(Brush);
+ DD_RELEASEDC;
+ mask &= ~DD_FRONT_LEFT_BIT;
+ } /* single-buffer */
+ } /* if masks are all 1's */
+
+ /* Call swrast if there is anything left to clear (like DEPTH) */
+ if (mask)
+ _swrast_Clear( ctx, mask, all, x, y, width, height );
+}
+
+
+//---------------------------------------------------------------------------
+
+
+static void enable( GLcontext* ctx, GLenum pname, GLboolean enable )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+
+ if (!Current)
+ return;
+
+ if (pname == GL_DITHER) {
+ if(enable == GL_FALSE){
+ Current->dither_flag = GL_FALSE;
+ if(Current->cColorBits == 8)
+ Current->pixelformat = PF_INDEX8;
+ }
+ else{
+ if (Current->rgb_flag && Current->cColorBits == 8){
+ Current->pixelformat = PF_DITHER8;
+ Current->dither_flag = GL_TRUE;
+ }
+ else
+ Current->dither_flag = GL_FALSE;
+ }
+ }
+}
+
+//---------------------------------------------------------------------------
+
+static GLboolean set_draw_buffer( GLcontext* ctx, GLenum mode )
+{
+ /* TODO: this could be better */
+ if (mode==GL_FRONT_LEFT || mode==GL_BACK_LEFT) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+
+static void set_read_buffer(GLcontext *ctx, GLframebuffer *colorBuffer,
+ GLenum buffer )
+{
+ /* XXX todo */
+ return;
+}
+
+
+//---------------------------------------------------------------------------
+
+
+/* Return characteristics of the output buffer. */
+//static void buffer_size( GLcontext* ctx, GLuint *width, GLuint *height )
+// Altered for Mesa 5.x. KeithH
+static void buffer_size(
+ GLframebuffer *buffer,
+ GLuint *width,
+ GLuint *height)
+{
+ // For some reason the context is not passed into this function.
+ // Therefore we have to explicitly retrieve it.
+ GET_CURRENT_CONTEXT(ctx);
+
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ int New_Size;
+ RECT CR;
+
+ GetClientRect(Current->Window,&CR);
+
+ *width=CR.right;
+ *height=CR.bottom;
+
+ New_Size=((*width)!=Current->width) || ((*height)!=Current->height);
+
+ if (New_Size){
+ Current->width=*width;
+ Current->height=*height;
+ Current->ScanWidth=Current->width;
+ if ((Current->ScanWidth%sizeof(long))!=0)
+ Current->ScanWidth+=(sizeof(long)-(Current->ScanWidth%sizeof(long)));
+
+ if (Current->db_flag){
+ if (Current->rgb_flag==GL_TRUE && Current->dither_flag!=GL_TRUE){
+ wmDeleteBackingStore(Current);
+ wmCreateBackingStore(Current, Current->width, Current->height);
+ }
+ }
+
+ }
+}
+
+
+
+/**********************************************************************/
+/***** Accelerated point, line, polygon rendering *****/
+/**********************************************************************/
+
+/* Accelerated routines are not implemented in 4.0. See OSMesa for ideas. */
+
+static void fast_rgb_points( GLcontext* ctx, GLuint first, GLuint last )
+{
+}
+
+//---------------------------------------------------------------------------
+
+/* Return pointer to accelerated points function */
+extern points_func choose_points_function( GLcontext* ctx )
+{
+ return NULL;
+}
+
+//---------------------------------------------------------------------------
+
+static void fast_flat_rgb_line( GLcontext* ctx, GLuint v0,
+ GLuint v1, GLuint pv )
+{
+}
+
+//---------------------------------------------------------------------------
+
+static line_func choose_line_function( GLcontext* ctx )
+{
+}
+
+
+/**********************************************************************/
+/***** Span-based pixel drawing *****/
+/**********************************************************************/
+
+
+/* Write a horizontal span of 32-bit color-index pixels with a boolean mask. */
+static void write_ci32_span( const GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLuint index[],
+ const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ PBYTE Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i]=index[i];
+}
+
+
+//---------------------------------------------------------------------------
+
+/* Write a horizontal span of 8-bit color-index pixels with a boolean mask. */
+static void write_ci8_span( const GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte index[],
+ const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ PBYTE Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i]=index[i];
+}
+
+
+//---------------------------------------------------------------------------
+
+
+/*
+ * Write a horizontal span of pixels with a boolean mask. The current
+ * color index is used for all pixels.
+ */
+static void write_mono_ci_span(const GLcontext* ctx,
+ GLuint n,GLint x,GLint y,
+ GLuint colorIndex, const GLubyte mask[])
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i]=colorIndex;
+}
+
+//---------------------------------------------------------------------------
+
+/*
+ * To improve the performance of this routine, frob the data into an actual
+ * scanline and call bitblt on the complete scan line instead of SetPixel.
+ */
+
+/* Write a horizontal span of RGBA color pixels with a boolean mask. */
+static void write_rgba_span( const GLcontext* ctx, GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4], const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ PWMC pwc = Current;
+
+ if (pwc->rgb_flag==GL_TRUE)
+ {
+ GLuint i;
+ HDC DC=DD_GETDC;
+ y=FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, y, x + i,
+ rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ wmSetPixel(pwc, y, x + i,
+ rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ DD_RELEASEDC;
+ }
+ else
+ {
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
+ y = FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i] = GetNearestPaletteIndex(Current->hPal,
+ RGB(rgba[i][RCOMP],
+ rgba[i][GCOMP],
+ rgba[i][BCOMP]));
+ }
+ else {
+ for (i=0; i<n; i++)
+ Mem[i] = GetNearestPaletteIndex(Current->hPal,
+ RGB(rgba[i][RCOMP],
+ rgba[i][GCOMP],
+ rgba[i][BCOMP]));
+ }
+ }
+}
+
+//---------------------------------------------------------------------------
+
+/* Write a horizontal span of RGB color pixels with a boolean mask. */
+static void write_rgb_span( const GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgb[][3], const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ PWMC pwc = Current;
+
+ if (pwc->rgb_flag==GL_TRUE)
+ {
+ GLuint i;
+ HDC DC=DD_GETDC;
+ y=FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, y, x + i,
+ rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ wmSetPixel(pwc, y, x + i,
+ rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+ }
+ DD_RELEASEDC;
+ }
+ else
+ {
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
+ y = FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i] = GetNearestPaletteIndex(Current->hPal,
+ RGB(rgb[i][RCOMP],
+ rgb[i][GCOMP],
+ rgb[i][BCOMP]));
+ }
+ else {
+ for (i=0; i<n; i++)
+ Mem[i] = GetNearestPaletteIndex(Current->hPal,
+ RGB(rgb[i][RCOMP],
+ rgb[i][GCOMP],
+ rgb[i][BCOMP]));
+ }
+ }
+}
+
+//---------------------------------------------------------------------------
+
+/*
+ * Write a horizontal span of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_span( const GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLchan color[4], const GLubyte mask[])
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ ULONG pixel = RGB( color[RCOMP], color[GCOMP], color[BCOMP] );
+ GLuint i;
+ HDC DC=DD_GETDC;
+ PWMC pwc = Current;
+ assert(Current->rgb_flag==GL_TRUE);
+ y=FLIP(y);
+ if(Current->rgb_flag==GL_TRUE){
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc,y,x+i,color[RCOMP], color[GCOMP], color[BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ SetPixel(DC, y, x+i, pixel);
+ }
+ DD_RELEASEDC;
+}
+
+
+
+/**********************************************************************/
+/***** Array-based pixel drawing *****/
+/**********************************************************************/
+
+
+/* Write an array of 32-bit index pixels with a boolean mask. */
+static void write_ci32_pixels( const GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLuint index[], const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ BYTE *Mem=Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i];
+ *Mem = index[i];
+ }
+ }
+}
+
+
+//---------------------------------------------------------------------------
+
+
+/*
+ * Write an array of pixels with a boolean mask. The current color
+ * index is used for all pixels.
+ */
+static void write_mono_ci_pixels( const GLcontext* ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ GLuint colorIndex, const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ BYTE *Mem=Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i];
+ *Mem = colorIndex;
+ }
+ }
+}
+
+
+//---------------------------------------------------------------------------
+
+
+/* Write an array of RGBA pixels with a boolean mask. */
+static void write_rgba_pixels( const GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte rgba[][4], const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ PWMC pwc = Current;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, FLIP(y[i]), x[i],
+ rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+ DD_RELEASEDC;
+}
+
+
+//---------------------------------------------------------------------------
+
+
+/*
+ * Write an array of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_mono_rgba_pixels( const GLcontext* ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLchan color[4],
+ const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ PWMC pwc = Current;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, FLIP(y[i]),x[i],color[RCOMP],
+ color[GCOMP], color[BCOMP]);
+ DD_RELEASEDC;
+}
+
+/**********************************************************************/
+/***** Read spans/arrays of pixels *****/
+/**********************************************************************/
+
+/* Read a horizontal span of color-index pixels. */
+static void read_ci32_span( const GLcontext* ctx, GLuint n, GLint x, GLint y,
+ GLuint index[])
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ index[i]=Mem[i];
+}
+
+//---------------------------------------------------------------------------
+
+/* Read an array of color index pixels. */
+static void read_ci32_pixels( const GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint indx[], const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ indx[i]=*(Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i]);
+ }
+ }
+}
+
+//---------------------------------------------------------------------------
+
+/* Read a horizontal span of color pixels. */
+static void read_rgba_span( const GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ UINT i;
+ COLORREF Color;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ y = Current->height - y - 1;
+ for (i=0; i<n; i++) {
+ Color=GetPixel(DC,x+i,y);
+ rgba[i][RCOMP] = GetRValue(Color);
+ rgba[i][GCOMP] = GetGValue(Color);
+ rgba[i][BCOMP] = GetBValue(Color);
+ rgba[i][ACOMP] = 255;
+ }
+ DD_RELEASEDC;
+}
+
+//---------------------------------------------------------------------------
+
+/* Read an array of color pixels. */
+static void read_rgba_pixels( const GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[] )
+{
+ GLD_context *gldCtx = GLD_GET_CONTEXT(ctx);
+ WMesaContext *Current = GLD_GET_WMESA_DRIVER(gldCtx);
+ GLuint i;
+ COLORREF Color;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLint y2 = Current->height - y[i] - 1;
+ Color=GetPixel(DC,x[i],y2);
+ rgba[i][RCOMP] = GetRValue(Color);
+ rgba[i][GCOMP] = GetGValue(Color);
+ rgba[i][BCOMP] = GetBValue(Color);
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ DD_RELEASEDC;
+}
+
+//---------------------------------------------------------------------------
+
+static void wmesa_update_state(
+ GLcontext *ctx,
+ GLuint new_state)
+{
+ _swrast_InvalidateState( ctx, new_state );
+ _swsetup_InvalidateState( ctx, new_state );
+ _ac_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+}
+
+//---------------------------------------------------------------------------
+
+static void wmesa_viewport(
+ GLcontext *ctx,
+ GLint x,
+ GLint y,
+ GLsizei w,
+ GLsizei h)
+{
+// ctx->Driver.ResizeBuffersMESA(ctx);
+}
+
+//---------------------------------------------------------------------------
+
+static void wmesa_update_state_first_time(
+ GLcontext *ctx,
+ GLuint new_state)
+{
+ struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx );
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ /*
+ * XXX these function pointers could be initialized just once during
+ * context creation since they don't depend on any state changes.
+ * kws - This is true - this function gets called a lot and it
+ * would be good to minimize setting all this when not needed.
+ */
+ // Good idea, so I'll do it. KeithH. :-)
+
+ ctx->Driver.GetString = _gldGetStringGeneric;
+ ctx->Driver.UpdateState = wmesa_update_state;
+ ctx->Driver.DrawBuffer = set_draw_buffer;
+ ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
+ ctx->Driver.GetBufferSize = buffer_size;
+
+ ctx->Driver.Viewport = wmesa_viewport;
+
+ ctx->Driver.Accum = _swrast_Accum;
+ ctx->Driver.Bitmap = _swrast_Bitmap;
+ ctx->Driver.Clear = clear;
+
+ ctx->Driver.Flush = flush;
+ ctx->Driver.ClearIndex = clear_index;
+ ctx->Driver.ClearColor = clear_color;
+ ctx->Driver.Enable = enable;
+
+ ctx->Driver.CopyPixels = _swrast_CopyPixels;
+ ctx->Driver.DrawPixels = _swrast_DrawPixels;
+ ctx->Driver.ReadPixels = _swrast_ReadPixels;
+
+ ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format;
+ ctx->Driver.TexImage1D = _mesa_store_teximage1d;
+ ctx->Driver.TexImage2D = _mesa_store_teximage2d;
+ ctx->Driver.TexImage3D = _mesa_store_teximage3d;
+ ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
+ ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d;
+ ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
+ ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
+
+ ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
+ ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
+ ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
+ ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
+ ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
+ ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
+ ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
+ ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
+ ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
+
+ // Does not apply for Mesa 5.x
+ //ctx->Driver.BaseCompressedTexFormat = _mesa_base_compressed_texformat;
+ //ctx->Driver.CompressedTextureSize = _mesa_compressed_texture_size;
+ //ctx->Driver.GetCompressedTexImage = _mesa_get_compressed_teximage;
+
+ swdd->SetBuffer = set_read_buffer;
+
+
+ /* Pixel/span writing functions: */
+ swdd->WriteRGBASpan = write_rgba_span;
+ swdd->WriteRGBSpan = write_rgb_span;
+ swdd->WriteMonoRGBASpan = write_mono_rgba_span;
+ swdd->WriteRGBAPixels = write_rgba_pixels;
+ swdd->WriteMonoRGBAPixels = write_mono_rgba_pixels;
+ swdd->WriteCI32Span = write_ci32_span;
+ swdd->WriteCI8Span = write_ci8_span;
+ swdd->WriteMonoCISpan = write_mono_ci_span;
+ swdd->WriteCI32Pixels = write_ci32_pixels;
+ swdd->WriteMonoCIPixels = write_mono_ci_pixels;
+
+ swdd->ReadCI32Span = read_ci32_span;
+ swdd->ReadRGBASpan = read_rgba_span;
+ swdd->ReadCI32Pixels = read_ci32_pixels;
+ swdd->ReadRGBAPixels = read_rgba_pixels;
+
+
+ tnl->Driver.RunPipeline = _tnl_run_pipeline;
+
+ wmesa_update_state(ctx, new_state);
+}
+
+//---------------------------------------------------------------------------
+// Driver interface functions
+//---------------------------------------------------------------------------
+
+BOOL gldCreateDrawable_MesaSW(
+ DGL_ctx *pCtx,
+ BOOL bPersistantInterface,
+ BOOL bPersistantBuffers)
+{
+ WMesaContext *c;
+ GLboolean true_color_flag;
+ GLboolean rgb_flag = GL_TRUE;
+ GLboolean db_flag = GL_TRUE;
+
+ if (pCtx == NULL)
+ return FALSE;
+
+ c = (struct wmesa_context * ) calloc(1,sizeof(struct wmesa_context));
+ if (!c)
+ return FALSE;
+
+ pCtx->glPriv = c;
+
+ c->hDC = pCtx->hDC;
+ c->Window = pCtx->hWnd;
+
+ true_color_flag = GetDeviceCaps(pCtx->hDC, BITSPIXEL) > 8;
+
+
+#ifdef DITHER
+ if ((true_color_flag==GL_FALSE) && (rgb_flag == GL_TRUE)){
+ c->dither_flag = GL_TRUE;
+ c->hPalHalfTone = WinGCreateHalftonePalette();
+ }
+ else
+ c->dither_flag = GL_FALSE;
+#else
+ c->dither_flag = GL_FALSE;
+#endif
+
+
+ if (rgb_flag==GL_FALSE)
+ {
+ c->rgb_flag = GL_FALSE;
+#if 0
+ /* Old WinG stuff???? */
+ c->db_flag = db_flag =GL_TRUE; /* WinG requires double buffering */
+ printf("Single buffer is not supported in color index mode, ",
+ "setting to double buffer.\n");
+#endif
+ }
+ else
+ {
+ c->rgb_flag = GL_TRUE;
+ }
+
+// db_flag = pCtx->lpPF->pfd.dwFlags & PFD_DOUBLEBUFFER ? GL_TRUE : GL_FALSE;
+ db_flag = GL_TRUE; // Force double-buffer
+ if (db_flag) {
+ c->db_flag = 1;
+ /* Double buffered */
+ {
+ wmCreateBackingStore(c, pCtx->dwWidth, pCtx->dwHeight);
+
+ }
+ } else {
+ /* Single Buffered */
+ if (c->rgb_flag)
+ c->db_flag = 0;
+ }
+
+ c->bEmulateSingleBuffer = (pCtx->lpPF->pfd.dwFlags & PFD_DOUBLEBUFFER)
+ ? FALSE : TRUE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldResizeDrawable_MesaSW(
+ DGL_ctx *ctx,
+ BOOL bDefaultDriver,
+ BOOL bPersistantInterface,
+ BOOL bPersistantBuffers)
+{
+ WMesaContext *c;
+
+ if (ctx == NULL)
+ return FALSE;
+
+ c = ctx->glPriv;
+ if (c == NULL)
+ return FALSE;
+
+ c->hDC = ctx->hDC;
+ c->Window = ctx->hWnd;
+// c->width = ctx->dwWidth;
+// c->height = ctx->dwHeight;
+
+ if (c->db_flag) {
+ wmDeleteBackingStore(c);
+ wmCreateBackingStore(c, ctx->dwWidth, ctx->dwHeight);
+ }
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldDestroyDrawable_MesaSW(
+ DGL_ctx *ctx)
+{
+ WMesaContext *c;
+
+ if (ctx == NULL)
+ return FALSE;
+
+ c = ctx->glPriv;
+ if (c == NULL)
+ return FALSE;
+
+ if (c->hPalHalfTone != NULL)
+ DeleteObject(c->hPalHalfTone);
+
+ if (c->db_flag)
+ wmDeleteBackingStore(c);
+
+ free(c);
+
+ ctx->glPriv = NULL;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldCreatePrivateGlobals_MesaSW(void)
+{
+ // Mesa Software driver needs no private globals
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldDestroyPrivateGlobals_MesaSW(void)
+{
+ // Mesa Software driver needs no private globals
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldBuildPixelformatList_MesaSW(void)
+{
+ // Release any existing pixelformat list
+ if (glb.lpPF) {
+ free(glb.lpPF);
+ }
+
+ glb.nPixelFormatCount = 0;
+ glb.lpPF = NULL;
+
+ glb.lpPF = (DGL_pixelFormat *)calloc(2, sizeof(DGL_pixelFormat));
+ if (glb.lpPF == NULL)
+ return FALSE;
+ // Single-buffered
+ memcpy(&glb.lpPF[0], &pfTemplateMesaSW, sizeof(DGL_pixelFormat));
+ glb.lpPF[0].pfd.dwFlags &= ~PFD_DOUBLEBUFFER; // Remove doublebuffer flag
+ // Double-buffered
+ memcpy(&glb.lpPF[1], &pfTemplateMesaSW, sizeof(DGL_pixelFormat));
+ glb.nPixelFormatCount = 2;
+
+ // Mark list as 'current'
+ glb.bPixelformatsDirty = FALSE;
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldInitialiseMesa_MesaSW(
+ DGL_ctx *gld)
+{
+ GLcontext *ctx;
+
+ if (gld == NULL)
+ return FALSE;
+
+ ctx = gld->glCtx;
+
+ // Set max texture size to 256
+ ctx->Const.MaxTextureLevels = 8;
+
+ // Multitexture enable/disable
+ ctx->Const.MaxTextureUnits = (glb.bMultitexture) ? MAX_TEXTURE_UNITS : 1;
+
+ /* Initialize the software rasterizer and helper modules.*/
+
+ // Added this to force max texture diminsion to 256. KeithH
+ ctx->Const.MaxTextureLevels = 8;
+
+ _mesa_enable_sw_extensions(ctx);
+ _mesa_enable_imaging_extensions(ctx);
+ _mesa_enable_1_3_extensions(ctx);
+
+// _swrast_CreateContext( ctx );
+// _ac_CreateContext( ctx );
+// _tnl_CreateContext( ctx );
+// _swsetup_CreateContext( ctx );
+
+ _swsetup_Wakeup( ctx );
+
+ wmesa_update_state_first_time(ctx, ~0);
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldSwapBuffers_MesaSW(
+ DGL_ctx *ctx,
+ HDC hDC,
+ HWND hWnd)
+{
+ WMesaContext *c;
+
+ if (ctx == NULL)
+ return FALSE;
+
+ c = ctx->glPriv;
+ if (c == NULL)
+ return FALSE;
+
+ /* If we're swapping the buffer associated with the current context
+ * we have to flush any pending rendering commands first.
+ */
+
+ // Altered to respect bEmulateSingleBuffer. KeithH
+// if (c->db_flag)
+ if (!c->bEmulateSingleBuffer)
+ wmFlush(c, hDC);
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
+PROC gldGetProcAddress_MesaSW(
+ LPCSTR a)
+{
+ int i;
+ PROC proc = NULL;
+
+ for (i=0; GLD_extList[i].proc; i++) {
+ if (!strcmp(a, GLD_extList[i].name)) {
+ proc = GLD_extList[i].proc;
+ break;
+ }
+ }
+
+ gldLogPrintf(GLDLOG_INFO, "GetProcAddress: %s (%s)", a, proc ? "OK" : "Failed");
+
+ return proc;
+}
+
+//---------------------------------------------------------------------------
+
+BOOL gldGetDisplayMode_MesaSW(
+ DGL_ctx *ctx,
+ GLD_displayMode *glddm)
+{
+ HDC hdcDesktop;
+
+ if (glddm == NULL)
+ return FALSE;
+
+ //
+ // A bit hacky... KeithH
+ //
+
+ hdcDesktop = GetDC(NULL);
+ glddm->Width = GetDeviceCaps(hdcDesktop, HORZRES);
+ glddm->Height = GetDeviceCaps(hdcDesktop, VERTRES);
+ glddm->BPP = GetDeviceCaps(hdcDesktop, BITSPIXEL);
+ glddm->Refresh = 0;
+ ReleaseDC(0, hdcDesktop);
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+
diff --git a/src/mesa/drivers/windows/gldirect/opengl32.def b/src/mesa/drivers/windows/gldirect/opengl32.def
new file mode 100644
index 0000000000..b213b6e047
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/opengl32.def
@@ -0,0 +1,488 @@
+;****************************************************************************
+;*
+;* Mesa 3-D graphics library
+;* Direct3D Driver Interface
+;*
+;* ========================================================================
+;*
+;* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+;*
+;* Permission is hereby granted, free of charge, to any person obtaining a
+;* copy of this software and associated documentation files (the "Software"),
+;* to deal in the Software without restriction, including without limitation
+;* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+;* and/or sell copies of the Software, and to permit persons to whom the
+;* Software is furnished to do so, subject to the following conditions:
+;*
+;* The above copyright notice and this permission notice shall be included
+;* in all copies or substantial portions of the Software.
+;*
+;* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+;* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+;* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+;* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+;* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+;* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+;* SOFTWARE.
+;*
+;* ======================================================================
+;*
+;* Language: ANSI C
+;* Environment: Windows 9x/2000/XP/XBox (Win32)
+;*
+;* Description: DLL Module definition file
+;*
+;****************************************************************************/
+
+DESCRIPTION 'GLDirect'
+
+VERSION 3.0
+
+EXPORTS
+ glAccum=glAccum @1
+ glAlphaFunc=glAlphaFunc @2
+ glAreTexturesResident=glAreTexturesResident @3
+ glArrayElement=glArrayElement @4
+ glBegin=glBegin @5
+ glBindTexture=glBindTexture @6
+ glBitmap=glBitmap @7
+ glBlendFunc=glBlendFunc @8
+ glCallList=glCallList @9
+ glCallLists=glCallLists @10
+ glClear=glClear @11
+ glClearAccum=glClearAccum @12
+ glClearIndex=glClearIndex @13
+ glClearColor=glClearColor @14
+ glClearDepth=glClearDepth @15
+ glClearStencil=glClearStencil @16
+ glClipPlane=glClipPlane @17
+ glColor3b=glColor3b @18
+ glColor3d=glColor3d @19
+ glColor3f=glColor3f @20
+ glColor3i=glColor3i @21
+ glColor3s=glColor3s @22
+ glColor3ub=glColor3ub @23
+ glColor3ui=glColor3ui @24
+ glColor3us=glColor3us @25
+ glColor4b=glColor4b @26
+ glColor4d=glColor4d @27
+ glColor4f=glColor4f @28
+ glColor4i=glColor4i @29
+ glColor4s=glColor4s @30
+ glColor4ub=glColor4ub @31
+ glColor4ui=glColor4ui @32
+ glColor4us=glColor4us @33
+ glColor3bv=glColor3bv @34
+ glColor3dv=glColor3dv @35
+ glColor3fv=glColor3fv @36
+ glColor3iv=glColor3iv @37
+ glColor3sv=glColor3sv @38
+ glColor3ubv=glColor3ubv @39
+ glColor3uiv=glColor3uiv @40
+ glColor3usv=glColor3usv @41
+ glColor4bv=glColor4bv @42
+ glColor4dv=glColor4dv @43
+ glColor4fv=glColor4fv @44
+ glColor4iv=glColor4iv @45
+ glColor4sv=glColor4sv @46
+ glColor4ubv=glColor4ubv @47
+ glColor4uiv=glColor4uiv @48
+ glColor4usv=glColor4usv @49
+ glColorMask=glColorMask @50
+ glColorMaterial=glColorMaterial @51
+ glColorPointer=glColorPointer @52
+ glColorTableEXT=glColorTableEXT @53
+ glColorSubTableEXT=glColorSubTableEXT @54
+ glCopyPixels=glCopyPixels @55
+ glCopyTexImage1D=glCopyTexImage1D @56
+ glCopyTexImage2D=glCopyTexImage2D @57
+ glCopyTexSubImage1D=glCopyTexSubImage1D @58
+ glCopyTexSubImage2D=glCopyTexSubImage2D @59
+ glCullFace=glCullFace @60
+ glDepthFunc=glDepthFunc @61
+ glDepthMask=glDepthMask @62
+ glDepthRange=glDepthRange @63
+ glDeleteLists=glDeleteLists @64
+ glDeleteTextures=glDeleteTextures @65
+ glDisable=glDisable @66
+ glDisableClientState=glDisableClientState @67
+ glDrawArrays=glDrawArrays @68
+ glDrawBuffer=glDrawBuffer @69
+ glDrawElements=glDrawElements @70
+ glDrawPixels=glDrawPixels @71
+ glEnable=glEnable @72
+ glEnableClientState=glEnableClientState @73
+ glEnd=glEnd @74
+ glEndList=glEndList @75
+ glEvalCoord1d=glEvalCoord1d @76
+ glEvalCoord1f=glEvalCoord1f @77
+ glEvalCoord1dv=glEvalCoord1dv @78
+ glEvalCoord1fv=glEvalCoord1fv @79
+ glEvalCoord2d=glEvalCoord2d @80
+ glEvalCoord2f=glEvalCoord2f @81
+ glEvalCoord2dv=glEvalCoord2dv @82
+ glEvalCoord2fv=glEvalCoord2fv @83
+ glEvalPoint1=glEvalPoint1 @84
+ glEvalPoint2=glEvalPoint2 @85
+ glEvalMesh1=glEvalMesh1 @86
+ glEdgeFlag=glEdgeFlag @87
+ glEdgeFlagv=glEdgeFlagv @88
+ glEdgeFlagPointer=glEdgeFlagPointer @89
+ glEvalMesh2=glEvalMesh2 @90
+ glFeedbackBuffer=glFeedbackBuffer @91
+ glFinish=glFinish @92
+ glFlush=glFlush @93
+ glFogf=glFogf @94
+ glFogi=glFogi @95
+ glFogfv=glFogfv @96
+ glFogiv=glFogiv @97
+ glFrontFace=glFrontFace @98
+ glFrustum=glFrustum @99
+ glGenLists=glGenLists @100
+ glGenTextures=glGenTextures @101
+ glGetBooleanv=glGetBooleanv @102
+ glGetClipPlane=glGetClipPlane @103
+ glGetColorTableEXT=glGetColorTableEXT @104
+ glGetColorTableParameterivEXT=glGetColorTableParameterivEXT @105
+ glGetColorTableParameterfvEXT=glGetColorTableParameterfvEXT @106
+ glGetDoublev=glGetDoublev @107
+ glGetError=glGetError @108
+ glGetFloatv=glGetFloatv @109
+ glGetIntegerv=glGetIntegerv @110
+ glGetLightfv=glGetLightfv @111
+ glGetLightiv=glGetLightiv @112
+ glGetMapdv=glGetMapdv @113
+ glGetMapfv=glGetMapfv @114
+ glGetMapiv=glGetMapiv @115
+ glGetMaterialfv=glGetMaterialfv @116
+ glGetMaterialiv=glGetMaterialiv @117
+ glGetPixelMapfv=glGetPixelMapfv @118
+ glGetPixelMapuiv=glGetPixelMapuiv @119
+ glGetPixelMapusv=glGetPixelMapusv @120
+ glGetPointerv=glGetPointerv @121
+ glGetPolygonStipple=glGetPolygonStipple @122
+ glGetString=glGetString @123
+ glGetTexEnvfv=glGetTexEnvfv @124
+ glGetTexEnviv=glGetTexEnviv @125
+ glGetTexGeniv=glGetTexGeniv @126
+ glGetTexGendv=glGetTexGendv @127
+ glGetTexGenfv=glGetTexGenfv @128
+ glGetTexImage=glGetTexImage @129
+ glGetTexLevelParameterfv=glGetTexLevelParameterfv @130
+ glGetTexLevelParameteriv=glGetTexLevelParameteriv @131
+ glGetTexParameterfv=glGetTexParameterfv @132
+ glGetTexParameteriv=glGetTexParameteriv @133
+ glHint=glHint @134
+ glIndexd=glIndexd @135
+ glIndexf=glIndexf @136
+ glIndexi=glIndexi @137
+ glIndexs=glIndexs @138
+ glIndexub=glIndexub @139
+ glIndexdv=glIndexdv @140
+ glIndexfv=glIndexfv @141
+ glIndexiv=glIndexiv @142
+ glIndexsv=glIndexsv @143
+ glIndexubv=glIndexubv @144
+ glIndexMask=glIndexMask @145
+ glIndexPointer=glIndexPointer @146
+ glInterleavedArrays=glInterleavedArrays @147
+ glInitNames=glInitNames @148
+ glIsList=glIsList @149
+ glIsTexture=glIsTexture @150
+ glLightf=glLightf @151
+ glLighti=glLighti @152
+ glLightfv=glLightfv @153
+ glLightiv=glLightiv @154
+ glLightModelf=glLightModelf @155
+ glLightModeli=glLightModeli @156
+ glLightModelfv=glLightModelfv @157
+ glLightModeliv=glLightModeliv @158
+ glLineWidth=glLineWidth @159
+ glLineStipple=glLineStipple @160
+ glListBase=glListBase @161
+ glLoadIdentity=glLoadIdentity @162
+ glLoadMatrixd=glLoadMatrixd @163
+ glLoadMatrixf=glLoadMatrixf @164
+ glLoadName=glLoadName @165
+ glLogicOp=glLogicOp @166
+ glMap1d=glMap1d @167
+ glMap1f=glMap1f @168
+ glMap2d=glMap2d @169
+ glMap2f=glMap2f @170
+ glMapGrid1d=glMapGrid1d @171
+ glMapGrid1f=glMapGrid1f @172
+ glMapGrid2d=glMapGrid2d @173
+ glMapGrid2f=glMapGrid2f @174
+ glMaterialf=glMaterialf @175
+ glMateriali=glMateriali @176
+ glMaterialfv=glMaterialfv @177
+ glMaterialiv=glMaterialiv @178
+ glMatrixMode=glMatrixMode @179
+ glMultMatrixd=glMultMatrixd @180
+ glMultMatrixf=glMultMatrixf @181
+ glNewList=glNewList @182
+ glNormal3b=glNormal3b @183
+ glNormal3d=glNormal3d @184
+ glNormal3f=glNormal3f @185
+ glNormal3i=glNormal3i @186
+ glNormal3s=glNormal3s @187
+ glNormal3bv=glNormal3bv @188
+ glNormal3dv=glNormal3dv @189
+ glNormal3fv=glNormal3fv @190
+ glNormal3iv=glNormal3iv @191
+ glNormal3sv=glNormal3sv @192
+ glNormalPointer=glNormalPointer @193
+ glOrtho=glOrtho @194
+ glPassThrough=glPassThrough @195
+ glPixelMapfv=glPixelMapfv @196
+ glPixelMapuiv=glPixelMapuiv @197
+ glPixelMapusv=glPixelMapusv @198
+ glPixelStoref=glPixelStoref @199
+ glPixelStorei=glPixelStorei @200
+ glPixelTransferf=glPixelTransferf @201
+ glPixelTransferi=glPixelTransferi @202
+ glPixelZoom=glPixelZoom @203
+ glPointSize=glPointSize @204
+ glPolygonMode=glPolygonMode @205
+ glPolygonOffset=glPolygonOffset @206
+ glPolygonOffsetEXT=glPolygonOffsetEXT @207
+ glPolygonStipple=glPolygonStipple @208
+ glPopAttrib=glPopAttrib @209
+ glPopClientAttrib=glPopClientAttrib @210
+ glPopMatrix=glPopMatrix @211
+ glPopName=glPopName @212
+ glPrioritizeTextures=glPrioritizeTextures @213
+ glPushMatrix=glPushMatrix @214
+ glRasterPos2d=glRasterPos2d @215
+ glRasterPos2f=glRasterPos2f @216
+ glRasterPos2i=glRasterPos2i @217
+ glRasterPos2s=glRasterPos2s @218
+ glRasterPos3d=glRasterPos3d @219
+ glRasterPos3f=glRasterPos3f @220
+ glRasterPos3i=glRasterPos3i @221
+ glRasterPos3s=glRasterPos3s @222
+ glRasterPos4d=glRasterPos4d @223
+ glRasterPos4f=glRasterPos4f @224
+ glRasterPos4i=glRasterPos4i @225
+ glRasterPos4s=glRasterPos4s @226
+ glRasterPos2dv=glRasterPos2dv @227
+ glRasterPos2fv=glRasterPos2fv @228
+ glRasterPos2iv=glRasterPos2iv @229
+ glRasterPos2sv=glRasterPos2sv @230
+ glRasterPos3dv=glRasterPos3dv @231
+ glRasterPos3fv=glRasterPos3fv @232
+ glRasterPos3iv=glRasterPos3iv @233
+ glRasterPos3sv=glRasterPos3sv @234
+ glRasterPos4dv=glRasterPos4dv @235
+ glRasterPos4fv=glRasterPos4fv @236
+ glRasterPos4iv=glRasterPos4iv @237
+ glRasterPos4sv=glRasterPos4sv @238
+ glReadBuffer=glReadBuffer @239
+ glReadPixels=glReadPixels @240
+ glRectd=glRectd @241
+ glRectf=glRectf @242
+ glRecti=glRecti @243
+ glRects=glRects @244
+ glRectdv=glRectdv @245
+ glRectfv=glRectfv @246
+ glRectiv=glRectiv @247
+ glRectsv=glRectsv @248
+ glScissor=glScissor @249
+ glIsEnabled=glIsEnabled @250
+ glPushAttrib=glPushAttrib @251
+ glPushClientAttrib=glPushClientAttrib @252
+ glPushName=glPushName @253
+ glRenderMode=glRenderMode @254
+ glRotated=glRotated @255
+ glRotatef=glRotatef @256
+ glSelectBuffer=glSelectBuffer @257
+ glScaled=glScaled @258
+ glScalef=glScalef @259
+ glShadeModel=glShadeModel @260
+ glStencilFunc=glStencilFunc @261
+ glStencilMask=glStencilMask @262
+ glStencilOp=glStencilOp @263
+ glTexCoord1d=glTexCoord1d @264
+ glTexCoord1f=glTexCoord1f @265
+ glTexCoord1i=glTexCoord1i @266
+ glTexCoord1s=glTexCoord1s @267
+ glTexCoord2d=glTexCoord2d @268
+ glTexCoord2f=glTexCoord2f @269
+ glTexCoord2i=glTexCoord2i @270
+ glTexCoord2s=glTexCoord2s @271
+ glTexCoord3d=glTexCoord3d @272
+ glTexCoord3f=glTexCoord3f @273
+ glTexCoord3i=glTexCoord3i @274
+ glTexCoord3s=glTexCoord3s @275
+ glTexCoord4d=glTexCoord4d @276
+ glTexCoord4f=glTexCoord4f @277
+ glTexCoord4i=glTexCoord4i @278
+ glTexCoord4s=glTexCoord4s @279
+ glTexCoord1dv=glTexCoord1dv @280
+ glTexCoord1fv=glTexCoord1fv @281
+ glTexCoord1iv=glTexCoord1iv @282
+ glTexCoord1sv=glTexCoord1sv @283
+ glTexCoord2dv=glTexCoord2dv @284
+ glTexCoord2fv=glTexCoord2fv @285
+ glTexCoord2iv=glTexCoord2iv @286
+ glTexCoord2sv=glTexCoord2sv @287
+ glTexCoord3dv=glTexCoord3dv @288
+ glTexCoord3fv=glTexCoord3fv @289
+ glTexCoord3iv=glTexCoord3iv @290
+ glTexCoord3sv=glTexCoord3sv @291
+ glTexCoord4dv=glTexCoord4dv @292
+ glTexCoord4fv=glTexCoord4fv @293
+ glTexCoord4iv=glTexCoord4iv @294
+ glTexCoord4sv=glTexCoord4sv @295
+ glTexCoordPointer=glTexCoordPointer @296
+ glTexGend=glTexGend @297
+ glTexGenf=glTexGenf @298
+ glTexGeni=glTexGeni @299
+ glTexGendv=glTexGendv @300
+ glTexGeniv=glTexGeniv @301
+ glTexGenfv=glTexGenfv @302
+ glTexEnvf=glTexEnvf @303
+ glTexEnvi=glTexEnvi @304
+ glTexEnvfv=glTexEnvfv @305
+ glTexEnviv=glTexEnviv @306
+ glTexImage1D=glTexImage1D @307
+ glTexImage2D=glTexImage2D @308
+ glTexParameterf=glTexParameterf @309
+ glTexParameteri=glTexParameteri @310
+ glTexParameterfv=glTexParameterfv @311
+ glTexParameteriv=glTexParameteriv @312
+ glTexSubImage1D=glTexSubImage1D @313
+ glTexSubImage2D=glTexSubImage2D @314
+ glTranslated=glTranslated @315
+ glTranslatef=glTranslatef @316
+ glVertex2d=glVertex2d @317
+ glVertex2f=glVertex2f @318
+ glVertex2i=glVertex2i @319
+ glVertex2s=glVertex2s @320
+ glVertex3d=glVertex3d @321
+ glVertex3f=glVertex3f @322
+ glVertex3i=glVertex3i @323
+ glVertex3s=glVertex3s @324
+ glVertex4d=glVertex4d @325
+ glVertex4f=glVertex4f @326
+ glVertex4i=glVertex4i @327
+ glVertex4s=glVertex4s @328
+ glVertex2dv=glVertex2dv @329
+ glVertex2fv=glVertex2fv @330
+ glVertex2iv=glVertex2iv @331
+ glVertex2sv=glVertex2sv @332
+ glVertex3dv=glVertex3dv @333
+ glVertex3fv=glVertex3fv @334
+ glVertex3iv=glVertex3iv @335
+ glVertex3sv=glVertex3sv @336
+ glVertex4dv=glVertex4dv @337
+ glVertex4fv=glVertex4fv @338
+ glVertex4iv=glVertex4iv @339
+ glVertex4sv=glVertex4sv @340
+ glVertexPointer=glVertexPointer @341
+ glViewport=glViewport @342
+ glBlendEquationEXT=glBlendEquationEXT @343
+ glBlendColorEXT=glBlendColorEXT @344
+ glVertexPointerEXT=glVertexPointerEXT @345
+ glNormalPointerEXT=glNormalPointerEXT @346
+ glColorPointerEXT=glColorPointerEXT @347
+ glIndexPointerEXT=glIndexPointerEXT @348
+ glTexCoordPointerEXT=glTexCoordPointerEXT @349
+ glEdgeFlagPointerEXT=glEdgeFlagPointerEXT @350
+ glGetPointervEXT=glGetPointervEXT @351
+ glArrayElementEXT=glArrayElementEXT @352
+ glDrawArraysEXT=glDrawArraysEXT @353
+ glBindTextureEXT=glBindTextureEXT @354
+ glDeleteTexturesEXT=glDeleteTexturesEXT @355
+ glGenTexturesEXT=glGenTexturesEXT @356
+ glPrioritizeTexturesEXT=glPrioritizeTexturesEXT @357
+ glCopyTexSubImage3DEXT=glCopyTexSubImage3DEXT @358
+ glTexImage3DEXT=glTexImage3DEXT @359
+ glTexSubImage3DEXT=glTexSubImage3DEXT @360
+ glWindowPos4fMESA=glWindowPos4fMESA @361
+ glWindowPos2iMESA=glWindowPos2iMESA @362
+ glWindowPos2sMESA=glWindowPos2sMESA @363
+ glWindowPos2fMESA=glWindowPos2fMESA @364
+ glWindowPos2dMESA=glWindowPos2dMESA @365
+ glWindowPos2ivMESA=glWindowPos2ivMESA @366
+ glWindowPos2svMESA=glWindowPos2svMESA @367
+ glWindowPos2fvMESA=glWindowPos2fvMESA @368
+ glWindowPos2dvMESA=glWindowPos2dvMESA @369
+ glWindowPos3iMESA=glWindowPos3iMESA @370
+ glWindowPos3sMESA=glWindowPos3sMESA @371
+ glWindowPos3fMESA=glWindowPos3fMESA @372
+ glWindowPos3dMESA=glWindowPos3dMESA @373
+ glWindowPos3ivMESA=glWindowPos3ivMESA @374
+ glWindowPos3svMESA=glWindowPos3svMESA @375
+ glWindowPos3fvMESA=glWindowPos3fvMESA @376
+ glWindowPos3dvMESA=glWindowPos3dvMESA @377
+ glWindowPos4iMESA=glWindowPos4iMESA @378
+ glWindowPos4sMESA=glWindowPos4sMESA @379
+ glWindowPos4dMESA=glWindowPos4dMESA @380
+ glWindowPos4ivMESA=glWindowPos4ivMESA @381
+ glWindowPos4svMESA=glWindowPos4svMESA @382
+ glWindowPos4fvMESA=glWindowPos4fvMESA @383
+ glWindowPos4dvMESA=glWindowPos4dvMESA @384
+ glResizeBuffersMESA=glResizeBuffersMESA @385
+ wglCopyContext=wglCopyContext @386
+ wglCreateContext=wglCreateContext @387
+ wglCreateLayerContext=wglCreateLayerContext @388
+ wglDeleteContext=wglDeleteContext @389
+ wglDescribeLayerPlane=wglDescribeLayerPlane @390
+ wglGetCurrentContext=wglGetCurrentContext @391
+ wglGetCurrentDC=wglGetCurrentDC @392
+ wglGetLayerPaletteEntries=wglGetLayerPaletteEntries @393
+ wglGetProcAddress=wglGetProcAddress @394
+ wglMakeCurrent=wglMakeCurrent @395
+ wglRealizeLayerPalette=wglRealizeLayerPalette @396
+ wglSetLayerPaletteEntries=wglSetLayerPaletteEntries @397
+ wglShareLists=wglShareLists @398
+ wglSwapLayerBuffers=wglSwapLayerBuffers @399
+ wglUseFontBitmapsA=wglUseFontBitmapsA @400
+ wglUseFontBitmapsW=wglUseFontBitmapsW @401
+ wglUseFontOutlinesA=wglUseFontOutlinesA @402
+ wglUseFontOutlinesW=wglUseFontOutlinesW @403
+ ChoosePixelFormat=ChoosePixelFormat @404
+ DescribePixelFormat=DescribePixelFormat @405
+ GetPixelFormat=GetPixelFormat @406
+ SetPixelFormat=SetPixelFormat @407
+ SwapBuffers=SwapBuffers @408
+ wglChoosePixelFormat=wglChoosePixelFormat @409
+ wglDescribePixelFormat=wglDescribePixelFormat @410
+ wglGetPixelFormat=wglGetPixelFormat @411
+ wglSetPixelFormat=wglSetPixelFormat @412
+ wglSwapBuffers=wglSwapBuffers @413
+ glActiveTextureARB=glActiveTextureARB @414
+ glClientActiveTextureARB=glClientActiveTextureARB @415
+ glMultiTexCoord1dARB=glMultiTexCoord1dARB @416
+ glMultiTexCoord1dvARB=glMultiTexCoord1dvARB @417
+ glMultiTexCoord1fARB=glMultiTexCoord1fARB @418
+ glMultiTexCoord1fvARB=glMultiTexCoord1fvARB @419
+ glMultiTexCoord1iARB=glMultiTexCoord1iARB @420
+ glMultiTexCoord1ivARB=glMultiTexCoord1ivARB @421
+ glMultiTexCoord1sARB=glMultiTexCoord1sARB @422
+ glMultiTexCoord1svARB=glMultiTexCoord1svARB @423
+ glMultiTexCoord2dARB=glMultiTexCoord2dARB @424
+ glMultiTexCoord2dvARB=glMultiTexCoord2dvARB @425
+ glMultiTexCoord2fARB=glMultiTexCoord2fARB @426
+ glMultiTexCoord2fvARB=glMultiTexCoord2fvARB @427
+ glMultiTexCoord2iARB=glMultiTexCoord2iARB @428
+ glMultiTexCoord2ivARB=glMultiTexCoord2ivARB @429
+ glMultiTexCoord2sARB=glMultiTexCoord2sARB @430
+ glMultiTexCoord2svARB=glMultiTexCoord2svARB @431
+ glMultiTexCoord3dARB=glMultiTexCoord3dARB @432
+ glMultiTexCoord3dvARB=glMultiTexCoord3dvARB @433
+ glMultiTexCoord3fARB=glMultiTexCoord3fARB @434
+ glMultiTexCoord3fvARB=glMultiTexCoord3fvARB @435
+ glMultiTexCoord3iARB=glMultiTexCoord3iARB @436
+ glMultiTexCoord3ivARB=glMultiTexCoord3ivARB @437
+ glMultiTexCoord3sARB=glMultiTexCoord3sARB @438
+ glMultiTexCoord3svARB=glMultiTexCoord3svARB @439
+ glMultiTexCoord4dARB=glMultiTexCoord4dARB @440
+ glMultiTexCoord4dvARB=glMultiTexCoord4dvARB @441
+ glMultiTexCoord4fARB=glMultiTexCoord4fARB @442
+ glMultiTexCoord4fvARB=glMultiTexCoord4fvARB @443
+ glMultiTexCoord4iARB=glMultiTexCoord4iARB @444
+ glMultiTexCoord4ivARB=glMultiTexCoord4ivARB @445
+ glMultiTexCoord4sARB=glMultiTexCoord4sARB @446
+ glMultiTexCoord4svARB=glMultiTexCoord4svARB @447
diff --git a/src/mesa/drivers/windows/gldirect/opengl32.ref b/src/mesa/drivers/windows/gldirect/opengl32.ref
new file mode 100644
index 0000000000..2f71faf216
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/opengl32.ref
@@ -0,0 +1,495 @@
+;****************************************************************************
+;*
+;* Mesa 3-D graphics library
+;* Direct3D Driver Interface
+;*
+;* ========================================================================
+;*
+;* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+;*
+;* Permission is hereby granted, free of charge, to any person obtaining a
+;* copy of this software and associated documentation files (the "Software"),
+;* to deal in the Software without restriction, including without limitation
+;* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+;* and/or sell copies of the Software, and to permit persons to whom the
+;* Software is furnished to do so, subject to the following conditions:
+;*
+;* The above copyright notice and this permission notice shall be included
+;* in all copies or substantial portions of the Software.
+;*
+;* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+;* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+;* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+;* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+;* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+;* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+;* SOFTWARE.
+;*
+;* ======================================================================
+;*
+;* Language: ANSI C
+;* Environment: Windows 9x/2000/XP/XBox (Win32)
+;*
+;* Description: DLL Module definition file
+;*
+;****************************************************************************/
+
+DESCRIPTION 'GLDirect'
+
+VERSION 3.0
+
+EXPORTS
+ glAccum
+ glAlphaFunc
+ glAreTexturesResident
+ glArrayElement
+ glBegin
+ glBindTexture
+ glBitmap
+ glBlendFunc
+ glCallList
+ glCallLists
+ glClear
+ glClearAccum
+ glClearIndex
+ glClearColor
+ glClearDepth
+ glClearStencil
+ glClipPlane
+ glColor3b
+ glColor3d
+ glColor3f
+ glColor3i
+ glColor3s
+ glColor3ub
+ glColor3ui
+ glColor3us
+ glColor4b
+ glColor4d
+ glColor4f
+ glColor4i
+ glColor4s
+ glColor4ub
+ glColor4ui
+ glColor4us
+ glColor3bv
+ glColor3dv
+ glColor3fv
+ glColor3iv
+ glColor3sv
+ glColor3ubv
+ glColor3uiv
+ glColor3usv
+ glColor4bv
+ glColor4dv
+ glColor4fv
+ glColor4iv
+ glColor4sv
+ glColor4ubv
+ glColor4uiv
+ glColor4usv
+ glColorMask
+ glColorMaterial
+ glColorPointer
+ glColorTableEXT
+ glColorSubTableEXT
+ glCopyPixels
+ glCopyTexImage1D
+ glCopyTexImage2D
+ glCopyTexSubImage1D
+ glCopyTexSubImage2D
+ glCullFace
+ glDepthFunc
+ glDepthMask
+ glDepthRange
+ glDeleteLists
+ glDeleteTextures
+ glDisable
+ glDisableClientState
+ glDrawArrays
+ glDrawBuffer
+ glDrawElements
+ glDrawPixels
+ glEnable
+ glEnableClientState
+ glEnd
+ glEndList
+ glEvalCoord1d
+ glEvalCoord1f
+ glEvalCoord1dv
+ glEvalCoord1fv
+ glEvalCoord2d
+ glEvalCoord2f
+ glEvalCoord2dv
+ glEvalCoord2fv
+ glEvalPoint1
+ glEvalPoint2
+ glEvalMesh1
+ glEdgeFlag
+ glEdgeFlagv
+ glEdgeFlagPointer
+ glEvalMesh2
+ glFeedbackBuffer
+ glFinish
+ glFlush
+ glFogf
+ glFogi
+ glFogfv
+ glFogiv
+ glFrontFace
+ glFrustum
+ glGenLists
+ glGenTextures
+ glGetBooleanv
+ glGetClipPlane
+ glGetColorTableEXT
+ glGetColorTableParameterivEXT
+ glGetColorTableParameterfvEXT
+ glGetDoublev
+ glGetError
+ glGetFloatv
+ glGetIntegerv
+ glGetLightfv
+ glGetLightiv
+ glGetMapdv
+ glGetMapfv
+ glGetMapiv
+ glGetMaterialfv
+ glGetMaterialiv
+ glGetPixelMapfv
+ glGetPixelMapuiv
+ glGetPixelMapusv
+ glGetPointerv
+ glGetPolygonStipple
+ glGetString
+ glGetTexEnvfv
+ glGetTexEnviv
+ glGetTexGeniv
+ glGetTexGendv
+ glGetTexGenfv
+ glGetTexImage
+ glGetTexLevelParameterfv
+ glGetTexLevelParameteriv
+ glGetTexParameterfv
+ glGetTexParameteriv
+ glHint
+ glIndexd
+ glIndexf
+ glIndexi
+ glIndexs
+ glIndexub
+ glIndexdv
+ glIndexfv
+ glIndexiv
+ glIndexsv
+ glIndexubv
+ glIndexMask
+ glIndexPointer
+ glInterleavedArrays
+ glInitNames
+ glIsList
+ glIsTexture
+ glLightf
+ glLighti
+ glLightfv
+ glLightiv
+ glLightModelf
+ glLightModeli
+ glLightModelfv
+ glLightModeliv
+ glLineWidth
+ glLineStipple
+ glListBase
+ glLoadIdentity
+ glLoadMatrixd
+ glLoadMatrixf
+ glLoadName
+ glLogicOp
+ glMap1d
+ glMap1f
+ glMap2d
+ glMap2f
+ glMapGrid1d
+ glMapGrid1f
+ glMapGrid2d
+ glMapGrid2f
+ glMaterialf
+ glMateriali
+ glMaterialfv
+ glMaterialiv
+ glMatrixMode
+ glMultMatrixd
+ glMultMatrixf
+ glNewList
+ glNormal3b
+ glNormal3d
+ glNormal3f
+ glNormal3i
+ glNormal3s
+ glNormal3bv
+ glNormal3dv
+ glNormal3fv
+ glNormal3iv
+ glNormal3sv
+ glNormalPointer
+ glOrtho
+ glPassThrough
+ glPixelMapfv
+ glPixelMapuiv
+ glPixelMapusv
+ glPixelStoref
+ glPixelStorei
+ glPixelTransferf
+ glPixelTransferi
+ glPixelZoom
+ glPointSize
+ glPolygonMode
+ glPolygonOffset
+ glPolygonOffsetEXT
+ glPolygonStipple
+ glPopAttrib
+ glPopClientAttrib
+ glPopMatrix
+ glPopName
+ glPrioritizeTextures
+ glPushMatrix
+ glRasterPos2d
+ glRasterPos2f
+ glRasterPos2i
+ glRasterPos2s
+ glRasterPos3d
+ glRasterPos3f
+ glRasterPos3i
+ glRasterPos3s
+ glRasterPos4d
+ glRasterPos4f
+ glRasterPos4i
+ glRasterPos4s
+ glRasterPos2dv
+ glRasterPos2fv
+ glRasterPos2iv
+ glRasterPos2sv
+ glRasterPos3dv
+ glRasterPos3fv
+ glRasterPos3iv
+ glRasterPos3sv
+ glRasterPos4dv
+ glRasterPos4fv
+ glRasterPos4iv
+ glRasterPos4sv
+ glReadBuffer
+ glReadPixels
+ glRectd
+ glRectf
+ glRecti
+ glRects
+ glRectdv
+ glRectfv
+ glRectiv
+ glRectsv
+ glScissor
+ glIsEnabled
+ glPushAttrib
+ glPushClientAttrib
+ glPushName
+ glRenderMode
+ glRotated
+ glRotatef
+ glSelectBuffer
+ glScaled
+ glScalef
+ glShadeModel
+ glStencilFunc
+ glStencilMask
+ glStencilOp
+ glTexCoord1d
+ glTexCoord1f
+ glTexCoord1i
+ glTexCoord1s
+ glTexCoord2d
+ glTexCoord2f
+ glTexCoord2i
+ glTexCoord2s
+ glTexCoord3d
+ glTexCoord3f
+ glTexCoord3i
+ glTexCoord3s
+ glTexCoord4d
+ glTexCoord4f
+ glTexCoord4i
+ glTexCoord4s
+ glTexCoord1dv
+ glTexCoord1fv
+ glTexCoord1iv
+ glTexCoord1sv
+ glTexCoord2dv
+ glTexCoord2fv
+ glTexCoord2iv
+ glTexCoord2sv
+ glTexCoord3dv
+ glTexCoord3fv
+ glTexCoord3iv
+ glTexCoord3sv
+ glTexCoord4dv
+ glTexCoord4fv
+ glTexCoord4iv
+ glTexCoord4sv
+ glTexCoordPointer
+ glTexGend
+ glTexGenf
+ glTexGeni
+ glTexGendv
+ glTexGeniv
+ glTexGenfv
+ glTexEnvf
+ glTexEnvi
+ glTexEnvfv
+ glTexEnviv
+ glTexImage1D
+ glTexImage2D
+ glTexParameterf
+ glTexParameteri
+ glTexParameterfv
+ glTexParameteriv
+ glTexSubImage1D
+ glTexSubImage2D
+ glTranslated
+ glTranslatef
+ glVertex2d
+ glVertex2f
+ glVertex2i
+ glVertex2s
+ glVertex3d
+ glVertex3f
+ glVertex3i
+ glVertex3s
+ glVertex4d
+ glVertex4f
+ glVertex4i
+ glVertex4s
+ glVertex2dv
+ glVertex2fv
+ glVertex2iv
+ glVertex2sv
+ glVertex3dv
+ glVertex3fv
+ glVertex3iv
+ glVertex3sv
+ glVertex4dv
+ glVertex4fv
+ glVertex4iv
+ glVertex4sv
+ glVertexPointer
+ glViewport
+
+ glBlendEquationEXT
+ glBlendColorEXT
+ glVertexPointerEXT
+ glNormalPointerEXT
+ glColorPointerEXT
+ glIndexPointerEXT
+ glTexCoordPointerEXT
+ glEdgeFlagPointerEXT
+ glGetPointervEXT
+ glArrayElementEXT
+ glDrawArraysEXT
+ glBindTextureEXT
+ glDeleteTexturesEXT
+ glGenTexturesEXT
+ glPrioritizeTexturesEXT
+ glCopyTexSubImage3DEXT
+ glTexImage3DEXT
+ glTexSubImage3DEXT
+
+ glWindowPos4fMESA
+ glWindowPos2iMESA
+ glWindowPos2sMESA
+ glWindowPos2fMESA
+ glWindowPos2dMESA
+ glWindowPos2ivMESA
+ glWindowPos2svMESA
+ glWindowPos2fvMESA
+ glWindowPos2dvMESA
+ glWindowPos3iMESA
+ glWindowPos3sMESA
+ glWindowPos3fMESA
+ glWindowPos3dMESA
+ glWindowPos3ivMESA
+ glWindowPos3svMESA
+ glWindowPos3fvMESA
+ glWindowPos3dvMESA
+ glWindowPos4iMESA
+ glWindowPos4sMESA
+ glWindowPos4dMESA
+ glWindowPos4ivMESA
+ glWindowPos4svMESA
+ glWindowPos4fvMESA
+ glWindowPos4dvMESA
+ glResizeBuffersMESA
+
+ wglCopyContext
+ wglCreateContext
+ wglCreateLayerContext
+ wglDeleteContext
+ wglDescribeLayerPlane
+ wglGetCurrentContext
+ wglGetCurrentDC
+ wglGetLayerPaletteEntries
+ wglGetProcAddress
+ wglMakeCurrent
+ wglRealizeLayerPalette
+ wglSetLayerPaletteEntries
+ wglShareLists
+ wglSwapLayerBuffers
+ wglUseFontBitmapsA
+ wglUseFontBitmapsW
+ wglUseFontOutlinesA
+ wglUseFontOutlinesW
+
+;These functions are identical and therefore share the same addresses
+ ChoosePixelFormat = wglChoosePixelFormat
+ DescribePixelFormat = wglDescribePixelFormat
+ GetPixelFormat = wglGetPixelFormat
+ SetPixelFormat = wglSetPixelFormat
+ SwapBuffers = wglSwapBuffers
+
+ wglChoosePixelFormat
+ wglDescribePixelFormat
+ wglGetPixelFormat
+ wglSetPixelFormat
+ wglSwapBuffers
+
+ glActiveTextureARB
+ glClientActiveTextureARB
+ glMultiTexCoord1dARB
+ glMultiTexCoord1dvARB
+ glMultiTexCoord1fARB
+ glMultiTexCoord1fvARB
+ glMultiTexCoord1iARB
+ glMultiTexCoord1ivARB
+ glMultiTexCoord1sARB
+ glMultiTexCoord1svARB
+ glMultiTexCoord2dARB
+ glMultiTexCoord2dvARB
+ glMultiTexCoord2fARB
+ glMultiTexCoord2fvARB
+ glMultiTexCoord2iARB
+ glMultiTexCoord2ivARB
+ glMultiTexCoord2sARB
+ glMultiTexCoord2svARB
+ glMultiTexCoord3dARB
+ glMultiTexCoord3dvARB
+ glMultiTexCoord3fARB
+ glMultiTexCoord3fvARB
+ glMultiTexCoord3iARB
+ glMultiTexCoord3ivARB
+ glMultiTexCoord3sARB
+ glMultiTexCoord3svARB
+ glMultiTexCoord4dARB
+ glMultiTexCoord4dvARB
+ glMultiTexCoord4fARB
+ glMultiTexCoord4fvARB
+ glMultiTexCoord4iARB
+ glMultiTexCoord4ivARB
+ glMultiTexCoord4sARB
+ glMultiTexCoord4svARB
diff --git a/src/mesa/drivers/windows/gldirect/pixpack.h b/src/mesa/drivers/windows/gldirect/pixpack.h
new file mode 100644
index 0000000000..ec848d455b
--- /dev/null
+++ b/src/mesa/drivers/windows/gldirect/pixpack.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+*
+* Mesa 3-D graphics library
+* Direct3D Driver Interface
+*
+* ========================================================================
+*
+* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* ======================================================================
+*
+* Language: ANSI C
+* Environment: Windows 9x (Win32)
+*
+* Description: Pixel packing functions.
+*
+****************************************************************************/
+
+#ifndef __PIXPACK_H
+#define __PIXPACK_H
+
+#include <GL\gl.h>
+#include <ddraw.h>
+
+#include "ddlog.h"
+
+/*---------------------- Macros and type definitions ----------------------*/
+
+#define PXAPI
+
+// Typedef that can be used for pixel packing function pointers.
+#define PX_PACK_FUNC(a) void PXAPI (a)(unsigned char *pixdata, void *dst, GLenum Format, const LPDDSURFACEDESC2 lpDDSD2)
+typedef void (PXAPI *PX_packFunc)(unsigned char *pixdata, void *dst, GLenum Format, const LPDDSURFACEDESC2 lpDDSD2);
+
+// Typedef that can be used for pixel unpacking function pointers.
+#define PX_UNPACK_FUNC(a) void PXAPI (a)(unsigned char *pixdata, void *src, GLenum Format, const LPDDSURFACEDESC2 lpDDSD2)
+typedef void (PXAPI *PX_unpackFunc)(unsigned char *pixdata, void *src, GLenum Format, const LPDDSURFACEDESC2 lpDDSD2);
+
+// Typedef that can be used for pixel span packing function pointers.
+#define PX_PACK_SPAN_FUNC(a) void PXAPI (a)(GLuint n, unsigned char *pixdata, unsigned char *dst, GLenum Format, const LPDDSURFACEDESC2 lpDDSD2)
+typedef void (PXAPI *PX_packSpanFunc)(GLuint n, unsigned char *pixdata, unsigned char *dst, GLenum Format, const LPDDSURFACEDESC2 lpDDSD2);
+
+/*------------------------- Function Prototypes ---------------------------*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Function that examines a pixel format and returns the relevent
+// pixel-packing function
+void PXAPI pxClassifyPixelFormat(const LPDDPIXELFORMAT lpddpf, PX_packFunc *lpPackFn ,PX_unpackFunc *lpUnpackFn, PX_packSpanFunc *lpPackSpanFn);
+
+// Packing functions
+PX_PACK_FUNC(pxPackGeneric);
+PX_PACK_FUNC(pxPackRGB555);
+PX_PACK_FUNC(pxPackARGB4444);
+PX_PACK_FUNC(pxPackARGB1555);
+PX_PACK_FUNC(pxPackRGB565);
+PX_PACK_FUNC(pxPackRGB332);
+PX_PACK_FUNC(pxPackRGB888);
+PX_PACK_FUNC(pxPackARGB8888);
+PX_PACK_FUNC(pxPackPAL8);
+
+// Unpacking functions
+PX_UNPACK_FUNC(pxUnpackGeneric);
+PX_UNPACK_FUNC(pxUnpackRGB555);
+PX_UNPACK_FUNC(pxUnpackARGB4444);
+PX_UNPACK_FUNC(pxUnpackARGB1555);
+PX_UNPACK_FUNC(pxUnpackRGB565);
+PX_UNPACK_FUNC(pxUnpackRGB332);
+PX_UNPACK_FUNC(pxUnpackRGB888);
+PX_UNPACK_FUNC(pxUnpackARGB8888);
+PX_UNPACK_FUNC(pxUnpackPAL8);
+
+// Span Packing functions
+PX_PACK_SPAN_FUNC(pxPackSpanGeneric);
+PX_PACK_SPAN_FUNC(pxPackSpanRGB555);
+PX_PACK_SPAN_FUNC(pxPackSpanARGB4444);
+PX_PACK_SPAN_FUNC(pxPackSpanARGB1555);
+PX_PACK_SPAN_FUNC(pxPackSpanRGB565);
+PX_PACK_SPAN_FUNC(pxPackSpanRGB332);
+PX_PACK_SPAN_FUNC(pxPackSpanRGB888);
+PX_PACK_SPAN_FUNC(pxPackSpanARGB8888);
+PX_PACK_SPAN_FUNC(pxPackSpanPAL8);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif