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 "gl/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 // Walk over all textures in hash table
1421 // XXX what about the default texture objects (id=0)?
1423 struct _mesa_HashTable
*textures
= ctx
->Shared
->TexObjects
;
1425 for (id
= _mesa_HashFirstEntry(textures
);
1427 id
= _mesa_HashNextEntry(textures
, id
)) {
1428 tObj
= (struct gl_texture_object
*) _mesa_HashLookup(textures
, id
);
1429 if (tObj
->DriverData
) {
1430 // We could call our TexImage function directly, but it's
1431 // safer to use the driver pointer.
1432 for (i
=0; i
<MAX_TEXTURE_LEVELS
; i
++) {
1433 image
= tObj
->Image
[i
];
1435 switch (tObj
->Dimensions
){
1437 if (ctx
->Driver
.TexImage
)
1438 (*ctx
->Driver
.TexImage
)(ctx
, GL_TEXTURE_1D
, tObj
, i
, image
->Format
, image
);
1441 if (ctx
->Driver
.TexImage
)
1442 (*ctx
->Driver
.TexImage
)(ctx
, GL_TEXTURE_2D
, tObj
, i
, image
->Format
, image
);
1453 // Re-Bind each texture Unit
1454 for (i
=0; i
<glb
.wMaxSimultaneousTextures
; i
++) {
1455 tObj
= ctx
->Texture
.Unit
[i
].Current
;
1457 DGL_texture
*lpTex
= (DGL_texture
*)tObj
->DriverData
;
1458 hResult
= dglSetTexture(dgl
, i
, lpTex
? lpTex
->lpTexture
: NULL
);
1459 if (FAILED(hResult
)) {
1460 ddlogError(DDLOG_ERROR
, "dglResize: SetTexture failed", hResult
);
1464 #endif // _USE_GLD3_WGL
1466 dgl
->bCanRender
= TRUE
;
1469 // Release serialized access
1470 if (glb
.bMultiThreaded
)
1471 LeaveCriticalSection(&CriticalSection
);
1477 cleanup_and_return_with_error
:
1478 // Relase all interfaces before returning.
1479 #ifdef _USE_GLD3_WGL
1480 _gldDriver
.DestroyDrawable(dgl
);
1481 #else // _USE_GLD3_WGL
1482 RELEASE(dgl
->lpDev3
);
1483 RELEASE(dgl
->lpDepth4
);
1484 RELEASE(dgl
->lpBack4
);
1485 if (glb
.bDirectDrawPersistant
&& glb
.bDirectDrawPrimary
)
1488 RELEASE(dgl
->lpFront4
);
1490 #undef DDLOG_CRITICAL_OR_WARN
1491 #endif // _USE_GLD3_WGL
1493 // Mark context as not being able to render
1494 dgl
->bCanRender
= FALSE
;
1497 // Release serialized access
1498 if (glb
.bMultiThreaded
)
1499 LeaveCriticalSection(&CriticalSection
);
1505 // ***********************************************************************
1506 // ***********************************************************************
1507 // Support for bitmap fonts.
1508 // ***********************************************************************
1509 // ***********************************************************************
1511 /*****************************************************************************
1513 ** InvertGlyphBitmap.
1515 ** Invert the bitmap so that it suits OpenGL's representation.
1516 ** Each row starts on a double word boundary.
1518 *****************************************************************************/
1520 static void InvertGlyphBitmap(
1526 int dWordsInRow
= (w
+31)/32;
1530 if (w
<= 0 || h
<= 0) {
1534 tptr
+= ((h
-1)*dWordsInRow
);
1535 for (i
= 0; i
< h
; i
++) {
1536 for (j
= 0; j
< dWordsInRow
; j
++) {
1537 *(tptr
+ j
) = *(fptr
+ j
);
1539 tptr
-= dWordsInRow
;
1540 fptr
+= dWordsInRow
;
1544 // ***********************************************************************
1546 /*****************************************************************************
1549 * Converts a subrange of the glyphs in a GDI font to OpenGL display
1552 * Extended to support any GDI font, not just TrueType fonts. (DaveM)
1554 *****************************************************************************/
1556 BOOL APIENTRY
_GLD_WGL_EXPORT(UseFontBitmapsA
)(
1562 int i
, ox
, oy
, ix
, iy
;
1564 int iBufSize
, iCurBufSize
= 0;
1565 DWORD
*bitmapBuffer
= NULL
;
1566 DWORD
*invertedBitmapBuffer
= NULL
;
1567 BOOL bSuccessOrFail
= TRUE
;
1568 BOOL bTrueType
= FALSE
;
1571 RASTERIZER_STATUS rs
;
1580 // Validate SciTech DirectGL license
1584 // Set up a unity matrix.
1585 ZeroMemory(&mat
, sizeof(mat
));
1589 // Test to see if selected font is TrueType or not
1590 ZeroMemory(&tm
, sizeof(tm
));
1591 if (!GetTextMetrics(hDC
, &tm
)) {
1592 ddlogMessage(DDLOG_ERROR
, "DGL_UseFontBitmaps: Font metrics error\n");
1595 bTrueType
= (tm
.tmPitchAndFamily
& TMPF_TRUETYPE
) ? TRUE
: FALSE
;
1597 // Test to see if TRUE-TYPE capabilities are installed
1598 // (only necessary if TrueType font selected)
1599 ZeroMemory(&rs
, sizeof(rs
));
1601 if (!GetRasterizerCaps (&rs
, sizeof (RASTERIZER_STATUS
))) {
1602 ddlogMessage(DDLOG_ERROR
, "DGL_UseFontBitmaps: Raster caps error\n");
1605 if (!(rs
.wFlags
& TT_ENABLED
)) {
1606 ddlogMessage(DDLOG_ERROR
, "DGL_UseFontBitmaps: No TrueType caps\n");
1611 // Trick to get the current font handle
1612 hFont
= SelectObject(hDC
, GetStockObject(SYSTEM_FONT
));
1613 SelectObject(hDC
, hFont
);
1615 // Have memory device context available for holding bitmaps of font glyphs
1616 hDCMem
= CreateCompatibleDC(hDC
);
1617 SelectObject(hDCMem
, hFont
);
1618 SetTextColor(hDCMem
, RGB(0xFF, 0xFF, 0xFF));
1619 SetBkColor(hDCMem
, 0);
1621 for (i
= first
; (DWORD
) i
< (first
+ count
); i
++) {
1622 // Find out how much space is needed for the bitmap so we can
1623 // Set the buffer size correctly.
1625 // Use TrueType support to get bitmap size of glyph
1626 iBufSize
= GetGlyphOutline(hDC
, i
, GGO_BITMAP
, &gm
,
1628 if (iBufSize
== GDI_ERROR
) {
1629 bSuccessOrFail
= FALSE
;
1634 // Use generic GDI support to compute bitmap size of glyph
1635 w
= tm
.tmMaxCharWidth
;
1637 if (GetTextExtentPoint32(hDC
, (LPCTSTR
)&i
, 1, &size
)) {
1642 // Use DWORD multiple for compatibility
1648 // If we need to allocate Larger Buffers, then do so - but allocate
1649 // An extra 50 % so that we don't do too many mallocs !
1650 if (iBufSize
> iCurBufSize
) {
1652 __wglFree(bitmapBuffer
);
1654 if (invertedBitmapBuffer
) {
1655 __wglFree(invertedBitmapBuffer
);
1658 iCurBufSize
= iBufSize
* 2;
1659 bitmapBuffer
= (DWORD
*) __wglMalloc(iCurBufSize
);
1660 invertedBitmapBuffer
= (DWORD
*) __wglMalloc(iCurBufSize
);
1662 if (bitmapBuffer
== NULL
|| invertedBitmapBuffer
== NULL
) {
1663 bSuccessOrFail
= FALSE
;
1668 // If we fail to get the Glyph data, delete the display lists
1669 // Created so far and return FALSE.
1671 // Use TrueType support to get bitmap of glyph
1672 if (GetGlyphOutline(hDC
, i
, GGO_BITMAP
, &gm
,
1673 iBufSize
, bitmapBuffer
, &mat
) == GDI_ERROR
) {
1674 bSuccessOrFail
= FALSE
;
1678 // Setup glBitmap parameters for current font glyph
1681 ox
= gm
.gmptGlyphOrigin
.x
;
1682 oy
= gm
.gmptGlyphOrigin
.y
;
1687 // Use generic GDI support to create bitmap of glyph
1688 ZeroMemory(bitmapBuffer
, iBufSize
);
1690 if (i
>= tm
.tmFirstChar
&& i
<= tm
.tmLastChar
) {
1691 // Only create bitmaps for actual font glyphs
1692 hBitmap
= CreateBitmap(w
, h
, 1, 1, NULL
);
1693 SelectObject(hDCMem
, hBitmap
);
1694 // Make bitmap of current font glyph
1695 SetRect(&rect
, 0, 0, w
, h
);
1696 DrawText(hDCMem
, (LPCTSTR
)&i
, 1, &rect
,
1697 DT_LEFT
| DT_BOTTOM
| DT_SINGLELINE
| DT_NOCLIP
);
1698 // Make copy of bitmap in our local buffer
1699 ZeroMemory(&bmi
, sizeof(bmi
));
1700 bmi
.bmiHeader
.biSize
= sizeof(BITMAPINFOHEADER
);
1701 bmi
.bmiHeader
.biWidth
= w
;
1702 bmi
.bmiHeader
.biHeight
= -h
;
1703 bmi
.bmiHeader
.biPlanes
= 1;
1704 bmi
.bmiHeader
.biBitCount
= 1;
1705 bmi
.bmiHeader
.biCompression
= BI_RGB
;
1706 GetDIBits(hDCMem
, hBitmap
, 0, h
, bitmapBuffer
, &bmi
, 0);
1707 DeleteObject(hBitmap
);
1710 // Otherwise use empty display list for non-existing glyph
1714 // Setup glBitmap parameters for current font glyph
1721 // Create an OpenGL display list.
1722 _GLD_glNewList((listBase
+ i
), GL_COMPILE
);
1724 // Some fonts have no data for the space character, yet advertise
1726 if (0 == iBufSize
) {
1727 _GLD_glBitmap(0, 0, 0.0f
, 0.0f
, (GLfloat
) ix
, (GLfloat
) iy
, NULL
);
1729 // Invert the Glyph data.
1730 InvertGlyphBitmap(w
, h
, bitmapBuffer
, invertedBitmapBuffer
);
1732 // Render an OpenGL bitmap and invert the origin.
1734 (GLfloat
) ox
, (GLfloat
) (h
-oy
),
1735 (GLfloat
) ix
, (GLfloat
) iy
,
1736 (GLubyte
*) invertedBitmapBuffer
);
1739 // Close this display list.
1743 if (bSuccessOrFail
== FALSE
) {
1744 ddlogMessage(DDLOG_ERROR
, "DGL_UseFontBitmaps: Get glyph failed\n");
1745 _GLD_glDeleteLists((i
+listBase
), (i
-first
));
1748 // Release resources used
1749 DeleteObject(hFont
);
1753 __wglFree(bitmapBuffer
);
1754 if (invertedBitmapBuffer
)
1755 __wglFree(invertedBitmapBuffer
);
1757 return(bSuccessOrFail
);
1760 // ***********************************************************************
1762 BOOL APIENTRY
_GLD_WGL_EXPORT(UseFontBitmapsW
)(
1772 return _GLD_WGL_EXPORT(UseFontBitmapsA
)(a
, b
, c
, d
);
1775 // ***********************************************************************
1776 // ***********************************************************************
1777 // Support for outline TrueType fonts.
1778 // ***********************************************************************
1779 // ***********************************************************************
1781 void * __wglRealloc(
1785 void *newPtr
= NULL
;
1788 newPtr
= (void *) GlobalAlloc(GPTR
, newSize
);
1789 if (oldPtr
&& newPtr
) {
1790 DWORD oldSize
= GlobalSize(oldPtr
);
1792 memcpy(newPtr
, oldPtr
, (oldSize
<= newSize
? oldSize
: newSize
));
1795 } else if (oldPtr
) {
1798 if (newPtr
== NULL
) {
1799 return NULL
; /* XXX out of memory error */
1804 // ***********************************************************************
1807 /*****************************************************************************
1808 * wglUseFontOutlinesW
1810 * Converts a subrange of the glyphs in a TrueType font to OpenGL display
1812 *****************************************************************************/
1814 BOOL APIENTRY
_GLD_WGL_EXPORT(UseFontOutlinesW
)(
1819 IN FLOAT chordalDeviation
,
1822 OUT LPGLYPHMETRICSFLOAT lpgmf
)
1824 return _GLD_WGL_EXPORT(UseFontOutlinesA
)(hDC
, first
, count
, listBase
,
1825 chordalDeviation
, extrusion
, format
, lpgmf
);
1828 /*****************************************************************************
1829 * wglUseFontOutlinesA
1831 * Converts a subrange of the glyphs in a TrueType font to OpenGL display
1833 *****************************************************************************/
1835 BOOL APIENTRY
_GLD_WGL_EXPORT(UseFontOutlinesA
)(
1840 IN FLOAT chordalDeviation
,
1843 OUT LPGLYPHMETRICSFLOAT glyphMetricsFloatArray
)
1851 * Flush any previous OpenGL errors. This allows us to check for
1852 * new errors so they can be reported via the function return value.
1854 while (_GLD_glGetError() != GL_NO_ERROR
)
1858 * Make sure that the current font can be sampled accurately.
1860 hNewFont
= CreateHighResolutionFont(hDC
);
1864 hOldFont
= SelectObject(hDC
, hNewFont
);
1869 * Preallocate a buffer for the outline data, and track its size:
1871 glyphBuf
= (UCHAR
*) __wglMalloc(glyphBufSize
= 10240);
1873 return FALSE
; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
1876 * Process each glyph in the given range:
1878 for (glyphIndex
= first
; glyphIndex
- first
< count
; ++glyphIndex
)
1880 GLYPHMETRICS glyphMetrics
;
1882 static MAT2 matrix
=
1887 LPGLYPHMETRICSFLOAT glyphMetricsFloat
=
1888 &glyphMetricsFloatArray
[glyphIndex
- first
];
1892 * Determine how much space is needed to store the glyph's
1893 * outlines. If our glyph buffer isn't large enough,
1896 glyphSize
= GetGlyphOutline( hDC
,
1905 return FALSE
; /*WGL_STATUS_FAILURE*/
1906 if (glyphSize
> glyphBufSize
)
1908 __wglFree(glyphBuf
);
1909 glyphBuf
= (UCHAR
*) __wglMalloc(glyphBufSize
= glyphSize
);
1911 return FALSE
; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
1916 * Get the glyph's outlines.
1918 if (GetGlyphOutline( hDC
,
1927 __wglFree(glyphBuf
);
1928 return FALSE
; /*WGL_STATUS_FAILURE*/
1931 glyphMetricsFloat
->gmfBlackBoxX
=
1932 (FLOAT
) glyphMetrics
.gmBlackBoxX
* ScaleFactor
;
1933 glyphMetricsFloat
->gmfBlackBoxY
=
1934 (FLOAT
) glyphMetrics
.gmBlackBoxY
* ScaleFactor
;
1935 glyphMetricsFloat
->gmfptGlyphOrigin
.x
=
1936 (FLOAT
) glyphMetrics
.gmptGlyphOrigin
.x
* ScaleFactor
;
1937 glyphMetricsFloat
->gmfptGlyphOrigin
.y
=
1938 (FLOAT
) glyphMetrics
.gmptGlyphOrigin
.y
* ScaleFactor
;
1939 glyphMetricsFloat
->gmfCellIncX
=
1940 (FLOAT
) glyphMetrics
.gmCellIncX
* ScaleFactor
;
1941 glyphMetricsFloat
->gmfCellIncY
=
1942 (FLOAT
) glyphMetrics
.gmCellIncY
* ScaleFactor
;
1945 * Turn the glyph into a display list:
1947 if (!MakeDisplayListFromGlyph( (glyphIndex
- first
) + listBase
,
1951 chordalDeviation
+ ScaleFactor
,
1955 __wglFree(glyphBuf
);
1956 return FALSE
; /*WGL_STATUS_FAILURE*/
1962 * Clean up temporary storage and return. If an error occurred,
1963 * clear all OpenGL error flags and return FAILURE status;
1964 * otherwise just return SUCCESS.
1966 __wglFree(glyphBuf
);
1968 SelectObject(hDC
, hOldFont
);
1970 if (_GLD_glGetError() == GL_NO_ERROR
)
1971 return TRUE
; /*WGL_STATUS_SUCCESS*/
1974 while (_GLD_glGetError() != GL_NO_ERROR
)
1976 return FALSE
; /*WGL_STATUS_FAILURE*/
1982 /*****************************************************************************
1983 * CreateHighResolutionFont
1985 * Gets metrics for the current font and creates an equivalent font
1986 * scaled to the design units of the font.
1988 *****************************************************************************/
1991 CreateHighResolutionFont(HDC hDC
)
1994 OUTLINETEXTMETRIC
*otm
;
1995 LONG fontHeight
, fontWidth
, fontUnits
;
1998 otmSize
= GetOutlineTextMetrics(hDC
, 0, NULL
);
2002 otm
= (OUTLINETEXTMETRIC
*) __wglMalloc(otmSize
);
2006 otm
->otmSize
= otmSize
;
2007 if (GetOutlineTextMetrics(hDC
, otmSize
, otm
) == 0)
2010 fontHeight
= otm
->otmTextMetrics
.tmHeight
-
2011 otm
->otmTextMetrics
.tmInternalLeading
;
2012 fontWidth
= otm
->otmTextMetrics
.tmAveCharWidth
;
2013 fontUnits
= (LONG
) otm
->otmEMSquare
;
2015 ScaleFactor
= 1.0F
/ (FLOAT
) fontUnits
;
2017 logFont
.lfHeight
= - ((LONG
) fontUnits
);
2018 logFont
.lfWidth
= (LONG
)
2019 ((FLOAT
) (fontWidth
* fontUnits
) / (FLOAT
) fontHeight
);
2020 logFont
.lfEscapement
= 0;
2021 logFont
.lfOrientation
= 0;
2022 logFont
.lfWeight
= otm
->otmTextMetrics
.tmWeight
;
2023 logFont
.lfItalic
= otm
->otmTextMetrics
.tmItalic
;
2024 logFont
.lfUnderline
= otm
->otmTextMetrics
.tmUnderlined
;
2025 logFont
.lfStrikeOut
= otm
->otmTextMetrics
.tmStruckOut
;
2026 logFont
.lfCharSet
= otm
->otmTextMetrics
.tmCharSet
;
2027 logFont
.lfOutPrecision
= OUT_OUTLINE_PRECIS
;
2028 logFont
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
2029 logFont
.lfQuality
= DEFAULT_QUALITY
;
2030 logFont
.lfPitchAndFamily
=
2031 otm
->otmTextMetrics
.tmPitchAndFamily
& 0xf0;
2032 strcpy(logFont
.lfFaceName
,
2033 (char *)otm
+ (int)otm
->otmpFaceName
);
2035 hNewFont
= CreateFontIndirect(&logFont
);
2036 if (hNewFont
== NULL
)
2046 /*****************************************************************************
2047 * MakeDisplayListFromGlyph
2049 * Converts the outline of a glyph to an OpenGL display list.
2051 * Return value is nonzero for success, zero for failure.
2053 * Does not check for OpenGL errors, so if the caller needs to know about them,
2054 * it should call glGetError().
2055 *****************************************************************************/
2058 MakeDisplayListFromGlyph( IN DWORD listName
,
2061 IN LPGLYPHMETRICSFLOAT glyphMetricsFloat
,
2062 IN FLOAT chordalDeviation
,
2068 _GLD_glNewList(listName
, GL_COMPILE
);
2069 status
= DrawGlyph( glyphBuf
,
2075 _GLD_glTranslatef(glyphMetricsFloat
->gmfCellIncX
,
2076 glyphMetricsFloat
->gmfCellIncY
,
2085 /*****************************************************************************
2088 * Converts the outline of a glyph to OpenGL drawing primitives, tessellating
2089 * as needed, and then draws the glyph. Tessellation of the quadratic splines
2090 * in the outline is controlled by "chordalDeviation", and the drawing
2091 * primitives (lines or polygons) are selected by "format".
2093 * Return value is nonzero for success, zero for failure.
2095 * Does not check for OpenGL errors, so if the caller needs to know about them,
2096 * it should call glGetError().
2097 *****************************************************************************/
2100 DrawGlyph( IN UCHAR
* glyphBuf
,
2102 IN FLOAT chordalDeviation
,
2110 GLUtesselator
* tess
= NULL
;
2114 * Initialize the global buffer into which we place the outlines:
2121 * Convert the glyph outlines to a set of polyline loops.
2122 * (See MakeLinesFromGlyph() for the format of the loop data
2125 if (!MakeLinesFromGlyph(glyphBuf
, glyphSize
, chordalDeviation
))
2131 * Now draw the loops in the appropriate format:
2133 if (format
== WGL_FONT_LINES
)
2136 * This is the easy case. Just draw the outlines.
2138 for (loop
= (DWORD
) *p
++; loop
; --loop
)
2140 _GLD_glBegin(GL_LINE_LOOP
);
2141 for (point
= (DWORD
) *p
++; point
; --point
)
2143 _GLD_glVertex2fv(p
);
2151 else if (format
== WGL_FONT_POLYGONS
)
2158 * This is the hard case. We have to set up a tessellator
2159 * to convert the outlines into a set of polygonal
2160 * primitives, which the tessellator passes to some
2161 * auxiliary routines for drawing.
2163 if (!LoadGLUTesselator())
2167 if (!(tess
= gluNewTessProc()))
2169 gluTessCallbackProc(tess
, GLU_BEGIN
, (void(CALLBACK
*)()) _GLD_glBegin
);
2170 gluTessCallbackProc(tess
, GLU_TESS_VERTEX_DATA
,
2171 (void(CALLBACK
*)()) TessVertexOutData
);
2172 gluTessCallbackProc(tess
, GLU_END
, (void(CALLBACK
*)()) _GLD_glEnd
);
2173 gluTessCallbackProc(tess
, GLU_ERROR
, (void(CALLBACK
*)()) TessError
);
2174 gluTessCallbackProc(tess
, GLU_TESS_COMBINE
, (void(CALLBACK
*)()) TessCombine
);
2175 gluTessNormalProc(tess
, 0.0F
, 0.0F
, 1.0F
);
2177 TessErrorOccurred
= 0;
2178 _GLD_glNormal3f(0.0f
, 0.0f
, 1.0f
);
2182 gluTessBeginPolygonProc(tess
, (void *)*(int *)&z_value
);
2183 for (loop
= (DWORD
) *p
++; loop
; --loop
)
2185 gluTessBeginContourProc(tess
);
2187 for (point
= (DWORD
) *p
++; point
; --point
)
2191 gluTessVertexProc(tess
, v
, p
);
2195 gluTessEndContourProc(tess
);
2197 gluTessEndPolygonProc(tess
);
2199 status
= !TessErrorOccurred
;
2201 /* Extrusion code */
2204 GLfloat thickness
= (GLfloat
) -extrusion
;
2205 FLOAT
*vert
, *vert2
;
2209 loops
= (DWORD
) *p
++;
2211 for (loop
= 0; loop
< loops
; loop
++) {
2212 GLfloat dx
, dy
, len
;
2215 count
= (DWORD
) *p
++;
2216 _GLD_glBegin(GL_QUAD_STRIP
);
2218 /* Check if the first and last vertex are identical
2219 * so we don't draw the same quad twice.
2221 vert
= p
+ (count
-1)*2;
2222 last
= (p
[0] == vert
[0] && p
[1] == vert
[1]) ? count
-1 : count
;
2224 for (point
= 0; point
<= last
; point
++) {
2225 vert
= p
+ 2 * (point
% last
);
2226 vert2
= p
+ 2 * ((point
+1) % last
);
2228 dx
= vert
[0] - vert2
[0];
2229 dy
= vert
[1] - vert2
[1];
2230 len
= (GLfloat
)sqrt(dx
* dx
+ dy
* dy
);
2232 _GLD_glNormal3f(dy
/ len
, -dx
/ len
, 0.0f
);
2233 _GLD_glVertex3f((GLfloat
) vert
[0],
2234 (GLfloat
) vert
[1], thickness
);
2235 _GLD_glVertex3f((GLfloat
) vert
[0],
2236 (GLfloat
) vert
[1], 0.0f
);
2243 /* Draw the back face */
2246 _GLD_glNormal3f(0.0f
, 0.0f
, -1.0f
);
2247 gluTessNormalProc(tess
, 0.0F
, 0.0F
, -1.0F
);
2249 gluTessBeginPolygonProc(tess
, (void *)*(int *)&thickness
);
2251 for (loop
= (DWORD
) *p
++; loop
; --loop
)
2253 count
= (DWORD
) *p
++;
2255 gluTessBeginContourProc(tess
);
2257 for (point
= 0; point
< count
; point
++)
2259 vert
= p
+ ((count
-point
-1)<<1);
2262 gluTessVertexProc(tess
, v
, vert
);
2266 gluTessEndContourProc(tess
);
2268 gluTessEndPolygonProc(tess
);
2272 if (TessErrorOccurred
)
2273 printf("Tessellation error %s\n",
2274 gluErrorString(TessErrorOccurred
));
2282 gluDeleteTessProc(tess
);
2283 // UnloadGLUTesselator();
2290 /*****************************************************************************
2293 * Maps the glu32.dll module and gets function pointers for the
2294 * tesselator functions.
2295 *****************************************************************************/
2298 LoadGLUTesselator(void)
2300 if (gluModuleHandle
!= NULL
)
2304 extern HINSTANCE hInstanceOpenGL
;
2305 char *gluName
= "GLU32.DLL";
2311 len = GetModuleFileName(hInstanceOpenGL, name, 255);
2315 while (ptr > name && *ptr != '\\')
2319 if (!stricmp(ptr, "cosmogl.dll"))
2321 gluName = "COSMOGLU.DLL";
2323 else if (!stricmp(ptr, "opengl32.dll"))
2325 gluName = "GLU32.DLL";
2329 if ((gluModuleHandle
= LoadLibrary(gluName
)) == NULL
)
2333 if ((gluNewTessProc
= (gluNewTessProto
)
2334 GetProcAddress(gluModuleHandle
, "gluNewTess")) == NULL
)
2337 if ((gluDeleteTessProc
= (gluDeleteTessProto
)
2338 GetProcAddress(gluModuleHandle
, "gluDeleteTess")) == NULL
)
2341 if ((gluTessBeginPolygonProc
= (gluTessBeginPolygonProto
)
2342 GetProcAddress(gluModuleHandle
, "gluTessBeginPolygon")) == NULL
)
2345 if ((gluTessBeginContourProc
= (gluTessBeginContourProto
)
2346 GetProcAddress(gluModuleHandle
, "gluTessBeginContour")) == NULL
)
2349 if ((gluTessVertexProc
= (gluTessVertexProto
)
2350 GetProcAddress(gluModuleHandle
, "gluTessVertex")) == NULL
)
2353 if ((gluTessEndContourProc
= (gluTessEndContourProto
)
2354 GetProcAddress(gluModuleHandle
, "gluTessEndContour")) == NULL
)
2357 if ((gluTessEndPolygonProc
= (gluTessEndPolygonProto
)
2358 GetProcAddress(gluModuleHandle
, "gluTessEndPolygon")) == NULL
)
2361 if ((gluTessPropertyProc
= (gluTessPropertyProto
)
2362 GetProcAddress(gluModuleHandle
, "gluTessProperty")) == NULL
)
2365 if ((gluTessNormalProc
= (gluTessNormalProto
)
2366 GetProcAddress(gluModuleHandle
, "gluTessNormal")) == NULL
)
2369 if ((gluTessCallbackProc
= (gluTessCallbackProto
)
2370 GetProcAddress(gluModuleHandle
, "gluTessCallback")) == NULL
)
2378 /*****************************************************************************
2379 * UnloadGLUTesselator
2381 * Unmaps the glu32.dll module.
2382 *****************************************************************************/
2385 UnloadGLUTesselator(void)
2387 if (gluModuleHandle
!= NULL
)
2388 if (FreeLibrary(gluModuleHandle
) == FALSE
)
2390 gluModuleHandle
= NULL
;
2395 /*****************************************************************************
2398 * Used by tessellator to handle output vertexes.
2399 *****************************************************************************/
2401 static void CALLBACK
2402 TessVertexOut(FLOAT p
[3])
2406 v
[0] = p
[0] * ScaleFactor
;
2407 v
[1] = p
[1] * ScaleFactor
;
2408 _GLD_glVertex2fv(v
);
2411 static void CALLBACK
2412 TessVertexOutData(FLOAT p
[3], GLfloat z
)
2416 v
[0] = (GLfloat
) p
[0];
2417 v
[1] = (GLfloat
) p
[1];
2419 _GLD_glVertex3fv(v
);
2423 /*****************************************************************************
2426 * Used by tessellator to handle self-intersecting contours and degenerate
2428 *****************************************************************************/
2430 static void CALLBACK
2431 TessCombine(double coords
[3],
2432 void* vertex_data
[4],
2436 if (!AppendToVertBuf((FLOAT
) coords
[0])
2437 || !AppendToVertBuf((FLOAT
) coords
[1])
2438 || !AppendToVertBuf((FLOAT
) coords
[2]))
2439 TessErrorOccurred
= GL_OUT_OF_MEMORY
;
2440 *outData
= VertBuf
+ (VertBufIndex
- 3);
2445 /*****************************************************************************
2448 * Saves the last tessellator error code in the global TessErrorOccurred.
2449 *****************************************************************************/
2451 static void CALLBACK
2452 TessError(GLenum error
)
2454 TessErrorOccurred
= error
;
2459 /*****************************************************************************
2460 * MakeLinesFromGlyph
2462 * Converts the outline of a glyph from the TTPOLYGON format to a simple
2463 * array of floating-point values containing one or more loops.
2465 * The first element of the output array is a count of the number of loops.
2466 * The loop data follows this count. Each loop consists of a count of the
2467 * number of vertices it contains, followed by the vertices. Each vertex
2468 * is an X and Y coordinate. For example, a single triangle might be
2469 * described by this array:
2471 * 1., 3., 0., 0., 1., 0., 0., 1.
2473 * #loops #verts x1 y1 x2 y2 x3 y3
2475 * A two-loop glyph would look like this:
2477 * 2., 3., 0.,0., 1.,0., 0.,1., 3., .2,.2, .4,.2, .2,.4
2479 * Line segments from the TTPOLYGON are transferred to the output array in
2480 * the obvious way. Quadratic splines in the TTPOLYGON are converted to
2481 * collections of line segments
2482 *****************************************************************************/
2485 MakeLinesFromGlyph(IN UCHAR
* glyphBuf
,
2487 IN FLOAT chordalDeviation
)
2494 * Pick up all the polygons (aka loops) that make up the glyph:
2496 if (!AppendToLineBuf(0.0F
)) /* loop count at LineBuf[0] */
2500 while (p
< glyphBuf
+ glyphSize
)
2502 if (!MakeLinesFromTTPolygon(&p
, chordalDeviation
))
2504 LineBuf
[0] += 1.0F
; /* increment loop count */
2515 /*****************************************************************************
2516 * MakeLinesFromTTPolygon
2518 * Converts a TTPOLYGONHEADER and its associated curve structures into a
2519 * single polyline loop in the global LineBuf.
2520 *****************************************************************************/
2523 MakeLinesFromTTPolygon( IN OUT UCHAR
** pp
,
2524 IN FLOAT chordalDeviation
)
2528 DWORD vertexCountIndex
;
2531 * Record where the polygon data begins, and where the loop's
2532 * vertex count resides:
2535 vertexCountIndex
= LineBufIndex
;
2536 if (!AppendToLineBuf(0.0F
))
2540 * Extract relevant data from the TTPOLYGONHEADER:
2542 polySize
= GetDWord(pp
);
2543 if (GetDWord(pp
) != TT_POLYGON_TYPE
) /* polygon type */
2545 if (!AppendToLineBuf((FLOAT
) GetFixed(pp
))) /* first X coord */
2547 if (!AppendToLineBuf((FLOAT
) GetFixed(pp
))) /* first Y coord */
2549 LineBuf
[vertexCountIndex
] += 1.0F
;
2552 * Process each of the TTPOLYCURVE structures in the polygon:
2554 while (*pp
< polyStart
+ polySize
)
2555 if (!MakeLinesFromTTPolycurve( pp
,
2565 /*****************************************************************************
2566 * MakeLinesFromTTPolyCurve
2568 * Converts the lines and splines in a single TTPOLYCURVE structure to points
2569 * in the global LineBuf.
2570 *****************************************************************************/
2573 MakeLinesFromTTPolycurve( IN OUT UCHAR
** pp
,
2574 IN DWORD vertexCountIndex
,
2575 IN FLOAT chordalDeviation
)
2582 * Pick up the relevant fields of the TTPOLYCURVE structure:
2584 type
= (WORD
) GetWord(pp
);
2585 pointCount
= (WORD
) GetWord(pp
);
2588 * Convert the "curve" to line segments:
2590 if (type
== TT_PRIM_LINE
)
2591 return MakeLinesFromTTLine( pp
,
2594 else if (type
== TT_PRIM_QSPLINE
)
2595 return MakeLinesFromTTQSpline( pp
,
2605 /*****************************************************************************
2606 * MakeLinesFromTTLine
2608 * Converts points from the polyline in a TT_PRIM_LINE structure to
2609 * equivalent points in the global LineBuf.
2610 *****************************************************************************/
2612 MakeLinesFromTTLine( IN OUT UCHAR
** pp
,
2613 IN DWORD vertexCountIndex
,
2617 * Just copy the line segments into the line buffer (converting
2620 LineBuf
[vertexCountIndex
] += pointCount
;
2621 while (pointCount
--)
2623 if (!AppendToLineBuf((FLOAT
) GetFixed(pp
)) /* X coord */
2624 || !AppendToLineBuf((FLOAT
) GetFixed(pp
))) /* Y coord */
2633 /*****************************************************************************
2634 * MakeLinesFromTTQSpline
2636 * Converts points from the poly quadratic spline in a TT_PRIM_QSPLINE
2637 * structure to polyline points in the global LineBuf.
2638 *****************************************************************************/
2641 MakeLinesFromTTQSpline( IN OUT UCHAR
** pp
,
2642 IN DWORD vertexCountIndex
,
2644 IN FLOAT chordalDeviation
)
2646 FLOAT x0
, y0
, x1
, y1
, x2
, y2
;
2650 * Process each of the non-interpolated points in the outline.
2651 * To do this, we need to generate two interpolated points (the
2652 * start and end of the arc) for each non-interpolated point.
2653 * The first interpolated point is always the one most recently
2654 * stored in LineBuf, so we just extract it from there. The
2655 * second interpolated point is either the average of the next
2656 * two points in the QSpline, or the last point in the QSpline
2657 * if only one remains.
2659 for (point
= 0; point
< pointCount
- 1; ++point
)
2661 x0
= LineBuf
[LineBufIndex
- 2];
2662 y0
= LineBuf
[LineBufIndex
- 1];
2664 x1
= (FLOAT
) GetFixed(pp
);
2665 y1
= (FLOAT
) GetFixed(pp
);
2667 if (point
== pointCount
- 2)
2670 * This is the last arc in the QSpline. The final
2671 * point is the end of the arc.
2673 x2
= (FLOAT
) GetFixed(pp
);
2674 y2
= (FLOAT
) GetFixed(pp
);
2679 * Peek at the next point in the input to compute
2680 * the end of the arc:
2682 x2
= 0.5F
* (x1
+ (FLOAT
) GetFixed(pp
));
2683 y2
= 0.5F
* (y1
+ (FLOAT
) GetFixed(pp
));
2685 * Push the point back onto the input so it will
2686 * be reused as the next off-curve point:
2691 if (!MakeLinesFromArc( x0
, y0
,
2695 chordalDeviation
* chordalDeviation
))
2704 /*****************************************************************************
2707 * Subdivides one arc of a quadratic spline until the chordal deviation
2708 * tolerance requirement is met, then places the resulting set of line
2709 * segments in the global LineBuf.
2710 *****************************************************************************/
2713 MakeLinesFromArc( IN FLOAT x0
,
2719 IN DWORD vertexCountIndex
,
2720 IN FLOAT chordalDeviationSquared
)
2732 * Calculate midpoint of the curve by de Casteljau:
2734 x01
= 0.5F
* (x0
+ x1
);
2735 y01
= 0.5F
* (y0
+ y1
);
2736 x12
= 0.5F
* (x1
+ x2
);
2737 y12
= 0.5F
* (y1
+ y2
);
2738 midPointX
= 0.5F
* (x01
+ x12
);
2739 midPointY
= 0.5F
* (y01
+ y12
);
2743 * Estimate chordal deviation by the distance from the midpoint
2744 * of the curve to its non-interpolated control point. If this
2745 * distance is greater than the specified chordal deviation
2746 * constraint, then subdivide. Otherwise, generate polylines
2747 * from the three control points.
2749 deltaX
= midPointX
- x1
;
2750 deltaY
= midPointY
- y1
;
2751 if (deltaX
* deltaX
+ deltaY
* deltaY
> chordalDeviationSquared
)
2753 MakeLinesFromArc( x0
, y0
,
2755 midPointX
, midPointY
,
2757 chordalDeviationSquared
);
2759 MakeLinesFromArc( midPointX
, midPointY
,
2763 chordalDeviationSquared
);
2768 * The "pen" is already at (x0, y0), so we don't need to
2769 * add that point to the LineBuf.
2771 if (!AppendToLineBuf(x1
)
2772 || !AppendToLineBuf(y1
)
2773 || !AppendToLineBuf(x2
)
2774 || !AppendToLineBuf(y2
))
2776 LineBuf
[vertexCountIndex
] += 2.0F
;
2784 /*****************************************************************************
2787 * Initializes the global LineBuf and its associated size and current-element
2789 *****************************************************************************/
2794 if (!(LineBuf
= (FLOAT
*)
2795 __wglMalloc((LineBufSize
= LINE_BUF_QUANT
) * sizeof(FLOAT
))))
2803 /*****************************************************************************
2806 * Initializes the global VertBuf and its associated size and current-element
2808 *****************************************************************************/
2813 if (!(VertBuf
= (FLOAT
*)
2814 __wglMalloc((VertBufSize
= VERT_BUF_QUANT
) * sizeof(FLOAT
))))
2822 /*****************************************************************************
2825 * Appends one floating-point value to the global LineBuf array. Return value
2826 * is non-zero for success, zero for failure.
2827 *****************************************************************************/
2830 AppendToLineBuf(FLOAT value
)
2832 if (LineBufIndex
>= LineBufSize
)
2836 f
= (FLOAT
*) __wglRealloc(LineBuf
,
2837 (LineBufSize
+= LINE_BUF_QUANT
) * sizeof(FLOAT
));
2842 LineBuf
[LineBufIndex
++] = value
;
2848 /*****************************************************************************
2851 * Appends one floating-point value to the global VertBuf array. Return value
2852 * is non-zero for success, zero for failure.
2854 * Note that we can't realloc this one, because the tessellator is using
2856 *****************************************************************************/
2859 AppendToVertBuf(FLOAT value
)
2861 if (VertBufIndex
>= VertBufSize
)
2863 VertBuf
[VertBufIndex
++] = value
;
2869 /*****************************************************************************
2872 * Cleans up vertex buffer structure.
2873 *****************************************************************************/
2887 /*****************************************************************************
2890 * Cleans up vertex buffer structure.
2891 *****************************************************************************/
2905 /*****************************************************************************
2908 * Fetch the next 16-bit word from a little-endian byte stream, and increment
2909 * the stream pointer to the next unscanned byte.
2910 *****************************************************************************/
2912 static long GetWord(UCHAR
** p
)
2916 value
= ((*p
)[1] << 8) + (*p
)[0];
2923 /*****************************************************************************
2926 * Fetch the next 32-bit word from a little-endian byte stream, and increment
2927 * the stream pointer to the next unscanned byte.
2928 *****************************************************************************/
2930 static long GetDWord(UCHAR
** p
)
2934 value
= ((*p
)[3] << 24) + ((*p
)[2] << 16) + ((*p
)[1] << 8) + (*p
)[0];
2942 /*****************************************************************************
2945 * Fetch the next 32-bit fixed-point value from a little-endian byte stream,
2946 * convert it to floating-point, and increment the stream pointer to the next
2948 *****************************************************************************/
2950 static double GetFixed(
2953 long hiBits
, loBits
;
2956 loBits
= GetWord(p
);
2957 hiBits
= GetWord(p
);
2958 value
= (double) ((hiBits
<< 16) | loBits
) / 65536.0;
2960 return value
* ScaleFactor
;
2963 // ***********************************************************************