test version of startmenu root with big icons
[reactos.git] / reactos / lib / mesa32 / src / drivers / windows / gldirect / dglwgl.c
1 /****************************************************************************
2 *
3 * Mesa 3-D graphics library
4 * Direct3D Driver Interface
5 *
6 * ========================================================================
7 *
8 * Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
9 *
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:
16 *
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
19 *
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
26 * SOFTWARE.
27 *
28 * ======================================================================
29 *
30 * Language: ANSI C
31 * Environment: Windows 9x (Win32)
32 *
33 * Description: OpenGL window functions (wgl*).
34 *
35 ****************************************************************************/
36
37 #include "dglwgl.h"
38 #ifdef _USE_GLD3_WGL
39 #include "gld_driver.h"
40 #endif
41
42 #include "glu.h" // MUST USE MICROSOFT'S GLU32!
43
44 #ifndef _USE_GLD3_WGL
45 extern DGL_mesaFuncs mesaFuncs;
46 #endif
47
48 // Need to export wgl* functions if using GLD3,
49 // otherwise export GLD2 DGL_* functions.
50 #ifdef _USE_GLD3_WGL
51 #define _GLD_WGL_EXPORT(a) wgl##a
52 #else
53 #define _GLD_WGL_EXPORT(a) DGL_##a
54 #endif
55
56 // Calls into Mesa 4.x are different
57 #ifdef _USE_GLD3_WGL
58 #include "dlist.h"
59 #include "drawpix.h"
60 #include "get.h"
61 #include "matrix.h"
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
90
91 // ***********************************************************************
92
93 // Emulate SGI DDK calls.
94 #define __wglMalloc(a) GlobalAlloc(GPTR, (a))
95 #define __wglFree(a) GlobalFree((a))
96
97 // ***********************************************************************
98
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
102
103 // For wglFontOutlines
104
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 *)());
115
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;
127
128 static HFONT hNewFont, hOldFont;
129 static FLOAT ScaleFactor;
130
131 #define LINE_BUF_QUANT 4000
132 #define VERT_BUF_QUANT 4000
133
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;
141
142 static int AppendToLineBuf(
143 FLOAT value);
144
145 static int AppendToVertBuf(
146 FLOAT value);
147
148 static int DrawGlyph(
149 UCHAR* glyphBuf,
150 DWORD glyphSize,
151 FLOAT chordalDeviation,
152 FLOAT extrusion,
153 INT format);
154
155 static void FreeLineBuf(void);
156
157 static void FreeVertBuf(void);
158
159 static long GetWord(
160 UCHAR** p);
161
162 static long GetDWord(
163 UCHAR** p);
164
165 static double GetFixed(
166 UCHAR** p);
167
168 static int InitLineBuf(void);
169
170 static int InitVertBuf(void);
171
172 static HFONT CreateHighResolutionFont(
173 HDC hDC);
174
175 static int MakeDisplayListFromGlyph(
176 DWORD listName,
177 UCHAR* glyphBuf,
178 DWORD glyphSize,
179 LPGLYPHMETRICSFLOAT glyphMetricsFloat,
180 FLOAT chordalDeviation,
181 FLOAT extrusion,
182 INT format);
183
184 static BOOL LoadGLUTesselator(void);
185 static BOOL UnloadGLUTesselator(void);
186
187 static int MakeLinesFromArc(
188 FLOAT x0,
189 FLOAT y0,
190 FLOAT x1,
191 FLOAT y1,
192 FLOAT x2,
193 FLOAT y2,
194 DWORD vertexCountIndex,
195 FLOAT chordalDeviationSquared);
196
197 static int MakeLinesFromGlyph( UCHAR* glyphBuf,
198 DWORD glyphSize,
199 FLOAT chordalDeviation);
200
201 static int MakeLinesFromTTLine( UCHAR** pp,
202 DWORD vertexCountIndex,
203 WORD pointCount);
204
205 static int MakeLinesFromTTPolycurve( UCHAR** pp,
206 DWORD vertexCountIndex,
207 FLOAT chordalDeviation);
208
209 static int MakeLinesFromTTPolygon( UCHAR** pp,
210 FLOAT chordalDeviation);
211
212 static int MakeLinesFromTTQSpline( UCHAR** pp,
213 DWORD vertexCountIndex,
214 WORD pointCount,
215 FLOAT chordalDeviation);
216
217 static void CALLBACK TessCombine( double coords[3],
218 void* vertex_data[4],
219 FLOAT weight[4],
220 void** outData);
221
222 static void CALLBACK TessError( GLenum error);
223
224 static void CALLBACK TessVertexOutData( FLOAT p[3],
225 GLfloat z);
226
227 // ***********************************************************************
228
229 #ifdef GLD_THREADS
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
233 #endif
234 int curPFD = 0; // Current PFD (static)
235
236 // ***********************************************************************
237
238 int dglGetPixelFormat(void)
239 {
240 #ifdef GLD_THREADS
241 int iPixelFormat;
242 // get thread-specific instance
243 if (glb.bMultiThreaded) {
244 __try {
245 iPixelFormat = (int)TlsGetValue(dwTLSPixelFormat);
246 }
247 __except(EXCEPTION_EXECUTE_HANDLER) {
248 iPixelFormat = curPFD;
249 }
250 }
251 // get global static var
252 else {
253 iPixelFormat = curPFD;
254 }
255 return iPixelFormat;
256 #else
257 return curPFD;
258 #endif
259 }
260
261 // ***********************************************************************
262
263 void dglSetPixelFormat(int iPixelFormat)
264 {
265 #ifdef GLD_THREADS
266 // set thread-specific instance
267 if (glb.bMultiThreaded) {
268 __try {
269 TlsSetValue(dwTLSPixelFormat, (LPVOID)iPixelFormat);
270 }
271 __except(EXCEPTION_EXECUTE_HANDLER) {
272 curPFD = iPixelFormat;
273 }
274 }
275 // set global static var
276 else {
277 curPFD = iPixelFormat;
278 }
279 #else
280 curPFD = iPixelFormat;
281 #endif
282 }
283
284 // ***********************************************************************
285
286 int APIENTRY _GLD_WGL_EXPORT(ChoosePixelFormat)(
287 HDC a,
288 CONST PIXELFORMATDESCRIPTOR *ppfd)
289 {
290 DGL_pixelFormat *lpPF = glb.lpPF;
291
292 PIXELFORMATDESCRIPTOR ppfdBest;
293 int i;
294 int bestIndex = -1;
295 int numPixelFormats;
296 DWORD dwFlags;
297
298 char buf[128];
299 char cat[8];
300
301 DWORD dwAllFlags =
302 PFD_DRAW_TO_WINDOW |
303 PFD_DRAW_TO_BITMAP |
304 PFD_SUPPORT_GDI |
305 PFD_SUPPORT_OPENGL |
306 PFD_GENERIC_FORMAT |
307 PFD_NEED_PALETTE |
308 PFD_NEED_SYSTEM_PALETTE |
309 PFD_DOUBLEBUFFER |
310 PFD_STEREO |
311 /*PFD_SWAP_LAYER_BUFFERS |*/
312 PFD_DOUBLEBUFFER_DONTCARE |
313 PFD_STEREO_DONTCARE |
314 PFD_SWAP_COPY |
315 PFD_SWAP_EXCHANGE |
316 PFD_GENERIC_ACCELERATED |
317 0;
318
319 // Validate license
320 if (!dglValidate())
321 return 0;
322
323 // List may not be built until dglValidate() is called! KeithH
324 lpPF = glb.lpPF;
325
326 //
327 // Lets print the input pixel format to the log
328 // ** Based on "wglinfo" by Nate Robins **
329 //
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");
338 sprintf(buf, " . ");
339
340 sprintf(cat, "%2d ", ppfd->cColorBits);
341 strcat(buf, cat);
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, ". ");
345 strcat(buf, cat);
346
347 /* should find transparent pixel from LAYERPLANEDESCRIPTOR */
348 sprintf(cat, " . ");
349 strcat(buf, cat);
350
351 sprintf(cat, "%2d ", ppfd->cColorBits);
352 strcat(buf, cat);
353
354 /* bReserved field indicates number of over/underlays */
355 if(ppfd->bReserved) sprintf(cat, " %d ", ppfd->bReserved);
356 else sprintf(cat, " . ");
357 strcat(buf, cat);
358
359 sprintf(cat, " %c ", ppfd->iPixelType == PFD_TYPE_RGBA ? 'r' : 'c');
360 strcat(buf, cat);
361
362 sprintf(cat, "%c ", ppfd->dwFlags & PFD_DOUBLEBUFFER ? 'y' : '.');
363 strcat(buf, cat);
364
365 sprintf(cat, " %c ", ppfd->dwFlags & PFD_STEREO ? 'y' : '.');
366 strcat(buf, cat);
367
368 if(ppfd->cRedBits && ppfd->iPixelType == PFD_TYPE_RGBA)
369 sprintf(cat, "%2d ", ppfd->cRedBits);
370 else sprintf(cat, " . ");
371 strcat(buf, cat);
372
373 if(ppfd->cGreenBits && ppfd->iPixelType == PFD_TYPE_RGBA)
374 sprintf(cat, "%2d ", ppfd->cGreenBits);
375 else sprintf(cat, " . ");
376 strcat(buf, cat);
377
378 if(ppfd->cBlueBits && ppfd->iPixelType == PFD_TYPE_RGBA)
379 sprintf(cat, "%2d ", ppfd->cBlueBits);
380 else sprintf(cat, " . ");
381 strcat(buf, cat);
382
383 if(ppfd->cAlphaBits && ppfd->iPixelType == PFD_TYPE_RGBA)
384 sprintf(cat, "%2d ", ppfd->cAlphaBits);
385 else sprintf(cat, " . ");
386 strcat(buf, cat);
387
388 if(ppfd->cAuxBuffers) sprintf(cat, "%2d ", ppfd->cAuxBuffers);
389 else sprintf(cat, " . ");
390 strcat(buf, cat);
391
392 if(ppfd->cDepthBits) sprintf(cat, "%2d ", ppfd->cDepthBits);
393 else sprintf(cat, " . ");
394 strcat(buf, cat);
395
396 if(ppfd->cStencilBits) sprintf(cat, "%2d ", ppfd->cStencilBits);
397 else sprintf(cat, " . ");
398 strcat(buf, cat);
399
400 if(ppfd->cAccumRedBits) sprintf(cat, "%2d ", ppfd->cAccumRedBits);
401 else sprintf(cat, " . ");
402 strcat(buf, cat);
403
404 if(ppfd->cAccumGreenBits) sprintf(cat, "%2d ", ppfd->cAccumGreenBits);
405 else sprintf(cat, " . ");
406 strcat(buf, cat);
407
408 if(ppfd->cAccumBlueBits) sprintf(cat, "%2d ", ppfd->cAccumBlueBits);
409 else sprintf(cat, " . ");
410 strcat(buf, cat);
411
412 if(ppfd->cAccumAlphaBits) sprintf(cat, "%2d ", ppfd->cAccumAlphaBits);
413 else sprintf(cat, " . ");
414 strcat(buf, cat);
415
416 /* no multisample in Win32 */
417 sprintf(cat, " . .\n");
418 strcat(buf, cat);
419
420 ddlogMessage(DDLOG_INFO, buf);
421 ddlogMessage(DDLOG_INFO,
422 "-----------------------------------------------------------------\n");
423 ddlogMessage(DDLOG_INFO, "\n");
424
425 //
426 // Examine the flags for correctness
427 //
428 dwFlags = ppfd->dwFlags;
429 if (dwFlags != (dwFlags & dwAllFlags))
430 {
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;
437 }
438
439 switch (ppfd->iPixelType) {
440 case PFD_TYPE_RGBA:
441 case PFD_TYPE_COLORINDEX:
442 break;
443 default:
444 /* error: bad iPixelType */
445 ddlogMessage(DDLOG_WARN, "ChoosePixelFormat: bad pixel type\n");
446 return 0;
447 }
448
449 switch (ppfd->iLayerType) {
450 case PFD_MAIN_PLANE:
451 case PFD_OVERLAY_PLANE:
452 case PFD_UNDERLAY_PLANE:
453 break;
454 default:
455 /* error: bad iLayerType */
456 ddlogMessage(DDLOG_WARN, "ChoosePixelFormat: bad layer type\n");
457 return 0;
458 }
459
460 numPixelFormats = glb.nPixelFormatCount;
461
462 /* loop through candidate pixel format descriptors */
463 for (i=0; i<numPixelFormats; ++i) {
464 PIXELFORMATDESCRIPTOR ppfdCandidate;
465
466 memcpy(&ppfdCandidate, &lpPF[i].pfd, sizeof(PIXELFORMATDESCRIPTOR));
467
468 /*
469 ** Check attributes which must match
470 */
471 if (ppfd->iPixelType != ppfdCandidate.iPixelType) {
472 continue;
473 }
474
475 if (ppfd->iLayerType != ppfdCandidate.iLayerType) {
476 continue;
477 }
478
479 if (((dwFlags ^ ppfdCandidate.dwFlags) & dwFlags) &
480 (PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP |
481 PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL))
482 {
483 continue;
484 }
485
486 if (!(dwFlags & PFD_DOUBLEBUFFER_DONTCARE)) {
487 if ((dwFlags & PFD_DOUBLEBUFFER) !=
488 (ppfdCandidate.dwFlags & PFD_DOUBLEBUFFER))
489 {
490 continue;
491 }
492 }
493
494 // if (!(dwFlags & PFD_STEREO_DONTCARE)) {
495 if ((dwFlags & PFD_STEREO) !=
496 (ppfdCandidate.dwFlags & PFD_STEREO))
497 {
498 continue;
499 }
500 // }
501
502 if (ppfd->iPixelType==PFD_TYPE_RGBA
503 && ppfd->cAlphaBits && !ppfdCandidate.cAlphaBits) {
504 continue;
505 }
506
507 if (ppfd->iPixelType==PFD_TYPE_RGBA
508 && ppfd->cAccumBits && !ppfdCandidate.cAccumBits) {
509 continue;
510 }
511
512 if (ppfd->cDepthBits && !ppfdCandidate.cDepthBits) {
513 continue;
514 }
515
516 if (ppfd->cStencilBits && !ppfdCandidate.cStencilBits) {
517 continue;
518 }
519
520 if (ppfd->cAuxBuffers && !ppfdCandidate.cAuxBuffers) {
521 continue;
522 }
523
524 /*
525 ** See if candidate is better than the previous best choice
526 */
527 if (bestIndex == -1) {
528 ppfdBest = ppfdCandidate;
529 bestIndex = i;
530 continue;
531 }
532
533 if ((ppfd->cColorBits > ppfdBest.cColorBits &&
534 ppfdCandidate.cColorBits > ppfdBest.cColorBits) ||
535 (ppfd->cColorBits <= ppfdCandidate.cColorBits &&
536 ppfdCandidate.cColorBits < ppfdBest.cColorBits))
537 {
538 ppfdBest = ppfdCandidate;
539 bestIndex = i;
540 continue;
541 }
542
543 if (ppfd->iPixelType==PFD_TYPE_RGBA
544 && ppfd->cAlphaBits
545 && ppfdCandidate.cAlphaBits > ppfdBest.cAlphaBits)
546 {
547 ppfdBest = ppfdCandidate;
548 bestIndex = i;
549 continue;
550 }
551
552 if (ppfd->iPixelType==PFD_TYPE_RGBA
553 && ppfd->cAccumBits
554 && ppfdCandidate.cAccumBits > ppfdBest.cAccumBits)
555 {
556 ppfdBest = ppfdCandidate;
557 bestIndex = i;
558 continue;
559 }
560
561 if ((ppfd->cDepthBits > ppfdBest.cDepthBits &&
562 ppfdCandidate.cDepthBits > ppfdBest.cDepthBits) ||
563 (ppfd->cDepthBits <= ppfdCandidate.cDepthBits &&
564 ppfdCandidate.cDepthBits < ppfdBest.cDepthBits))
565 {
566 ppfdBest = ppfdCandidate;
567 bestIndex = i;
568 continue;
569 }
570
571 if (ppfd->cStencilBits &&
572 ppfdCandidate.cStencilBits > ppfdBest.cStencilBits)
573 {
574 ppfdBest = ppfdCandidate;
575 bestIndex = i;
576 continue;
577 }
578
579 if (ppfd->cAuxBuffers &&
580 ppfdCandidate.cAuxBuffers > ppfdBest.cAuxBuffers)
581 {
582 ppfdBest = ppfdCandidate;
583 bestIndex = i;
584 continue;
585 }
586 }
587
588 if (bestIndex != -1) {
589 ddlogPrintf(DDLOG_SYSTEM, "Pixel Format %d chosen as best match", bestIndex+1);
590 return bestIndex + 1;
591 }
592
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);
599 return (bestIndex);
600 }
601
602 // ***********************************************************************
603
604 BOOL APIENTRY _GLD_WGL_EXPORT(CopyContext)(
605 HGLRC a,
606 HGLRC b,
607 UINT c)
608 {
609 // Validate license
610 if (!dglValidate())
611 return FALSE;
612 UNSUPPORTED("wglCopyContext")
613 return FALSE; // Failed
614 }
615
616 // ***********************************************************************
617
618 HGLRC APIENTRY _GLD_WGL_EXPORT(CreateContext)(
619 HDC a)
620 {
621 int ipf;
622
623 // Validate license
624 if (!dglValidate())
625 return 0;
626
627 // Check that the current PFD is valid
628 ipf = dglGetPixelFormat();
629 if (!IsValidPFD(ipf))
630 return (HGLRC)0;
631
632 return dglCreateContext(a, &glb.lpPF[ipf-1]);
633 }
634
635 // ***********************************************************************
636
637 HGLRC APIENTRY _GLD_WGL_EXPORT(CreateLayerContext)(
638 HDC a,
639 int b)
640 {
641 // Validate license
642 if (!dglValidate())
643 return 0;
644
645 UNSUPPORTED("wglCreateLayerContext")
646 return NULL; // Failed
647 }
648
649 // ***********************************************************************
650
651 BOOL APIENTRY _GLD_WGL_EXPORT(DeleteContext)(
652 HGLRC a)
653 {
654 // Validate license
655 if (!dglValidate())
656 return FALSE;
657
658 return dglDeleteContext(a);
659 }
660
661 // ***********************************************************************
662
663 BOOL APIENTRY _GLD_WGL_EXPORT(DescribeLayerPlane)(
664 HDC hDC,
665 int iPixelFormat,
666 int iLayerPlane,
667 UINT nBytes,
668 LPLAYERPLANEDESCRIPTOR plpd)
669 {
670 // Validate license
671 if (!dglValidate())
672 return FALSE;
673
674 UNSUPPORTED("DGL_DescribeLayerPlane")
675
676 // gldLogPrintf(GLDLOG_INFO, "DescribeLayerPlane: %d, %d", iPixelFormat, iLayerPlane);
677
678 return FALSE;
679 }
680
681 // ***********************************************************************
682
683 int APIENTRY _GLD_WGL_EXPORT(DescribePixelFormat)(
684 HDC a,
685 int b,
686 UINT c,
687 LPPIXELFORMATDESCRIPTOR d)
688 {
689 UINT nSize;
690
691 // Validate license
692 if (!dglValidate())
693 return 0;
694
695 if (d == NULL) // Calling app requires max number of PF's
696 return glb.nPixelFormatCount;
697
698 // The supplied buffer may be larger than the info that we
699 // will be copying.
700 if (c > sizeof(PIXELFORMATDESCRIPTOR))
701 nSize = sizeof(PIXELFORMATDESCRIPTOR);
702 else
703 nSize = c;
704
705 // Setup an empty PFD before doing validation check
706 memset(d, 0, nSize);
707 d->nSize = nSize;
708 d->nVersion = 1;
709
710 if (!IsValidPFD(b))
711 return 0; // Bail if PFD index is invalid
712
713 memcpy(d, &glb.lpPF[b-1].pfd, nSize);
714
715 return glb.nPixelFormatCount;
716 }
717
718 // ***********************************************************************
719
720 HGLRC APIENTRY _GLD_WGL_EXPORT(GetCurrentContext)(void)
721 {
722 // Validate license
723 if (!dglValidate())
724 return 0;
725
726 return dglGetCurrentContext();
727 }
728
729 // ***********************************************************************
730
731 HDC APIENTRY _GLD_WGL_EXPORT(GetCurrentDC)(void)
732 {
733 // Validate license
734 if (!dglValidate())
735 return 0;
736
737 return dglGetCurrentDC();
738 }
739
740 // ***********************************************************************
741
742 PROC APIENTRY _GLD_WGL_EXPORT(GetDefaultProcAddress)(
743 LPCSTR a)
744 {
745 // Validate license
746 if (!dglValidate())
747 return NULL;
748
749 UNSUPPORTED("DGL_GetDefaultProcAddress")
750 return NULL;
751 }
752
753 // ***********************************************************************
754
755 int APIENTRY _GLD_WGL_EXPORT(GetLayerPaletteEntries)(
756 HDC a,
757 int b,
758 int c,
759 int d,
760 COLORREF *e)
761 {
762 // Validate license
763 if (!dglValidate())
764 return 0;
765
766 UNSUPPORTED("DGL_GetLayerPaletteEntries")
767 return 0;
768 }
769
770 // ***********************************************************************
771
772 int APIENTRY _GLD_WGL_EXPORT(GetPixelFormat)(
773 HDC a)
774 {
775 // Validate license
776 if (!dglValidate())
777 return 0;
778
779 return dglGetPixelFormat();
780 }
781
782 // ***********************************************************************
783
784 PROC APIENTRY _GLD_WGL_EXPORT(GetProcAddress)(
785 LPCSTR a)
786 {
787 PROC dglGetProcAddressD3D(LPCSTR a);
788
789 // Validate license
790 if (!dglValidate())
791 return NULL;
792
793 #ifdef _USE_GLD3_WGL
794 return _gldDriver.wglGetProcAddress(a);
795 #else
796 return dglGetProcAddressD3D(a);
797 #endif
798 }
799
800 // ***********************************************************************
801
802 BOOL APIENTRY _GLD_WGL_EXPORT(MakeCurrent)(
803 HDC a,
804 HGLRC b)
805 {
806 // Validate license
807 if (!dglValidate())
808 return FALSE;
809
810 return dglMakeCurrent(a, b);
811 }
812
813 // ***********************************************************************
814
815 BOOL APIENTRY _GLD_WGL_EXPORT(RealizeLayerPalette)(
816 HDC a,
817 int b,
818 BOOL c)
819 {
820 // Validate license
821 if (!dglValidate())
822 return FALSE;
823
824 UNSUPPORTED("DGL_RealizeLayerPalette")
825 return FALSE;
826 }
827
828 // ***********************************************************************
829
830 int APIENTRY _GLD_WGL_EXPORT(SetLayerPaletteEntries)(
831 HDC a,
832 int b,
833 int c,
834 int d,
835 CONST COLORREF *e)
836 {
837 // Validate license
838 if (!dglValidate())
839 return 0;
840
841 UNSUPPORTED("DGL_SetLayerPaletteEntries")
842 return 0;
843 }
844
845 // ***********************************************************************
846
847 BOOL APIENTRY _GLD_WGL_EXPORT(SetPixelFormat)(
848 HDC a,
849 int b,
850 CONST PIXELFORMATDESCRIPTOR *c)
851 {
852 // Validate license
853 if (!dglValidate())
854 return FALSE;
855
856 if (IsValidPFD(b)) {
857 ddlogPrintf(DDLOG_SYSTEM, "SetPixelFormat: PixelFormat %d has been set", b);
858 dglSetPixelFormat(b);
859 return TRUE;
860 } else {
861 ddlogPrintf(DDLOG_ERROR,
862 "SetPixelFormat: PixelFormat %d is invalid and cannot be set", b);
863 return FALSE;
864 }
865 }
866
867 // ***********************************************************************
868 /*
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)
872 */
873 //
874 // Copied from GLD2.x. KeithH
875 //
876 static GLboolean _gldShareLists(
877 GLcontext *ctx1,
878 GLcontext *ctx2)
879 {
880 /* Sanity check context pointers */
881 if (ctx1 == NULL || ctx2 == NULL)
882 return GL_FALSE;
883 /* Sanity check shared list pointers */
884 if (ctx1->Shared == NULL || ctx2->Shared == NULL)
885 return GL_FALSE;
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);
891 #endif
892 /* Re-assign list from sharer to sharee and increment reference count */
893 ctx2->Shared = ctx1->Shared;
894 ctx1->Shared->RefCount++;
895 return GL_TRUE;
896 }
897
898 // ***********************************************************************
899
900 BOOL APIENTRY _GLD_WGL_EXPORT(ShareLists)(
901 HGLRC a,
902 HGLRC b)
903 {
904 DGL_ctx *dgl1, *dgl2;
905
906 // Validate license
907 if (!dglValidate())
908 return FALSE;
909
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) {
917 #ifdef _USE_GLD3_WGL
918 return _gldShareLists(dgl1->glCtx, dgl2->glCtx);
919 #else
920 return (*mesaFuncs.gl_share_lists)(dgl1->glCtx, dgl2->glCtx);
921 #endif
922 }
923 return FALSE;
924 }
925
926 // ***********************************************************************
927
928 BOOL APIENTRY _GLD_WGL_EXPORT(SwapBuffers)(
929 HDC a)
930 {
931 // Validate license
932 if (!dglValidate())
933 return FALSE;
934
935 return dglSwapBuffers(a);
936 }
937
938 // ***********************************************************************
939
940 BOOL APIENTRY _GLD_WGL_EXPORT(SwapLayerBuffers)(
941 HDC a,
942 UINT b)
943 {
944 // Validate license
945 if (!dglValidate())
946 return FALSE;
947
948 return dglSwapBuffers(a);
949 }
950
951 // ***********************************************************************
952
953 // ***********************************************************************
954 // Note: This ResizeBuffers() function may be called from
955 // either MESA glViewport() or GLD wglMakeCurrent().
956
957 BOOL dglWglResizeBuffers(
958 GLcontext *ctx,
959 BOOL bDefaultDriver)
960 {
961 DGL_ctx *dgl = NULL;
962 RECT rcScreenRect;
963 DWORD dwWidth;
964 DWORD dwHeight;
965 DDSURFACEDESC2 ddsd2;
966 DDSCAPS2 ddscaps2;
967 IDirectDrawClipper *lpddClipper = NULL;
968 DWORD dwFlags;
969 HRESULT hResult;
970
971 DWORD dwMemoryType;
972
973 int i;
974 struct gl_texture_object *tObj;
975 struct gl_texture_image *image;
976
977 BOOL bWasFullscreen;
978 BOOL bSaveDesktop;
979 BOOL bFullScrnWin = FALSE;
980 DDSURFACEDESC2 ddsd2DisplayMode;
981
982 DDBLTFX ddbltfx;
983 POINT pt;
984 RECT rcDst;
985 #ifdef _USE_GLD3_WGL
986 GLD_displayMode glddm;
987 #endif
988
989 #define DDLOG_CRITICAL_OR_WARN (bDefaultDriver ? DDLOG_WARN : DDLOG_CRITICAL)
990
991 // Validate license
992 if (!dglValidate())
993 return FALSE;
994
995 // Sanity checks
996 if (ctx == NULL)
997 return FALSE;
998 dgl = ctx->DriverCtx;
999 if (dgl == NULL)
1000 return FALSE;
1001
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);
1007 }
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);
1013
1014 // This will occur on Alt-Tab
1015 if ((dwWidth == 0) && (dwHeight == 0)) {
1016 //dgl->bCanRender = FALSE;
1017 return TRUE; // No resize possible!
1018 }
1019
1020 // Some apps zero only 1 dimension for non-visible window... (DaveM)
1021 if ((dwWidth == 0) || (dwHeight == 0)) {
1022 dwWidth = 8;
1023 dwHeight = 8;
1024 }
1025
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
1030 }
1031
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
1037
1038 // Note previous fullscreen vs window display status
1039 bWasFullscreen = dgl->bFullscreen;
1040
1041 #ifdef _USE_GLD3_WGL
1042 if (_gldDriver.GetDisplayMode(dgl, &glddm)) {
1043 if ( (dwWidth == glddm.Width) &&
1044 (dwHeight == glddm.Height) ) {
1045 bFullScrnWin = TRUE;
1046 }
1047 if (bFullScrnWin && glb.bPrimary && !glb.bFullscreenBlit && !glb.bDirectDrawPersistant) {
1048 dgl->bFullscreen = TRUE;
1049 ddlogMessage(DDLOG_INFO, "Fullscreen window after resize.\n");
1050 }
1051 else {
1052 dgl->bFullscreen = FALSE;
1053 ddlogMessage(DDLOG_INFO, "Non-Fullscreen window after resize.\n");
1054 }
1055 // Cache the display mode dimensions
1056 dgl->dwModeWidth = glddm.Width;
1057 dgl->dwModeHeight = glddm.Height;
1058 }
1059
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(
1074 dgl->lpDD4,
1075 &ddsd2DisplayMode);
1076 if (SUCCEEDED(hResult)) {
1077 if ( (dwWidth == ddsd2DisplayMode.dwWidth) &&
1078 (dwHeight == ddsd2DisplayMode.dwHeight) ) {
1079 bFullScrnWin = TRUE;
1080 }
1081 if (bFullScrnWin && glb.bPrimary && !glb.bFullscreenBlit && !glb.bDirectDrawPersistant) {
1082 dgl->bFullscreen = TRUE;
1083 ddlogMessage(DDLOG_INFO, "Fullscreen window after resize.\n");
1084 }
1085 else {
1086 dgl->bFullscreen = FALSE;
1087 ddlogMessage(DDLOG_INFO, "Non-Fullscreen window after resize.\n");
1088 }
1089 // Cache the display mode dimensions
1090 dgl->dwModeWidth = ddsd2DisplayMode.dwWidth;
1091 dgl->dwModeHeight = ddsd2DisplayMode.dwHeight;
1092 }
1093
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
1104
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...
1110
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);
1122 return TRUE;
1123 }
1124
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;
1131 }
1132 #endif // _USE_GLD3_WGL
1133 dgl->bCanRender = FALSE;
1134
1135 #ifdef GLD_THREADS
1136 // Serialize access to DirectDraw and DDS operations
1137 if (glb.bMultiThreaded)
1138 EnterCriticalSection(&CriticalSection);
1139 #endif
1140
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)
1147 ;
1148 else
1149 RELEASE(dgl->lpFront4);
1150 #endif // _USE_GLD3_WGL
1151 dgl->dwWidth = dwWidth;
1152 dgl->dwHeight = dwHeight;
1153
1154 // Set defaults
1155 dgl->dwModeWidth = dgl->dwWidth;
1156 dgl->dwModeHeight = dgl->dwHeight;
1157
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
1162
1163 if (dgl->bFullscreen) {
1164 //
1165 // FULLSCREEN
1166 //
1167
1168 // Disable warning popups when in fullscreen mode
1169 ddlogWarnOption(FALSE);
1170
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;
1178 }
1179
1180 dwFlags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT;
1181 if (glb.bFastFPU)
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;
1187 }
1188
1189 hResult = IDirectDraw4_SetDisplayMode(dgl->lpDD4,
1190 dgl->dwModeWidth,
1191 dgl->dwModeHeight,
1192 dgl->dwBPP,
1193 0,
1194 0);
1195 if (FAILED(hResult)) {
1196 ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetDisplayMode failed", hResult);
1197 goto cleanup_and_return_with_error;
1198 }
1199
1200 // ** The display mode has changed, so dont use MessageBox! **
1201
1202 ZeroMemory(&ddsd2, sizeof(ddsd2));
1203 ddsd2.dwSize = sizeof(ddsd2);
1204
1205 if (dgl->bDoubleBuffer) {
1206 // Double buffered
1207 // Primary surface
1208 ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
1209 ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
1210 DDSCAPS_FLIP |
1211 DDSCAPS_COMPLEX |
1212 DDSCAPS_3DDEVICE |
1213 dwMemoryType;
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;
1219 }
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;
1227 }
1228 } else {
1229 // Single buffered
1230 // Primary surface
1231 ddsd2.dwFlags = DDSD_CAPS;
1232 ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
1233 //DDSCAPS_3DDEVICE |
1234 dwMemoryType;
1235
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;
1240 }
1241
1242 dgl->lpBack4 = NULL;
1243 }
1244 } else {
1245 // WINDOWED
1246
1247 // OK to enable warning popups in windowed mode
1248 ddlogWarnOption(glb.bMessageBoxWarnings);
1249
1250 // Ditto if persistant DirectDraw primary
1251 if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
1252 goto DoClipperOnly;
1253
1254 // WINDOWED
1255 dwFlags = DDSCL_NORMAL;
1256 if (glb.bMultiThreaded)
1257 dwFlags |= DDSCL_MULTITHREADED;
1258 if (glb.bFastFPU)
1259 dwFlags |= DDSCL_FPUSETUP; // optional
1260 hResult = IDirectDraw4_SetCooperativeLevel(dgl->lpDD4,
1261 dgl->hWnd,
1262 dwFlags);
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;
1266 }
1267 // Primary surface
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;
1276 }
1277
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;
1283 }
1284
1285 // Clipper object
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;
1290 }
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;
1296 }
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;
1302 }
1303 DoClipperOnly:
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);
1309 }
1310
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 |
1320 dwMemoryType;
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;
1325 }
1326
1327 } else {
1328 dgl->lpBack4 = NULL;
1329 }
1330 }
1331
1332 //
1333 // Now create the Zbuffer
1334 //
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) );
1347
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;
1353 }
1354
1355 // Attach Zbuffer to render target
1356 TRY(IDirectDrawSurface4_AddAttachedSurface(
1357 dgl->bDoubleBuffer ? dgl->lpBack4 : dgl->lpFront4,
1358 dgl->lpDepth4),
1359 "dglResize: Attach Zbuffer");
1360
1361 }
1362
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);
1369
1370 //
1371 // Now that we have a zbuffer we can create the 3D device
1372 //
1373 hResult = IDirect3D3_CreateDevice(dgl->lpD3D3,
1374 bDefaultDriver ? &glb.d3dGuid : &IID_IDirect3DRGBDevice,
1375 dgl->bDoubleBuffer ? dgl->lpBack4 : dgl->lpFront4,
1376 &dgl->lpDev3,
1377 NULL);
1378 if (FAILED(hResult)) {
1379 ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Could not create Direct3D device", hResult);
1380 goto cleanup_and_return_with_error;
1381 }
1382
1383 // We must do this as soon as the device is created
1384 dglInitStateCaches(dgl);
1385
1386 //
1387 // Viewport
1388 //
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;
1393 }
1394
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");
1409
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;
1414 }
1415
1416 // (Re)Initialise all the Direct3D renderstates
1417 dglInitStateD3D(ctx);
1418
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];
1428 if (image) {
1429 switch (tObj->Dimensions){
1430 case 1:
1431 if (ctx->Driver.TexImage)
1432 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_1D, tObj, i, image->Format, image);
1433 break;
1434 case 2:
1435 if (ctx->Driver.TexImage)
1436 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, tObj, i, image->Format, image);
1437 break;
1438 default:
1439 break;
1440 }
1441 }
1442 }
1443 }
1444 tObj = tObj->Next;
1445 }
1446
1447 // Re-Bind each texture Unit
1448 for (i=0; i<glb.wMaxSimultaneousTextures; i++) {
1449 tObj = ctx->Texture.Unit[i].Current;
1450 if (tObj) {
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);
1455 }
1456 }
1457 }
1458 #endif // _USE_GLD3_WGL
1459
1460 dgl->bCanRender = TRUE;
1461
1462 #ifdef GLD_THREADS
1463 // Release serialized access
1464 if (glb.bMultiThreaded)
1465 LeaveCriticalSection(&CriticalSection);
1466 #endif
1467
1468 // SUCCESS.
1469 return TRUE;
1470
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)
1480 ;
1481 else
1482 RELEASE(dgl->lpFront4);
1483
1484 #undef DDLOG_CRITICAL_OR_WARN
1485 #endif // _USE_GLD3_WGL
1486
1487 // Mark context as not being able to render
1488 dgl->bCanRender = FALSE;
1489
1490 #ifdef GLD_THREADS
1491 // Release serialized access
1492 if (glb.bMultiThreaded)
1493 LeaveCriticalSection(&CriticalSection);
1494 #endif
1495
1496 return FALSE;
1497 }
1498
1499 // ***********************************************************************
1500 // ***********************************************************************
1501 // Support for bitmap fonts.
1502 // ***********************************************************************
1503 // ***********************************************************************
1504
1505 /*****************************************************************************
1506 **
1507 ** InvertGlyphBitmap.
1508 **
1509 ** Invert the bitmap so that it suits OpenGL's representation.
1510 ** Each row starts on a double word boundary.
1511 **
1512 *****************************************************************************/
1513
1514 static void InvertGlyphBitmap(
1515 int w,
1516 int h,
1517 DWORD *fptr,
1518 DWORD *tptr)
1519 {
1520 int dWordsInRow = (w+31)/32;
1521 int i, j;
1522 DWORD *tmp = tptr;
1523
1524 if (w <= 0 || h <= 0) {
1525 return;
1526 }
1527
1528 tptr += ((h-1)*dWordsInRow);
1529 for (i = 0; i < h; i++) {
1530 for (j = 0; j < dWordsInRow; j++) {
1531 *(tptr + j) = *(fptr + j);
1532 }
1533 tptr -= dWordsInRow;
1534 fptr += dWordsInRow;
1535 }
1536 }
1537
1538 // ***********************************************************************
1539
1540 /*****************************************************************************
1541 * wglUseFontBitmaps
1542 *
1543 * Converts a subrange of the glyphs in a GDI font to OpenGL display
1544 * lists.
1545 *
1546 * Extended to support any GDI font, not just TrueType fonts. (DaveM)
1547 *
1548 *****************************************************************************/
1549
1550 BOOL APIENTRY _GLD_WGL_EXPORT(UseFontBitmapsA)(
1551 HDC hDC,
1552 DWORD first,
1553 DWORD count,
1554 DWORD listBase)
1555 {
1556 int i, ox, oy, ix, iy;
1557 int w, h;
1558 int iBufSize, iCurBufSize = 0;
1559 DWORD *bitmapBuffer = NULL;
1560 DWORD *invertedBitmapBuffer = NULL;
1561 BOOL bSuccessOrFail = TRUE;
1562 BOOL bTrueType = FALSE;
1563 TEXTMETRIC tm;
1564 GLYPHMETRICS gm;
1565 RASTERIZER_STATUS rs;
1566 MAT2 mat;
1567 SIZE size;
1568 RECT rect;
1569 HDC hDCMem;
1570 HBITMAP hBitmap;
1571 BITMAPINFO bmi;
1572 HFONT hFont;
1573
1574 // Validate SciTech DirectGL license
1575 if (!dglValidate())
1576 return FALSE;
1577
1578 // Set up a unity matrix.
1579 ZeroMemory(&mat, sizeof(mat));
1580 mat.eM11.value = 1;
1581 mat.eM22.value = 1;
1582
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");
1587 return (FALSE);
1588 }
1589 bTrueType = (tm.tmPitchAndFamily & TMPF_TRUETYPE) ? TRUE : FALSE;
1590
1591 // Test to see if TRUE-TYPE capabilities are installed
1592 // (only necessary if TrueType font selected)
1593 ZeroMemory(&rs, sizeof(rs));
1594 if (bTrueType) {
1595 if (!GetRasterizerCaps (&rs, sizeof (RASTERIZER_STATUS))) {
1596 ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Raster caps error\n");
1597 return (FALSE);
1598 }
1599 if (!(rs.wFlags & TT_ENABLED)) {
1600 ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: No TrueType caps\n");
1601 return (FALSE);
1602 }
1603 }
1604
1605 // Trick to get the current font handle
1606 hFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
1607 SelectObject(hDC, hFont);
1608
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);
1614
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.
1618 if (bTrueType) {
1619 // Use TrueType support to get bitmap size of glyph
1620 iBufSize = GetGlyphOutline(hDC, i, GGO_BITMAP, &gm,
1621 0, NULL, &mat);
1622 if (iBufSize == GDI_ERROR) {
1623 bSuccessOrFail = FALSE;
1624 break;
1625 }
1626 }
1627 else {
1628 // Use generic GDI support to compute bitmap size of glyph
1629 w = tm.tmMaxCharWidth;
1630 h = tm.tmHeight;
1631 if (GetTextExtentPoint32(hDC, (LPCTSTR)&i, 1, &size)) {
1632 w = size.cx;
1633 h = size.cy;
1634 }
1635 iBufSize = w * h;
1636 // Use DWORD multiple for compatibility
1637 iBufSize += 3;
1638 iBufSize /= 4;
1639 iBufSize *= 4;
1640 }
1641
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) {
1645 if (bitmapBuffer) {
1646 __wglFree(bitmapBuffer);
1647 }
1648 if (invertedBitmapBuffer) {
1649 __wglFree(invertedBitmapBuffer);
1650 }
1651
1652 iCurBufSize = iBufSize * 2;
1653 bitmapBuffer = (DWORD *) __wglMalloc(iCurBufSize);
1654 invertedBitmapBuffer = (DWORD *) __wglMalloc(iCurBufSize);
1655
1656 if (bitmapBuffer == NULL || invertedBitmapBuffer == NULL) {
1657 bSuccessOrFail = FALSE;
1658 break;
1659 }
1660 }
1661
1662 // If we fail to get the Glyph data, delete the display lists
1663 // Created so far and return FALSE.
1664 if (bTrueType) {
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;
1669 break;
1670 }
1671
1672 // Setup glBitmap parameters for current font glyph
1673 w = gm.gmBlackBoxX;
1674 h = gm.gmBlackBoxY;
1675 ox = gm.gmptGlyphOrigin.x;
1676 oy = gm.gmptGlyphOrigin.y;
1677 ix = gm.gmCellIncX;
1678 iy = gm.gmCellIncY;
1679 }
1680 else {
1681 // Use generic GDI support to create bitmap of glyph
1682 ZeroMemory(bitmapBuffer, iBufSize);
1683
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);
1702 }
1703 else {
1704 // Otherwise use empty display list for non-existing glyph
1705 iBufSize = 0;
1706 }
1707
1708 // Setup glBitmap parameters for current font glyph
1709 ox = 0;
1710 oy = tm.tmDescent;
1711 ix = w;
1712 iy = 0;
1713 }
1714
1715 // Create an OpenGL display list.
1716 _GLD_glNewList((listBase + i), GL_COMPILE);
1717
1718 // Some fonts have no data for the space character, yet advertise
1719 // a non-zero size.
1720 if (0 == iBufSize) {
1721 _GLD_glBitmap(0, 0, 0.0f, 0.0f, (GLfloat) ix, (GLfloat) iy, NULL);
1722 } else {
1723 // Invert the Glyph data.
1724 InvertGlyphBitmap(w, h, bitmapBuffer, invertedBitmapBuffer);
1725
1726 // Render an OpenGL bitmap and invert the origin.
1727 _GLD_glBitmap(w, h,
1728 (GLfloat) ox, (GLfloat) (h-oy),
1729 (GLfloat) ix, (GLfloat) iy,
1730 (GLubyte *) invertedBitmapBuffer);
1731 }
1732
1733 // Close this display list.
1734 _GLD_glEndList();
1735 }
1736
1737 if (bSuccessOrFail == FALSE) {
1738 ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Get glyph failed\n");
1739 _GLD_glDeleteLists((i+listBase), (i-first));
1740 }
1741
1742 // Release resources used
1743 DeleteObject(hFont);
1744 DeleteDC(hDCMem);
1745
1746 if (bitmapBuffer)
1747 __wglFree(bitmapBuffer);
1748 if (invertedBitmapBuffer)
1749 __wglFree(invertedBitmapBuffer);
1750
1751 return(bSuccessOrFail);
1752 }
1753
1754 // ***********************************************************************
1755
1756 BOOL APIENTRY _GLD_WGL_EXPORT(UseFontBitmapsW)(
1757 HDC a,
1758 DWORD b,
1759 DWORD c,
1760 DWORD d)
1761 {
1762 // Validate license
1763 if (!dglValidate())
1764 return FALSE;
1765
1766 return _GLD_WGL_EXPORT(UseFontBitmapsA)(a, b, c, d);
1767 }
1768
1769 // ***********************************************************************
1770 // ***********************************************************************
1771 // Support for outline TrueType fonts.
1772 // ***********************************************************************
1773 // ***********************************************************************
1774
1775 void * __wglRealloc(
1776 void *oldPtr,
1777 size_t newSize)
1778 {
1779 void *newPtr = NULL;
1780
1781 if (newSize != 0) {
1782 newPtr = (void *) GlobalAlloc(GPTR, newSize);
1783 if (oldPtr && newPtr) {
1784 DWORD oldSize = GlobalSize(oldPtr);
1785
1786 memcpy(newPtr, oldPtr, (oldSize <= newSize ? oldSize : newSize));
1787 GlobalFree(oldPtr);
1788 }
1789 } else if (oldPtr) {
1790 GlobalFree(oldPtr);
1791 }
1792 if (newPtr == NULL) {
1793 return NULL; /* XXX out of memory error */
1794 }
1795 return newPtr;
1796 }
1797
1798 // ***********************************************************************
1799
1800
1801 /*****************************************************************************
1802 * wglUseFontOutlinesW
1803 *
1804 * Converts a subrange of the glyphs in a TrueType font to OpenGL display
1805 * lists.
1806 *****************************************************************************/
1807
1808 BOOL APIENTRY _GLD_WGL_EXPORT(UseFontOutlinesW)(
1809 IN HDC hDC,
1810 IN DWORD first,
1811 IN DWORD count,
1812 IN DWORD listBase,
1813 IN FLOAT chordalDeviation,
1814 IN FLOAT extrusion,
1815 IN INT format,
1816 OUT LPGLYPHMETRICSFLOAT lpgmf)
1817 {
1818 return _GLD_WGL_EXPORT(UseFontOutlinesA)(hDC, first, count, listBase,
1819 chordalDeviation, extrusion, format, lpgmf);
1820 }
1821
1822 /*****************************************************************************
1823 * wglUseFontOutlinesA
1824 *
1825 * Converts a subrange of the glyphs in a TrueType font to OpenGL display
1826 * lists.
1827 *****************************************************************************/
1828
1829 BOOL APIENTRY _GLD_WGL_EXPORT(UseFontOutlinesA)(
1830 IN HDC hDC,
1831 IN DWORD first,
1832 IN DWORD count,
1833 IN DWORD listBase,
1834 IN FLOAT chordalDeviation,
1835 IN FLOAT extrusion,
1836 IN INT format,
1837 OUT LPGLYPHMETRICSFLOAT glyphMetricsFloatArray)
1838 {
1839 DWORD glyphIndex;
1840 UCHAR* glyphBuf;
1841 DWORD glyphBufSize;
1842
1843
1844 /*
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.
1847 */
1848 while (_GLD_glGetError() != GL_NO_ERROR)
1849 ;
1850
1851 /*
1852 * Make sure that the current font can be sampled accurately.
1853 */
1854 hNewFont = CreateHighResolutionFont(hDC);
1855 if (!hNewFont)
1856 return FALSE;
1857
1858 hOldFont = SelectObject(hDC, hNewFont);
1859 if (!hOldFont)
1860 return FALSE;
1861
1862 /*
1863 * Preallocate a buffer for the outline data, and track its size:
1864 */
1865 glyphBuf = (UCHAR*) __wglMalloc(glyphBufSize = 10240);
1866 if (!glyphBuf)
1867 return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
1868
1869 /*
1870 * Process each glyph in the given range:
1871 */
1872 for (glyphIndex = first; glyphIndex - first < count; ++glyphIndex)
1873 {
1874 GLYPHMETRICS glyphMetrics;
1875 DWORD glyphSize;
1876 static MAT2 matrix =
1877 {
1878 {0, 1}, {0, 0},
1879 {0, 0}, {0, 1}
1880 };
1881 LPGLYPHMETRICSFLOAT glyphMetricsFloat =
1882 &glyphMetricsFloatArray[glyphIndex - first];
1883
1884
1885 /*
1886 * Determine how much space is needed to store the glyph's
1887 * outlines. If our glyph buffer isn't large enough,
1888 * resize it.
1889 */
1890 glyphSize = GetGlyphOutline( hDC,
1891 glyphIndex,
1892 GGO_NATIVE,
1893 &glyphMetrics,
1894 0,
1895 NULL,
1896 &matrix
1897 );
1898 if (glyphSize < 0)
1899 return FALSE; /*WGL_STATUS_FAILURE*/
1900 if (glyphSize > glyphBufSize)
1901 {
1902 __wglFree(glyphBuf);
1903 glyphBuf = (UCHAR*) __wglMalloc(glyphBufSize = glyphSize);
1904 if (!glyphBuf)
1905 return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
1906 }
1907
1908
1909 /*
1910 * Get the glyph's outlines.
1911 */
1912 if (GetGlyphOutline( hDC,
1913 glyphIndex,
1914 GGO_NATIVE,
1915 &glyphMetrics,
1916 glyphBufSize,
1917 glyphBuf,
1918 &matrix
1919 ) < 0)
1920 {
1921 __wglFree(glyphBuf);
1922 return FALSE; /*WGL_STATUS_FAILURE*/
1923 }
1924
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;
1937
1938 /*
1939 * Turn the glyph into a display list:
1940 */
1941 if (!MakeDisplayListFromGlyph( (glyphIndex - first) + listBase,
1942 glyphBuf,
1943 glyphSize,
1944 glyphMetricsFloat,
1945 chordalDeviation + ScaleFactor,
1946 extrusion,
1947 format))
1948 {
1949 __wglFree(glyphBuf);
1950 return FALSE; /*WGL_STATUS_FAILURE*/
1951 }
1952 }
1953
1954
1955 /*
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.
1959 */
1960 __wglFree(glyphBuf);
1961
1962 SelectObject(hDC, hOldFont);
1963
1964 if (_GLD_glGetError() == GL_NO_ERROR)
1965 return TRUE; /*WGL_STATUS_SUCCESS*/
1966 else
1967 {
1968 while (_GLD_glGetError() != GL_NO_ERROR)
1969 ;
1970 return FALSE; /*WGL_STATUS_FAILURE*/
1971 }
1972 }
1973
1974
1975
1976 /*****************************************************************************
1977 * CreateHighResolutionFont
1978 *
1979 * Gets metrics for the current font and creates an equivalent font
1980 * scaled to the design units of the font.
1981 *
1982 *****************************************************************************/
1983
1984 static HFONT
1985 CreateHighResolutionFont(HDC hDC)
1986 {
1987 UINT otmSize;
1988 OUTLINETEXTMETRIC *otm;
1989 LONG fontHeight, fontWidth, fontUnits;
1990 LOGFONT logFont;
1991
1992 otmSize = GetOutlineTextMetrics(hDC, 0, NULL);
1993 if (otmSize == 0)
1994 return NULL;
1995
1996 otm = (OUTLINETEXTMETRIC *) __wglMalloc(otmSize);
1997 if (otm == NULL)
1998 return NULL;
1999
2000 otm->otmSize = otmSize;
2001 if (GetOutlineTextMetrics(hDC, otmSize, otm) == 0)
2002 return NULL;
2003
2004 fontHeight = otm->otmTextMetrics.tmHeight -
2005 otm->otmTextMetrics.tmInternalLeading;
2006 fontWidth = otm->otmTextMetrics.tmAveCharWidth;
2007 fontUnits = (LONG) otm->otmEMSquare;
2008
2009 ScaleFactor = 1.0F / (FLOAT) fontUnits;
2010
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);
2028
2029 hNewFont = CreateFontIndirect(&logFont);
2030 if (hNewFont == NULL)
2031 return NULL;
2032
2033 __wglFree(otm);
2034
2035 return hNewFont;
2036 }
2037
2038
2039
2040 /*****************************************************************************
2041 * MakeDisplayListFromGlyph
2042 *
2043 * Converts the outline of a glyph to an OpenGL display list.
2044 *
2045 * Return value is nonzero for success, zero for failure.
2046 *
2047 * Does not check for OpenGL errors, so if the caller needs to know about them,
2048 * it should call glGetError().
2049 *****************************************************************************/
2050
2051 static int
2052 MakeDisplayListFromGlyph( IN DWORD listName,
2053 IN UCHAR* glyphBuf,
2054 IN DWORD glyphSize,
2055 IN LPGLYPHMETRICSFLOAT glyphMetricsFloat,
2056 IN FLOAT chordalDeviation,
2057 IN FLOAT extrusion,
2058 IN INT format)
2059 {
2060 int status;
2061
2062 _GLD_glNewList(listName, GL_COMPILE);
2063 status = DrawGlyph( glyphBuf,
2064 glyphSize,
2065 chordalDeviation,
2066 extrusion,
2067 format);
2068
2069 _GLD_glTranslatef(glyphMetricsFloat->gmfCellIncX,
2070 glyphMetricsFloat->gmfCellIncY,
2071 0.0F);
2072 _GLD_glEndList();
2073
2074 return status;
2075 }
2076
2077
2078
2079 /*****************************************************************************
2080 * DrawGlyph
2081 *
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".
2086 *
2087 * Return value is nonzero for success, zero for failure.
2088 *
2089 * Does not check for OpenGL errors, so if the caller needs to know about them,
2090 * it should call glGetError().
2091 *****************************************************************************/
2092
2093 static int
2094 DrawGlyph( IN UCHAR* glyphBuf,
2095 IN DWORD glyphSize,
2096 IN FLOAT chordalDeviation,
2097 IN FLOAT extrusion,
2098 IN INT format)
2099 {
2100 INT status = 0;
2101 FLOAT* p;
2102 DWORD loop;
2103 DWORD point;
2104 GLUtesselator* tess = NULL;
2105
2106
2107 /*
2108 * Initialize the global buffer into which we place the outlines:
2109 */
2110 if (!InitLineBuf())
2111 goto exit;
2112
2113
2114 /*
2115 * Convert the glyph outlines to a set of polyline loops.
2116 * (See MakeLinesFromGlyph() for the format of the loop data
2117 * structure.)
2118 */
2119 if (!MakeLinesFromGlyph(glyphBuf, glyphSize, chordalDeviation))
2120 goto exit;
2121 p = LineBuf;
2122
2123
2124 /*
2125 * Now draw the loops in the appropriate format:
2126 */
2127 if (format == WGL_FONT_LINES)
2128 {
2129 /*
2130 * This is the easy case. Just draw the outlines.
2131 */
2132 for (loop = (DWORD) *p++; loop; --loop)
2133 {
2134 _GLD_glBegin(GL_LINE_LOOP);
2135 for (point = (DWORD) *p++; point; --point)
2136 {
2137 _GLD_glVertex2fv(p);
2138 p += 2;
2139 }
2140 _GLD_glEnd();
2141 }
2142 status = 1;
2143 }
2144
2145 else if (format == WGL_FONT_POLYGONS)
2146 {
2147 double v[3];
2148 FLOAT *save_p = p;
2149 GLfloat z_value;
2150
2151 /*
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.
2156 */
2157 if (!LoadGLUTesselator())
2158 goto exit;
2159 if (!InitVertBuf())
2160 goto exit;
2161 if (!(tess = gluNewTessProc()))
2162 goto exit;
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);
2170
2171 TessErrorOccurred = 0;
2172 _GLD_glNormal3f(0.0f, 0.0f, 1.0f);
2173 v[2] = 0.0;
2174 z_value = 0.0f;
2175
2176 gluTessBeginPolygonProc(tess, (void *)*(int *)&z_value);
2177 for (loop = (DWORD) *p++; loop; --loop)
2178 {
2179 gluTessBeginContourProc(tess);
2180
2181 for (point = (DWORD) *p++; point; --point)
2182 {
2183 v[0] = p[0];
2184 v[1] = p[1];
2185 gluTessVertexProc(tess, v, p);
2186 p += 2;
2187 }
2188
2189 gluTessEndContourProc(tess);
2190 }
2191 gluTessEndPolygonProc(tess);
2192
2193 status = !TessErrorOccurred;
2194
2195 /* Extrusion code */
2196 if (extrusion) {
2197 DWORD loops;
2198 GLfloat thickness = (GLfloat) -extrusion;
2199 FLOAT *vert, *vert2;
2200 DWORD count;
2201
2202 p = save_p;
2203 loops = (DWORD) *p++;
2204
2205 for (loop = 0; loop < loops; loop++) {
2206 GLfloat dx, dy, len;
2207 DWORD last;
2208
2209 count = (DWORD) *p++;
2210 _GLD_glBegin(GL_QUAD_STRIP);
2211
2212 /* Check if the first and last vertex are identical
2213 * so we don't draw the same quad twice.
2214 */
2215 vert = p + (count-1)*2;
2216 last = (p[0] == vert[0] && p[1] == vert[1]) ? count-1 : count;
2217
2218 for (point = 0; point <= last; point++) {
2219 vert = p + 2 * (point % last);
2220 vert2 = p + 2 * ((point+1) % last);
2221
2222 dx = vert[0] - vert2[0];
2223 dy = vert[1] - vert2[1];
2224 len = (GLfloat)sqrt(dx * dx + dy * dy);
2225
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);
2231 }
2232
2233 _GLD_glEnd();
2234 p += count*2;
2235 }
2236
2237 /* Draw the back face */
2238 p = save_p;
2239 v[2] = thickness;
2240 _GLD_glNormal3f(0.0f, 0.0f, -1.0f);
2241 gluTessNormalProc(tess, 0.0F, 0.0F, -1.0F);
2242
2243 gluTessBeginPolygonProc(tess, (void *)*(int *)&thickness);
2244
2245 for (loop = (DWORD) *p++; loop; --loop)
2246 {
2247 count = (DWORD) *p++;
2248
2249 gluTessBeginContourProc(tess);
2250
2251 for (point = 0; point < count; point++)
2252 {
2253 vert = p + ((count-point-1)<<1);
2254 v[0] = vert[0];
2255 v[1] = vert[1];
2256 gluTessVertexProc(tess, v, vert);
2257 }
2258 p += count*2;
2259
2260 gluTessEndContourProc(tess);
2261 }
2262 gluTessEndPolygonProc(tess);
2263 }
2264
2265 #if DEBUG
2266 if (TessErrorOccurred)
2267 printf("Tessellation error %s\n",
2268 gluErrorString(TessErrorOccurred));
2269 #endif
2270 }
2271
2272
2273 exit:
2274 FreeLineBuf();
2275 if (tess)
2276 gluDeleteTessProc(tess);
2277 // UnloadGLUTesselator();
2278 FreeVertBuf();
2279 return status;
2280 }
2281
2282
2283
2284 /*****************************************************************************
2285 * LoadGLUTesselator
2286 *
2287 * Maps the glu32.dll module and gets function pointers for the
2288 * tesselator functions.
2289 *****************************************************************************/
2290
2291 static BOOL
2292 LoadGLUTesselator(void)
2293 {
2294 if (gluModuleHandle != NULL)
2295 return TRUE;
2296
2297 {
2298 extern HINSTANCE hInstanceOpenGL;
2299 char *gluName = "GLU32.DLL";
2300 // char name[256];
2301 // char *ptr;
2302 // int len;
2303
2304 /*
2305 len = GetModuleFileName(hInstanceOpenGL, name, 255);
2306 if (len != 0)
2307 {
2308 ptr = name+len-1;
2309 while (ptr > name && *ptr != '\\')
2310 ptr--;
2311 if (*ptr == '\\')
2312 ptr++;
2313 if (!stricmp(ptr, "cosmogl.dll"))
2314 {
2315 gluName = "COSMOGLU.DLL";
2316 }
2317 else if (!stricmp(ptr, "opengl32.dll"))
2318 {
2319 gluName = "GLU32.DLL";
2320 }
2321 }
2322 */
2323 if ((gluModuleHandle = LoadLibrary(gluName)) == NULL)
2324 return FALSE;
2325 }
2326
2327 if ((gluNewTessProc = (gluNewTessProto)
2328 GetProcAddress(gluModuleHandle, "gluNewTess")) == NULL)
2329 return FALSE;
2330
2331 if ((gluDeleteTessProc = (gluDeleteTessProto)
2332 GetProcAddress(gluModuleHandle, "gluDeleteTess")) == NULL)
2333 return FALSE;
2334
2335 if ((gluTessBeginPolygonProc = (gluTessBeginPolygonProto)
2336 GetProcAddress(gluModuleHandle, "gluTessBeginPolygon")) == NULL)
2337 return FALSE;
2338
2339 if ((gluTessBeginContourProc = (gluTessBeginContourProto)
2340 GetProcAddress(gluModuleHandle, "gluTessBeginContour")) == NULL)
2341 return FALSE;
2342
2343 if ((gluTessVertexProc = (gluTessVertexProto)
2344 GetProcAddress(gluModuleHandle, "gluTessVertex")) == NULL)
2345 return FALSE;
2346
2347 if ((gluTessEndContourProc = (gluTessEndContourProto)
2348 GetProcAddress(gluModuleHandle, "gluTessEndContour")) == NULL)
2349 return FALSE;
2350
2351 if ((gluTessEndPolygonProc = (gluTessEndPolygonProto)
2352 GetProcAddress(gluModuleHandle, "gluTessEndPolygon")) == NULL)
2353 return FALSE;
2354
2355 if ((gluTessPropertyProc = (gluTessPropertyProto)
2356 GetProcAddress(gluModuleHandle, "gluTessProperty")) == NULL)
2357 return FALSE;
2358
2359 if ((gluTessNormalProc = (gluTessNormalProto)
2360 GetProcAddress(gluModuleHandle, "gluTessNormal")) == NULL)
2361 return FALSE;
2362
2363 if ((gluTessCallbackProc = (gluTessCallbackProto)
2364 GetProcAddress(gluModuleHandle, "gluTessCallback")) == NULL)
2365 return FALSE;
2366
2367 return TRUE;
2368 }
2369
2370
2371
2372 /*****************************************************************************
2373 * UnloadGLUTesselator
2374 *
2375 * Unmaps the glu32.dll module.
2376 *****************************************************************************/
2377
2378 static BOOL
2379 UnloadGLUTesselator(void)
2380 {
2381 if (gluModuleHandle != NULL)
2382 if (FreeLibrary(gluModuleHandle) == FALSE)
2383 return FALSE;
2384 gluModuleHandle = NULL;
2385 }
2386
2387
2388
2389 /*****************************************************************************
2390 * TessVertexOut
2391 *
2392 * Used by tessellator to handle output vertexes.
2393 *****************************************************************************/
2394
2395 static void CALLBACK
2396 TessVertexOut(FLOAT p[3])
2397 {
2398 GLfloat v[2];
2399
2400 v[0] = p[0] * ScaleFactor;
2401 v[1] = p[1] * ScaleFactor;
2402 _GLD_glVertex2fv(v);
2403 }
2404
2405 static void CALLBACK
2406 TessVertexOutData(FLOAT p[3], GLfloat z)
2407 {
2408 GLfloat v[3];
2409
2410 v[0] = (GLfloat) p[0];
2411 v[1] = (GLfloat) p[1];
2412 v[2] = z;
2413 _GLD_glVertex3fv(v);
2414 }
2415
2416
2417 /*****************************************************************************
2418 * TessCombine
2419 *
2420 * Used by tessellator to handle self-intersecting contours and degenerate
2421 * geometry.
2422 *****************************************************************************/
2423
2424 static void CALLBACK
2425 TessCombine(double coords[3],
2426 void* vertex_data[4],
2427 FLOAT weight[4],
2428 void** outData)
2429 {
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);
2435 }
2436
2437
2438
2439 /*****************************************************************************
2440 * TessError
2441 *
2442 * Saves the last tessellator error code in the global TessErrorOccurred.
2443 *****************************************************************************/
2444
2445 static void CALLBACK
2446 TessError(GLenum error)
2447 {
2448 TessErrorOccurred = error;
2449 }
2450
2451
2452
2453 /*****************************************************************************
2454 * MakeLinesFromGlyph
2455 *
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.
2458 *
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:
2464 *
2465 * 1., 3., 0., 0., 1., 0., 0., 1.
2466 * ^ ^ ^ ^ ^ ^ ^ ^
2467 * #loops #verts x1 y1 x2 y2 x3 y3
2468 *
2469 * A two-loop glyph would look like this:
2470 *
2471 * 2., 3., 0.,0., 1.,0., 0.,1., 3., .2,.2, .4,.2, .2,.4
2472 *
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 *****************************************************************************/
2477
2478 static int
2479 MakeLinesFromGlyph(IN UCHAR* glyphBuf,
2480 IN DWORD glyphSize,
2481 IN FLOAT chordalDeviation)
2482 {
2483 UCHAR* p;
2484 int status = 0;
2485
2486
2487 /*
2488 * Pick up all the polygons (aka loops) that make up the glyph:
2489 */
2490 if (!AppendToLineBuf(0.0F)) /* loop count at LineBuf[0] */
2491 goto exit;
2492
2493 p = glyphBuf;
2494 while (p < glyphBuf + glyphSize)
2495 {
2496 if (!MakeLinesFromTTPolygon(&p, chordalDeviation))
2497 goto exit;
2498 LineBuf[0] += 1.0F; /* increment loop count */
2499 }
2500
2501 status = 1;
2502
2503 exit:
2504 return status;
2505 }
2506
2507
2508
2509 /*****************************************************************************
2510 * MakeLinesFromTTPolygon
2511 *
2512 * Converts a TTPOLYGONHEADER and its associated curve structures into a
2513 * single polyline loop in the global LineBuf.
2514 *****************************************************************************/
2515
2516 static int
2517 MakeLinesFromTTPolygon( IN OUT UCHAR** pp,
2518 IN FLOAT chordalDeviation)
2519 {
2520 DWORD polySize;
2521 UCHAR* polyStart;
2522 DWORD vertexCountIndex;
2523
2524 /*
2525 * Record where the polygon data begins, and where the loop's
2526 * vertex count resides:
2527 */
2528 polyStart = *pp;
2529 vertexCountIndex = LineBufIndex;
2530 if (!AppendToLineBuf(0.0F))
2531 return 0;
2532
2533 /*
2534 * Extract relevant data from the TTPOLYGONHEADER:
2535 */
2536 polySize = GetDWord(pp);
2537 if (GetDWord(pp) != TT_POLYGON_TYPE) /* polygon type */
2538 return 0;
2539 if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first X coord */
2540 return 0;
2541 if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first Y coord */
2542 return 0;
2543 LineBuf[vertexCountIndex] += 1.0F;
2544
2545 /*
2546 * Process each of the TTPOLYCURVE structures in the polygon:
2547 */
2548 while (*pp < polyStart + polySize)
2549 if (!MakeLinesFromTTPolycurve( pp,
2550 vertexCountIndex,
2551 chordalDeviation))
2552 return 0;
2553
2554 return 1;
2555 }
2556
2557
2558
2559 /*****************************************************************************
2560 * MakeLinesFromTTPolyCurve
2561 *
2562 * Converts the lines and splines in a single TTPOLYCURVE structure to points
2563 * in the global LineBuf.
2564 *****************************************************************************/
2565
2566 static int
2567 MakeLinesFromTTPolycurve( IN OUT UCHAR** pp,
2568 IN DWORD vertexCountIndex,
2569 IN FLOAT chordalDeviation)
2570 {
2571 WORD type;
2572 WORD pointCount;
2573
2574
2575 /*
2576 * Pick up the relevant fields of the TTPOLYCURVE structure:
2577 */
2578 type = (WORD) GetWord(pp);
2579 pointCount = (WORD) GetWord(pp);
2580
2581 /*
2582 * Convert the "curve" to line segments:
2583 */
2584 if (type == TT_PRIM_LINE)
2585 return MakeLinesFromTTLine( pp,
2586 vertexCountIndex,
2587 pointCount);
2588 else if (type == TT_PRIM_QSPLINE)
2589 return MakeLinesFromTTQSpline( pp,
2590 vertexCountIndex,
2591 pointCount,
2592 chordalDeviation);
2593 else
2594 return 0;
2595 }
2596
2597
2598
2599 /*****************************************************************************
2600 * MakeLinesFromTTLine
2601 *
2602 * Converts points from the polyline in a TT_PRIM_LINE structure to
2603 * equivalent points in the global LineBuf.
2604 *****************************************************************************/
2605 static int
2606 MakeLinesFromTTLine( IN OUT UCHAR** pp,
2607 IN DWORD vertexCountIndex,
2608 IN WORD pointCount)
2609 {
2610 /*
2611 * Just copy the line segments into the line buffer (converting
2612 * type as we go):
2613 */
2614 LineBuf[vertexCountIndex] += pointCount;
2615 while (pointCount--)
2616 {
2617 if (!AppendToLineBuf((FLOAT) GetFixed(pp)) /* X coord */
2618 || !AppendToLineBuf((FLOAT) GetFixed(pp))) /* Y coord */
2619 return 0;
2620 }
2621
2622 return 1;
2623 }
2624
2625
2626
2627 /*****************************************************************************
2628 * MakeLinesFromTTQSpline
2629 *
2630 * Converts points from the poly quadratic spline in a TT_PRIM_QSPLINE
2631 * structure to polyline points in the global LineBuf.
2632 *****************************************************************************/
2633
2634 static int
2635 MakeLinesFromTTQSpline( IN OUT UCHAR** pp,
2636 IN DWORD vertexCountIndex,
2637 IN WORD pointCount,
2638 IN FLOAT chordalDeviation)
2639 {
2640 FLOAT x0, y0, x1, y1, x2, y2;
2641 WORD point;
2642
2643 /*
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.
2652 */
2653 for (point = 0; point < pointCount - 1; ++point)
2654 {
2655 x0 = LineBuf[LineBufIndex - 2];
2656 y0 = LineBuf[LineBufIndex - 1];
2657
2658 x1 = (FLOAT) GetFixed(pp);
2659 y1 = (FLOAT) GetFixed(pp);
2660
2661 if (point == pointCount - 2)
2662 {
2663 /*
2664 * This is the last arc in the QSpline. The final
2665 * point is the end of the arc.
2666 */
2667 x2 = (FLOAT) GetFixed(pp);
2668 y2 = (FLOAT) GetFixed(pp);
2669 }
2670 else
2671 {
2672 /*
2673 * Peek at the next point in the input to compute
2674 * the end of the arc:
2675 */
2676 x2 = 0.5F * (x1 + (FLOAT) GetFixed(pp));
2677 y2 = 0.5F * (y1 + (FLOAT) GetFixed(pp));
2678 /*
2679 * Push the point back onto the input so it will
2680 * be reused as the next off-curve point:
2681 */
2682 *pp -= 8;
2683 }
2684
2685 if (!MakeLinesFromArc( x0, y0,
2686 x1, y1,
2687 x2, y2,
2688 vertexCountIndex,
2689 chordalDeviation * chordalDeviation))
2690 return 0;
2691 }
2692
2693 return 1;
2694 }
2695
2696
2697
2698 /*****************************************************************************
2699 * MakeLinesFromArc
2700 *
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 *****************************************************************************/
2705
2706 static int
2707 MakeLinesFromArc( IN FLOAT x0,
2708 IN FLOAT y0,
2709 IN FLOAT x1,
2710 IN FLOAT y1,
2711 IN FLOAT x2,
2712 IN FLOAT y2,
2713 IN DWORD vertexCountIndex,
2714 IN FLOAT chordalDeviationSquared)
2715 {
2716 FLOAT x01;
2717 FLOAT y01;
2718 FLOAT x12;
2719 FLOAT y12;
2720 FLOAT midPointX;
2721 FLOAT midPointY;
2722 FLOAT deltaX;
2723 FLOAT deltaY;
2724
2725 /*
2726 * Calculate midpoint of the curve by de Casteljau:
2727 */
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);
2734
2735
2736 /*
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.
2742 */
2743 deltaX = midPointX - x1;
2744 deltaY = midPointY - y1;
2745 if (deltaX * deltaX + deltaY * deltaY > chordalDeviationSquared)
2746 {
2747 MakeLinesFromArc( x0, y0,
2748 x01, y01,
2749 midPointX, midPointY,
2750 vertexCountIndex,
2751 chordalDeviationSquared);
2752
2753 MakeLinesFromArc( midPointX, midPointY,
2754 x12, y12,
2755 x2, y2,
2756 vertexCountIndex,
2757 chordalDeviationSquared);
2758 }
2759 else
2760 {
2761 /*
2762 * The "pen" is already at (x0, y0), so we don't need to
2763 * add that point to the LineBuf.
2764 */
2765 if (!AppendToLineBuf(x1)
2766 || !AppendToLineBuf(y1)
2767 || !AppendToLineBuf(x2)
2768 || !AppendToLineBuf(y2))
2769 return 0;
2770 LineBuf[vertexCountIndex] += 2.0F;
2771 }
2772
2773 return 1;
2774 }
2775
2776
2777
2778 /*****************************************************************************
2779 * InitLineBuf
2780 *
2781 * Initializes the global LineBuf and its associated size and current-element
2782 * counters.
2783 *****************************************************************************/
2784
2785 static int
2786 InitLineBuf(void)
2787 {
2788 if (!(LineBuf = (FLOAT*)
2789 __wglMalloc((LineBufSize = LINE_BUF_QUANT) * sizeof(FLOAT))))
2790 return 0;
2791 LineBufIndex = 0;
2792 return 1;
2793 }
2794
2795
2796
2797 /*****************************************************************************
2798 * InitVertBuf
2799 *
2800 * Initializes the global VertBuf and its associated size and current-element
2801 * counters.
2802 *****************************************************************************/
2803
2804 static int
2805 InitVertBuf(void)
2806 {
2807 if (!(VertBuf = (FLOAT*)
2808 __wglMalloc((VertBufSize = VERT_BUF_QUANT) * sizeof(FLOAT))))
2809 return 0;
2810 VertBufIndex = 0;
2811 return 1;
2812 }
2813
2814
2815
2816 /*****************************************************************************
2817 * AppendToLineBuf
2818 *
2819 * Appends one floating-point value to the global LineBuf array. Return value
2820 * is non-zero for success, zero for failure.
2821 *****************************************************************************/
2822
2823 static int
2824 AppendToLineBuf(FLOAT value)
2825 {
2826 if (LineBufIndex >= LineBufSize)
2827 {
2828 FLOAT* f;
2829
2830 f = (FLOAT*) __wglRealloc(LineBuf,
2831 (LineBufSize += LINE_BUF_QUANT) * sizeof(FLOAT));
2832 if (!f)
2833 return 0;
2834 LineBuf = f;
2835 }
2836 LineBuf[LineBufIndex++] = value;
2837 return 1;
2838 }
2839
2840
2841
2842 /*****************************************************************************
2843 * AppendToVertBuf
2844 *
2845 * Appends one floating-point value to the global VertBuf array. Return value
2846 * is non-zero for success, zero for failure.
2847 *
2848 * Note that we can't realloc this one, because the tessellator is using
2849 * pointers into it.
2850 *****************************************************************************/
2851
2852 static int
2853 AppendToVertBuf(FLOAT value)
2854 {
2855 if (VertBufIndex >= VertBufSize)
2856 return 0;
2857 VertBuf[VertBufIndex++] = value;
2858 return 1;
2859 }
2860
2861
2862
2863 /*****************************************************************************
2864 * FreeLineBuf
2865 *
2866 * Cleans up vertex buffer structure.
2867 *****************************************************************************/
2868
2869 static void
2870 FreeLineBuf(void)
2871 {
2872 if (LineBuf)
2873 {
2874 __wglFree(LineBuf);
2875 LineBuf = NULL;
2876 }
2877 }
2878
2879
2880
2881 /*****************************************************************************
2882 * FreeVertBuf
2883 *
2884 * Cleans up vertex buffer structure.
2885 *****************************************************************************/
2886
2887 static void
2888 FreeVertBuf(void)
2889 {
2890 if (VertBuf)
2891 {
2892 __wglFree(VertBuf);
2893 VertBuf = NULL;
2894 }
2895 }
2896
2897
2898
2899 /*****************************************************************************
2900 * GetWord
2901 *
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 *****************************************************************************/
2905
2906 static long GetWord(UCHAR** p)
2907 {
2908 long value;
2909
2910 value = ((*p)[1] << 8) + (*p)[0];
2911 *p += 2;
2912 return value;
2913 }
2914
2915
2916
2917 /*****************************************************************************
2918 * GetDWord
2919 *
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 *****************************************************************************/
2923
2924 static long GetDWord(UCHAR** p)
2925 {
2926 long value;
2927
2928 value = ((*p)[3] << 24) + ((*p)[2] << 16) + ((*p)[1] << 8) + (*p)[0];
2929 *p += 4;
2930 return value;
2931 }
2932
2933
2934
2935
2936 /*****************************************************************************
2937 * GetFixed
2938 *
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
2941 * unscanned byte.
2942 *****************************************************************************/
2943
2944 static double GetFixed(
2945 UCHAR** p)
2946 {
2947 long hiBits, loBits;
2948 double value;
2949
2950 loBits = GetWord(p);
2951 hiBits = GetWord(p);
2952 value = (double) ((hiBits << 16) | loBits) / 65536.0;
2953
2954 return value * ScaleFactor;
2955 }
2956
2957 // ***********************************************************************
2958