1 /****************************************************************************
3 * Mesa 3-D graphics library
4 * Direct3D Driver Interface
6 * ========================================================================
8 * Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
25 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 * ======================================================================
31 * Environment: Windows 9x (Win32)
33 * Description: OpenGL window functions (wgl*).
35 ****************************************************************************/
39 #include "gld_driver.h"
42 #include "glu.h" // MUST USE MICROSOFT'S GLU32!
45 extern DGL_mesaFuncs mesaFuncs
;
48 // Need to export wgl* functions if using GLD3,
49 // otherwise export GLD2 DGL_* functions.
51 #define _GLD_WGL_EXPORT(a) wgl##a
53 #define _GLD_WGL_EXPORT(a) DGL_##a
56 // Calls into Mesa 4.x are different
62 // NOTE: All the _GLD* macros now call the gl* functions direct.
63 // This ensures that the correct internal pathway is taken. KeithH
64 #define _GLD_glNewList glNewList
65 #define _GLD_glBitmap glBitmap
66 #define _GLD_glEndList glEndList
67 #define _GLD_glDeleteLists glDeleteLists
68 #define _GLD_glGetError glGetError
69 #define _GLD_glTranslatef glTranslatef
70 #define _GLD_glBegin glBegin
71 #define _GLD_glVertex2fv glVertex2fv
72 #define _GLD_glEnd glEnd
73 #define _GLD_glNormal3f glNormal3f
74 #define _GLD_glVertex3f glVertex3f
75 #define _GLD_glVertex3fv glVertex3fv
76 #else // _USE_GLD3_WGL
77 #define _GLD_glNewList (*mesaFuncs.glNewList)
78 #define _GLD_glBitmap (*mesaFuncs.glBitmap)
79 #define _GLD_glEndList (*mesaFuncs.glEndList)
80 #define _GLD_glDeleteLists (*mesaFuncs.glDeleteLists)
81 #define _GLD_glGetError (*mesaFuncs.glGetError)
82 #define _GLD_glTranslatef (*mesaFuncs.glTranslatef)
83 #define _GLD_glBegin (*mesaFuncs.glBegin)
84 #define _GLD_glVertex2fv (*mesaFuncs.glVertex2fv)
85 #define _GLD_glEnd (*mesaFuncs.glEnd)
86 #define _GLD_glNormal3f (*mesaFuncs.glNormal3f)
87 #define _GLD_glVertex3f (*mesaFuncs.glVertex3f)
88 #define _GLD_glVertex3fv (*mesaFuncs.glVertex3fv)
89 #endif // _USE_GLD3_WGL
91 // ***********************************************************************
93 // Emulate SGI DDK calls.
94 #define __wglMalloc(a) GlobalAlloc(GPTR, (a))
95 #define __wglFree(a) GlobalFree((a))
97 // ***********************************************************************
99 // Mesa glu.h and MS glu.h call these different things...
100 //#define GLUtesselator GLUtriangulatorObj
101 //#define GLU_TESS_VERTEX_DATA GLU_VERTEX_DATA
103 // For wglFontOutlines
105 typedef GLUtesselator
*(APIENTRY
*gluNewTessProto
)(void);
106 typedef void (APIENTRY
*gluDeleteTessProto
)(GLUtesselator
*tess
);
107 typedef void (APIENTRY
*gluTessBeginPolygonProto
)(GLUtesselator
*tess
, void *polygon_data
);
108 typedef void (APIENTRY
*gluTessBeginContourProto
)(GLUtesselator
*tess
);
109 typedef void (APIENTRY
*gluTessVertexProto
)(GLUtesselator
*tess
, GLdouble coords
[3], void *data
);
110 typedef void (APIENTRY
*gluTessEndContourProto
)(GLUtesselator
*tess
);
111 typedef void (APIENTRY
*gluTessEndPolygonProto
)(GLUtesselator
*tess
);
112 typedef void (APIENTRY
*gluTessPropertyProto
)(GLUtesselator
*tess
, GLenum which
, GLdouble value
);
113 typedef void (APIENTRY
*gluTessNormalProto
)(GLUtesselator
*tess
, GLdouble x
, GLdouble y
, GLdouble z
);
114 typedef void (APIENTRY
*gluTessCallbackProto
)(GLUtesselator
*tess
, GLenum which
, void (CALLBACK
*)());
116 static HINSTANCE gluModuleHandle
;
117 static gluNewTessProto gluNewTessProc
;
118 static gluDeleteTessProto gluDeleteTessProc
;
119 static gluTessBeginPolygonProto gluTessBeginPolygonProc
;
120 static gluTessBeginContourProto gluTessBeginContourProc
;
121 static gluTessVertexProto gluTessVertexProc
;
122 static gluTessEndContourProto gluTessEndContourProc
;
123 static gluTessEndPolygonProto gluTessEndPolygonProc
;
124 static gluTessPropertyProto gluTessPropertyProc
;
125 static gluTessNormalProto gluTessNormalProc
;
126 static gluTessCallbackProto gluTessCallbackProc
;
128 static HFONT hNewFont
, hOldFont
;
129 static FLOAT ScaleFactor
;
131 #define LINE_BUF_QUANT 4000
132 #define VERT_BUF_QUANT 4000
134 static FLOAT
* LineBuf
;
135 static DWORD LineBufSize
;
136 static DWORD LineBufIndex
;
137 static FLOAT
* VertBuf
;
138 static DWORD VertBufSize
;
139 static DWORD VertBufIndex
;
140 static GLenum TessErrorOccurred
;
142 static int AppendToLineBuf(
145 static int AppendToVertBuf(
148 static int DrawGlyph(
151 FLOAT chordalDeviation
,
155 static void FreeLineBuf(void);
157 static void FreeVertBuf(void);
162 static long GetDWord(
165 static double GetFixed(
168 static int InitLineBuf(void);
170 static int InitVertBuf(void);
172 static HFONT
CreateHighResolutionFont(
175 static int MakeDisplayListFromGlyph(
179 LPGLYPHMETRICSFLOAT glyphMetricsFloat
,
180 FLOAT chordalDeviation
,
184 static BOOL
LoadGLUTesselator(void);
185 static BOOL
UnloadGLUTesselator(void);
187 static int MakeLinesFromArc(
194 DWORD vertexCountIndex
,
195 FLOAT chordalDeviationSquared
);
197 static int MakeLinesFromGlyph( UCHAR
* glyphBuf
,
199 FLOAT chordalDeviation
);
201 static int MakeLinesFromTTLine( UCHAR
** pp
,
202 DWORD vertexCountIndex
,
205 static int MakeLinesFromTTPolycurve( UCHAR
** pp
,
206 DWORD vertexCountIndex
,
207 FLOAT chordalDeviation
);
209 static int MakeLinesFromTTPolygon( UCHAR
** pp
,
210 FLOAT chordalDeviation
);
212 static int MakeLinesFromTTQSpline( UCHAR
** pp
,
213 DWORD vertexCountIndex
,
215 FLOAT chordalDeviation
);
217 static void CALLBACK
TessCombine( double coords
[3],
218 void* vertex_data
[4],
222 static void CALLBACK
TessError( GLenum error
);
224 static void CALLBACK
TessVertexOutData( FLOAT p
[3],
227 // ***********************************************************************
230 #pragma message("compiling DGLWGL.C vars for multi-threaded support")
231 extern CRITICAL_SECTION CriticalSection
;
232 extern DWORD dwTLSPixelFormat
; // TLS index for current pixel format
234 int curPFD
= 0; // Current PFD (static)
236 // ***********************************************************************
238 int dglGetPixelFormat(void)
242 // get thread-specific instance
243 if (glb
.bMultiThreaded
) {
245 iPixelFormat
= (int)TlsGetValue(dwTLSPixelFormat
);
247 __except(EXCEPTION_EXECUTE_HANDLER
) {
248 iPixelFormat
= curPFD
;
251 // get global static var
253 iPixelFormat
= curPFD
;
261 // ***********************************************************************
263 void dglSetPixelFormat(int iPixelFormat
)
266 // set thread-specific instance
267 if (glb
.bMultiThreaded
) {
269 TlsSetValue(dwTLSPixelFormat
, (LPVOID
)iPixelFormat
);
271 __except(EXCEPTION_EXECUTE_HANDLER
) {
272 curPFD
= iPixelFormat
;
275 // set global static var
277 curPFD
= iPixelFormat
;
280 curPFD
= iPixelFormat
;
284 // ***********************************************************************
286 int APIENTRY
_GLD_WGL_EXPORT(ChoosePixelFormat
)(
288 CONST PIXELFORMATDESCRIPTOR
*ppfd
)
290 DGL_pixelFormat
*lpPF
= glb
.lpPF
;
292 PIXELFORMATDESCRIPTOR ppfdBest
;
308 PFD_NEED_SYSTEM_PALETTE
|
311 /*PFD_SWAP_LAYER_BUFFERS |*/
312 PFD_DOUBLEBUFFER_DONTCARE
|
313 PFD_STEREO_DONTCARE
|
316 PFD_GENERIC_ACCELERATED
|
323 // List may not be built until dglValidate() is called! KeithH
327 // Lets print the input pixel format to the log
328 // ** Based on "wglinfo" by Nate Robins **
330 ddlogMessage(DDLOG_SYSTEM
, "ChoosePixelFormat:\n");
331 ddlogMessage(DDLOG_INFO
, "Input pixel format for ChoosePixelFormat:\n");
332 ddlogMessage(DDLOG_INFO
,
333 " visual x bf lv rg d st r g b a ax dp st accum buffs ms\n");
334 ddlogMessage(DDLOG_INFO
,
335 " id dep cl sp sz l ci b ro sz sz sz sz bf th cl r g b a ns b\n");
336 ddlogMessage(DDLOG_INFO
,
337 "-----------------------------------------------------------------\n");
340 sprintf(cat
, "%2d ", ppfd
->cColorBits
);
342 if(ppfd
->dwFlags
& PFD_DRAW_TO_WINDOW
) sprintf(cat
, "wn ");
343 else if(ppfd
->dwFlags
& PFD_DRAW_TO_BITMAP
) sprintf(cat
, "bm ");
344 else sprintf(cat
, ". ");
347 /* should find transparent pixel from LAYERPLANEDESCRIPTOR */
351 sprintf(cat
, "%2d ", ppfd
->cColorBits
);
354 /* bReserved field indicates number of over/underlays */
355 if(ppfd
->bReserved
) sprintf(cat
, " %d ", ppfd
->bReserved
);
356 else sprintf(cat
, " . ");
359 sprintf(cat
, " %c ", ppfd
->iPixelType
== PFD_TYPE_RGBA
? 'r' : 'c');
362 sprintf(cat
, "%c ", ppfd
->dwFlags
& PFD_DOUBLEBUFFER
? 'y' : '.');
365 sprintf(cat
, " %c ", ppfd
->dwFlags
& PFD_STEREO
? 'y' : '.');
368 if(ppfd
->cRedBits
&& ppfd
->iPixelType
== PFD_TYPE_RGBA
)
369 sprintf(cat
, "%2d ", ppfd
->cRedBits
);
370 else sprintf(cat
, " . ");
373 if(ppfd
->cGreenBits
&& ppfd
->iPixelType
== PFD_TYPE_RGBA
)
374 sprintf(cat
, "%2d ", ppfd
->cGreenBits
);
375 else sprintf(cat
, " . ");
378 if(ppfd
->cBlueBits
&& ppfd
->iPixelType
== PFD_TYPE_RGBA
)
379 sprintf(cat
, "%2d ", ppfd
->cBlueBits
);
380 else sprintf(cat
, " . ");
383 if(ppfd
->cAlphaBits
&& ppfd
->iPixelType
== PFD_TYPE_RGBA
)
384 sprintf(cat
, "%2d ", ppfd
->cAlphaBits
);
385 else sprintf(cat
, " . ");
388 if(ppfd
->cAuxBuffers
) sprintf(cat
, "%2d ", ppfd
->cAuxBuffers
);
389 else sprintf(cat
, " . ");
392 if(ppfd
->cDepthBits
) sprintf(cat
, "%2d ", ppfd
->cDepthBits
);
393 else sprintf(cat
, " . ");
396 if(ppfd
->cStencilBits
) sprintf(cat
, "%2d ", ppfd
->cStencilBits
);
397 else sprintf(cat
, " . ");
400 if(ppfd
->cAccumRedBits
) sprintf(cat
, "%2d ", ppfd
->cAccumRedBits
);
401 else sprintf(cat
, " . ");
404 if(ppfd
->cAccumGreenBits
) sprintf(cat
, "%2d ", ppfd
->cAccumGreenBits
);
405 else sprintf(cat
, " . ");
408 if(ppfd
->cAccumBlueBits
) sprintf(cat
, "%2d ", ppfd
->cAccumBlueBits
);
409 else sprintf(cat
, " . ");
412 if(ppfd
->cAccumAlphaBits
) sprintf(cat
, "%2d ", ppfd
->cAccumAlphaBits
);
413 else sprintf(cat
, " . ");
416 /* no multisample in Win32 */
417 sprintf(cat
, " . .\n");
420 ddlogMessage(DDLOG_INFO
, buf
);
421 ddlogMessage(DDLOG_INFO
,
422 "-----------------------------------------------------------------\n");
423 ddlogMessage(DDLOG_INFO
, "\n");
426 // Examine the flags for correctness
428 dwFlags
= ppfd
->dwFlags
;
429 if (dwFlags
!= (dwFlags
& dwAllFlags
))
431 /* error: bad dwFlags */
432 ddlogPrintf(DDLOG_WARN
,
433 "ChoosePixelFormat: bad flags (0x%x)",
434 dwFlags
& (~dwAllFlags
));
435 // Mask illegal flags and continue
436 dwFlags
= dwFlags
& dwAllFlags
;
439 switch (ppfd
->iPixelType
) {
441 case PFD_TYPE_COLORINDEX
:
444 /* error: bad iPixelType */
445 ddlogMessage(DDLOG_WARN
, "ChoosePixelFormat: bad pixel type\n");
449 switch (ppfd
->iLayerType
) {
451 case PFD_OVERLAY_PLANE
:
452 case PFD_UNDERLAY_PLANE
:
455 /* error: bad iLayerType */
456 ddlogMessage(DDLOG_WARN
, "ChoosePixelFormat: bad layer type\n");
460 numPixelFormats
= glb
.nPixelFormatCount
;
462 /* loop through candidate pixel format descriptors */
463 for (i
=0; i
<numPixelFormats
; ++i
) {
464 PIXELFORMATDESCRIPTOR ppfdCandidate
;
466 memcpy(&ppfdCandidate
, &lpPF
[i
].pfd
, sizeof(PIXELFORMATDESCRIPTOR
));
469 ** Check attributes which must match
471 if (ppfd
->iPixelType
!= ppfdCandidate
.iPixelType
) {
475 if (ppfd
->iLayerType
!= ppfdCandidate
.iLayerType
) {
479 if (((dwFlags
^ ppfdCandidate
.dwFlags
) & dwFlags
) &
480 (PFD_DRAW_TO_WINDOW
| PFD_DRAW_TO_BITMAP
|
481 PFD_SUPPORT_GDI
| PFD_SUPPORT_OPENGL
))
486 if (!(dwFlags
& PFD_DOUBLEBUFFER_DONTCARE
)) {
487 if ((dwFlags
& PFD_DOUBLEBUFFER
) !=
488 (ppfdCandidate
.dwFlags
& PFD_DOUBLEBUFFER
))
494 // if (!(dwFlags & PFD_STEREO_DONTCARE)) {
495 if ((dwFlags
& PFD_STEREO
) !=
496 (ppfdCandidate
.dwFlags
& PFD_STEREO
))
502 if (ppfd
->iPixelType
==PFD_TYPE_RGBA
503 && ppfd
->cAlphaBits
&& !ppfdCandidate
.cAlphaBits
) {
507 if (ppfd
->iPixelType
==PFD_TYPE_RGBA
508 && ppfd
->cAccumBits
&& !ppfdCandidate
.cAccumBits
) {
512 if (ppfd
->cDepthBits
&& !ppfdCandidate
.cDepthBits
) {
516 if (ppfd
->cStencilBits
&& !ppfdCandidate
.cStencilBits
) {
520 if (ppfd
->cAuxBuffers
&& !ppfdCandidate
.cAuxBuffers
) {
525 ** See if candidate is better than the previous best choice
527 if (bestIndex
== -1) {
528 ppfdBest
= ppfdCandidate
;
533 if ((ppfd
->cColorBits
> ppfdBest
.cColorBits
&&
534 ppfdCandidate
.cColorBits
> ppfdBest
.cColorBits
) ||
535 (ppfd
->cColorBits
<= ppfdCandidate
.cColorBits
&&
536 ppfdCandidate
.cColorBits
< ppfdBest
.cColorBits
))
538 ppfdBest
= ppfdCandidate
;
543 if (ppfd
->iPixelType
==PFD_TYPE_RGBA
545 && ppfdCandidate
.cAlphaBits
> ppfdBest
.cAlphaBits
)
547 ppfdBest
= ppfdCandidate
;
552 if (ppfd
->iPixelType
==PFD_TYPE_RGBA
554 && ppfdCandidate
.cAccumBits
> ppfdBest
.cAccumBits
)
556 ppfdBest
= ppfdCandidate
;
561 if ((ppfd
->cDepthBits
> ppfdBest
.cDepthBits
&&
562 ppfdCandidate
.cDepthBits
> ppfdBest
.cDepthBits
) ||
563 (ppfd
->cDepthBits
<= ppfdCandidate
.cDepthBits
&&
564 ppfdCandidate
.cDepthBits
< ppfdBest
.cDepthBits
))
566 ppfdBest
= ppfdCandidate
;
571 if (ppfd
->cStencilBits
&&
572 ppfdCandidate
.cStencilBits
> ppfdBest
.cStencilBits
)
574 ppfdBest
= ppfdCandidate
;
579 if (ppfd
->cAuxBuffers
&&
580 ppfdCandidate
.cAuxBuffers
> ppfdBest
.cAuxBuffers
)
582 ppfdBest
= ppfdCandidate
;
588 if (bestIndex
!= -1) {
589 ddlogPrintf(DDLOG_SYSTEM
, "Pixel Format %d chosen as best match", bestIndex
+1);
590 return bestIndex
+ 1;
593 // Return the pixelformat that has the most capabilities.
594 // ** NOTE: This is only possible due to the way the list
595 // of pixelformats is built. **
596 // Now picks best pixelformat. KeithH
597 bestIndex
= numPixelFormats
; // most capable double buffer format
598 ddlogPrintf(DDLOG_SYSTEM
, "Pixel Format %d chosen by default", bestIndex
);
602 // ***********************************************************************
604 BOOL APIENTRY
_GLD_WGL_EXPORT(CopyContext
)(
612 UNSUPPORTED("wglCopyContext")
613 return FALSE
; // Failed
616 // ***********************************************************************
618 HGLRC APIENTRY
_GLD_WGL_EXPORT(CreateContext
)(
627 // Check that the current PFD is valid
628 ipf
= dglGetPixelFormat();
629 if (!IsValidPFD(ipf
))
632 return dglCreateContext(a
, &glb
.lpPF
[ipf
-1]);
635 // ***********************************************************************
637 HGLRC APIENTRY
_GLD_WGL_EXPORT(CreateLayerContext
)(
645 UNSUPPORTED("wglCreateLayerContext")
646 return NULL
; // Failed
649 // ***********************************************************************
651 BOOL APIENTRY
_GLD_WGL_EXPORT(DeleteContext
)(
658 return dglDeleteContext(a
);
661 // ***********************************************************************
663 BOOL APIENTRY
_GLD_WGL_EXPORT(DescribeLayerPlane
)(
668 LPLAYERPLANEDESCRIPTOR plpd
)
674 UNSUPPORTED("DGL_DescribeLayerPlane")
676 // gldLogPrintf(GLDLOG_INFO, "DescribeLayerPlane: %d, %d", iPixelFormat, iLayerPlane);
681 // ***********************************************************************
683 int APIENTRY
_GLD_WGL_EXPORT(DescribePixelFormat
)(
687 LPPIXELFORMATDESCRIPTOR d
)
695 if (d
== NULL
) // Calling app requires max number of PF's
696 return glb
.nPixelFormatCount
;
698 // The supplied buffer may be larger than the info that we
700 if (c
> sizeof(PIXELFORMATDESCRIPTOR
))
701 nSize
= sizeof(PIXELFORMATDESCRIPTOR
);
705 // Setup an empty PFD before doing validation check
711 return 0; // Bail if PFD index is invalid
713 memcpy(d
, &glb
.lpPF
[b
-1].pfd
, nSize
);
715 return glb
.nPixelFormatCount
;
718 // ***********************************************************************
720 HGLRC APIENTRY
_GLD_WGL_EXPORT(GetCurrentContext
)(void)
726 return dglGetCurrentContext();
729 // ***********************************************************************
731 HDC APIENTRY
_GLD_WGL_EXPORT(GetCurrentDC
)(void)
737 return dglGetCurrentDC();
740 // ***********************************************************************
742 PROC APIENTRY
_GLD_WGL_EXPORT(GetDefaultProcAddress
)(
749 UNSUPPORTED("DGL_GetDefaultProcAddress")
753 // ***********************************************************************
755 int APIENTRY
_GLD_WGL_EXPORT(GetLayerPaletteEntries
)(
766 UNSUPPORTED("DGL_GetLayerPaletteEntries")
770 // ***********************************************************************
772 int APIENTRY
_GLD_WGL_EXPORT(GetPixelFormat
)(
779 return dglGetPixelFormat();
782 // ***********************************************************************
784 PROC APIENTRY
_GLD_WGL_EXPORT(GetProcAddress
)(
787 PROC
dglGetProcAddressD3D(LPCSTR a
);
794 return _gldDriver
.wglGetProcAddress(a
);
796 return dglGetProcAddressD3D(a
);
800 // ***********************************************************************
802 BOOL APIENTRY
_GLD_WGL_EXPORT(MakeCurrent
)(
810 return dglMakeCurrent(a
, b
);
813 // ***********************************************************************
815 BOOL APIENTRY
_GLD_WGL_EXPORT(RealizeLayerPalette
)(
824 UNSUPPORTED("DGL_RealizeLayerPalette")
828 // ***********************************************************************
830 int APIENTRY
_GLD_WGL_EXPORT(SetLayerPaletteEntries
)(
841 UNSUPPORTED("DGL_SetLayerPaletteEntries")
845 // ***********************************************************************
847 BOOL APIENTRY
_GLD_WGL_EXPORT(SetPixelFormat
)(
850 CONST PIXELFORMATDESCRIPTOR
*c
)
857 ddlogPrintf(DDLOG_SYSTEM
, "SetPixelFormat: PixelFormat %d has been set", b
);
858 dglSetPixelFormat(b
);
861 ddlogPrintf(DDLOG_ERROR
,
862 "SetPixelFormat: PixelFormat %d is invalid and cannot be set", b
);
867 // ***********************************************************************
869 * Share lists between two gl_context structures.
870 * This was added for WIN32 WGL function support, since wglShareLists()
871 * must be called *after* wglCreateContext() with valid GLRCs. (DaveM)
874 // Copied from GLD2.x. KeithH
876 static GLboolean
_gldShareLists(
880 /* Sanity check context pointers */
881 if (ctx1
== NULL
|| ctx2
== NULL
)
883 /* Sanity check shared list pointers */
884 if (ctx1
->Shared
== NULL
|| ctx2
->Shared
== NULL
)
886 /* Decrement reference count on sharee to release previous list */
887 ctx2
->Shared
->RefCount
--;
888 #if 0 /* 3DStudio exits on this memory release */
889 if (ctx2
->Shared
->RefCount
== 0)
890 free_shared_state(ctx2
, ctx2
->Shared
);
892 /* Re-assign list from sharer to sharee and increment reference count */
893 ctx2
->Shared
= ctx1
->Shared
;
894 ctx1
->Shared
->RefCount
++;
898 // ***********************************************************************
900 BOOL APIENTRY
_GLD_WGL_EXPORT(ShareLists
)(
904 DGL_ctx
*dgl1
, *dgl2
;
910 // Mesa supports shared lists, but you need to supply the shared
911 // GL context info when calling gl_create_context(). An auxiliary
912 // function gl_share_lists() has been added to update the shared
913 // list info after the GL contexts have been created. (DaveM)
914 dgl1
= dglGetContextAddress(a
);
915 dgl2
= dglGetContextAddress(b
);
916 if (dgl1
->bAllocated
&& dgl2
->bAllocated
) {
918 return _gldShareLists(dgl1
->glCtx
, dgl2
->glCtx
);
920 return (*mesaFuncs
.gl_share_lists
)(dgl1
->glCtx
, dgl2
->glCtx
);
926 // ***********************************************************************
928 BOOL APIENTRY
_GLD_WGL_EXPORT(SwapBuffers
)(
935 return dglSwapBuffers(a
);
938 // ***********************************************************************
940 BOOL APIENTRY
_GLD_WGL_EXPORT(SwapLayerBuffers
)(
948 return dglSwapBuffers(a
);
951 // ***********************************************************************
953 // ***********************************************************************
954 // Note: This ResizeBuffers() function may be called from
955 // either MESA glViewport() or GLD wglMakeCurrent().
957 BOOL
dglWglResizeBuffers(
965 DDSURFACEDESC2 ddsd2
;
967 IDirectDrawClipper
*lpddClipper
= NULL
;
974 struct gl_texture_object
*tObj
;
975 struct gl_texture_image
*image
;
979 BOOL bFullScrnWin
= FALSE
;
980 DDSURFACEDESC2 ddsd2DisplayMode
;
986 GLD_displayMode glddm
;
989 #define DDLOG_CRITICAL_OR_WARN (bDefaultDriver ? DDLOG_WARN : DDLOG_CRITICAL)
998 dgl
= ctx
->DriverCtx
;
1002 // Get the window size and calculate its dimensions
1003 if (dgl
->hWnd
== NULL
) {
1004 // Check for non-window DC = memory DC ?
1005 if (GetClipBox(dgl
->hDC
, &rcScreenRect
) == ERROR
)
1006 SetRect(&rcScreenRect
, 0, 0, 0, 0);
1008 else if (!GetClientRect(dgl
->hWnd
, &rcScreenRect
))
1009 SetRect(&rcScreenRect
, 0, 0, 0, 0);
1010 dwWidth
= rcScreenRect
.right
- rcScreenRect
.left
;
1011 dwHeight
= rcScreenRect
.bottom
- rcScreenRect
.top
;
1012 CopyRect(&dgl
->rcScreenRect
, &rcScreenRect
);
1014 // This will occur on Alt-Tab
1015 if ((dwWidth
== 0) && (dwHeight
== 0)) {
1016 //dgl->bCanRender = FALSE;
1017 return TRUE
; // No resize possible!
1020 // Some apps zero only 1 dimension for non-visible window... (DaveM)
1021 if ((dwWidth
== 0) || (dwHeight
== 0)) {
1026 // Test to see if a resize is required.
1027 // Note that the dimensions will be the same if a prior resize attempt failed.
1028 if ((dwWidth
== dgl
->dwWidth
) && (dwHeight
== dgl
->dwHeight
) && bDefaultDriver
) {
1029 return TRUE
; // No resize required
1032 ddlogPrintf(DDLOG_SYSTEM
, "dglResize: %dx%d", dwWidth
, dwHeight
);
1033 #ifndef _USE_GLD3_WGL
1034 // Work out where we want our surfaces created
1035 dwMemoryType
= (bDefaultDriver
) ? glb
.dwMemoryType
: DDSCAPS_SYSTEMMEMORY
;
1036 #endif // _USE_GLD3_WGL
1038 // Note previous fullscreen vs window display status
1039 bWasFullscreen
= dgl
->bFullscreen
;
1041 #ifdef _USE_GLD3_WGL
1042 if (_gldDriver
.GetDisplayMode(dgl
, &glddm
)) {
1043 if ( (dwWidth
== glddm
.Width
) &&
1044 (dwHeight
== glddm
.Height
) ) {
1045 bFullScrnWin
= TRUE
;
1047 if (bFullScrnWin
&& glb
.bPrimary
&& !glb
.bFullscreenBlit
&& !glb
.bDirectDrawPersistant
) {
1048 dgl
->bFullscreen
= TRUE
;
1049 ddlogMessage(DDLOG_INFO
, "Fullscreen window after resize.\n");
1052 dgl
->bFullscreen
= FALSE
;
1053 ddlogMessage(DDLOG_INFO
, "Non-Fullscreen window after resize.\n");
1055 // Cache the display mode dimensions
1056 dgl
->dwModeWidth
= glddm
.Width
;
1057 dgl
->dwModeHeight
= glddm
.Height
;
1060 // Clamp the effective window dimensions to primary surface.
1061 // We need to do this for D3D viewport dimensions even if wide
1062 // surfaces are supported. This also is a good idea for handling
1063 // whacked-out window dimensions passed for non-drawable windows
1064 // like Solid Edge. (DaveM)
1065 if (dgl
->dwWidth
> glddm
.Width
)
1066 dgl
->dwWidth
= glddm
.Width
;
1067 if (dgl
->dwHeight
> glddm
.Height
)
1068 dgl
->dwHeight
= glddm
.Height
;
1069 #else // _USE_GLD3_WGL
1070 // Window resize may have changed to fullscreen
1071 ZeroMemory(&ddsd2DisplayMode
, sizeof(ddsd2DisplayMode
));
1072 ddsd2DisplayMode
.dwSize
= sizeof(ddsd2DisplayMode
);
1073 hResult
= IDirectDraw4_GetDisplayMode(
1076 if (SUCCEEDED(hResult
)) {
1077 if ( (dwWidth
== ddsd2DisplayMode
.dwWidth
) &&
1078 (dwHeight
== ddsd2DisplayMode
.dwHeight
) ) {
1079 bFullScrnWin
= TRUE
;
1081 if (bFullScrnWin
&& glb
.bPrimary
&& !glb
.bFullscreenBlit
&& !glb
.bDirectDrawPersistant
) {
1082 dgl
->bFullscreen
= TRUE
;
1083 ddlogMessage(DDLOG_INFO
, "Fullscreen window after resize.\n");
1086 dgl
->bFullscreen
= FALSE
;
1087 ddlogMessage(DDLOG_INFO
, "Non-Fullscreen window after resize.\n");
1089 // Cache the display mode dimensions
1090 dgl
->dwModeWidth
= ddsd2DisplayMode
.dwWidth
;
1091 dgl
->dwModeHeight
= ddsd2DisplayMode
.dwHeight
;
1094 // Clamp the effective window dimensions to primary surface.
1095 // We need to do this for D3D viewport dimensions even if wide
1096 // surfaces are supported. This also is a good idea for handling
1097 // whacked-out window dimensions passed for non-drawable windows
1098 // like Solid Edge. (DaveM)
1099 if (dgl
->dwWidth
> ddsd2DisplayMode
.dwWidth
)
1100 dgl
->dwWidth
= ddsd2DisplayMode
.dwWidth
;
1101 if (dgl
->dwHeight
> ddsd2DisplayMode
.dwHeight
)
1102 dgl
->dwHeight
= ddsd2DisplayMode
.dwHeight
;
1103 #endif // _USE_GLD3_WGL
1105 // Note if fullscreen vs window display has changed?
1106 bSaveDesktop
= (!bWasFullscreen
&& !dgl
->bFullscreen
) ? TRUE
: FALSE
;
1107 // Save the desktop primary surface from being destroyed
1108 // whenever remaining in windowed mode, since the stereo mode
1109 // switches are expensive...
1111 #ifndef _USE_GLD3_WGL
1112 // Don't need to re-allocate persistant buffers. (DaveM)
1113 // Though we should clear the back buffers to hide artifacts.
1114 if (glb
.bDirectDrawPersistant
&& glb
.bPersistantBuffers
) {
1115 dgl
->dwWidth
= dwWidth
;
1116 dgl
->dwHeight
= dwHeight
;
1117 ZeroMemory(&ddbltfx
, sizeof(ddbltfx
));
1118 ddbltfx
.dwSize
= sizeof(ddbltfx
);
1119 ddbltfx
.dwFillColor
= dgl
->dwClearColorPF
;
1120 IDirectDrawSurface4_Blt(dgl
->lpBack4
, &rcScreenRect
, NULL
, NULL
,
1121 DDBLT_WAIT
| DDBLT_COLORFILL
, &ddbltfx
);
1125 // Ensure all rendering is complete
1126 if (ctx
->Driver
.Finish
)
1127 (*ctx
->Driver
.Finish
)(ctx
);
1128 if (dgl
->bSceneStarted
== TRUE
) {
1129 IDirect3DDevice3_EndScene(dgl
->lpDev3
);
1130 dgl
->bSceneStarted
= FALSE
;
1132 #endif // _USE_GLD3_WGL
1133 dgl
->bCanRender
= FALSE
;
1136 // Serialize access to DirectDraw and DDS operations
1137 if (glb
.bMultiThreaded
)
1138 EnterCriticalSection(&CriticalSection
);
1141 #ifndef _USE_GLD3_WGL
1142 // Release existing surfaces
1143 RELEASE(dgl
->lpDev3
);
1144 RELEASE(dgl
->lpDepth4
);
1145 RELEASE(dgl
->lpBack4
);
1146 if (glb
.bDirectDrawPersistant
&& glb
.bDirectDrawPrimary
)
1149 RELEASE(dgl
->lpFront4
);
1150 #endif // _USE_GLD3_WGL
1151 dgl
->dwWidth
= dwWidth
;
1152 dgl
->dwHeight
= dwHeight
;
1155 dgl
->dwModeWidth
= dgl
->dwWidth
;
1156 dgl
->dwModeHeight
= dgl
->dwHeight
;
1158 #ifdef _USE_GLD3_WGL
1159 if (!_gldDriver
.ResizeDrawable(dgl
, bDefaultDriver
, glb
.bDirectDrawPersistant
, glb
.bPersistantBuffers
))
1160 goto cleanup_and_return_with_error
;
1161 #else // _USE_GLD3_WGL
1163 if (dgl
->bFullscreen
) {
1168 // Disable warning popups when in fullscreen mode
1169 ddlogWarnOption(FALSE
);
1171 // Have to release the persistant DirectDraw primary surface
1172 // if switching to fullscreen mode. So if application wants
1173 // persistant display in fullscreen mode, a fullscreen-size
1174 // window should be used instead via fullscreen-blit option.
1175 if (glb
.bDirectDrawPersistant
&& glb
.bDirectDrawPrimary
) {
1176 RELEASE(glb
.lpPrimary4
);
1177 glb
.bDirectDrawPrimary
= FALSE
;
1180 dwFlags
= DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
| DDSCL_ALLOWREBOOT
;
1182 dwFlags
|= DDSCL_FPUSETUP
; // optional
1183 hResult
= IDirectDraw4_SetCooperativeLevel(dgl
->lpDD4
, dgl
->hWnd
, dwFlags
);
1184 if (FAILED(hResult
)) {
1185 ddlogError(DDLOG_CRITICAL_OR_WARN
, "dglResize: Unable to set Exclusive Fullscreen mode", hResult
);
1186 goto cleanup_and_return_with_error
;
1189 hResult
= IDirectDraw4_SetDisplayMode(dgl
->lpDD4
,
1195 if (FAILED(hResult
)) {
1196 ddlogError(DDLOG_CRITICAL_OR_WARN
, "dglResize: SetDisplayMode failed", hResult
);
1197 goto cleanup_and_return_with_error
;
1200 // ** The display mode has changed, so dont use MessageBox! **
1202 ZeroMemory(&ddsd2
, sizeof(ddsd2
));
1203 ddsd2
.dwSize
= sizeof(ddsd2
);
1205 if (dgl
->bDoubleBuffer
) {
1208 ddsd2
.dwFlags
= DDSD_CAPS
| DDSD_BACKBUFFERCOUNT
;
1209 ddsd2
.ddsCaps
.dwCaps
= DDSCAPS_PRIMARYSURFACE
|
1214 ddsd2
.dwBackBufferCount
= 1;
1215 hResult
= IDirectDraw4_CreateSurface(dgl
->lpDD4
, &ddsd2
, &dgl
->lpFront4
, NULL
);
1216 if (FAILED(hResult
)) {
1217 ddlogError(DDLOG_CRITICAL_OR_WARN
, "dglResize: CreateSurface (primary) failed", hResult
);
1218 goto cleanup_and_return_with_error
;
1220 // Render target surface
1221 ZeroMemory(&ddscaps2
, sizeof(ddscaps2
)); // Clear the entire struct.
1222 ddscaps2
.dwCaps
= DDSCAPS_BACKBUFFER
;
1223 hResult
= IDirectDrawSurface4_GetAttachedSurface(dgl
->lpFront4
, &ddscaps2
, &dgl
->lpBack4
);
1224 if (FAILED(hResult
)) {
1225 ddlogError(DDLOG_CRITICAL_OR_WARN
, "dglResize: GetAttachedSurface failed", hResult
);
1226 goto cleanup_and_return_with_error
;
1231 ddsd2
.dwFlags
= DDSD_CAPS
;
1232 ddsd2
.ddsCaps
.dwCaps
= DDSCAPS_PRIMARYSURFACE
|
1233 //DDSCAPS_3DDEVICE |
1236 hResult
= IDirectDraw4_CreateSurface(dgl
->lpDD4
, &ddsd2
, &dgl
->lpFront4
, NULL
);
1237 if (FAILED(hResult
)) {
1238 ddlogError(DDLOG_CRITICAL_OR_WARN
, "dglResize: CreateSurface (primary) failed", hResult
);
1239 goto cleanup_and_return_with_error
;
1242 dgl
->lpBack4
= NULL
;
1247 // OK to enable warning popups in windowed mode
1248 ddlogWarnOption(glb
.bMessageBoxWarnings
);
1250 // Ditto if persistant DirectDraw primary
1251 if (glb
.bDirectDrawPersistant
&& glb
.bDirectDrawPrimary
)
1255 dwFlags
= DDSCL_NORMAL
;
1256 if (glb
.bMultiThreaded
)
1257 dwFlags
|= DDSCL_MULTITHREADED
;
1259 dwFlags
|= DDSCL_FPUSETUP
; // optional
1260 hResult
= IDirectDraw4_SetCooperativeLevel(dgl
->lpDD4
,
1263 if (FAILED(hResult
)) {
1264 ddlogError(DDLOG_CRITICAL_OR_WARN
, "dglResize: Unable to set Normal coop level", hResult
);
1265 goto cleanup_and_return_with_error
;
1268 ZeroMemory(&ddsd2
, sizeof(ddsd2
));
1269 ddsd2
.dwSize
= sizeof(ddsd2
);
1270 ddsd2
.dwFlags
= DDSD_CAPS
;
1271 ddsd2
.ddsCaps
.dwCaps
= DDSCAPS_PRIMARYSURFACE
;
1272 hResult
= IDirectDraw4_CreateSurface(dgl
->lpDD4
, &ddsd2
, &dgl
->lpFront4
, NULL
);
1273 if (FAILED(hResult
)) {
1274 ddlogError(DDLOG_CRITICAL_OR_WARN
, "dglResize: CreateSurface (primary) failed", hResult
);
1275 goto cleanup_and_return_with_error
;
1278 // Cache the primary surface for persistant DirectDraw state
1279 if (glb
.bDirectDrawPersistant
&& !glb
.bDirectDrawPrimary
) {
1280 glb
.lpPrimary4
= dgl
->lpFront4
;
1281 IDirectDrawSurface4_AddRef(glb
.lpPrimary4
);
1282 glb
.bDirectDrawPrimary
= TRUE
;
1286 hResult
= DirectDrawCreateClipper(0, &lpddClipper
, NULL
);
1287 if (FAILED(hResult
)) {
1288 ddlogError(DDLOG_CRITICAL_OR_WARN
, "dglResize: CreateClipper failed", hResult
);
1289 goto cleanup_and_return_with_error
;
1291 hResult
= IDirectDrawClipper_SetHWnd(lpddClipper
, 0, dgl
->hWnd
);
1292 if (FAILED(hResult
)) {
1293 RELEASE(lpddClipper
);
1294 ddlogError(DDLOG_CRITICAL_OR_WARN
, "dglResize: SetHWnd failed", hResult
);
1295 goto cleanup_and_return_with_error
;
1297 hResult
= IDirectDrawSurface4_SetClipper(dgl
->lpFront4
, lpddClipper
);
1298 RELEASE(lpddClipper
); // We have finished with it.
1299 if (FAILED(hResult
)) {
1300 ddlogError(DDLOG_CRITICAL_OR_WARN
, "dglResize: SetClipper failed", hResult
);
1301 goto cleanup_and_return_with_error
;
1304 // Update the window for the original clipper
1305 if ((glb
.bDirectDrawPersistant
&& glb
.bDirectDrawPrimary
) || bSaveDesktop
) {
1306 IDirectDrawSurface4_GetClipper(dgl
->lpFront4
, &lpddClipper
);
1307 IDirectDrawClipper_SetHWnd(lpddClipper
, 0, dgl
->hWnd
);
1308 RELEASE(lpddClipper
);
1311 if (dgl
->bDoubleBuffer
) {
1312 // Render target surface
1313 ZeroMemory(&ddsd2
, sizeof(ddsd2
));
1314 ddsd2
.dwSize
= sizeof(ddsd2
);
1315 ddsd2
.dwFlags
= DDSD_CAPS
| DDSD_WIDTH
| DDSD_HEIGHT
;
1316 ddsd2
.dwWidth
= dgl
->dwWidth
;
1317 ddsd2
.dwHeight
= dgl
->dwHeight
;
1318 ddsd2
.ddsCaps
.dwCaps
= DDSCAPS_3DDEVICE
|
1319 DDSCAPS_OFFSCREENPLAIN
|
1321 hResult
= IDirectDraw4_CreateSurface(dgl
->lpDD4
, &ddsd2
, &dgl
->lpBack4
, NULL
);
1322 if (FAILED(hResult
)) {
1323 ddlogError(DDLOG_CRITICAL_OR_WARN
, "dglResize: Create Backbuffer failed", hResult
);
1324 goto cleanup_and_return_with_error
;
1328 dgl
->lpBack4
= NULL
;
1333 // Now create the Zbuffer
1335 if (dgl
->bDepthBuffer
) {
1336 // Get z-buffer dimensions from the render target
1337 // Setup the surface desc for the z-buffer.
1338 ZeroMemory(&ddsd2
, sizeof(ddsd2
));
1339 ddsd2
.dwSize
= sizeof(ddsd2
);
1340 ddsd2
.dwFlags
= DDSD_CAPS
| DDSD_WIDTH
| DDSD_HEIGHT
| DDSD_PIXELFORMAT
;
1341 ddsd2
.ddsCaps
.dwCaps
= DDSCAPS_ZBUFFER
| dwMemoryType
;
1342 ddsd2
.dwWidth
= dgl
->dwWidth
;
1343 ddsd2
.dwHeight
= dgl
->dwHeight
;
1344 memcpy(&ddsd2
.ddpfPixelFormat
,
1345 &glb
.lpZBufferPF
[dgl
->iZBufferPF
],
1346 sizeof(DDPIXELFORMAT
) );
1348 // Create a z-buffer
1349 hResult
= IDirectDraw4_CreateSurface(dgl
->lpDD4
, &ddsd2
, &dgl
->lpDepth4
, NULL
);
1350 if (FAILED(hResult
)) {
1351 ddlogError(DDLOG_CRITICAL_OR_WARN
, "dglResize: CreateSurface (ZBuffer) failed", hResult
);
1352 goto cleanup_and_return_with_error
;
1355 // Attach Zbuffer to render target
1356 TRY(IDirectDrawSurface4_AddAttachedSurface(
1357 dgl
->bDoubleBuffer
? dgl
->lpBack4
: dgl
->lpFront4
,
1359 "dglResize: Attach Zbuffer");
1363 // Clear the newly resized back buffers for the window client area.
1364 ZeroMemory(&ddbltfx
, sizeof(ddbltfx
));
1365 ddbltfx
.dwSize
= sizeof(ddbltfx
);
1366 ddbltfx
.dwFillColor
= dgl
->dwClearColorPF
;
1367 IDirectDrawSurface4_Blt(dgl
->lpBack4
, &rcScreenRect
, NULL
, NULL
,
1368 DDBLT_WAIT
| DDBLT_COLORFILL
, &ddbltfx
);
1371 // Now that we have a zbuffer we can create the 3D device
1373 hResult
= IDirect3D3_CreateDevice(dgl
->lpD3D3
,
1374 bDefaultDriver
? &glb
.d3dGuid
: &IID_IDirect3DRGBDevice
,
1375 dgl
->bDoubleBuffer
? dgl
->lpBack4
: dgl
->lpFront4
,
1378 if (FAILED(hResult
)) {
1379 ddlogError(DDLOG_CRITICAL_OR_WARN
, "dglResize: Could not create Direct3D device", hResult
);
1380 goto cleanup_and_return_with_error
;
1383 // We must do this as soon as the device is created
1384 dglInitStateCaches(dgl
);
1389 hResult
= IDirect3DDevice3_AddViewport(dgl
->lpDev3
, dgl
->lpViewport3
);
1390 if (FAILED(hResult
)) {
1391 ddlogError(DDLOG_CRITICAL_OR_WARN
, "dglResize: AddViewport failed", hResult
);
1392 goto cleanup_and_return_with_error
;
1395 // Initialise the viewport
1396 dgl
->d3dViewport
.dwSize
= sizeof(dgl
->d3dViewport
);
1397 dgl
->d3dViewport
.dwX
= 0;
1398 dgl
->d3dViewport
.dwY
= 0;
1399 dgl
->d3dViewport
.dwWidth
= dgl
->dwWidth
;
1400 dgl
->d3dViewport
.dwHeight
= dgl
->dwHeight
;
1401 dgl
->d3dViewport
.dvClipX
= 0;
1402 dgl
->d3dViewport
.dvClipY
= 0;
1403 dgl
->d3dViewport
.dvClipWidth
= dgl
->dwWidth
;
1404 dgl
->d3dViewport
.dvClipHeight
= dgl
->dwHeight
;
1405 // dgl->d3dViewport.dvMinZ = 0.0f;
1406 // dgl->d3dViewport.dvMaxZ = 1.0f;
1407 TRY(IDirect3DViewport3_SetViewport2(dgl
->lpViewport3
, &dgl
->d3dViewport
),
1408 "dglResize: SetViewport2");
1410 hResult
= IDirect3DDevice3_SetCurrentViewport(dgl
->lpDev3
, dgl
->lpViewport3
);
1411 if (FAILED(hResult
)) {
1412 ddlogError(DDLOG_CRITICAL_OR_WARN
, "dglResize: SetCurrentViewport failed", hResult
);
1413 goto cleanup_and_return_with_error
;
1416 // (Re)Initialise all the Direct3D renderstates
1417 dglInitStateD3D(ctx
);
1419 // Now we have to recreate all of our textures (+ mipmaps).
1420 // Luckily, Mesa has a list of them.
1421 tObj
= ctx
->Shared
->TexObjectList
;
1422 while (tObj
!= NULL
) {
1423 if (tObj
->DriverData
) {
1424 // We could call our TexImage function directly, but it's
1425 // safer to use the driver pointer.
1426 for (i
=0; i
<MAX_TEXTURE_LEVELS
; i
++) {
1427 image
= tObj
->Image
[i
];
1429 switch (tObj
->Dimensions
){
1431 if (ctx
->Driver
.TexImage
)
1432 (*ctx
->Driver
.TexImage
)(ctx
, GL_TEXTURE_1D
, tObj
, i
, image
->Format
, image
);
1435 if (ctx
->Driver
.TexImage
)
1436 (*ctx
->Driver
.TexImage
)(ctx
, GL_TEXTURE_2D
, tObj
, i
, image
->Format
, image
);
1447 // Re-Bind each texture Unit
1448 for (i
=0; i
<glb
.wMaxSimultaneousTextures
; i
++) {
1449 tObj
= ctx
->Texture
.Unit
[i
].Current
;
1451 DGL_texture
*lpTex
= (DGL_texture
*)tObj
->DriverData
;
1452 hResult
= dglSetTexture(dgl
, i
, lpTex
? lpTex
->lpTexture
: NULL
);
1453 if (FAILED(hResult
)) {
1454 ddlogError(DDLOG_ERROR
, "dglResize: SetTexture failed", hResult
);
1458 #endif // _USE_GLD3_WGL
1460 dgl
->bCanRender
= TRUE
;
1463 // Release serialized access
1464 if (glb
.bMultiThreaded
)
1465 LeaveCriticalSection(&CriticalSection
);
1471 cleanup_and_return_with_error
:
1472 // Relase all interfaces before returning.
1473 #ifdef _USE_GLD3_WGL
1474 _gldDriver
.DestroyDrawable(dgl
);
1475 #else // _USE_GLD3_WGL
1476 RELEASE(dgl
->lpDev3
);
1477 RELEASE(dgl
->lpDepth4
);
1478 RELEASE(dgl
->lpBack4
);
1479 if (glb
.bDirectDrawPersistant
&& glb
.bDirectDrawPrimary
)
1482 RELEASE(dgl
->lpFront4
);
1484 #undef DDLOG_CRITICAL_OR_WARN
1485 #endif // _USE_GLD3_WGL
1487 // Mark context as not being able to render
1488 dgl
->bCanRender
= FALSE
;
1491 // Release serialized access
1492 if (glb
.bMultiThreaded
)
1493 LeaveCriticalSection(&CriticalSection
);
1499 // ***********************************************************************
1500 // ***********************************************************************
1501 // Support for bitmap fonts.
1502 // ***********************************************************************
1503 // ***********************************************************************
1505 /*****************************************************************************
1507 ** InvertGlyphBitmap.
1509 ** Invert the bitmap so that it suits OpenGL's representation.
1510 ** Each row starts on a double word boundary.
1512 *****************************************************************************/
1514 static void InvertGlyphBitmap(
1520 int dWordsInRow
= (w
+31)/32;
1524 if (w
<= 0 || h
<= 0) {
1528 tptr
+= ((h
-1)*dWordsInRow
);
1529 for (i
= 0; i
< h
; i
++) {
1530 for (j
= 0; j
< dWordsInRow
; j
++) {
1531 *(tptr
+ j
) = *(fptr
+ j
);
1533 tptr
-= dWordsInRow
;
1534 fptr
+= dWordsInRow
;
1538 // ***********************************************************************
1540 /*****************************************************************************
1543 * Converts a subrange of the glyphs in a GDI font to OpenGL display
1546 * Extended to support any GDI font, not just TrueType fonts. (DaveM)
1548 *****************************************************************************/
1550 BOOL APIENTRY
_GLD_WGL_EXPORT(UseFontBitmapsA
)(
1556 int i
, ox
, oy
, ix
, iy
;
1558 int iBufSize
, iCurBufSize
= 0;
1559 DWORD
*bitmapBuffer
= NULL
;
1560 DWORD
*invertedBitmapBuffer
= NULL
;
1561 BOOL bSuccessOrFail
= TRUE
;
1562 BOOL bTrueType
= FALSE
;
1565 RASTERIZER_STATUS rs
;
1574 // Validate SciTech DirectGL license
1578 // Set up a unity matrix.
1579 ZeroMemory(&mat
, sizeof(mat
));
1583 // Test to see if selected font is TrueType or not
1584 ZeroMemory(&tm
, sizeof(tm
));
1585 if (!GetTextMetrics(hDC
, &tm
)) {
1586 ddlogMessage(DDLOG_ERROR
, "DGL_UseFontBitmaps: Font metrics error\n");
1589 bTrueType
= (tm
.tmPitchAndFamily
& TMPF_TRUETYPE
) ? TRUE
: FALSE
;
1591 // Test to see if TRUE-TYPE capabilities are installed
1592 // (only necessary if TrueType font selected)
1593 ZeroMemory(&rs
, sizeof(rs
));
1595 if (!GetRasterizerCaps (&rs
, sizeof (RASTERIZER_STATUS
))) {
1596 ddlogMessage(DDLOG_ERROR
, "DGL_UseFontBitmaps: Raster caps error\n");
1599 if (!(rs
.wFlags
& TT_ENABLED
)) {
1600 ddlogMessage(DDLOG_ERROR
, "DGL_UseFontBitmaps: No TrueType caps\n");
1605 // Trick to get the current font handle
1606 hFont
= SelectObject(hDC
, GetStockObject(SYSTEM_FONT
));
1607 SelectObject(hDC
, hFont
);
1609 // Have memory device context available for holding bitmaps of font glyphs
1610 hDCMem
= CreateCompatibleDC(hDC
);
1611 SelectObject(hDCMem
, hFont
);
1612 SetTextColor(hDCMem
, RGB(0xFF, 0xFF, 0xFF));
1613 SetBkColor(hDCMem
, 0);
1615 for (i
= first
; (DWORD
) i
< (first
+ count
); i
++) {
1616 // Find out how much space is needed for the bitmap so we can
1617 // Set the buffer size correctly.
1619 // Use TrueType support to get bitmap size of glyph
1620 iBufSize
= GetGlyphOutline(hDC
, i
, GGO_BITMAP
, &gm
,
1622 if (iBufSize
== GDI_ERROR
) {
1623 bSuccessOrFail
= FALSE
;
1628 // Use generic GDI support to compute bitmap size of glyph
1629 w
= tm
.tmMaxCharWidth
;
1631 if (GetTextExtentPoint32(hDC
, (LPCTSTR
)&i
, 1, &size
)) {
1636 // Use DWORD multiple for compatibility
1642 // If we need to allocate Larger Buffers, then do so - but allocate
1643 // An extra 50 % so that we don't do too many mallocs !
1644 if (iBufSize
> iCurBufSize
) {
1646 __wglFree(bitmapBuffer
);
1648 if (invertedBitmapBuffer
) {
1649 __wglFree(invertedBitmapBuffer
);
1652 iCurBufSize
= iBufSize
* 2;
1653 bitmapBuffer
= (DWORD
*) __wglMalloc(iCurBufSize
);
1654 invertedBitmapBuffer
= (DWORD
*) __wglMalloc(iCurBufSize
);
1656 if (bitmapBuffer
== NULL
|| invertedBitmapBuffer
== NULL
) {
1657 bSuccessOrFail
= FALSE
;
1662 // If we fail to get the Glyph data, delete the display lists
1663 // Created so far and return FALSE.
1665 // Use TrueType support to get bitmap of glyph
1666 if (GetGlyphOutline(hDC
, i
, GGO_BITMAP
, &gm
,
1667 iBufSize
, bitmapBuffer
, &mat
) == GDI_ERROR
) {
1668 bSuccessOrFail
= FALSE
;
1672 // Setup glBitmap parameters for current font glyph
1675 ox
= gm
.gmptGlyphOrigin
.x
;
1676 oy
= gm
.gmptGlyphOrigin
.y
;
1681 // Use generic GDI support to create bitmap of glyph
1682 ZeroMemory(bitmapBuffer
, iBufSize
);
1684 if (i
>= tm
.tmFirstChar
&& i
<= tm
.tmLastChar
) {
1685 // Only create bitmaps for actual font glyphs
1686 hBitmap
= CreateBitmap(w
, h
, 1, 1, NULL
);
1687 SelectObject(hDCMem
, hBitmap
);
1688 // Make bitmap of current font glyph
1689 SetRect(&rect
, 0, 0, w
, h
);
1690 DrawText(hDCMem
, (LPCTSTR
)&i
, 1, &rect
,
1691 DT_LEFT
| DT_BOTTOM
| DT_SINGLELINE
| DT_NOCLIP
);
1692 // Make copy of bitmap in our local buffer
1693 ZeroMemory(&bmi
, sizeof(bmi
));
1694 bmi
.bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
1695 bmi
.bmiHeader
.biWidth
= w
;
1696 bmi
.bmiHeader
.biHeight
= -h
;
1697 bmi
.bmiHeader
.biPlanes
= 1;
1698 bmi
.bmiHeader
.biBitCount
= 1;
1699 bmi
.bmiHeader
.biCompression
= BI_RGB
;
1700 GetDIBits(hDCMem
, hBitmap
, 0, h
, bitmapBuffer
, &bmi
, 0);
1701 DeleteObject(hBitmap
);
1704 // Otherwise use empty display list for non-existing glyph
1708 // Setup glBitmap parameters for current font glyph
1715 // Create an OpenGL display list.
1716 _GLD_glNewList((listBase
+ i
), GL_COMPILE
);
1718 // Some fonts have no data for the space character, yet advertise
1720 if (0 == iBufSize
) {
1721 _GLD_glBitmap(0, 0, 0.0f
, 0.0f
, (GLfloat
) ix
, (GLfloat
) iy
, NULL
);
1723 // Invert the Glyph data.
1724 InvertGlyphBitmap(w
, h
, bitmapBuffer
, invertedBitmapBuffer
);
1726 // Render an OpenGL bitmap and invert the origin.
1728 (GLfloat
) ox
, (GLfloat
) (h
-oy
),
1729 (GLfloat
) ix
, (GLfloat
) iy
,
1730 (GLubyte
*) invertedBitmapBuffer
);
1733 // Close this display list.
1737 if (bSuccessOrFail
== FALSE
) {
1738 ddlogMessage(DDLOG_ERROR
, "DGL_UseFontBitmaps: Get glyph failed\n");
1739 _GLD_glDeleteLists((i
+listBase
), (i
-first
));
1742 // Release resources used
1743 DeleteObject(hFont
);
1747 __wglFree(bitmapBuffer
);
1748 if (invertedBitmapBuffer
)
1749 __wglFree(invertedBitmapBuffer
);
1751 return(bSuccessOrFail
);
1754 // ***********************************************************************
1756 BOOL APIENTRY
_GLD_WGL_EXPORT(UseFontBitmapsW
)(
1766 return _GLD_WGL_EXPORT(UseFontBitmapsA
)(a
, b
, c
, d
);
1769 // ***********************************************************************
1770 // ***********************************************************************
1771 // Support for outline TrueType fonts.
1772 // ***********************************************************************
1773 // ***********************************************************************
1775 void * __wglRealloc(
1779 void *newPtr
= NULL
;
1782 newPtr
= (void *) GlobalAlloc(GPTR
, newSize
);
1783 if (oldPtr
&& newPtr
) {
1784 DWORD oldSize
= GlobalSize(oldPtr
);
1786 memcpy(newPtr
, oldPtr
, (oldSize
<= newSize
? oldSize
: newSize
));
1789 } else if (oldPtr
) {
1792 if (newPtr
== NULL
) {
1793 return NULL
; /* XXX out of memory error */
1798 // ***********************************************************************
1801 /*****************************************************************************
1802 * wglUseFontOutlinesW
1804 * Converts a subrange of the glyphs in a TrueType font to OpenGL display
1806 *****************************************************************************/
1808 BOOL APIENTRY
_GLD_WGL_EXPORT(UseFontOutlinesW
)(
1813 IN FLOAT chordalDeviation
,
1816 OUT LPGLYPHMETRICSFLOAT lpgmf
)
1818 return _GLD_WGL_EXPORT(UseFontOutlinesA
)(hDC
, first
, count
, listBase
,
1819 chordalDeviation
, extrusion
, format
, lpgmf
);
1822 /*****************************************************************************
1823 * wglUseFontOutlinesA
1825 * Converts a subrange of the glyphs in a TrueType font to OpenGL display
1827 *****************************************************************************/
1829 BOOL APIENTRY
_GLD_WGL_EXPORT(UseFontOutlinesA
)(
1834 IN FLOAT chordalDeviation
,
1837 OUT LPGLYPHMETRICSFLOAT glyphMetricsFloatArray
)
1845 * Flush any previous OpenGL errors. This allows us to check for
1846 * new errors so they can be reported via the function return value.
1848 while (_GLD_glGetError() != GL_NO_ERROR
)
1852 * Make sure that the current font can be sampled accurately.
1854 hNewFont
= CreateHighResolutionFont(hDC
);
1858 hOldFont
= SelectObject(hDC
, hNewFont
);
1863 * Preallocate a buffer for the outline data, and track its size:
1865 glyphBuf
= (UCHAR
*) __wglMalloc(glyphBufSize
= 10240);
1867 return FALSE
; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
1870 * Process each glyph in the given range:
1872 for (glyphIndex
= first
; glyphIndex
- first
< count
; ++glyphIndex
)
1874 GLYPHMETRICS glyphMetrics
;
1876 static MAT2 matrix
=
1881 LPGLYPHMETRICSFLOAT glyphMetricsFloat
=
1882 &glyphMetricsFloatArray
[glyphIndex
- first
];
1886 * Determine how much space is needed to store the glyph's
1887 * outlines. If our glyph buffer isn't large enough,
1890 glyphSize
= GetGlyphOutline( hDC
,
1899 return FALSE
; /*WGL_STATUS_FAILURE*/
1900 if (glyphSize
> glyphBufSize
)
1902 __wglFree(glyphBuf
);
1903 glyphBuf
= (UCHAR
*) __wglMalloc(glyphBufSize
= glyphSize
);
1905 return FALSE
; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
1910 * Get the glyph's outlines.
1912 if (GetGlyphOutline( hDC
,
1921 __wglFree(glyphBuf
);
1922 return FALSE
; /*WGL_STATUS_FAILURE*/
1925 glyphMetricsFloat
->gmfBlackBoxX
=
1926 (FLOAT
) glyphMetrics
.gmBlackBoxX
* ScaleFactor
;
1927 glyphMetricsFloat
->gmfBlackBoxY
=
1928 (FLOAT
) glyphMetrics
.gmBlackBoxY
* ScaleFactor
;
1929 glyphMetricsFloat
->gmfptGlyphOrigin
.x
=
1930 (FLOAT
) glyphMetrics
.gmptGlyphOrigin
.x
* ScaleFactor
;
1931 glyphMetricsFloat
->gmfptGlyphOrigin
.y
=
1932 (FLOAT
) glyphMetrics
.gmptGlyphOrigin
.y
* ScaleFactor
;
1933 glyphMetricsFloat
->gmfCellIncX
=
1934 (FLOAT
) glyphMetrics
.gmCellIncX
* ScaleFactor
;
1935 glyphMetricsFloat
->gmfCellIncY
=
1936 (FLOAT
) glyphMetrics
.gmCellIncY
* ScaleFactor
;
1939 * Turn the glyph into a display list:
1941 if (!MakeDisplayListFromGlyph( (glyphIndex
- first
) + listBase
,
1945 chordalDeviation
+ ScaleFactor
,
1949 __wglFree(glyphBuf
);
1950 return FALSE
; /*WGL_STATUS_FAILURE*/
1956 * Clean up temporary storage and return. If an error occurred,
1957 * clear all OpenGL error flags and return FAILURE status;
1958 * otherwise just return SUCCESS.
1960 __wglFree(glyphBuf
);
1962 SelectObject(hDC
, hOldFont
);
1964 if (_GLD_glGetError() == GL_NO_ERROR
)
1965 return TRUE
; /*WGL_STATUS_SUCCESS*/
1968 while (_GLD_glGetError() != GL_NO_ERROR
)
1970 return FALSE
; /*WGL_STATUS_FAILURE*/
1976 /*****************************************************************************
1977 * CreateHighResolutionFont
1979 * Gets metrics for the current font and creates an equivalent font
1980 * scaled to the design units of the font.
1982 *****************************************************************************/
1985 CreateHighResolutionFont(HDC hDC
)
1988 OUTLINETEXTMETRIC
*otm
;
1989 LONG fontHeight
, fontWidth
, fontUnits
;
1992 otmSize
= GetOutlineTextMetrics(hDC
, 0, NULL
);
1996 otm
= (OUTLINETEXTMETRIC
*) __wglMalloc(otmSize
);
2000 otm
->otmSize
= otmSize
;
2001 if (GetOutlineTextMetrics(hDC
, otmSize
, otm
) == 0)
2004 fontHeight
= otm
->otmTextMetrics
.tmHeight
-
2005 otm
->otmTextMetrics
.tmInternalLeading
;
2006 fontWidth
= otm
->otmTextMetrics
.tmAveCharWidth
;
2007 fontUnits
= (LONG
) otm
->otmEMSquare
;
2009 ScaleFactor
= 1.0F
/ (FLOAT
) fontUnits
;
2011 logFont
.lfHeight
= - ((LONG
) fontUnits
);
2012 logFont
.lfWidth
= (LONG
)
2013 ((FLOAT
) (fontWidth
* fontUnits
) / (FLOAT
) fontHeight
);
2014 logFont
.lfEscapement
= 0;
2015 logFont
.lfOrientation
= 0;
2016 logFont
.lfWeight
= otm
->otmTextMetrics
.tmWeight
;
2017 logFont
.lfItalic
= otm
->otmTextMetrics
.tmItalic
;
2018 logFont
.lfUnderline
= otm
->otmTextMetrics
.tmUnderlined
;
2019 logFont
.lfStrikeOut
= otm
->otmTextMetrics
.tmStruckOut
;
2020 logFont
.lfCharSet
= otm
->otmTextMetrics
.tmCharSet
;
2021 logFont
.lfOutPrecision
= OUT_OUTLINE_PRECIS
;
2022 logFont
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
2023 logFont
.lfQuality
= DEFAULT_QUALITY
;
2024 logFont
.lfPitchAndFamily
=
2025 otm
->otmTextMetrics
.tmPitchAndFamily
& 0xf0;
2026 strcpy(logFont
.lfFaceName
,
2027 (char *)otm
+ (int)otm
->otmpFaceName
);
2029 hNewFont
= CreateFontIndirect(&logFont
);
2030 if (hNewFont
== NULL
)
2040 /*****************************************************************************
2041 * MakeDisplayListFromGlyph
2043 * Converts the outline of a glyph to an OpenGL display list.
2045 * Return value is nonzero for success, zero for failure.
2047 * Does not check for OpenGL errors, so if the caller needs to know about them,
2048 * it should call glGetError().
2049 *****************************************************************************/
2052 MakeDisplayListFromGlyph( IN DWORD listName
,
2055 IN LPGLYPHMETRICSFLOAT glyphMetricsFloat
,
2056 IN FLOAT chordalDeviation
,
2062 _GLD_glNewList(listName
, GL_COMPILE
);
2063 status
= DrawGlyph( glyphBuf
,
2069 _GLD_glTranslatef(glyphMetricsFloat
->gmfCellIncX
,
2070 glyphMetricsFloat
->gmfCellIncY
,
2079 /*****************************************************************************
2082 * Converts the outline of a glyph to OpenGL drawing primitives, tessellating
2083 * as needed, and then draws the glyph. Tessellation of the quadratic splines
2084 * in the outline is controlled by "chordalDeviation", and the drawing
2085 * primitives (lines or polygons) are selected by "format".
2087 * Return value is nonzero for success, zero for failure.
2089 * Does not check for OpenGL errors, so if the caller needs to know about them,
2090 * it should call glGetError().
2091 *****************************************************************************/
2094 DrawGlyph( IN UCHAR
* glyphBuf
,
2096 IN FLOAT chordalDeviation
,
2104 GLUtesselator
* tess
= NULL
;
2108 * Initialize the global buffer into which we place the outlines:
2115 * Convert the glyph outlines to a set of polyline loops.
2116 * (See MakeLinesFromGlyph() for the format of the loop data
2119 if (!MakeLinesFromGlyph(glyphBuf
, glyphSize
, chordalDeviation
))
2125 * Now draw the loops in the appropriate format:
2127 if (format
== WGL_FONT_LINES
)
2130 * This is the easy case. Just draw the outlines.
2132 for (loop
= (DWORD
) *p
++; loop
; --loop
)
2134 _GLD_glBegin(GL_LINE_LOOP
);
2135 for (point
= (DWORD
) *p
++; point
; --point
)
2137 _GLD_glVertex2fv(p
);
2145 else if (format
== WGL_FONT_POLYGONS
)
2152 * This is the hard case. We have to set up a tessellator
2153 * to convert the outlines into a set of polygonal
2154 * primitives, which the tessellator passes to some
2155 * auxiliary routines for drawing.
2157 if (!LoadGLUTesselator())
2161 if (!(tess
= gluNewTessProc()))
2163 gluTessCallbackProc(tess
, GLU_BEGIN
, (void(CALLBACK
*)()) _GLD_glBegin
);
2164 gluTessCallbackProc(tess
, GLU_TESS_VERTEX_DATA
,
2165 (void(CALLBACK
*)()) TessVertexOutData
);
2166 gluTessCallbackProc(tess
, GLU_END
, (void(CALLBACK
*)()) _GLD_glEnd
);
2167 gluTessCallbackProc(tess
, GLU_ERROR
, (void(CALLBACK
*)()) TessError
);
2168 gluTessCallbackProc(tess
, GLU_TESS_COMBINE
, (void(CALLBACK
*)()) TessCombine
);
2169 gluTessNormalProc(tess
, 0.0F
, 0.0F
, 1.0F
);
2171 TessErrorOccurred
= 0;
2172 _GLD_glNormal3f(0.0f
, 0.0f
, 1.0f
);
2176 gluTessBeginPolygonProc(tess
, (void *)*(int *)&z_value
);
2177 for (loop
= (DWORD
) *p
++; loop
; --loop
)
2179 gluTessBeginContourProc(tess
);
2181 for (point
= (DWORD
) *p
++; point
; --point
)
2185 gluTessVertexProc(tess
, v
, p
);
2189 gluTessEndContourProc(tess
);
2191 gluTessEndPolygonProc(tess
);
2193 status
= !TessErrorOccurred
;
2195 /* Extrusion code */
2198 GLfloat thickness
= (GLfloat
) -extrusion
;
2199 FLOAT
*vert
, *vert2
;
2203 loops
= (DWORD
) *p
++;
2205 for (loop
= 0; loop
< loops
; loop
++) {
2206 GLfloat dx
, dy
, len
;
2209 count
= (DWORD
) *p
++;
2210 _GLD_glBegin(GL_QUAD_STRIP
);
2212 /* Check if the first and last vertex are identical
2213 * so we don't draw the same quad twice.
2215 vert
= p
+ (count
-1)*2;
2216 last
= (p
[0] == vert
[0] && p
[1] == vert
[1]) ? count
-1 : count
;
2218 for (point
= 0; point
<= last
; point
++) {
2219 vert
= p
+ 2 * (point
% last
);
2220 vert2
= p
+ 2 * ((point
+1) % last
);
2222 dx
= vert
[0] - vert2
[0];
2223 dy
= vert
[1] - vert2
[1];
2224 len
= (GLfloat
)sqrt(dx
* dx
+ dy
* dy
);
2226 _GLD_glNormal3f(dy
/ len
, -dx
/ len
, 0.0f
);
2227 _GLD_glVertex3f((GLfloat
) vert
[0],
2228 (GLfloat
) vert
[1], thickness
);
2229 _GLD_glVertex3f((GLfloat
) vert
[0],
2230 (GLfloat
) vert
[1], 0.0f
);
2237 /* Draw the back face */
2240 _GLD_glNormal3f(0.0f
, 0.0f
, -1.0f
);
2241 gluTessNormalProc(tess
, 0.0F
, 0.0F
, -1.0F
);
2243 gluTessBeginPolygonProc(tess
, (void *)*(int *)&thickness
);
2245 for (loop
= (DWORD
) *p
++; loop
; --loop
)
2247 count
= (DWORD
) *p
++;
2249 gluTessBeginContourProc(tess
);
2251 for (point
= 0; point
< count
; point
++)
2253 vert
= p
+ ((count
-point
-1)<<1);
2256 gluTessVertexProc(tess
, v
, vert
);
2260 gluTessEndContourProc(tess
);
2262 gluTessEndPolygonProc(tess
);
2266 if (TessErrorOccurred
)
2267 printf("Tessellation error %s\n",
2268 gluErrorString(TessErrorOccurred
));
2276 gluDeleteTessProc(tess
);
2277 // UnloadGLUTesselator();
2284 /*****************************************************************************
2287 * Maps the glu32.dll module and gets function pointers for the
2288 * tesselator functions.
2289 *****************************************************************************/
2292 LoadGLUTesselator(void)
2294 if (gluModuleHandle
!= NULL
)
2298 extern HINSTANCE hInstanceOpenGL
;
2299 char *gluName
= "GLU32.DLL";
2305 len = GetModuleFileName(hInstanceOpenGL, name, 255);
2309 while (ptr > name && *ptr != '\\')
2313 if (!stricmp(ptr, "cosmogl.dll"))
2315 gluName = "COSMOGLU.DLL";
2317 else if (!stricmp(ptr, "opengl32.dll"))
2319 gluName = "GLU32.DLL";
2323 if ((gluModuleHandle
= LoadLibrary(gluName
)) == NULL
)
2327 if ((gluNewTessProc
= (gluNewTessProto
)
2328 GetProcAddress(gluModuleHandle
, "gluNewTess")) == NULL
)
2331 if ((gluDeleteTessProc
= (gluDeleteTessProto
)
2332 GetProcAddress(gluModuleHandle
, "gluDeleteTess")) == NULL
)
2335 if ((gluTessBeginPolygonProc
= (gluTessBeginPolygonProto
)
2336 GetProcAddress(gluModuleHandle
, "gluTessBeginPolygon")) == NULL
)
2339 if ((gluTessBeginContourProc
= (gluTessBeginContourProto
)
2340 GetProcAddress(gluModuleHandle
, "gluTessBeginContour")) == NULL
)
2343 if ((gluTessVertexProc
= (gluTessVertexProto
)
2344 GetProcAddress(gluModuleHandle
, "gluTessVertex")) == NULL
)
2347 if ((gluTessEndContourProc
= (gluTessEndContourProto
)
2348 GetProcAddress(gluModuleHandle
, "gluTessEndContour")) == NULL
)
2351 if ((gluTessEndPolygonProc
= (gluTessEndPolygonProto
)
2352 GetProcAddress(gluModuleHandle
, "gluTessEndPolygon")) == NULL
)
2355 if ((gluTessPropertyProc
= (gluTessPropertyProto
)
2356 GetProcAddress(gluModuleHandle
, "gluTessProperty")) == NULL
)
2359 if ((gluTessNormalProc
= (gluTessNormalProto
)
2360 GetProcAddress(gluModuleHandle
, "gluTessNormal")) == NULL
)
2363 if ((gluTessCallbackProc
= (gluTessCallbackProto
)
2364 GetProcAddress(gluModuleHandle
, "gluTessCallback")) == NULL
)
2372 /*****************************************************************************
2373 * UnloadGLUTesselator
2375 * Unmaps the glu32.dll module.
2376 *****************************************************************************/
2379 UnloadGLUTesselator(void)
2381 if (gluModuleHandle
!= NULL
)
2382 if (FreeLibrary(gluModuleHandle
) == FALSE
)
2384 gluModuleHandle
= NULL
;
2389 /*****************************************************************************
2392 * Used by tessellator to handle output vertexes.
2393 *****************************************************************************/
2395 static void CALLBACK
2396 TessVertexOut(FLOAT p
[3])
2400 v
[0] = p
[0] * ScaleFactor
;
2401 v
[1] = p
[1] * ScaleFactor
;
2402 _GLD_glVertex2fv(v
);
2405 static void CALLBACK
2406 TessVertexOutData(FLOAT p
[3], GLfloat z
)
2410 v
[0] = (GLfloat
) p
[0];
2411 v
[1] = (GLfloat
) p
[1];
2413 _GLD_glVertex3fv(v
);
2417 /*****************************************************************************
2420 * Used by tessellator to handle self-intersecting contours and degenerate
2422 *****************************************************************************/
2424 static void CALLBACK
2425 TessCombine(double coords
[3],
2426 void* vertex_data
[4],
2430 if (!AppendToVertBuf((FLOAT
) coords
[0])
2431 || !AppendToVertBuf((FLOAT
) coords
[1])
2432 || !AppendToVertBuf((FLOAT
) coords
[2]))
2433 TessErrorOccurred
= GL_OUT_OF_MEMORY
;
2434 *outData
= VertBuf
+ (VertBufIndex
- 3);
2439 /*****************************************************************************
2442 * Saves the last tessellator error code in the global TessErrorOccurred.
2443 *****************************************************************************/
2445 static void CALLBACK
2446 TessError(GLenum error
)
2448 TessErrorOccurred
= error
;
2453 /*****************************************************************************
2454 * MakeLinesFromGlyph
2456 * Converts the outline of a glyph from the TTPOLYGON format to a simple
2457 * array of floating-point values containing one or more loops.
2459 * The first element of the output array is a count of the number of loops.
2460 * The loop data follows this count. Each loop consists of a count of the
2461 * number of vertices it contains, followed by the vertices. Each vertex
2462 * is an X and Y coordinate. For example, a single triangle might be
2463 * described by this array:
2465 * 1., 3., 0., 0., 1., 0., 0., 1.
2467 * #loops #verts x1 y1 x2 y2 x3 y3
2469 * A two-loop glyph would look like this:
2471 * 2., 3., 0.,0., 1.,0., 0.,1., 3., .2,.2, .4,.2, .2,.4
2473 * Line segments from the TTPOLYGON are transferred to the output array in
2474 * the obvious way. Quadratic splines in the TTPOLYGON are converted to
2475 * collections of line segments
2476 *****************************************************************************/
2479 MakeLinesFromGlyph(IN UCHAR
* glyphBuf
,
2481 IN FLOAT chordalDeviation
)
2488 * Pick up all the polygons (aka loops) that make up the glyph:
2490 if (!AppendToLineBuf(0.0F
)) /* loop count at LineBuf[0] */
2494 while (p
< glyphBuf
+ glyphSize
)
2496 if (!MakeLinesFromTTPolygon(&p
, chordalDeviation
))
2498 LineBuf
[0] += 1.0F
; /* increment loop count */
2509 /*****************************************************************************
2510 * MakeLinesFromTTPolygon
2512 * Converts a TTPOLYGONHEADER and its associated curve structures into a
2513 * single polyline loop in the global LineBuf.
2514 *****************************************************************************/
2517 MakeLinesFromTTPolygon( IN OUT UCHAR
** pp
,
2518 IN FLOAT chordalDeviation
)
2522 DWORD vertexCountIndex
;
2525 * Record where the polygon data begins, and where the loop's
2526 * vertex count resides:
2529 vertexCountIndex
= LineBufIndex
;
2530 if (!AppendToLineBuf(0.0F
))
2534 * Extract relevant data from the TTPOLYGONHEADER:
2536 polySize
= GetDWord(pp
);
2537 if (GetDWord(pp
) != TT_POLYGON_TYPE
) /* polygon type */
2539 if (!AppendToLineBuf((FLOAT
) GetFixed(pp
))) /* first X coord */
2541 if (!AppendToLineBuf((FLOAT
) GetFixed(pp
))) /* first Y coord */
2543 LineBuf
[vertexCountIndex
] += 1.0F
;
2546 * Process each of the TTPOLYCURVE structures in the polygon:
2548 while (*pp
< polyStart
+ polySize
)
2549 if (!MakeLinesFromTTPolycurve( pp
,
2559 /*****************************************************************************
2560 * MakeLinesFromTTPolyCurve
2562 * Converts the lines and splines in a single TTPOLYCURVE structure to points
2563 * in the global LineBuf.
2564 *****************************************************************************/
2567 MakeLinesFromTTPolycurve( IN OUT UCHAR
** pp
,
2568 IN DWORD vertexCountIndex
,
2569 IN FLOAT chordalDeviation
)
2576 * Pick up the relevant fields of the TTPOLYCURVE structure:
2578 type
= (WORD
) GetWord(pp
);
2579 pointCount
= (WORD
) GetWord(pp
);
2582 * Convert the "curve" to line segments:
2584 if (type
== TT_PRIM_LINE
)
2585 return MakeLinesFromTTLine( pp
,
2588 else if (type
== TT_PRIM_QSPLINE
)
2589 return MakeLinesFromTTQSpline( pp
,
2599 /*****************************************************************************
2600 * MakeLinesFromTTLine
2602 * Converts points from the polyline in a TT_PRIM_LINE structure to
2603 * equivalent points in the global LineBuf.
2604 *****************************************************************************/
2606 MakeLinesFromTTLine( IN OUT UCHAR
** pp
,
2607 IN DWORD vertexCountIndex
,
2611 * Just copy the line segments into the line buffer (converting
2614 LineBuf
[vertexCountIndex
] += pointCount
;
2615 while (pointCount
--)
2617 if (!AppendToLineBuf((FLOAT
) GetFixed(pp
)) /* X coord */
2618 || !AppendToLineBuf((FLOAT
) GetFixed(pp
))) /* Y coord */
2627 /*****************************************************************************
2628 * MakeLinesFromTTQSpline
2630 * Converts points from the poly quadratic spline in a TT_PRIM_QSPLINE
2631 * structure to polyline points in the global LineBuf.
2632 *****************************************************************************/
2635 MakeLinesFromTTQSpline( IN OUT UCHAR
** pp
,
2636 IN DWORD vertexCountIndex
,
2638 IN FLOAT chordalDeviation
)
2640 FLOAT x0
, y0
, x1
, y1
, x2
, y2
;
2644 * Process each of the non-interpolated points in the outline.
2645 * To do this, we need to generate two interpolated points (the
2646 * start and end of the arc) for each non-interpolated point.
2647 * The first interpolated point is always the one most recently
2648 * stored in LineBuf, so we just extract it from there. The
2649 * second interpolated point is either the average of the next
2650 * two points in the QSpline, or the last point in the QSpline
2651 * if only one remains.
2653 for (point
= 0; point
< pointCount
- 1; ++point
)
2655 x0
= LineBuf
[LineBufIndex
- 2];
2656 y0
= LineBuf
[LineBufIndex
- 1];
2658 x1
= (FLOAT
) GetFixed(pp
);
2659 y1
= (FLOAT
) GetFixed(pp
);
2661 if (point
== pointCount
- 2)
2664 * This is the last arc in the QSpline. The final
2665 * point is the end of the arc.
2667 x2
= (FLOAT
) GetFixed(pp
);
2668 y2
= (FLOAT
) GetFixed(pp
);
2673 * Peek at the next point in the input to compute
2674 * the end of the arc:
2676 x2
= 0.5F
* (x1
+ (FLOAT
) GetFixed(pp
));
2677 y2
= 0.5F
* (y1
+ (FLOAT
) GetFixed(pp
));
2679 * Push the point back onto the input so it will
2680 * be reused as the next off-curve point:
2685 if (!MakeLinesFromArc( x0
, y0
,
2689 chordalDeviation
* chordalDeviation
))
2698 /*****************************************************************************
2701 * Subdivides one arc of a quadratic spline until the chordal deviation
2702 * tolerance requirement is met, then places the resulting set of line
2703 * segments in the global LineBuf.
2704 *****************************************************************************/
2707 MakeLinesFromArc( IN FLOAT x0
,
2713 IN DWORD vertexCountIndex
,
2714 IN FLOAT chordalDeviationSquared
)
2726 * Calculate midpoint of the curve by de Casteljau:
2728 x01
= 0.5F
* (x0
+ x1
);
2729 y01
= 0.5F
* (y0
+ y1
);
2730 x12
= 0.5F
* (x1
+ x2
);
2731 y12
= 0.5F
* (y1
+ y2
);
2732 midPointX
= 0.5F
* (x01
+ x12
);
2733 midPointY
= 0.5F
* (y01
+ y12
);
2737 * Estimate chordal deviation by the distance from the midpoint
2738 * of the curve to its non-interpolated control point. If this
2739 * distance is greater than the specified chordal deviation
2740 * constraint, then subdivide. Otherwise, generate polylines
2741 * from the three control points.
2743 deltaX
= midPointX
- x1
;
2744 deltaY
= midPointY
- y1
;
2745 if (deltaX
* deltaX
+ deltaY
* deltaY
> chordalDeviationSquared
)
2747 MakeLinesFromArc( x0
, y0
,
2749 midPointX
, midPointY
,
2751 chordalDeviationSquared
);
2753 MakeLinesFromArc( midPointX
, midPointY
,
2757 chordalDeviationSquared
);
2762 * The "pen" is already at (x0, y0), so we don't need to
2763 * add that point to the LineBuf.
2765 if (!AppendToLineBuf(x1
)
2766 || !AppendToLineBuf(y1
)
2767 || !AppendToLineBuf(x2
)
2768 || !AppendToLineBuf(y2
))
2770 LineBuf
[vertexCountIndex
] += 2.0F
;
2778 /*****************************************************************************
2781 * Initializes the global LineBuf and its associated size and current-element
2783 *****************************************************************************/
2788 if (!(LineBuf
= (FLOAT
*)
2789 __wglMalloc((LineBufSize
= LINE_BUF_QUANT
) * sizeof(FLOAT
))))
2797 /*****************************************************************************
2800 * Initializes the global VertBuf and its associated size and current-element
2802 *****************************************************************************/
2807 if (!(VertBuf
= (FLOAT
*)
2808 __wglMalloc((VertBufSize
= VERT_BUF_QUANT
) * sizeof(FLOAT
))))
2816 /*****************************************************************************
2819 * Appends one floating-point value to the global LineBuf array. Return value
2820 * is non-zero for success, zero for failure.
2821 *****************************************************************************/
2824 AppendToLineBuf(FLOAT value
)
2826 if (LineBufIndex
>= LineBufSize
)
2830 f
= (FLOAT
*) __wglRealloc(LineBuf
,
2831 (LineBufSize
+= LINE_BUF_QUANT
) * sizeof(FLOAT
));
2836 LineBuf
[LineBufIndex
++] = value
;
2842 /*****************************************************************************
2845 * Appends one floating-point value to the global VertBuf array. Return value
2846 * is non-zero for success, zero for failure.
2848 * Note that we can't realloc this one, because the tessellator is using
2850 *****************************************************************************/
2853 AppendToVertBuf(FLOAT value
)
2855 if (VertBufIndex
>= VertBufSize
)
2857 VertBuf
[VertBufIndex
++] = value
;
2863 /*****************************************************************************
2866 * Cleans up vertex buffer structure.
2867 *****************************************************************************/
2881 /*****************************************************************************
2884 * Cleans up vertex buffer structure.
2885 *****************************************************************************/
2899 /*****************************************************************************
2902 * Fetch the next 16-bit word from a little-endian byte stream, and increment
2903 * the stream pointer to the next unscanned byte.
2904 *****************************************************************************/
2906 static long GetWord(UCHAR
** p
)
2910 value
= ((*p
)[1] << 8) + (*p
)[0];
2917 /*****************************************************************************
2920 * Fetch the next 32-bit word from a little-endian byte stream, and increment
2921 * the stream pointer to the next unscanned byte.
2922 *****************************************************************************/
2924 static long GetDWord(UCHAR
** p
)
2928 value
= ((*p
)[3] << 24) + ((*p
)[2] << 16) + ((*p
)[1] << 8) + (*p
)[0];
2936 /*****************************************************************************
2939 * Fetch the next 32-bit fixed-point value from a little-endian byte stream,
2940 * convert it to floating-point, and increment the stream pointer to the next
2942 *****************************************************************************/
2944 static double GetFixed(
2947 long hiBits
, loBits
;
2950 loBits
= GetWord(p
);
2951 hiBits
= GetWord(p
);
2952 value
= (double) ((hiBits
<< 16) | loBits
) / 65536.0;
2954 return value
* ScaleFactor
;
2957 // ***********************************************************************