draw: corrections to allow for different cliptest cases
[mesa.git] / src / mesa / 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 "gl/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 // Walk over all textures in hash table
1421 // XXX what about the default texture objects (id=0)?
1422 {
1423 struct _mesa_HashTable *textures = ctx->Shared->TexObjects;
1424 GLuint id;
1425 for (id = _mesa_HashFirstEntry(textures);
1426 id;
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];
1434 if (image) {
1435 switch (tObj->Dimensions){
1436 case 1:
1437 if (ctx->Driver.TexImage)
1438 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_1D, tObj, i, image->Format, image);
1439 break;
1440 case 2:
1441 if (ctx->Driver.TexImage)
1442 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, tObj, i, image->Format, image);
1443 break;
1444 default:
1445 break;
1446 }
1447 }
1448 }
1449 }
1450 }
1451 }
1452
1453 // Re-Bind each texture Unit
1454 for (i=0; i<glb.wMaxSimultaneousTextures; i++) {
1455 tObj = ctx->Texture.Unit[i].Current;
1456 if (tObj) {
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);
1461 }
1462 }
1463 }
1464 #endif // _USE_GLD3_WGL
1465
1466 dgl->bCanRender = TRUE;
1467
1468 #ifdef GLD_THREADS
1469 // Release serialized access
1470 if (glb.bMultiThreaded)
1471 LeaveCriticalSection(&CriticalSection);
1472 #endif
1473
1474 // SUCCESS.
1475 return TRUE;
1476
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)
1486 ;
1487 else
1488 RELEASE(dgl->lpFront4);
1489
1490 #undef DDLOG_CRITICAL_OR_WARN
1491 #endif // _USE_GLD3_WGL
1492
1493 // Mark context as not being able to render
1494 dgl->bCanRender = FALSE;
1495
1496 #ifdef GLD_THREADS
1497 // Release serialized access
1498 if (glb.bMultiThreaded)
1499 LeaveCriticalSection(&CriticalSection);
1500 #endif
1501
1502 return FALSE;
1503 }
1504
1505 // ***********************************************************************
1506 // ***********************************************************************
1507 // Support for bitmap fonts.
1508 // ***********************************************************************
1509 // ***********************************************************************
1510
1511 /*****************************************************************************
1512 **
1513 ** InvertGlyphBitmap.
1514 **
1515 ** Invert the bitmap so that it suits OpenGL's representation.
1516 ** Each row starts on a double word boundary.
1517 **
1518 *****************************************************************************/
1519
1520 static void InvertGlyphBitmap(
1521 int w,
1522 int h,
1523 DWORD *fptr,
1524 DWORD *tptr)
1525 {
1526 int dWordsInRow = (w+31)/32;
1527 int i, j;
1528 DWORD *tmp = tptr;
1529
1530 if (w <= 0 || h <= 0) {
1531 return;
1532 }
1533
1534 tptr += ((h-1)*dWordsInRow);
1535 for (i = 0; i < h; i++) {
1536 for (j = 0; j < dWordsInRow; j++) {
1537 *(tptr + j) = *(fptr + j);
1538 }
1539 tptr -= dWordsInRow;
1540 fptr += dWordsInRow;
1541 }
1542 }
1543
1544 // ***********************************************************************
1545
1546 /*****************************************************************************
1547 * wglUseFontBitmaps
1548 *
1549 * Converts a subrange of the glyphs in a GDI font to OpenGL display
1550 * lists.
1551 *
1552 * Extended to support any GDI font, not just TrueType fonts. (DaveM)
1553 *
1554 *****************************************************************************/
1555
1556 BOOL APIENTRY _GLD_WGL_EXPORT(UseFontBitmapsA)(
1557 HDC hDC,
1558 DWORD first,
1559 DWORD count,
1560 DWORD listBase)
1561 {
1562 int i, ox, oy, ix, iy;
1563 int w, h;
1564 int iBufSize, iCurBufSize = 0;
1565 DWORD *bitmapBuffer = NULL;
1566 DWORD *invertedBitmapBuffer = NULL;
1567 BOOL bSuccessOrFail = TRUE;
1568 BOOL bTrueType = FALSE;
1569 TEXTMETRIC tm;
1570 GLYPHMETRICS gm;
1571 RASTERIZER_STATUS rs;
1572 MAT2 mat;
1573 SIZE size;
1574 RECT rect;
1575 HDC hDCMem;
1576 HBITMAP hBitmap;
1577 BITMAPINFO bmi;
1578 HFONT hFont;
1579
1580 // Validate SciTech DirectGL license
1581 if (!dglValidate())
1582 return FALSE;
1583
1584 // Set up a unity matrix.
1585 ZeroMemory(&mat, sizeof(mat));
1586 mat.eM11.value = 1;
1587 mat.eM22.value = 1;
1588
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");
1593 return (FALSE);
1594 }
1595 bTrueType = (tm.tmPitchAndFamily & TMPF_TRUETYPE) ? TRUE : FALSE;
1596
1597 // Test to see if TRUE-TYPE capabilities are installed
1598 // (only necessary if TrueType font selected)
1599 ZeroMemory(&rs, sizeof(rs));
1600 if (bTrueType) {
1601 if (!GetRasterizerCaps (&rs, sizeof (RASTERIZER_STATUS))) {
1602 ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Raster caps error\n");
1603 return (FALSE);
1604 }
1605 if (!(rs.wFlags & TT_ENABLED)) {
1606 ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: No TrueType caps\n");
1607 return (FALSE);
1608 }
1609 }
1610
1611 // Trick to get the current font handle
1612 hFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
1613 SelectObject(hDC, hFont);
1614
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);
1620
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.
1624 if (bTrueType) {
1625 // Use TrueType support to get bitmap size of glyph
1626 iBufSize = GetGlyphOutline(hDC, i, GGO_BITMAP, &gm,
1627 0, NULL, &mat);
1628 if (iBufSize == GDI_ERROR) {
1629 bSuccessOrFail = FALSE;
1630 break;
1631 }
1632 }
1633 else {
1634 // Use generic GDI support to compute bitmap size of glyph
1635 w = tm.tmMaxCharWidth;
1636 h = tm.tmHeight;
1637 if (GetTextExtentPoint32(hDC, (LPCTSTR)&i, 1, &size)) {
1638 w = size.cx;
1639 h = size.cy;
1640 }
1641 iBufSize = w * h;
1642 // Use DWORD multiple for compatibility
1643 iBufSize += 3;
1644 iBufSize /= 4;
1645 iBufSize *= 4;
1646 }
1647
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) {
1651 if (bitmapBuffer) {
1652 __wglFree(bitmapBuffer);
1653 }
1654 if (invertedBitmapBuffer) {
1655 __wglFree(invertedBitmapBuffer);
1656 }
1657
1658 iCurBufSize = iBufSize * 2;
1659 bitmapBuffer = (DWORD *) __wglMalloc(iCurBufSize);
1660 invertedBitmapBuffer = (DWORD *) __wglMalloc(iCurBufSize);
1661
1662 if (bitmapBuffer == NULL || invertedBitmapBuffer == NULL) {
1663 bSuccessOrFail = FALSE;
1664 break;
1665 }
1666 }
1667
1668 // If we fail to get the Glyph data, delete the display lists
1669 // Created so far and return FALSE.
1670 if (bTrueType) {
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;
1675 break;
1676 }
1677
1678 // Setup glBitmap parameters for current font glyph
1679 w = gm.gmBlackBoxX;
1680 h = gm.gmBlackBoxY;
1681 ox = gm.gmptGlyphOrigin.x;
1682 oy = gm.gmptGlyphOrigin.y;
1683 ix = gm.gmCellIncX;
1684 iy = gm.gmCellIncY;
1685 }
1686 else {
1687 // Use generic GDI support to create bitmap of glyph
1688 ZeroMemory(bitmapBuffer, iBufSize);
1689
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);
1708 }
1709 else {
1710 // Otherwise use empty display list for non-existing glyph
1711 iBufSize = 0;
1712 }
1713
1714 // Setup glBitmap parameters for current font glyph
1715 ox = 0;
1716 oy = tm.tmDescent;
1717 ix = w;
1718 iy = 0;
1719 }
1720
1721 // Create an OpenGL display list.
1722 _GLD_glNewList((listBase + i), GL_COMPILE);
1723
1724 // Some fonts have no data for the space character, yet advertise
1725 // a non-zero size.
1726 if (0 == iBufSize) {
1727 _GLD_glBitmap(0, 0, 0.0f, 0.0f, (GLfloat) ix, (GLfloat) iy, NULL);
1728 } else {
1729 // Invert the Glyph data.
1730 InvertGlyphBitmap(w, h, bitmapBuffer, invertedBitmapBuffer);
1731
1732 // Render an OpenGL bitmap and invert the origin.
1733 _GLD_glBitmap(w, h,
1734 (GLfloat) ox, (GLfloat) (h-oy),
1735 (GLfloat) ix, (GLfloat) iy,
1736 (GLubyte *) invertedBitmapBuffer);
1737 }
1738
1739 // Close this display list.
1740 _GLD_glEndList();
1741 }
1742
1743 if (bSuccessOrFail == FALSE) {
1744 ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Get glyph failed\n");
1745 _GLD_glDeleteLists((i+listBase), (i-first));
1746 }
1747
1748 // Release resources used
1749 DeleteObject(hFont);
1750 DeleteDC(hDCMem);
1751
1752 if (bitmapBuffer)
1753 __wglFree(bitmapBuffer);
1754 if (invertedBitmapBuffer)
1755 __wglFree(invertedBitmapBuffer);
1756
1757 return(bSuccessOrFail);
1758 }
1759
1760 // ***********************************************************************
1761
1762 BOOL APIENTRY _GLD_WGL_EXPORT(UseFontBitmapsW)(
1763 HDC a,
1764 DWORD b,
1765 DWORD c,
1766 DWORD d)
1767 {
1768 // Validate license
1769 if (!dglValidate())
1770 return FALSE;
1771
1772 return _GLD_WGL_EXPORT(UseFontBitmapsA)(a, b, c, d);
1773 }
1774
1775 // ***********************************************************************
1776 // ***********************************************************************
1777 // Support for outline TrueType fonts.
1778 // ***********************************************************************
1779 // ***********************************************************************
1780
1781 void * __wglRealloc(
1782 void *oldPtr,
1783 size_t newSize)
1784 {
1785 void *newPtr = NULL;
1786
1787 if (newSize != 0) {
1788 newPtr = (void *) GlobalAlloc(GPTR, newSize);
1789 if (oldPtr && newPtr) {
1790 DWORD oldSize = GlobalSize(oldPtr);
1791
1792 memcpy(newPtr, oldPtr, (oldSize <= newSize ? oldSize : newSize));
1793 GlobalFree(oldPtr);
1794 }
1795 } else if (oldPtr) {
1796 GlobalFree(oldPtr);
1797 }
1798 if (newPtr == NULL) {
1799 return NULL; /* XXX out of memory error */
1800 }
1801 return newPtr;
1802 }
1803
1804 // ***********************************************************************
1805
1806
1807 /*****************************************************************************
1808 * wglUseFontOutlinesW
1809 *
1810 * Converts a subrange of the glyphs in a TrueType font to OpenGL display
1811 * lists.
1812 *****************************************************************************/
1813
1814 BOOL APIENTRY _GLD_WGL_EXPORT(UseFontOutlinesW)(
1815 IN HDC hDC,
1816 IN DWORD first,
1817 IN DWORD count,
1818 IN DWORD listBase,
1819 IN FLOAT chordalDeviation,
1820 IN FLOAT extrusion,
1821 IN INT format,
1822 OUT LPGLYPHMETRICSFLOAT lpgmf)
1823 {
1824 return _GLD_WGL_EXPORT(UseFontOutlinesA)(hDC, first, count, listBase,
1825 chordalDeviation, extrusion, format, lpgmf);
1826 }
1827
1828 /*****************************************************************************
1829 * wglUseFontOutlinesA
1830 *
1831 * Converts a subrange of the glyphs in a TrueType font to OpenGL display
1832 * lists.
1833 *****************************************************************************/
1834
1835 BOOL APIENTRY _GLD_WGL_EXPORT(UseFontOutlinesA)(
1836 IN HDC hDC,
1837 IN DWORD first,
1838 IN DWORD count,
1839 IN DWORD listBase,
1840 IN FLOAT chordalDeviation,
1841 IN FLOAT extrusion,
1842 IN INT format,
1843 OUT LPGLYPHMETRICSFLOAT glyphMetricsFloatArray)
1844 {
1845 DWORD glyphIndex;
1846 UCHAR* glyphBuf;
1847 DWORD glyphBufSize;
1848
1849
1850 /*
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.
1853 */
1854 while (_GLD_glGetError() != GL_NO_ERROR)
1855 ;
1856
1857 /*
1858 * Make sure that the current font can be sampled accurately.
1859 */
1860 hNewFont = CreateHighResolutionFont(hDC);
1861 if (!hNewFont)
1862 return FALSE;
1863
1864 hOldFont = SelectObject(hDC, hNewFont);
1865 if (!hOldFont)
1866 return FALSE;
1867
1868 /*
1869 * Preallocate a buffer for the outline data, and track its size:
1870 */
1871 glyphBuf = (UCHAR*) __wglMalloc(glyphBufSize = 10240);
1872 if (!glyphBuf)
1873 return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
1874
1875 /*
1876 * Process each glyph in the given range:
1877 */
1878 for (glyphIndex = first; glyphIndex - first < count; ++glyphIndex)
1879 {
1880 GLYPHMETRICS glyphMetrics;
1881 DWORD glyphSize;
1882 static MAT2 matrix =
1883 {
1884 {0, 1}, {0, 0},
1885 {0, 0}, {0, 1}
1886 };
1887 LPGLYPHMETRICSFLOAT glyphMetricsFloat =
1888 &glyphMetricsFloatArray[glyphIndex - first];
1889
1890
1891 /*
1892 * Determine how much space is needed to store the glyph's
1893 * outlines. If our glyph buffer isn't large enough,
1894 * resize it.
1895 */
1896 glyphSize = GetGlyphOutline( hDC,
1897 glyphIndex,
1898 GGO_NATIVE,
1899 &glyphMetrics,
1900 0,
1901 NULL,
1902 &matrix
1903 );
1904 if (glyphSize < 0)
1905 return FALSE; /*WGL_STATUS_FAILURE*/
1906 if (glyphSize > glyphBufSize)
1907 {
1908 __wglFree(glyphBuf);
1909 glyphBuf = (UCHAR*) __wglMalloc(glyphBufSize = glyphSize);
1910 if (!glyphBuf)
1911 return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
1912 }
1913
1914
1915 /*
1916 * Get the glyph's outlines.
1917 */
1918 if (GetGlyphOutline( hDC,
1919 glyphIndex,
1920 GGO_NATIVE,
1921 &glyphMetrics,
1922 glyphBufSize,
1923 glyphBuf,
1924 &matrix
1925 ) < 0)
1926 {
1927 __wglFree(glyphBuf);
1928 return FALSE; /*WGL_STATUS_FAILURE*/
1929 }
1930
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;
1943
1944 /*
1945 * Turn the glyph into a display list:
1946 */
1947 if (!MakeDisplayListFromGlyph( (glyphIndex - first) + listBase,
1948 glyphBuf,
1949 glyphSize,
1950 glyphMetricsFloat,
1951 chordalDeviation + ScaleFactor,
1952 extrusion,
1953 format))
1954 {
1955 __wglFree(glyphBuf);
1956 return FALSE; /*WGL_STATUS_FAILURE*/
1957 }
1958 }
1959
1960
1961 /*
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.
1965 */
1966 __wglFree(glyphBuf);
1967
1968 SelectObject(hDC, hOldFont);
1969
1970 if (_GLD_glGetError() == GL_NO_ERROR)
1971 return TRUE; /*WGL_STATUS_SUCCESS*/
1972 else
1973 {
1974 while (_GLD_glGetError() != GL_NO_ERROR)
1975 ;
1976 return FALSE; /*WGL_STATUS_FAILURE*/
1977 }
1978 }
1979
1980
1981
1982 /*****************************************************************************
1983 * CreateHighResolutionFont
1984 *
1985 * Gets metrics for the current font and creates an equivalent font
1986 * scaled to the design units of the font.
1987 *
1988 *****************************************************************************/
1989
1990 static HFONT
1991 CreateHighResolutionFont(HDC hDC)
1992 {
1993 UINT otmSize;
1994 OUTLINETEXTMETRIC *otm;
1995 LONG fontHeight, fontWidth, fontUnits;
1996 LOGFONT logFont;
1997
1998 otmSize = GetOutlineTextMetrics(hDC, 0, NULL);
1999 if (otmSize == 0)
2000 return NULL;
2001
2002 otm = (OUTLINETEXTMETRIC *) __wglMalloc(otmSize);
2003 if (otm == NULL)
2004 return NULL;
2005
2006 otm->otmSize = otmSize;
2007 if (GetOutlineTextMetrics(hDC, otmSize, otm) == 0)
2008 return NULL;
2009
2010 fontHeight = otm->otmTextMetrics.tmHeight -
2011 otm->otmTextMetrics.tmInternalLeading;
2012 fontWidth = otm->otmTextMetrics.tmAveCharWidth;
2013 fontUnits = (LONG) otm->otmEMSquare;
2014
2015 ScaleFactor = 1.0F / (FLOAT) fontUnits;
2016
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);
2034
2035 hNewFont = CreateFontIndirect(&logFont);
2036 if (hNewFont == NULL)
2037 return NULL;
2038
2039 __wglFree(otm);
2040
2041 return hNewFont;
2042 }
2043
2044
2045
2046 /*****************************************************************************
2047 * MakeDisplayListFromGlyph
2048 *
2049 * Converts the outline of a glyph to an OpenGL display list.
2050 *
2051 * Return value is nonzero for success, zero for failure.
2052 *
2053 * Does not check for OpenGL errors, so if the caller needs to know about them,
2054 * it should call glGetError().
2055 *****************************************************************************/
2056
2057 static int
2058 MakeDisplayListFromGlyph( IN DWORD listName,
2059 IN UCHAR* glyphBuf,
2060 IN DWORD glyphSize,
2061 IN LPGLYPHMETRICSFLOAT glyphMetricsFloat,
2062 IN FLOAT chordalDeviation,
2063 IN FLOAT extrusion,
2064 IN INT format)
2065 {
2066 int status;
2067
2068 _GLD_glNewList(listName, GL_COMPILE);
2069 status = DrawGlyph( glyphBuf,
2070 glyphSize,
2071 chordalDeviation,
2072 extrusion,
2073 format);
2074
2075 _GLD_glTranslatef(glyphMetricsFloat->gmfCellIncX,
2076 glyphMetricsFloat->gmfCellIncY,
2077 0.0F);
2078 _GLD_glEndList();
2079
2080 return status;
2081 }
2082
2083
2084
2085 /*****************************************************************************
2086 * DrawGlyph
2087 *
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".
2092 *
2093 * Return value is nonzero for success, zero for failure.
2094 *
2095 * Does not check for OpenGL errors, so if the caller needs to know about them,
2096 * it should call glGetError().
2097 *****************************************************************************/
2098
2099 static int
2100 DrawGlyph( IN UCHAR* glyphBuf,
2101 IN DWORD glyphSize,
2102 IN FLOAT chordalDeviation,
2103 IN FLOAT extrusion,
2104 IN INT format)
2105 {
2106 INT status = 0;
2107 FLOAT* p;
2108 DWORD loop;
2109 DWORD point;
2110 GLUtesselator* tess = NULL;
2111
2112
2113 /*
2114 * Initialize the global buffer into which we place the outlines:
2115 */
2116 if (!InitLineBuf())
2117 goto exit;
2118
2119
2120 /*
2121 * Convert the glyph outlines to a set of polyline loops.
2122 * (See MakeLinesFromGlyph() for the format of the loop data
2123 * structure.)
2124 */
2125 if (!MakeLinesFromGlyph(glyphBuf, glyphSize, chordalDeviation))
2126 goto exit;
2127 p = LineBuf;
2128
2129
2130 /*
2131 * Now draw the loops in the appropriate format:
2132 */
2133 if (format == WGL_FONT_LINES)
2134 {
2135 /*
2136 * This is the easy case. Just draw the outlines.
2137 */
2138 for (loop = (DWORD) *p++; loop; --loop)
2139 {
2140 _GLD_glBegin(GL_LINE_LOOP);
2141 for (point = (DWORD) *p++; point; --point)
2142 {
2143 _GLD_glVertex2fv(p);
2144 p += 2;
2145 }
2146 _GLD_glEnd();
2147 }
2148 status = 1;
2149 }
2150
2151 else if (format == WGL_FONT_POLYGONS)
2152 {
2153 double v[3];
2154 FLOAT *save_p = p;
2155 GLfloat z_value;
2156
2157 /*
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.
2162 */
2163 if (!LoadGLUTesselator())
2164 goto exit;
2165 if (!InitVertBuf())
2166 goto exit;
2167 if (!(tess = gluNewTessProc()))
2168 goto exit;
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);
2176
2177 TessErrorOccurred = 0;
2178 _GLD_glNormal3f(0.0f, 0.0f, 1.0f);
2179 v[2] = 0.0;
2180 z_value = 0.0f;
2181
2182 gluTessBeginPolygonProc(tess, (void *)*(int *)&z_value);
2183 for (loop = (DWORD) *p++; loop; --loop)
2184 {
2185 gluTessBeginContourProc(tess);
2186
2187 for (point = (DWORD) *p++; point; --point)
2188 {
2189 v[0] = p[0];
2190 v[1] = p[1];
2191 gluTessVertexProc(tess, v, p);
2192 p += 2;
2193 }
2194
2195 gluTessEndContourProc(tess);
2196 }
2197 gluTessEndPolygonProc(tess);
2198
2199 status = !TessErrorOccurred;
2200
2201 /* Extrusion code */
2202 if (extrusion) {
2203 DWORD loops;
2204 GLfloat thickness = (GLfloat) -extrusion;
2205 FLOAT *vert, *vert2;
2206 DWORD count;
2207
2208 p = save_p;
2209 loops = (DWORD) *p++;
2210
2211 for (loop = 0; loop < loops; loop++) {
2212 GLfloat dx, dy, len;
2213 DWORD last;
2214
2215 count = (DWORD) *p++;
2216 _GLD_glBegin(GL_QUAD_STRIP);
2217
2218 /* Check if the first and last vertex are identical
2219 * so we don't draw the same quad twice.
2220 */
2221 vert = p + (count-1)*2;
2222 last = (p[0] == vert[0] && p[1] == vert[1]) ? count-1 : count;
2223
2224 for (point = 0; point <= last; point++) {
2225 vert = p + 2 * (point % last);
2226 vert2 = p + 2 * ((point+1) % last);
2227
2228 dx = vert[0] - vert2[0];
2229 dy = vert[1] - vert2[1];
2230 len = (GLfloat)sqrt(dx * dx + dy * dy);
2231
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);
2237 }
2238
2239 _GLD_glEnd();
2240 p += count*2;
2241 }
2242
2243 /* Draw the back face */
2244 p = save_p;
2245 v[2] = thickness;
2246 _GLD_glNormal3f(0.0f, 0.0f, -1.0f);
2247 gluTessNormalProc(tess, 0.0F, 0.0F, -1.0F);
2248
2249 gluTessBeginPolygonProc(tess, (void *)*(int *)&thickness);
2250
2251 for (loop = (DWORD) *p++; loop; --loop)
2252 {
2253 count = (DWORD) *p++;
2254
2255 gluTessBeginContourProc(tess);
2256
2257 for (point = 0; point < count; point++)
2258 {
2259 vert = p + ((count-point-1)<<1);
2260 v[0] = vert[0];
2261 v[1] = vert[1];
2262 gluTessVertexProc(tess, v, vert);
2263 }
2264 p += count*2;
2265
2266 gluTessEndContourProc(tess);
2267 }
2268 gluTessEndPolygonProc(tess);
2269 }
2270
2271 #if DEBUG
2272 if (TessErrorOccurred)
2273 printf("Tessellation error %s\n",
2274 gluErrorString(TessErrorOccurred));
2275 #endif
2276 }
2277
2278
2279 exit:
2280 FreeLineBuf();
2281 if (tess)
2282 gluDeleteTessProc(tess);
2283 // UnloadGLUTesselator();
2284 FreeVertBuf();
2285 return status;
2286 }
2287
2288
2289
2290 /*****************************************************************************
2291 * LoadGLUTesselator
2292 *
2293 * Maps the glu32.dll module and gets function pointers for the
2294 * tesselator functions.
2295 *****************************************************************************/
2296
2297 static BOOL
2298 LoadGLUTesselator(void)
2299 {
2300 if (gluModuleHandle != NULL)
2301 return TRUE;
2302
2303 {
2304 extern HINSTANCE hInstanceOpenGL;
2305 char *gluName = "GLU32.DLL";
2306 // char name[256];
2307 // char *ptr;
2308 // int len;
2309
2310 /*
2311 len = GetModuleFileName(hInstanceOpenGL, name, 255);
2312 if (len != 0)
2313 {
2314 ptr = name+len-1;
2315 while (ptr > name && *ptr != '\\')
2316 ptr--;
2317 if (*ptr == '\\')
2318 ptr++;
2319 if (!stricmp(ptr, "cosmogl.dll"))
2320 {
2321 gluName = "COSMOGLU.DLL";
2322 }
2323 else if (!stricmp(ptr, "opengl32.dll"))
2324 {
2325 gluName = "GLU32.DLL";
2326 }
2327 }
2328 */
2329 if ((gluModuleHandle = LoadLibrary(gluName)) == NULL)
2330 return FALSE;
2331 }
2332
2333 if ((gluNewTessProc = (gluNewTessProto)
2334 GetProcAddress(gluModuleHandle, "gluNewTess")) == NULL)
2335 return FALSE;
2336
2337 if ((gluDeleteTessProc = (gluDeleteTessProto)
2338 GetProcAddress(gluModuleHandle, "gluDeleteTess")) == NULL)
2339 return FALSE;
2340
2341 if ((gluTessBeginPolygonProc = (gluTessBeginPolygonProto)
2342 GetProcAddress(gluModuleHandle, "gluTessBeginPolygon")) == NULL)
2343 return FALSE;
2344
2345 if ((gluTessBeginContourProc = (gluTessBeginContourProto)
2346 GetProcAddress(gluModuleHandle, "gluTessBeginContour")) == NULL)
2347 return FALSE;
2348
2349 if ((gluTessVertexProc = (gluTessVertexProto)
2350 GetProcAddress(gluModuleHandle, "gluTessVertex")) == NULL)
2351 return FALSE;
2352
2353 if ((gluTessEndContourProc = (gluTessEndContourProto)
2354 GetProcAddress(gluModuleHandle, "gluTessEndContour")) == NULL)
2355 return FALSE;
2356
2357 if ((gluTessEndPolygonProc = (gluTessEndPolygonProto)
2358 GetProcAddress(gluModuleHandle, "gluTessEndPolygon")) == NULL)
2359 return FALSE;
2360
2361 if ((gluTessPropertyProc = (gluTessPropertyProto)
2362 GetProcAddress(gluModuleHandle, "gluTessProperty")) == NULL)
2363 return FALSE;
2364
2365 if ((gluTessNormalProc = (gluTessNormalProto)
2366 GetProcAddress(gluModuleHandle, "gluTessNormal")) == NULL)
2367 return FALSE;
2368
2369 if ((gluTessCallbackProc = (gluTessCallbackProto)
2370 GetProcAddress(gluModuleHandle, "gluTessCallback")) == NULL)
2371 return FALSE;
2372
2373 return TRUE;
2374 }
2375
2376
2377
2378 /*****************************************************************************
2379 * UnloadGLUTesselator
2380 *
2381 * Unmaps the glu32.dll module.
2382 *****************************************************************************/
2383
2384 static BOOL
2385 UnloadGLUTesselator(void)
2386 {
2387 if (gluModuleHandle != NULL)
2388 if (FreeLibrary(gluModuleHandle) == FALSE)
2389 return FALSE;
2390 gluModuleHandle = NULL;
2391 }
2392
2393
2394
2395 /*****************************************************************************
2396 * TessVertexOut
2397 *
2398 * Used by tessellator to handle output vertexes.
2399 *****************************************************************************/
2400
2401 static void CALLBACK
2402 TessVertexOut(FLOAT p[3])
2403 {
2404 GLfloat v[2];
2405
2406 v[0] = p[0] * ScaleFactor;
2407 v[1] = p[1] * ScaleFactor;
2408 _GLD_glVertex2fv(v);
2409 }
2410
2411 static void CALLBACK
2412 TessVertexOutData(FLOAT p[3], GLfloat z)
2413 {
2414 GLfloat v[3];
2415
2416 v[0] = (GLfloat) p[0];
2417 v[1] = (GLfloat) p[1];
2418 v[2] = z;
2419 _GLD_glVertex3fv(v);
2420 }
2421
2422
2423 /*****************************************************************************
2424 * TessCombine
2425 *
2426 * Used by tessellator to handle self-intersecting contours and degenerate
2427 * geometry.
2428 *****************************************************************************/
2429
2430 static void CALLBACK
2431 TessCombine(double coords[3],
2432 void* vertex_data[4],
2433 FLOAT weight[4],
2434 void** outData)
2435 {
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);
2441 }
2442
2443
2444
2445 /*****************************************************************************
2446 * TessError
2447 *
2448 * Saves the last tessellator error code in the global TessErrorOccurred.
2449 *****************************************************************************/
2450
2451 static void CALLBACK
2452 TessError(GLenum error)
2453 {
2454 TessErrorOccurred = error;
2455 }
2456
2457
2458
2459 /*****************************************************************************
2460 * MakeLinesFromGlyph
2461 *
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.
2464 *
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:
2470 *
2471 * 1., 3., 0., 0., 1., 0., 0., 1.
2472 * ^ ^ ^ ^ ^ ^ ^ ^
2473 * #loops #verts x1 y1 x2 y2 x3 y3
2474 *
2475 * A two-loop glyph would look like this:
2476 *
2477 * 2., 3., 0.,0., 1.,0., 0.,1., 3., .2,.2, .4,.2, .2,.4
2478 *
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 *****************************************************************************/
2483
2484 static int
2485 MakeLinesFromGlyph(IN UCHAR* glyphBuf,
2486 IN DWORD glyphSize,
2487 IN FLOAT chordalDeviation)
2488 {
2489 UCHAR* p;
2490 int status = 0;
2491
2492
2493 /*
2494 * Pick up all the polygons (aka loops) that make up the glyph:
2495 */
2496 if (!AppendToLineBuf(0.0F)) /* loop count at LineBuf[0] */
2497 goto exit;
2498
2499 p = glyphBuf;
2500 while (p < glyphBuf + glyphSize)
2501 {
2502 if (!MakeLinesFromTTPolygon(&p, chordalDeviation))
2503 goto exit;
2504 LineBuf[0] += 1.0F; /* increment loop count */
2505 }
2506
2507 status = 1;
2508
2509 exit:
2510 return status;
2511 }
2512
2513
2514
2515 /*****************************************************************************
2516 * MakeLinesFromTTPolygon
2517 *
2518 * Converts a TTPOLYGONHEADER and its associated curve structures into a
2519 * single polyline loop in the global LineBuf.
2520 *****************************************************************************/
2521
2522 static int
2523 MakeLinesFromTTPolygon( IN OUT UCHAR** pp,
2524 IN FLOAT chordalDeviation)
2525 {
2526 DWORD polySize;
2527 UCHAR* polyStart;
2528 DWORD vertexCountIndex;
2529
2530 /*
2531 * Record where the polygon data begins, and where the loop's
2532 * vertex count resides:
2533 */
2534 polyStart = *pp;
2535 vertexCountIndex = LineBufIndex;
2536 if (!AppendToLineBuf(0.0F))
2537 return 0;
2538
2539 /*
2540 * Extract relevant data from the TTPOLYGONHEADER:
2541 */
2542 polySize = GetDWord(pp);
2543 if (GetDWord(pp) != TT_POLYGON_TYPE) /* polygon type */
2544 return 0;
2545 if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first X coord */
2546 return 0;
2547 if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first Y coord */
2548 return 0;
2549 LineBuf[vertexCountIndex] += 1.0F;
2550
2551 /*
2552 * Process each of the TTPOLYCURVE structures in the polygon:
2553 */
2554 while (*pp < polyStart + polySize)
2555 if (!MakeLinesFromTTPolycurve( pp,
2556 vertexCountIndex,
2557 chordalDeviation))
2558 return 0;
2559
2560 return 1;
2561 }
2562
2563
2564
2565 /*****************************************************************************
2566 * MakeLinesFromTTPolyCurve
2567 *
2568 * Converts the lines and splines in a single TTPOLYCURVE structure to points
2569 * in the global LineBuf.
2570 *****************************************************************************/
2571
2572 static int
2573 MakeLinesFromTTPolycurve( IN OUT UCHAR** pp,
2574 IN DWORD vertexCountIndex,
2575 IN FLOAT chordalDeviation)
2576 {
2577 WORD type;
2578 WORD pointCount;
2579
2580
2581 /*
2582 * Pick up the relevant fields of the TTPOLYCURVE structure:
2583 */
2584 type = (WORD) GetWord(pp);
2585 pointCount = (WORD) GetWord(pp);
2586
2587 /*
2588 * Convert the "curve" to line segments:
2589 */
2590 if (type == TT_PRIM_LINE)
2591 return MakeLinesFromTTLine( pp,
2592 vertexCountIndex,
2593 pointCount);
2594 else if (type == TT_PRIM_QSPLINE)
2595 return MakeLinesFromTTQSpline( pp,
2596 vertexCountIndex,
2597 pointCount,
2598 chordalDeviation);
2599 else
2600 return 0;
2601 }
2602
2603
2604
2605 /*****************************************************************************
2606 * MakeLinesFromTTLine
2607 *
2608 * Converts points from the polyline in a TT_PRIM_LINE structure to
2609 * equivalent points in the global LineBuf.
2610 *****************************************************************************/
2611 static int
2612 MakeLinesFromTTLine( IN OUT UCHAR** pp,
2613 IN DWORD vertexCountIndex,
2614 IN WORD pointCount)
2615 {
2616 /*
2617 * Just copy the line segments into the line buffer (converting
2618 * type as we go):
2619 */
2620 LineBuf[vertexCountIndex] += pointCount;
2621 while (pointCount--)
2622 {
2623 if (!AppendToLineBuf((FLOAT) GetFixed(pp)) /* X coord */
2624 || !AppendToLineBuf((FLOAT) GetFixed(pp))) /* Y coord */
2625 return 0;
2626 }
2627
2628 return 1;
2629 }
2630
2631
2632
2633 /*****************************************************************************
2634 * MakeLinesFromTTQSpline
2635 *
2636 * Converts points from the poly quadratic spline in a TT_PRIM_QSPLINE
2637 * structure to polyline points in the global LineBuf.
2638 *****************************************************************************/
2639
2640 static int
2641 MakeLinesFromTTQSpline( IN OUT UCHAR** pp,
2642 IN DWORD vertexCountIndex,
2643 IN WORD pointCount,
2644 IN FLOAT chordalDeviation)
2645 {
2646 FLOAT x0, y0, x1, y1, x2, y2;
2647 WORD point;
2648
2649 /*
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.
2658 */
2659 for (point = 0; point < pointCount - 1; ++point)
2660 {
2661 x0 = LineBuf[LineBufIndex - 2];
2662 y0 = LineBuf[LineBufIndex - 1];
2663
2664 x1 = (FLOAT) GetFixed(pp);
2665 y1 = (FLOAT) GetFixed(pp);
2666
2667 if (point == pointCount - 2)
2668 {
2669 /*
2670 * This is the last arc in the QSpline. The final
2671 * point is the end of the arc.
2672 */
2673 x2 = (FLOAT) GetFixed(pp);
2674 y2 = (FLOAT) GetFixed(pp);
2675 }
2676 else
2677 {
2678 /*
2679 * Peek at the next point in the input to compute
2680 * the end of the arc:
2681 */
2682 x2 = 0.5F * (x1 + (FLOAT) GetFixed(pp));
2683 y2 = 0.5F * (y1 + (FLOAT) GetFixed(pp));
2684 /*
2685 * Push the point back onto the input so it will
2686 * be reused as the next off-curve point:
2687 */
2688 *pp -= 8;
2689 }
2690
2691 if (!MakeLinesFromArc( x0, y0,
2692 x1, y1,
2693 x2, y2,
2694 vertexCountIndex,
2695 chordalDeviation * chordalDeviation))
2696 return 0;
2697 }
2698
2699 return 1;
2700 }
2701
2702
2703
2704 /*****************************************************************************
2705 * MakeLinesFromArc
2706 *
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 *****************************************************************************/
2711
2712 static int
2713 MakeLinesFromArc( IN FLOAT x0,
2714 IN FLOAT y0,
2715 IN FLOAT x1,
2716 IN FLOAT y1,
2717 IN FLOAT x2,
2718 IN FLOAT y2,
2719 IN DWORD vertexCountIndex,
2720 IN FLOAT chordalDeviationSquared)
2721 {
2722 FLOAT x01;
2723 FLOAT y01;
2724 FLOAT x12;
2725 FLOAT y12;
2726 FLOAT midPointX;
2727 FLOAT midPointY;
2728 FLOAT deltaX;
2729 FLOAT deltaY;
2730
2731 /*
2732 * Calculate midpoint of the curve by de Casteljau:
2733 */
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);
2740
2741
2742 /*
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.
2748 */
2749 deltaX = midPointX - x1;
2750 deltaY = midPointY - y1;
2751 if (deltaX * deltaX + deltaY * deltaY > chordalDeviationSquared)
2752 {
2753 MakeLinesFromArc( x0, y0,
2754 x01, y01,
2755 midPointX, midPointY,
2756 vertexCountIndex,
2757 chordalDeviationSquared);
2758
2759 MakeLinesFromArc( midPointX, midPointY,
2760 x12, y12,
2761 x2, y2,
2762 vertexCountIndex,
2763 chordalDeviationSquared);
2764 }
2765 else
2766 {
2767 /*
2768 * The "pen" is already at (x0, y0), so we don't need to
2769 * add that point to the LineBuf.
2770 */
2771 if (!AppendToLineBuf(x1)
2772 || !AppendToLineBuf(y1)
2773 || !AppendToLineBuf(x2)
2774 || !AppendToLineBuf(y2))
2775 return 0;
2776 LineBuf[vertexCountIndex] += 2.0F;
2777 }
2778
2779 return 1;
2780 }
2781
2782
2783
2784 /*****************************************************************************
2785 * InitLineBuf
2786 *
2787 * Initializes the global LineBuf and its associated size and current-element
2788 * counters.
2789 *****************************************************************************/
2790
2791 static int
2792 InitLineBuf(void)
2793 {
2794 if (!(LineBuf = (FLOAT*)
2795 __wglMalloc((LineBufSize = LINE_BUF_QUANT) * sizeof(FLOAT))))
2796 return 0;
2797 LineBufIndex = 0;
2798 return 1;
2799 }
2800
2801
2802
2803 /*****************************************************************************
2804 * InitVertBuf
2805 *
2806 * Initializes the global VertBuf and its associated size and current-element
2807 * counters.
2808 *****************************************************************************/
2809
2810 static int
2811 InitVertBuf(void)
2812 {
2813 if (!(VertBuf = (FLOAT*)
2814 __wglMalloc((VertBufSize = VERT_BUF_QUANT) * sizeof(FLOAT))))
2815 return 0;
2816 VertBufIndex = 0;
2817 return 1;
2818 }
2819
2820
2821
2822 /*****************************************************************************
2823 * AppendToLineBuf
2824 *
2825 * Appends one floating-point value to the global LineBuf array. Return value
2826 * is non-zero for success, zero for failure.
2827 *****************************************************************************/
2828
2829 static int
2830 AppendToLineBuf(FLOAT value)
2831 {
2832 if (LineBufIndex >= LineBufSize)
2833 {
2834 FLOAT* f;
2835
2836 f = (FLOAT*) __wglRealloc(LineBuf,
2837 (LineBufSize += LINE_BUF_QUANT) * sizeof(FLOAT));
2838 if (!f)
2839 return 0;
2840 LineBuf = f;
2841 }
2842 LineBuf[LineBufIndex++] = value;
2843 return 1;
2844 }
2845
2846
2847
2848 /*****************************************************************************
2849 * AppendToVertBuf
2850 *
2851 * Appends one floating-point value to the global VertBuf array. Return value
2852 * is non-zero for success, zero for failure.
2853 *
2854 * Note that we can't realloc this one, because the tessellator is using
2855 * pointers into it.
2856 *****************************************************************************/
2857
2858 static int
2859 AppendToVertBuf(FLOAT value)
2860 {
2861 if (VertBufIndex >= VertBufSize)
2862 return 0;
2863 VertBuf[VertBufIndex++] = value;
2864 return 1;
2865 }
2866
2867
2868
2869 /*****************************************************************************
2870 * FreeLineBuf
2871 *
2872 * Cleans up vertex buffer structure.
2873 *****************************************************************************/
2874
2875 static void
2876 FreeLineBuf(void)
2877 {
2878 if (LineBuf)
2879 {
2880 __wglFree(LineBuf);
2881 LineBuf = NULL;
2882 }
2883 }
2884
2885
2886
2887 /*****************************************************************************
2888 * FreeVertBuf
2889 *
2890 * Cleans up vertex buffer structure.
2891 *****************************************************************************/
2892
2893 static void
2894 FreeVertBuf(void)
2895 {
2896 if (VertBuf)
2897 {
2898 __wglFree(VertBuf);
2899 VertBuf = NULL;
2900 }
2901 }
2902
2903
2904
2905 /*****************************************************************************
2906 * GetWord
2907 *
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 *****************************************************************************/
2911
2912 static long GetWord(UCHAR** p)
2913 {
2914 long value;
2915
2916 value = ((*p)[1] << 8) + (*p)[0];
2917 *p += 2;
2918 return value;
2919 }
2920
2921
2922
2923 /*****************************************************************************
2924 * GetDWord
2925 *
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 *****************************************************************************/
2929
2930 static long GetDWord(UCHAR** p)
2931 {
2932 long value;
2933
2934 value = ((*p)[3] << 24) + ((*p)[2] << 16) + ((*p)[1] << 8) + (*p)[0];
2935 *p += 4;
2936 return value;
2937 }
2938
2939
2940
2941
2942 /*****************************************************************************
2943 * GetFixed
2944 *
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
2947 * unscanned byte.
2948 *****************************************************************************/
2949
2950 static double GetFixed(
2951 UCHAR** p)
2952 {
2953 long hiBits, loBits;
2954 double value;
2955
2956 loBits = GetWord(p);
2957 hiBits = GetWord(p);
2958 value = (double) ((hiBits << 16) | loBits) / 65536.0;
2959
2960 return value * ScaleFactor;
2961 }
2962
2963 // ***********************************************************************
2964