ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

dglwgl.c
Go to the documentation of this file.
00001 /****************************************************************************
00002 *
00003 *                        Mesa 3-D graphics library
00004 *                        Direct3D Driver Interface
00005 *
00006 *  ========================================================================
00007 *
00008 *   Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
00009 *
00010 *   Permission is hereby granted, free of charge, to any person obtaining a
00011 *   copy of this software and associated documentation files (the "Software"),
00012 *   to deal in the Software without restriction, including without limitation
00013 *   the rights to use, copy, modify, merge, publish, distribute, sublicense,
00014 *   and/or sell copies of the Software, and to permit persons to whom the
00015 *   Software is furnished to do so, subject to the following conditions:
00016 *
00017 *   The above copyright notice and this permission notice shall be included
00018 *   in all copies or substantial portions of the Software.
00019 *
00020 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00021 *   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00022 *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00023 *   SCITECH SOFTWARE INC BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
00024 *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
00025 *   OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00026 *   SOFTWARE.
00027 *
00028 *  ======================================================================
00029 *
00030 * Language:     ANSI C
00031 * Environment:  Windows 9x (Win32)
00032 *
00033 * Description:  OpenGL window  functions (wgl*).
00034 *
00035 ****************************************************************************/
00036 
00037 #include "dglwgl.h"
00038 #ifdef _USE_GLD3_WGL
00039 #include "gld_driver.h"
00040 #endif
00041 
00042 #include "gl/glu.h" // MUST USE MICROSOFT'S GLU32!
00043 
00044 #ifndef _USE_GLD3_WGL
00045 extern DGL_mesaFuncs mesaFuncs;
00046 #endif
00047 
00048 // Need to export wgl* functions if using GLD3,
00049 // otherwise export GLD2 DGL_* functions.
00050 #ifdef _USE_GLD3_WGL
00051 #define _GLD_WGL_EXPORT(a) wgl##a
00052 #else
00053 #define _GLD_WGL_EXPORT(a) DGL_##a
00054 #endif
00055 
00056 // Calls into Mesa 4.x are different
00057 #ifdef _USE_GLD3_WGL
00058 #include "dlist.h"
00059 #include "drawpix.h"
00060 #include "get.h"
00061 #include "matrix.h"
00062 // NOTE: All the _GLD* macros now call the gl* functions direct.
00063 //       This ensures that the correct internal pathway is taken. KeithH
00064 #define _GLD_glNewList      glNewList
00065 #define _GLD_glBitmap       glBitmap
00066 #define _GLD_glEndList      glEndList
00067 #define _GLD_glDeleteLists  glDeleteLists
00068 #define _GLD_glGetError     glGetError
00069 #define _GLD_glTranslatef   glTranslatef
00070 #define _GLD_glBegin        glBegin
00071 #define _GLD_glVertex2fv    glVertex2fv
00072 #define _GLD_glEnd          glEnd
00073 #define _GLD_glNormal3f     glNormal3f
00074 #define _GLD_glVertex3f     glVertex3f
00075 #define _GLD_glVertex3fv    glVertex3fv
00076 #else // _USE_GLD3_WGL
00077 #define _GLD_glNewList      (*mesaFuncs.glNewList)
00078 #define _GLD_glBitmap       (*mesaFuncs.glBitmap)
00079 #define _GLD_glEndList      (*mesaFuncs.glEndList)
00080 #define _GLD_glDeleteLists  (*mesaFuncs.glDeleteLists)
00081 #define _GLD_glGetError     (*mesaFuncs.glGetError)
00082 #define _GLD_glTranslatef   (*mesaFuncs.glTranslatef)
00083 #define _GLD_glBegin        (*mesaFuncs.glBegin)
00084 #define _GLD_glVertex2fv    (*mesaFuncs.glVertex2fv)
00085 #define _GLD_glEnd          (*mesaFuncs.glEnd)
00086 #define _GLD_glNormal3f     (*mesaFuncs.glNormal3f)
00087 #define _GLD_glVertex3f     (*mesaFuncs.glVertex3f)
00088 #define _GLD_glVertex3fv    (*mesaFuncs.glVertex3fv)
00089 #endif // _USE_GLD3_WGL
00090 
00091 // ***********************************************************************
00092 
00093 // Emulate SGI DDK calls.
00094 #define __wglMalloc(a) GlobalAlloc(GPTR, (a))
00095 #define __wglFree(a) GlobalFree((a))
00096 
00097 // ***********************************************************************
00098 
00099 // Mesa glu.h and MS glu.h call these different things...
00100 //#define GLUtesselator GLUtriangulatorObj
00101 //#define GLU_TESS_VERTEX_DATA GLU_VERTEX_DATA
00102 
00103 // For wglFontOutlines
00104 
00105 typedef GLUtesselator *(APIENTRY *gluNewTessProto)(void);
00106 typedef void (APIENTRY *gluDeleteTessProto)(GLUtesselator *tess);
00107 typedef void (APIENTRY *gluTessBeginPolygonProto)(GLUtesselator *tess, void *polygon_data);
00108 typedef void (APIENTRY *gluTessBeginContourProto)(GLUtesselator *tess);
00109 typedef void (APIENTRY *gluTessVertexProto)(GLUtesselator *tess, GLdouble coords[3], void *data);
00110 typedef void (APIENTRY *gluTessEndContourProto)(GLUtesselator *tess);
00111 typedef void (APIENTRY *gluTessEndPolygonProto)(GLUtesselator *tess);
00112 typedef void (APIENTRY *gluTessPropertyProto)(GLUtesselator *tess, GLenum which, GLdouble value);
00113 typedef void (APIENTRY *gluTessNormalProto)(GLUtesselator *tess, GLdouble x, GLdouble y, GLdouble z);
00114 typedef void (APIENTRY *gluTessCallbackProto)(GLUtesselator *tess, GLenum which, void (CALLBACK *)());
00115 
00116 static HINSTANCE        gluModuleHandle;
00117 static gluNewTessProto      gluNewTessProc;
00118 static gluDeleteTessProto   gluDeleteTessProc;
00119 static gluTessBeginPolygonProto gluTessBeginPolygonProc;
00120 static gluTessBeginContourProto gluTessBeginContourProc;
00121 static gluTessVertexProto   gluTessVertexProc;
00122 static gluTessEndContourProto   gluTessEndContourProc;
00123 static gluTessEndPolygonProto   gluTessEndPolygonProc;
00124 static gluTessPropertyProto gluTessPropertyProc;
00125 static gluTessNormalProto   gluTessNormalProc;
00126 static gluTessCallbackProto gluTessCallbackProc;
00127 
00128 static HFONT    hNewFont, hOldFont;
00129 static FLOAT    ScaleFactor;
00130 
00131 #define LINE_BUF_QUANT 4000
00132 #define VERT_BUF_QUANT 4000
00133 
00134 static FLOAT*   LineBuf;
00135 static DWORD    LineBufSize;
00136 static DWORD    LineBufIndex;
00137 static FLOAT*   VertBuf;
00138 static DWORD    VertBufSize;
00139 static DWORD    VertBufIndex;
00140 static GLenum   TessErrorOccurred;
00141 
00142 static int AppendToLineBuf(
00143     FLOAT value);
00144 
00145 static int AppendToVertBuf(
00146     FLOAT value);
00147 
00148 static int DrawGlyph(
00149     UCHAR*      glyphBuf,
00150     DWORD       glyphSize,
00151     FLOAT       chordalDeviation,
00152     FLOAT       extrusion,
00153     INT     format);
00154 
00155 static void FreeLineBuf(void);
00156 
00157 static void FreeVertBuf(void);
00158 
00159 static long GetWord(
00160     UCHAR**     p);
00161 
00162 static long GetDWord(
00163     UCHAR**     p);
00164 
00165 static double GetFixed(
00166     UCHAR**     p);
00167 
00168 static int InitLineBuf(void);
00169 
00170 static int InitVertBuf(void);
00171 
00172 static HFONT CreateHighResolutionFont(
00173     HDC     hDC);
00174 
00175 static int MakeDisplayListFromGlyph(
00176     DWORD           listName,
00177     UCHAR*          glyphBuf,
00178     DWORD           glyphSize,
00179     LPGLYPHMETRICSFLOAT glyphMetricsFloat,
00180     FLOAT           chordalDeviation,
00181     FLOAT           extrusion,
00182     INT         format);
00183 
00184 static BOOL LoadGLUTesselator(void);
00185 static BOOL UnloadGLUTesselator(void);
00186 
00187 static int MakeLinesFromArc(
00188     FLOAT       x0,
00189     FLOAT       y0,
00190     FLOAT       x1,
00191     FLOAT       y1,
00192     FLOAT       x2,
00193     FLOAT       y2,
00194     DWORD       vertexCountIndex,
00195     FLOAT       chordalDeviationSquared);
00196 
00197 static int MakeLinesFromGlyph(      UCHAR*      glyphBuf,
00198                     DWORD       glyphSize,
00199                     FLOAT       chordalDeviation);
00200 
00201 static int MakeLinesFromTTLine(     UCHAR**     pp,
00202                     DWORD       vertexCountIndex,
00203                     WORD        pointCount);
00204 
00205 static int MakeLinesFromTTPolycurve(    UCHAR**     pp,
00206                     DWORD       vertexCountIndex,
00207                     FLOAT       chordalDeviation);
00208 
00209 static int MakeLinesFromTTPolygon(  UCHAR**     pp,
00210                     FLOAT       chordalDeviation);
00211 
00212 static int MakeLinesFromTTQSpline(  UCHAR**     pp,
00213                     DWORD       vertexCountIndex,
00214                     WORD        pointCount,
00215                     FLOAT       chordalDeviation);
00216 
00217 static void CALLBACK TessCombine(   double      coords[3],
00218                     void*       vertex_data[4],
00219                     FLOAT       weight[4],
00220                     void**      outData);
00221 
00222 static void CALLBACK TessError(     GLenum      error);
00223 
00224 static void CALLBACK TessVertexOutData( FLOAT       p[3],
00225                     GLfloat     z);
00226 
00227 // ***********************************************************************
00228 
00229 #ifdef GLD_THREADS
00230 #pragma message("compiling DGLWGL.C vars for multi-threaded support")
00231 extern CRITICAL_SECTION CriticalSection;
00232 extern DWORD dwTLSPixelFormat;          // TLS index for current pixel format
00233 #endif
00234 int curPFD = 0;                         // Current PFD (static)
00235 
00236 // ***********************************************************************
00237 
00238 int dglGetPixelFormat(void)
00239 {
00240 #ifdef GLD_THREADS
00241     int iPixelFormat;
00242     // get thread-specific instance
00243     if (glb.bMultiThreaded) {
00244         __try {
00245             iPixelFormat = (int)TlsGetValue(dwTLSPixelFormat);
00246         }
00247         __except(EXCEPTION_EXECUTE_HANDLER) {
00248             iPixelFormat = curPFD;
00249         }
00250     }
00251     // get global static var
00252     else {
00253         iPixelFormat = curPFD;
00254     }
00255     return iPixelFormat;
00256 #else
00257     return curPFD;
00258 #endif
00259 }
00260 
00261 // ***********************************************************************
00262 
00263 void dglSetPixelFormat(int iPixelFormat)
00264 {
00265 #ifdef GLD_THREADS
00266     // set thread-specific instance
00267     if (glb.bMultiThreaded) {
00268         __try {
00269             TlsSetValue(dwTLSPixelFormat, (LPVOID)iPixelFormat);
00270         }
00271         __except(EXCEPTION_EXECUTE_HANDLER) {
00272             curPFD = iPixelFormat;
00273         }
00274     }
00275     // set global static var
00276     else {
00277         curPFD = iPixelFormat;
00278     }
00279 #else
00280     curPFD = iPixelFormat;
00281 #endif
00282 }
00283 
00284 // ***********************************************************************
00285 
00286 int APIENTRY _GLD_WGL_EXPORT(ChoosePixelFormat)(
00287     HDC a,
00288     CONST PIXELFORMATDESCRIPTOR *ppfd)
00289 {
00290     DGL_pixelFormat         *lpPF = glb.lpPF;
00291 
00292     PIXELFORMATDESCRIPTOR   ppfdBest;
00293     int                     i;
00294     int                     bestIndex = -1;
00295     int                     numPixelFormats;
00296     DWORD                   dwFlags;
00297 
00298     char                    buf[128];
00299     char                    cat[8];
00300 
00301     DWORD dwAllFlags = 
00302                     PFD_DRAW_TO_WINDOW |
00303                     PFD_DRAW_TO_BITMAP |
00304                     PFD_SUPPORT_GDI |
00305                     PFD_SUPPORT_OPENGL |
00306                     PFD_GENERIC_FORMAT |
00307                     PFD_NEED_PALETTE |
00308                     PFD_NEED_SYSTEM_PALETTE |
00309                     PFD_DOUBLEBUFFER |
00310                     PFD_STEREO |
00311                     /*PFD_SWAP_LAYER_BUFFERS |*/
00312                     PFD_DOUBLEBUFFER_DONTCARE |
00313                     PFD_STEREO_DONTCARE |
00314                     PFD_SWAP_COPY |
00315                     PFD_SWAP_EXCHANGE |
00316                     PFD_GENERIC_ACCELERATED |
00317                     0;
00318 
00319     // Validate license
00320     if (!dglValidate())
00321         return 0;
00322 
00323     // List may not be built until dglValidate() is called! KeithH
00324     lpPF = glb.lpPF;
00325 
00326     //
00327     // Lets print the input pixel format to the log
00328     // ** Based on "wglinfo" by Nate Robins **
00329     //
00330     ddlogMessage(DDLOG_SYSTEM, "ChoosePixelFormat:\n");
00331     ddlogMessage(DDLOG_INFO, "Input pixel format for ChoosePixelFormat:\n");
00332     ddlogMessage(DDLOG_INFO,
00333         "   visual  x  bf lv rg d st  r  g  b a  ax dp st accum buffs  ms\n");
00334     ddlogMessage(DDLOG_INFO,
00335         " id dep cl sp sz l  ci b ro sz sz sz sz bf th cl  r  g  b  a ns b\n");
00336     ddlogMessage(DDLOG_INFO,
00337         "-----------------------------------------------------------------\n");
00338     sprintf(buf, "  .  ");
00339 
00340     sprintf(cat, "%2d ", ppfd->cColorBits);
00341     strcat(buf, cat);
00342     if(ppfd->dwFlags & PFD_DRAW_TO_WINDOW)      sprintf(cat, "wn ");
00343     else if(ppfd->dwFlags & PFD_DRAW_TO_BITMAP) sprintf(cat, "bm ");
00344     else sprintf(cat, ".  ");
00345     strcat(buf, cat);
00346 
00347     /* should find transparent pixel from LAYERPLANEDESCRIPTOR */
00348     sprintf(cat, " . "); 
00349     strcat(buf, cat);
00350 
00351     sprintf(cat, "%2d ", ppfd->cColorBits);
00352     strcat(buf, cat);
00353 
00354     /* bReserved field indicates number of over/underlays */
00355     if(ppfd->bReserved) sprintf(cat, " %d ", ppfd->bReserved);
00356     else sprintf(cat, " . "); 
00357     strcat(buf, cat);
00358 
00359     sprintf(cat, " %c ", ppfd->iPixelType == PFD_TYPE_RGBA ? 'r' : 'c');
00360     strcat(buf, cat);
00361 
00362     sprintf(cat, "%c ", ppfd->dwFlags & PFD_DOUBLEBUFFER ? 'y' : '.');
00363     strcat(buf, cat);
00364 
00365     sprintf(cat, " %c ", ppfd->dwFlags & PFD_STEREO ? 'y' : '.');
00366     strcat(buf, cat);
00367 
00368     if(ppfd->cRedBits && ppfd->iPixelType == PFD_TYPE_RGBA) 
00369         sprintf(cat, "%2d ", ppfd->cRedBits);
00370     else sprintf(cat, " . ");
00371     strcat(buf, cat);
00372 
00373     if(ppfd->cGreenBits && ppfd->iPixelType == PFD_TYPE_RGBA) 
00374         sprintf(cat, "%2d ", ppfd->cGreenBits);
00375     else sprintf(cat, " . ");
00376     strcat(buf, cat);
00377 
00378     if(ppfd->cBlueBits && ppfd->iPixelType == PFD_TYPE_RGBA) 
00379         sprintf(cat, "%2d ", ppfd->cBlueBits);
00380     else sprintf(cat, " . ");
00381     strcat(buf, cat);
00382     
00383     if(ppfd->cAlphaBits && ppfd->iPixelType == PFD_TYPE_RGBA) 
00384         sprintf(cat, "%2d ", ppfd->cAlphaBits);
00385     else sprintf(cat, " . ");
00386     strcat(buf, cat);
00387     
00388     if(ppfd->cAuxBuffers)     sprintf(cat, "%2d ", ppfd->cAuxBuffers);
00389     else sprintf(cat, " . ");
00390     strcat(buf, cat);
00391     
00392     if(ppfd->cDepthBits)      sprintf(cat, "%2d ", ppfd->cDepthBits);
00393     else sprintf(cat, " . ");
00394     strcat(buf, cat);
00395     
00396     if(ppfd->cStencilBits)    sprintf(cat, "%2d ", ppfd->cStencilBits);
00397     else sprintf(cat, " . ");
00398     strcat(buf, cat);
00399     
00400     if(ppfd->cAccumRedBits)   sprintf(cat, "%2d ", ppfd->cAccumRedBits);
00401     else sprintf(cat, " . ");
00402     strcat(buf, cat);
00403 
00404     if(ppfd->cAccumGreenBits) sprintf(cat, "%2d ", ppfd->cAccumGreenBits);
00405     else sprintf(cat, " . ");
00406     strcat(buf, cat);
00407     
00408     if(ppfd->cAccumBlueBits)  sprintf(cat, "%2d ", ppfd->cAccumBlueBits);
00409     else sprintf(cat, " . ");
00410     strcat(buf, cat);
00411     
00412     if(ppfd->cAccumAlphaBits) sprintf(cat, "%2d ", ppfd->cAccumAlphaBits);
00413     else sprintf(cat, " . ");
00414     strcat(buf, cat);
00415     
00416     /* no multisample in Win32 */
00417     sprintf(cat, " . .\n");
00418     strcat(buf, cat);
00419 
00420     ddlogMessage(DDLOG_INFO, buf);
00421     ddlogMessage(DDLOG_INFO,
00422         "-----------------------------------------------------------------\n");
00423     ddlogMessage(DDLOG_INFO, "\n");
00424 
00425     //
00426     // Examine the flags for correctness
00427     //
00428     dwFlags = ppfd->dwFlags;
00429     if (dwFlags != (dwFlags & dwAllFlags))
00430     {
00431         /* error: bad dwFlags */
00432         ddlogPrintf(DDLOG_WARN,
00433                     "ChoosePixelFormat: bad flags (0x%x)",
00434                     dwFlags & (~dwAllFlags));
00435         // Mask illegal flags and continue
00436         dwFlags = dwFlags & dwAllFlags;
00437     }
00438     
00439     switch (ppfd->iPixelType) {
00440     case PFD_TYPE_RGBA:
00441     case PFD_TYPE_COLORINDEX:
00442         break;
00443     default:
00444         /* error: bad iPixelType */
00445         ddlogMessage(DDLOG_WARN, "ChoosePixelFormat: bad pixel type\n");
00446         return 0;
00447     }
00448     
00449     switch (ppfd->iLayerType) {
00450     case PFD_MAIN_PLANE:
00451     case PFD_OVERLAY_PLANE:
00452     case PFD_UNDERLAY_PLANE:
00453         break;
00454     default:
00455         /* error: bad iLayerType */
00456         ddlogMessage(DDLOG_WARN, "ChoosePixelFormat: bad layer type\n");
00457         return 0;
00458     }
00459     
00460     numPixelFormats = glb.nPixelFormatCount;
00461     
00462     /* loop through candidate pixel format descriptors */
00463     for (i=0; i<numPixelFormats; ++i) {
00464         PIXELFORMATDESCRIPTOR ppfdCandidate;
00465         
00466         memcpy(&ppfdCandidate, &lpPF[i].pfd, sizeof(PIXELFORMATDESCRIPTOR));
00467         
00468         /*
00469         ** Check attributes which must match
00470         */
00471         if (ppfd->iPixelType != ppfdCandidate.iPixelType) {
00472             continue;
00473         }
00474 
00475         if (ppfd->iLayerType != ppfdCandidate.iLayerType) {
00476             continue;
00477         }
00478         
00479         if (((dwFlags ^ ppfdCandidate.dwFlags) & dwFlags) &
00480             (PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP |
00481             PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL))
00482         {
00483             continue;
00484         }
00485         
00486         if (!(dwFlags & PFD_DOUBLEBUFFER_DONTCARE)) {
00487             if ((dwFlags & PFD_DOUBLEBUFFER) !=
00488                 (ppfdCandidate.dwFlags & PFD_DOUBLEBUFFER))
00489             {
00490                 continue;
00491             }
00492         }
00493         
00494 //      if (!(dwFlags & PFD_STEREO_DONTCARE)) {
00495             if ((dwFlags & PFD_STEREO) !=
00496                 (ppfdCandidate.dwFlags & PFD_STEREO))
00497             {
00498                 continue;
00499             }
00500 //      }
00501         
00502         if (ppfd->iPixelType==PFD_TYPE_RGBA
00503             && ppfd->cAlphaBits && !ppfdCandidate.cAlphaBits) {
00504             continue;
00505         }
00506         
00507         if (ppfd->iPixelType==PFD_TYPE_RGBA
00508             && ppfd->cAccumBits && !ppfdCandidate.cAccumBits) {
00509             continue;
00510         }
00511         
00512         if (ppfd->cDepthBits && !ppfdCandidate.cDepthBits) {
00513             continue;
00514         }
00515         
00516         if (ppfd->cStencilBits && !ppfdCandidate.cStencilBits) {
00517             continue;
00518         }
00519 
00520         if (ppfd->cAuxBuffers && !ppfdCandidate.cAuxBuffers) {
00521             continue;
00522         }
00523         
00524         /*
00525         ** See if candidate is better than the previous best choice
00526         */
00527         if (bestIndex == -1) {
00528             ppfdBest = ppfdCandidate;
00529             bestIndex = i;
00530             continue;
00531         }
00532         
00533         if ((ppfd->cColorBits > ppfdBest.cColorBits &&
00534             ppfdCandidate.cColorBits > ppfdBest.cColorBits) ||
00535             (ppfd->cColorBits <= ppfdCandidate.cColorBits &&
00536             ppfdCandidate.cColorBits < ppfdBest.cColorBits))
00537         {
00538             ppfdBest = ppfdCandidate;
00539             bestIndex = i;
00540             continue;
00541         }
00542         
00543         if (ppfd->iPixelType==PFD_TYPE_RGBA
00544             && ppfd->cAlphaBits
00545             && ppfdCandidate.cAlphaBits > ppfdBest.cAlphaBits)
00546         {
00547             ppfdBest = ppfdCandidate;
00548             bestIndex = i;
00549             continue;
00550         }
00551         
00552         if (ppfd->iPixelType==PFD_TYPE_RGBA
00553             && ppfd->cAccumBits
00554             && ppfdCandidate.cAccumBits > ppfdBest.cAccumBits)
00555         {
00556             ppfdBest = ppfdCandidate;
00557             bestIndex = i;
00558             continue;
00559         }
00560         
00561         if ((ppfd->cDepthBits > ppfdBest.cDepthBits &&
00562             ppfdCandidate.cDepthBits > ppfdBest.cDepthBits) ||
00563             (ppfd->cDepthBits <= ppfdCandidate.cDepthBits &&
00564             ppfdCandidate.cDepthBits < ppfdBest.cDepthBits))
00565         {
00566             ppfdBest = ppfdCandidate;
00567             bestIndex = i;
00568             continue;
00569         }
00570         
00571         if (ppfd->cStencilBits &&
00572             ppfdCandidate.cStencilBits > ppfdBest.cStencilBits)
00573         {
00574             ppfdBest = ppfdCandidate;
00575             bestIndex = i;
00576             continue;
00577         }
00578         
00579         if (ppfd->cAuxBuffers &&
00580             ppfdCandidate.cAuxBuffers > ppfdBest.cAuxBuffers)
00581         {
00582             ppfdBest = ppfdCandidate;
00583             bestIndex = i;
00584             continue;
00585         }
00586     }
00587 
00588     if (bestIndex != -1) {
00589         ddlogPrintf(DDLOG_SYSTEM, "Pixel Format %d chosen as best match", bestIndex+1);
00590         return bestIndex + 1;
00591     }
00592 
00593     // Return the pixelformat that has the most capabilities.
00594     // ** NOTE: This is only possible due to the way the list
00595     // of pixelformats is built. **
00596     // Now picks best pixelformat. KeithH
00597     bestIndex = numPixelFormats;    // most capable double buffer format
00598     ddlogPrintf(DDLOG_SYSTEM, "Pixel Format %d chosen by default", bestIndex);
00599     return (bestIndex);
00600 }
00601 
00602 // ***********************************************************************
00603 
00604 BOOL APIENTRY _GLD_WGL_EXPORT(CopyContext)(
00605     HGLRC a,
00606     HGLRC b,
00607     UINT c)
00608 {
00609     // Validate license
00610     if (!dglValidate())
00611         return FALSE;
00612     UNSUPPORTED("wglCopyContext")
00613     return FALSE; // Failed
00614 }
00615 
00616 // ***********************************************************************
00617 
00618 HGLRC APIENTRY _GLD_WGL_EXPORT(CreateContext)(
00619     HDC a)
00620 {
00621     int ipf;
00622 
00623     // Validate license
00624     if (!dglValidate())
00625         return 0;
00626 
00627     // Check that the current PFD is valid
00628     ipf = dglGetPixelFormat();
00629     if (!IsValidPFD(ipf))
00630         return (HGLRC)0;
00631 
00632     return dglCreateContext(a, &glb.lpPF[ipf-1]);
00633 }
00634 
00635 // ***********************************************************************
00636 
00637 HGLRC APIENTRY _GLD_WGL_EXPORT(CreateLayerContext)(
00638     HDC a,
00639     int b)
00640 {
00641     // Validate license
00642     if (!dglValidate())
00643         return 0;
00644 
00645     UNSUPPORTED("wglCreateLayerContext")
00646     return NULL; // Failed
00647 }
00648 
00649 // ***********************************************************************
00650 
00651 BOOL APIENTRY _GLD_WGL_EXPORT(DeleteContext)(
00652     HGLRC a)
00653 {
00654     // Validate license
00655     if (!dglValidate())
00656         return FALSE;
00657 
00658     return dglDeleteContext(a);
00659 }
00660 
00661 // ***********************************************************************
00662 
00663 BOOL APIENTRY _GLD_WGL_EXPORT(DescribeLayerPlane)(
00664     HDC hDC,
00665     int iPixelFormat,
00666     int iLayerPlane,
00667     UINT nBytes,
00668     LPLAYERPLANEDESCRIPTOR plpd)
00669 {
00670     // Validate license
00671     if (!dglValidate())
00672         return FALSE;
00673 
00674     UNSUPPORTED("DGL_DescribeLayerPlane")
00675 
00676 //  gldLogPrintf(GLDLOG_INFO, "DescribeLayerPlane: %d, %d", iPixelFormat, iLayerPlane);
00677 
00678     return FALSE;
00679 }
00680 
00681 // ***********************************************************************
00682 
00683 int APIENTRY _GLD_WGL_EXPORT(DescribePixelFormat)(
00684     HDC a,
00685     int b,
00686     UINT c,
00687     LPPIXELFORMATDESCRIPTOR d)
00688 {
00689     UINT nSize;
00690 
00691     // Validate license
00692     if (!dglValidate())
00693         return 0;
00694 
00695     if (d == NULL) // Calling app requires max number of PF's
00696         return glb.nPixelFormatCount;
00697 
00698     // The supplied buffer may be larger than the info that we
00699     // will be copying.
00700     if (c > sizeof(PIXELFORMATDESCRIPTOR))
00701         nSize = sizeof(PIXELFORMATDESCRIPTOR);
00702     else
00703         nSize = c;
00704 
00705     // Setup an empty PFD before doing validation check
00706     memset(d, 0, nSize);
00707     d->nSize = nSize;
00708     d->nVersion = 1;
00709 
00710     if (!IsValidPFD(b))
00711         return 0; // Bail if PFD index is invalid
00712 
00713     memcpy(d, &glb.lpPF[b-1].pfd, nSize);
00714 
00715     return glb.nPixelFormatCount;
00716 }
00717 
00718 // ***********************************************************************
00719 
00720 HGLRC APIENTRY _GLD_WGL_EXPORT(GetCurrentContext)(void)
00721 {
00722     // Validate license
00723     if (!dglValidate())
00724         return 0;
00725 
00726     return dglGetCurrentContext();
00727 }
00728 
00729 // ***********************************************************************
00730 
00731 HDC APIENTRY _GLD_WGL_EXPORT(GetCurrentDC)(void)
00732 {
00733     // Validate license
00734     if (!dglValidate())
00735         return 0;
00736 
00737     return dglGetCurrentDC();
00738 }
00739 
00740 // ***********************************************************************
00741 
00742 PROC APIENTRY _GLD_WGL_EXPORT(GetDefaultProcAddress)(
00743     LPCSTR a)
00744 {
00745     // Validate license
00746     if (!dglValidate())
00747         return NULL;
00748 
00749     UNSUPPORTED("DGL_GetDefaultProcAddress")
00750     return NULL;
00751 }
00752 
00753 // ***********************************************************************
00754 
00755 int APIENTRY _GLD_WGL_EXPORT(GetLayerPaletteEntries)(
00756     HDC a,
00757     int b,
00758     int c,
00759     int d,
00760     COLORREF *e)
00761 {
00762     // Validate license
00763     if (!dglValidate())
00764         return 0;
00765 
00766     UNSUPPORTED("DGL_GetLayerPaletteEntries")
00767     return 0;
00768 }
00769 
00770 // ***********************************************************************
00771 
00772 int APIENTRY _GLD_WGL_EXPORT(GetPixelFormat)(
00773     HDC a)
00774 {
00775     // Validate license
00776     if (!dglValidate())
00777         return 0;
00778 
00779     return dglGetPixelFormat();
00780 }
00781 
00782 // ***********************************************************************
00783 
00784 PROC APIENTRY _GLD_WGL_EXPORT(GetProcAddress)(
00785     LPCSTR a)
00786 {
00787     PROC dglGetProcAddressD3D(LPCSTR a);
00788 
00789     // Validate license
00790     if (!dglValidate())
00791         return NULL;
00792 
00793 #ifdef _USE_GLD3_WGL
00794     return _gldDriver.wglGetProcAddress(a);
00795 #else
00796     return dglGetProcAddressD3D(a);
00797 #endif
00798 }
00799 
00800 // ***********************************************************************
00801 
00802 BOOL APIENTRY _GLD_WGL_EXPORT(MakeCurrent)(
00803     HDC a,
00804     HGLRC b)
00805 {
00806     // Validate license
00807     if (!dglValidate())
00808         return FALSE;
00809 
00810     return dglMakeCurrent(a, b);
00811 }
00812 
00813 // ***********************************************************************
00814 
00815 BOOL APIENTRY _GLD_WGL_EXPORT(RealizeLayerPalette)(
00816     HDC a,
00817     int b,
00818     BOOL c)
00819 {
00820     // Validate license
00821     if (!dglValidate())
00822         return FALSE;
00823 
00824     UNSUPPORTED("DGL_RealizeLayerPalette")
00825     return FALSE;
00826 }
00827 
00828 // ***********************************************************************
00829 
00830 int APIENTRY _GLD_WGL_EXPORT(SetLayerPaletteEntries)(
00831     HDC a,
00832     int b,
00833     int c,
00834     int d,
00835     CONST COLORREF *e)
00836 {
00837     // Validate license
00838     if (!dglValidate())
00839         return 0;
00840 
00841     UNSUPPORTED("DGL_SetLayerPaletteEntries")
00842     return 0;
00843 }
00844 
00845 // ***********************************************************************
00846 
00847 BOOL APIENTRY _GLD_WGL_EXPORT(SetPixelFormat)(
00848     HDC a,
00849     int b,
00850     CONST PIXELFORMATDESCRIPTOR *c)
00851 {
00852     // Validate license
00853     if (!dglValidate())
00854         return FALSE;
00855 
00856     if (IsValidPFD(b)) {
00857         ddlogPrintf(DDLOG_SYSTEM, "SetPixelFormat: PixelFormat %d has been set", b);
00858         dglSetPixelFormat(b);
00859         return TRUE;
00860     } else {
00861         ddlogPrintf(DDLOG_ERROR,
00862                     "SetPixelFormat: PixelFormat %d is invalid and cannot be set", b);
00863         return FALSE;
00864     }
00865 }
00866 
00867 // ***********************************************************************
00868 /*
00869  * Share lists between two gl_context structures.
00870  * This was added for WIN32 WGL function support, since wglShareLists()
00871  * must be called *after* wglCreateContext() with valid GLRCs. (DaveM)
00872  */
00873 //
00874 // Copied from GLD2.x. KeithH
00875 //
00876 static GLboolean _gldShareLists(
00877     GLcontext *ctx1,
00878     GLcontext *ctx2)
00879 {
00880     /* Sanity check context pointers */
00881     if (ctx1 == NULL || ctx2 == NULL)
00882         return GL_FALSE;
00883     /* Sanity check shared list pointers */
00884     if (ctx1->Shared == NULL || ctx2->Shared == NULL)
00885         return GL_FALSE;
00886     /* Decrement reference count on sharee to release previous list */
00887     ctx2->Shared->RefCount--;
00888 #if 0   /* 3DStudio exits on this memory release */
00889     if (ctx2->Shared->RefCount == 0)
00890         free_shared_state(ctx2, ctx2->Shared);
00891 #endif
00892     /* Re-assign list from sharer to sharee and increment reference count */
00893     ctx2->Shared = ctx1->Shared;
00894     ctx1->Shared->RefCount++;
00895     return GL_TRUE;
00896 }
00897 
00898 // ***********************************************************************
00899 
00900 BOOL APIENTRY _GLD_WGL_EXPORT(ShareLists)(
00901     HGLRC a,
00902     HGLRC b)
00903 {
00904     DGL_ctx *dgl1, *dgl2;
00905 
00906     // Validate license
00907     if (!dglValidate())
00908         return FALSE;
00909 
00910     // Mesa supports shared lists, but you need to supply the shared
00911     // GL context info when calling gl_create_context(). An auxiliary
00912     // function gl_share_lists() has been added to update the shared
00913     // list info after the GL contexts have been created. (DaveM)
00914     dgl1 = dglGetContextAddress(a);
00915     dgl2 = dglGetContextAddress(b);
00916     if (dgl1->bAllocated && dgl2->bAllocated) {
00917 #ifdef _USE_GLD3_WGL
00918         return _gldShareLists(dgl1->glCtx, dgl2->glCtx);
00919 #else
00920         return (*mesaFuncs.gl_share_lists)(dgl1->glCtx, dgl2->glCtx);
00921 #endif
00922     }
00923     return FALSE;
00924 }
00925 
00926 // ***********************************************************************
00927 
00928 BOOL APIENTRY _GLD_WGL_EXPORT(SwapBuffers)(
00929     HDC a)
00930 {
00931     // Validate license
00932     if (!dglValidate())
00933         return FALSE;
00934 
00935     return dglSwapBuffers(a);
00936 }
00937 
00938 // ***********************************************************************
00939 
00940 BOOL APIENTRY _GLD_WGL_EXPORT(SwapLayerBuffers)(
00941     HDC a,
00942     UINT b)
00943 {
00944     // Validate license
00945     if (!dglValidate())
00946         return FALSE;
00947 
00948     return dglSwapBuffers(a);
00949 }
00950 
00951 // ***********************************************************************
00952 
00953 // ***********************************************************************
00954 // Note: This ResizeBuffers() function may be called from
00955 // either MESA glViewport() or GLD wglMakeCurrent().
00956 
00957 BOOL dglWglResizeBuffers(
00958     GLcontext *ctx,
00959     BOOL bDefaultDriver)
00960 {
00961     DGL_ctx                     *dgl = NULL;
00962     RECT                        rcScreenRect;
00963     DWORD                       dwWidth;
00964     DWORD                       dwHeight;
00965     DDSURFACEDESC2              ddsd2;
00966     DDSCAPS2                    ddscaps2;
00967     IDirectDrawClipper          *lpddClipper = NULL;
00968     DWORD                       dwFlags;
00969     HRESULT                     hResult;
00970 
00971     DWORD                       dwMemoryType;
00972 
00973     int                         i;
00974     struct gl_texture_object    *tObj;
00975     struct gl_texture_image     *image;
00976 
00977     BOOL                        bWasFullscreen;
00978     BOOL                        bSaveDesktop;
00979     BOOL                        bFullScrnWin = FALSE;
00980     DDSURFACEDESC2              ddsd2DisplayMode;
00981 
00982     DDBLTFX                     ddbltfx;
00983     POINT                       pt;
00984     RECT                        rcDst;
00985 #ifdef _USE_GLD3_WGL
00986     GLD_displayMode             glddm;
00987 #endif
00988 
00989 #define DDLOG_CRITICAL_OR_WARN  (bDefaultDriver ? DDLOG_WARN : DDLOG_CRITICAL)
00990 
00991     // Validate license
00992     if (!dglValidate())
00993         return FALSE;
00994 
00995     // Sanity checks
00996     if (ctx == NULL)
00997         return FALSE;
00998     dgl = ctx->DriverCtx;
00999     if (dgl == NULL)
01000         return FALSE;
01001 
01002     // Get the window size and calculate its dimensions
01003     if (dgl->hWnd == NULL) {
01004         // Check for non-window DC = memory DC ?
01005         if (GetClipBox(dgl->hDC, &rcScreenRect) == ERROR)
01006             SetRect(&rcScreenRect, 0, 0, 0, 0);
01007     }
01008     else if (!GetClientRect(dgl->hWnd, &rcScreenRect))
01009         SetRect(&rcScreenRect, 0, 0, 0, 0);
01010     dwWidth = rcScreenRect.right - rcScreenRect.left;
01011     dwHeight = rcScreenRect.bottom - rcScreenRect.top;
01012     CopyRect(&dgl->rcScreenRect, &rcScreenRect);
01013 
01014     // This will occur on Alt-Tab
01015     if ((dwWidth == 0) && (dwHeight == 0)) {
01016         //dgl->bCanRender = FALSE;
01017         return TRUE; // No resize possible!
01018     }
01019 
01020     // Some apps zero only 1 dimension for non-visible window... (DaveM)
01021     if ((dwWidth == 0) || (dwHeight == 0)) {
01022         dwWidth = 8;
01023         dwHeight = 8;
01024     }
01025 
01026     // Test to see if a resize is required.
01027     // Note that the dimensions will be the same if a prior resize attempt failed.
01028     if ((dwWidth == dgl->dwWidth) && (dwHeight == dgl->dwHeight) && bDefaultDriver) {
01029         return TRUE; // No resize required
01030     }
01031 
01032     ddlogPrintf(DDLOG_SYSTEM, "dglResize: %dx%d", dwWidth, dwHeight);
01033 #ifndef _USE_GLD3_WGL
01034     // Work out where we want our surfaces created
01035     dwMemoryType = (bDefaultDriver) ? glb.dwMemoryType : DDSCAPS_SYSTEMMEMORY;
01036 #endif // _USE_GLD3_WGL
01037 
01038     // Note previous fullscreen vs window display status
01039     bWasFullscreen = dgl->bFullscreen;
01040 
01041 #ifdef _USE_GLD3_WGL
01042     if (_gldDriver.GetDisplayMode(dgl, &glddm)) {
01043         if ( (dwWidth == glddm.Width) &&
01044                  (dwHeight == glddm.Height) ) {
01045             bFullScrnWin = TRUE;
01046         }
01047         if (bFullScrnWin && glb.bPrimary && !glb.bFullscreenBlit && !glb.bDirectDrawPersistant) {
01048             dgl->bFullscreen = TRUE;
01049             ddlogMessage(DDLOG_INFO, "Fullscreen window after resize.\n");
01050         }
01051         else {
01052             dgl->bFullscreen = FALSE;
01053             ddlogMessage(DDLOG_INFO, "Non-Fullscreen window after resize.\n");
01054         }
01055         // Cache the display mode dimensions
01056         dgl->dwModeWidth = glddm.Width;
01057         dgl->dwModeHeight = glddm.Height;
01058     }
01059 
01060     // Clamp the effective window dimensions to primary surface.
01061     // We need to do this for D3D viewport dimensions even if wide
01062     // surfaces are supported. This also is a good idea for handling
01063     // whacked-out window dimensions passed for non-drawable windows
01064     // like Solid Edge. (DaveM)
01065     if (dgl->dwWidth > glddm.Width)
01066         dgl->dwWidth = glddm.Width;
01067     if (dgl->dwHeight > glddm.Height)
01068         dgl->dwHeight = glddm.Height;
01069 #else // _USE_GLD3_WGL
01070     // Window resize may have changed to fullscreen
01071     ZeroMemory(&ddsd2DisplayMode, sizeof(ddsd2DisplayMode));
01072     ddsd2DisplayMode.dwSize = sizeof(ddsd2DisplayMode);
01073     hResult = IDirectDraw4_GetDisplayMode(
01074                     dgl->lpDD4,
01075                     &ddsd2DisplayMode);
01076     if (SUCCEEDED(hResult)) {
01077         if ( (dwWidth == ddsd2DisplayMode.dwWidth) &&
01078                  (dwHeight == ddsd2DisplayMode.dwHeight) ) {
01079             bFullScrnWin = TRUE;
01080         }
01081         if (bFullScrnWin && glb.bPrimary && !glb.bFullscreenBlit && !glb.bDirectDrawPersistant) {
01082             dgl->bFullscreen = TRUE;
01083             ddlogMessage(DDLOG_INFO, "Fullscreen window after resize.\n");
01084         }
01085         else {
01086             dgl->bFullscreen = FALSE;
01087             ddlogMessage(DDLOG_INFO, "Non-Fullscreen window after resize.\n");
01088         }
01089         // Cache the display mode dimensions
01090         dgl->dwModeWidth = ddsd2DisplayMode.dwWidth;
01091         dgl->dwModeHeight = ddsd2DisplayMode.dwHeight;
01092     }
01093 
01094     // Clamp the effective window dimensions to primary surface.
01095     // We need to do this for D3D viewport dimensions even if wide
01096     // surfaces are supported. This also is a good idea for handling
01097     // whacked-out window dimensions passed for non-drawable windows
01098     // like Solid Edge. (DaveM)
01099     if (dgl->dwWidth > ddsd2DisplayMode.dwWidth)
01100         dgl->dwWidth = ddsd2DisplayMode.dwWidth;
01101     if (dgl->dwHeight > ddsd2DisplayMode.dwHeight)
01102         dgl->dwHeight = ddsd2DisplayMode.dwHeight;
01103 #endif // _USE_GLD3_WGL
01104 
01105     // Note if fullscreen vs window display has changed?
01106     bSaveDesktop = (!bWasFullscreen && !dgl->bFullscreen) ? TRUE : FALSE;
01107     // Save the desktop primary surface from being destroyed
01108     // whenever remaining in windowed mode, since the stereo mode
01109     // switches are expensive...
01110 
01111 #ifndef _USE_GLD3_WGL
01112     // Don't need to re-allocate persistant buffers. (DaveM)
01113     // Though we should clear the back buffers to hide artifacts.
01114     if (glb.bDirectDrawPersistant && glb.bPersistantBuffers) {
01115         dgl->dwWidth = dwWidth;
01116         dgl->dwHeight = dwHeight;
01117         ZeroMemory(&ddbltfx, sizeof(ddbltfx));
01118         ddbltfx.dwSize = sizeof(ddbltfx);
01119         ddbltfx.dwFillColor = dgl->dwClearColorPF;
01120         IDirectDrawSurface4_Blt(dgl->lpBack4, &rcScreenRect, NULL, NULL,
01121             DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);
01122         return TRUE;
01123     }
01124 
01125     // Ensure all rendering is complete
01126     if (ctx->Driver.Finish)
01127         (*ctx->Driver.Finish)(ctx);
01128     if (dgl->bSceneStarted == TRUE) {
01129         IDirect3DDevice3_EndScene(dgl->lpDev3);
01130         dgl->bSceneStarted = FALSE;
01131     }
01132 #endif // _USE_GLD3_WGL
01133     dgl->bCanRender = FALSE;
01134 
01135 #ifdef GLD_THREADS
01136     // Serialize access to DirectDraw and DDS operations
01137     if (glb.bMultiThreaded)
01138         EnterCriticalSection(&CriticalSection);
01139 #endif
01140 
01141 #ifndef _USE_GLD3_WGL
01142     // Release existing surfaces
01143     RELEASE(dgl->lpDev3);
01144     RELEASE(dgl->lpDepth4);
01145     RELEASE(dgl->lpBack4);
01146     if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
01147         ;
01148     else
01149     RELEASE(dgl->lpFront4);
01150 #endif // _USE_GLD3_WGL
01151     dgl->dwWidth = dwWidth;
01152     dgl->dwHeight = dwHeight;
01153 
01154     // Set defaults
01155     dgl->dwModeWidth = dgl->dwWidth;
01156     dgl->dwModeHeight = dgl->dwHeight;
01157 
01158 #ifdef _USE_GLD3_WGL
01159     if (!_gldDriver.ResizeDrawable(dgl, bDefaultDriver, glb.bDirectDrawPersistant, glb.bPersistantBuffers))
01160         goto cleanup_and_return_with_error;
01161 #else // _USE_GLD3_WGL
01162 
01163     if (dgl->bFullscreen) {
01164         //
01165         // FULLSCREEN
01166         //
01167 
01168         // Disable warning popups when in fullscreen mode
01169         ddlogWarnOption(FALSE);
01170 
01171         // Have to release the persistant DirectDraw primary surface
01172         // if switching to fullscreen mode. So if application wants
01173         // persistant display in fullscreen mode, a fullscreen-size
01174         // window should be used instead via fullscreen-blit option.
01175         if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) {
01176             RELEASE(glb.lpPrimary4);
01177             glb.bDirectDrawPrimary = FALSE;
01178         }
01179 
01180         dwFlags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT;
01181         if (glb.bFastFPU)
01182             dwFlags |= DDSCL_FPUSETUP;  // optional
01183         hResult = IDirectDraw4_SetCooperativeLevel(dgl->lpDD4, dgl->hWnd, dwFlags);
01184         if (FAILED(hResult)) {
01185             ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Unable to set Exclusive Fullscreen mode", hResult);
01186             goto cleanup_and_return_with_error;
01187         }
01188 
01189         hResult = IDirectDraw4_SetDisplayMode(dgl->lpDD4,
01190                                               dgl->dwModeWidth,
01191                                               dgl->dwModeHeight,
01192                                               dgl->dwBPP,
01193                                               0,
01194                                               0);
01195         if (FAILED(hResult)) {
01196             ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetDisplayMode failed", hResult);
01197             goto cleanup_and_return_with_error;
01198         }
01199 
01200         // ** The display mode has changed, so dont use MessageBox! **
01201 
01202         ZeroMemory(&ddsd2, sizeof(ddsd2));
01203         ddsd2.dwSize = sizeof(ddsd2);
01204 
01205         if (dgl->bDoubleBuffer) {
01206             // Double buffered
01207             // Primary surface
01208             ddsd2.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
01209             ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
01210                                    DDSCAPS_FLIP |
01211                                    DDSCAPS_COMPLEX |
01212                                    DDSCAPS_3DDEVICE |
01213                                    dwMemoryType;
01214             ddsd2.dwBackBufferCount = 1;
01215             hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
01216             if (FAILED(hResult)) {
01217                 ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
01218                 goto cleanup_and_return_with_error;
01219             }
01220             // Render target surface
01221             ZeroMemory(&ddscaps2, sizeof(ddscaps2)); // Clear the entire struct.
01222             ddscaps2.dwCaps = DDSCAPS_BACKBUFFER;
01223             hResult = IDirectDrawSurface4_GetAttachedSurface(dgl->lpFront4, &ddscaps2, &dgl->lpBack4);
01224             if (FAILED(hResult)) {
01225                 ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: GetAttachedSurface failed", hResult);
01226                 goto cleanup_and_return_with_error;
01227             }
01228         } else {
01229             // Single buffered
01230             // Primary surface
01231             ddsd2.dwFlags = DDSD_CAPS;
01232             ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
01233                                    //DDSCAPS_3DDEVICE |
01234                                    dwMemoryType;
01235 
01236             hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
01237             if (FAILED(hResult)) {
01238                 ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
01239                 goto cleanup_and_return_with_error;
01240             }
01241 
01242             dgl->lpBack4 = NULL;
01243         }
01244     } else {
01245         // WINDOWED
01246 
01247         // OK to enable warning popups in windowed mode
01248         ddlogWarnOption(glb.bMessageBoxWarnings);
01249 
01250         // Ditto if persistant DirectDraw primary
01251         if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
01252             goto DoClipperOnly;
01253 
01254         // WINDOWED
01255         dwFlags = DDSCL_NORMAL;
01256         if (glb.bMultiThreaded)
01257             dwFlags |= DDSCL_MULTITHREADED;
01258         if (glb.bFastFPU)
01259             dwFlags |= DDSCL_FPUSETUP;  // optional
01260         hResult = IDirectDraw4_SetCooperativeLevel(dgl->lpDD4,
01261                                                   dgl->hWnd,
01262                                                   dwFlags);
01263         if (FAILED(hResult)) {
01264             ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Unable to set Normal coop level", hResult);
01265             goto cleanup_and_return_with_error;
01266         }
01267         // Primary surface
01268         ZeroMemory(&ddsd2, sizeof(ddsd2));
01269         ddsd2.dwSize = sizeof(ddsd2);
01270         ddsd2.dwFlags = DDSD_CAPS;
01271         ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
01272         hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpFront4, NULL);
01273         if (FAILED(hResult)) {
01274             ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (primary) failed", hResult);
01275             goto cleanup_and_return_with_error;
01276         }
01277 
01278         // Cache the primary surface for persistant DirectDraw state
01279         if (glb.bDirectDrawPersistant && !glb.bDirectDrawPrimary) {
01280             glb.lpPrimary4 = dgl->lpFront4;
01281             IDirectDrawSurface4_AddRef(glb.lpPrimary4);
01282             glb.bDirectDrawPrimary = TRUE;
01283         }
01284 
01285         // Clipper object
01286         hResult = DirectDrawCreateClipper(0, &lpddClipper, NULL);
01287         if (FAILED(hResult)) {
01288             ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateClipper failed", hResult);
01289             goto cleanup_and_return_with_error;
01290         }
01291         hResult = IDirectDrawClipper_SetHWnd(lpddClipper, 0, dgl->hWnd);
01292         if (FAILED(hResult)) {
01293             RELEASE(lpddClipper);
01294             ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetHWnd failed", hResult);
01295             goto cleanup_and_return_with_error;
01296         }
01297         hResult = IDirectDrawSurface4_SetClipper(dgl->lpFront4, lpddClipper);
01298         RELEASE(lpddClipper); // We have finished with it.
01299         if (FAILED(hResult)) {
01300             ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetClipper failed", hResult);
01301             goto cleanup_and_return_with_error;
01302         }
01303 DoClipperOnly:
01304         // Update the window for the original clipper
01305         if ((glb.bDirectDrawPersistant && glb.bDirectDrawPrimary) || bSaveDesktop) {
01306             IDirectDrawSurface4_GetClipper(dgl->lpFront4, &lpddClipper);
01307             IDirectDrawClipper_SetHWnd(lpddClipper, 0, dgl->hWnd);
01308             RELEASE(lpddClipper);
01309         }
01310 
01311         if (dgl->bDoubleBuffer) {
01312             // Render target surface
01313             ZeroMemory(&ddsd2, sizeof(ddsd2));
01314             ddsd2.dwSize = sizeof(ddsd2);
01315             ddsd2.dwFlags        = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
01316             ddsd2.dwWidth        = dgl->dwWidth;
01317             ddsd2.dwHeight       = dgl->dwHeight;
01318             ddsd2.ddsCaps.dwCaps = DDSCAPS_3DDEVICE |
01319                                    DDSCAPS_OFFSCREENPLAIN |
01320                                    dwMemoryType;
01321             hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpBack4, NULL);
01322             if (FAILED(hResult)) {
01323                 ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Create Backbuffer failed", hResult);
01324                 goto cleanup_and_return_with_error;
01325             }
01326 
01327         } else {
01328             dgl->lpBack4 = NULL;
01329         }
01330     }
01331 
01332     //
01333     // Now create the Zbuffer
01334     //
01335     if (dgl->bDepthBuffer) {
01336         // Get z-buffer dimensions from the render target
01337         // Setup the surface desc for the z-buffer.
01338         ZeroMemory(&ddsd2, sizeof(ddsd2));
01339         ddsd2.dwSize = sizeof(ddsd2);
01340         ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
01341         ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | dwMemoryType;
01342         ddsd2.dwWidth = dgl->dwWidth;
01343         ddsd2.dwHeight = dgl->dwHeight;
01344         memcpy(&ddsd2.ddpfPixelFormat,
01345                &glb.lpZBufferPF[dgl->iZBufferPF],
01346                sizeof(DDPIXELFORMAT) );
01347 
01348         // Create a z-buffer
01349         hResult = IDirectDraw4_CreateSurface(dgl->lpDD4, &ddsd2, &dgl->lpDepth4, NULL);
01350         if (FAILED(hResult)) {
01351             ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: CreateSurface (ZBuffer) failed", hResult);
01352             goto cleanup_and_return_with_error;
01353         }
01354 
01355         // Attach Zbuffer to render target
01356         TRY(IDirectDrawSurface4_AddAttachedSurface(
01357             dgl->bDoubleBuffer ? dgl->lpBack4 : dgl->lpFront4,
01358             dgl->lpDepth4),
01359             "dglResize: Attach Zbuffer");
01360 
01361     }
01362 
01363     // Clear the newly resized back buffers for the window client area.
01364     ZeroMemory(&ddbltfx, sizeof(ddbltfx));
01365     ddbltfx.dwSize = sizeof(ddbltfx);
01366     ddbltfx.dwFillColor = dgl->dwClearColorPF;
01367     IDirectDrawSurface4_Blt(dgl->lpBack4, &rcScreenRect, NULL, NULL,
01368         DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);
01369 
01370     //
01371     // Now that we have a zbuffer we can create the 3D device
01372     //
01373     hResult = IDirect3D3_CreateDevice(dgl->lpD3D3,
01374                                       bDefaultDriver ? &glb.d3dGuid : &IID_IDirect3DRGBDevice,
01375                                       dgl->bDoubleBuffer ? dgl->lpBack4 : dgl->lpFront4,
01376                                       &dgl->lpDev3,
01377                                       NULL);
01378     if (FAILED(hResult)) {
01379         ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: Could not create Direct3D device", hResult);
01380         goto cleanup_and_return_with_error;
01381     }
01382 
01383     // We must do this as soon as the device is created
01384     dglInitStateCaches(dgl);
01385 
01386     //
01387     // Viewport
01388     //
01389     hResult = IDirect3DDevice3_AddViewport(dgl->lpDev3, dgl->lpViewport3);
01390     if (FAILED(hResult)) {
01391         ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: AddViewport failed", hResult);
01392         goto cleanup_and_return_with_error;
01393     }
01394 
01395     // Initialise the viewport
01396     dgl->d3dViewport.dwSize = sizeof(dgl->d3dViewport);
01397     dgl->d3dViewport.dwX = 0;
01398     dgl->d3dViewport.dwY = 0;
01399     dgl->d3dViewport.dwWidth = dgl->dwWidth;
01400     dgl->d3dViewport.dwHeight = dgl->dwHeight;
01401     dgl->d3dViewport.dvClipX = 0;
01402     dgl->d3dViewport.dvClipY = 0;
01403     dgl->d3dViewport.dvClipWidth = dgl->dwWidth;
01404     dgl->d3dViewport.dvClipHeight = dgl->dwHeight;
01405 //  dgl->d3dViewport.dvMinZ = 0.0f;
01406 //  dgl->d3dViewport.dvMaxZ = 1.0f;
01407     TRY(IDirect3DViewport3_SetViewport2(dgl->lpViewport3, &dgl->d3dViewport),
01408         "dglResize: SetViewport2");
01409 
01410     hResult = IDirect3DDevice3_SetCurrentViewport(dgl->lpDev3, dgl->lpViewport3);
01411     if (FAILED(hResult)) {
01412         ddlogError(DDLOG_CRITICAL_OR_WARN, "dglResize: SetCurrentViewport failed", hResult);
01413         goto cleanup_and_return_with_error;
01414     }
01415 
01416     // (Re)Initialise all the Direct3D renderstates
01417     dglInitStateD3D(ctx);
01418 
01419     // Now we have to recreate all of our textures (+ mipmaps).
01420     // Walk over all textures in hash table
01421     // XXX what about the default texture objects (id=0)?
01422     {
01423         struct _mesa_HashTable *textures = ctx->Shared->TexObjects;
01424         GLuint id;
01425         for (id = _mesa_HashFirstEntry(textures);
01426                  id;
01427                  id = _mesa_HashNextEntry(textures, id)) {
01428             tObj = (struct gl_texture_object *) _mesa_HashLookup(textures, id);
01429             if (tObj->DriverData) {
01430                 // We could call our TexImage function directly, but it's
01431                 // safer to use the driver pointer.
01432                 for (i=0; i<MAX_TEXTURE_LEVELS; i++) {
01433                     image = tObj->Image[i];
01434                     if (image) {
01435                         switch (tObj->Dimensions){
01436                         case 1:
01437                             if (ctx->Driver.TexImage)
01438                                 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_1D, tObj, i, image->Format, image);
01439                             break;
01440                         case 2:
01441                             if (ctx->Driver.TexImage)
01442                                 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, tObj, i, image->Format, image);
01443                             break;
01444                         default:
01445                             break;
01446                         }
01447                     }
01448                 }
01449             }
01450         }
01451     }
01452 
01453     // Re-Bind each texture Unit
01454     for (i=0; i<glb.wMaxSimultaneousTextures; i++) {
01455         tObj = ctx->Texture.Unit[i].Current;
01456         if (tObj) {
01457             DGL_texture *lpTex = (DGL_texture *)tObj->DriverData;
01458             hResult = dglSetTexture(dgl, i, lpTex ? lpTex->lpTexture : NULL);
01459             if (FAILED(hResult)) {
01460                 ddlogError(DDLOG_ERROR, "dglResize: SetTexture failed", hResult);
01461             }
01462         }
01463     }
01464 #endif // _USE_GLD3_WGL
01465 
01466     dgl->bCanRender = TRUE;
01467 
01468 #ifdef GLD_THREADS
01469     // Release serialized access
01470     if (glb.bMultiThreaded)
01471         LeaveCriticalSection(&CriticalSection);
01472 #endif
01473 
01474     // SUCCESS.
01475     return TRUE;
01476 
01477 cleanup_and_return_with_error:
01478     // Relase all interfaces before returning.
01479 #ifdef _USE_GLD3_WGL
01480     _gldDriver.DestroyDrawable(dgl);
01481 #else // _USE_GLD3_WGL
01482     RELEASE(dgl->lpDev3);
01483     RELEASE(dgl->lpDepth4);
01484     RELEASE(dgl->lpBack4);
01485     if (glb.bDirectDrawPersistant && glb.bDirectDrawPrimary)
01486         ;
01487     else
01488     RELEASE(dgl->lpFront4);
01489 
01490 #undef DDLOG_CRITICAL_OR_WARN
01491 #endif // _USE_GLD3_WGL
01492 
01493     // Mark context as not being able to render
01494     dgl->bCanRender = FALSE;
01495 
01496 #ifdef GLD_THREADS
01497     // Release serialized access
01498     if (glb.bMultiThreaded)
01499         LeaveCriticalSection(&CriticalSection);
01500 #endif
01501 
01502     return FALSE;
01503 }
01504 
01505 // ***********************************************************************
01506 // ***********************************************************************
01507 // Support for bitmap fonts.
01508 // ***********************************************************************
01509 // ***********************************************************************
01510 
01511 /*****************************************************************************
01512 **
01513 ** InvertGlyphBitmap.
01514 **
01515 ** Invert the bitmap so that it suits OpenGL's representation.
01516 ** Each row starts on a double word boundary.
01517 **
01518 *****************************************************************************/
01519 
01520 static void InvertGlyphBitmap(
01521     int w,
01522     int h,
01523     DWORD *fptr,
01524     DWORD *tptr)
01525 {
01526     int dWordsInRow = (w+31)/32;
01527     int i, j;
01528     DWORD *tmp = tptr;
01529 
01530     if (w <= 0 || h <= 0) {
01531     return;
01532     }
01533 
01534     tptr += ((h-1)*dWordsInRow);
01535     for (i = 0; i < h; i++) {
01536     for (j = 0; j < dWordsInRow; j++) {
01537         *(tptr + j) = *(fptr + j);
01538     }
01539     tptr -= dWordsInRow;
01540     fptr += dWordsInRow;
01541     }
01542 }
01543 
01544 // ***********************************************************************
01545 
01546 /*****************************************************************************
01547  * wglUseFontBitmaps
01548  *
01549  * Converts a subrange of the glyphs in a GDI font to OpenGL display
01550  * lists.
01551  *
01552  * Extended to support any GDI font, not just TrueType fonts. (DaveM)
01553  *
01554  *****************************************************************************/
01555 
01556 BOOL APIENTRY _GLD_WGL_EXPORT(UseFontBitmapsA)(
01557     HDC hDC,
01558     DWORD first,
01559     DWORD count,
01560     DWORD listBase)
01561 {
01562     int                 i, ox, oy, ix, iy;
01563     int                 w, h;
01564     int                 iBufSize, iCurBufSize = 0;
01565     DWORD               *bitmapBuffer = NULL;
01566     DWORD               *invertedBitmapBuffer = NULL;
01567     BOOL                bSuccessOrFail = TRUE;
01568     BOOL                bTrueType = FALSE;
01569     TEXTMETRIC          tm;
01570     GLYPHMETRICS        gm;
01571     RASTERIZER_STATUS   rs;
01572     MAT2                mat;
01573     SIZE                size;
01574     RECT                rect;
01575     HDC                 hDCMem;
01576     HBITMAP             hBitmap;
01577     BITMAPINFO          bmi;
01578     HFONT               hFont;
01579 
01580     // Validate SciTech DirectGL license
01581     if (!dglValidate())
01582         return FALSE;
01583 
01584     // Set up a unity matrix.
01585     ZeroMemory(&mat, sizeof(mat));
01586     mat.eM11.value = 1;
01587     mat.eM22.value = 1;
01588 
01589     // Test to see if selected font is TrueType or not
01590     ZeroMemory(&tm, sizeof(tm));
01591     if (!GetTextMetrics(hDC, &tm)) {
01592         ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Font metrics error\n");
01593         return (FALSE);
01594     }
01595     bTrueType = (tm.tmPitchAndFamily & TMPF_TRUETYPE) ? TRUE : FALSE;
01596 
01597     // Test to see if TRUE-TYPE capabilities are installed
01598     // (only necessary if TrueType font selected)
01599     ZeroMemory(&rs, sizeof(rs));
01600     if (bTrueType) {
01601         if (!GetRasterizerCaps (&rs, sizeof (RASTERIZER_STATUS))) {
01602             ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Raster caps error\n");
01603             return (FALSE);
01604         }
01605         if (!(rs.wFlags & TT_ENABLED)) {
01606             ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: No TrueType caps\n");
01607             return (FALSE);
01608         }
01609     }
01610 
01611     // Trick to get the current font handle
01612     hFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
01613     SelectObject(hDC, hFont);
01614 
01615     // Have memory device context available for holding bitmaps of font glyphs
01616     hDCMem = CreateCompatibleDC(hDC);
01617     SelectObject(hDCMem, hFont);
01618     SetTextColor(hDCMem, RGB(0xFF, 0xFF, 0xFF));
01619     SetBkColor(hDCMem, 0);
01620 
01621     for (i = first; (DWORD) i < (first + count); i++) {
01622         // Find out how much space is needed for the bitmap so we can
01623         // Set the buffer size correctly.
01624         if (bTrueType) {
01625             // Use TrueType support to get bitmap size of glyph
01626             iBufSize = GetGlyphOutline(hDC, i, GGO_BITMAP, &gm,
01627                 0, NULL, &mat);
01628             if (iBufSize == GDI_ERROR) {
01629                 bSuccessOrFail = FALSE;
01630                 break;
01631             }
01632         }
01633         else {
01634             // Use generic GDI support to compute bitmap size of glyph
01635             w = tm.tmMaxCharWidth;
01636             h = tm.tmHeight;
01637             if (GetTextExtentPoint32(hDC, (LPCTSTR)&i, 1, &size)) {
01638                 w = size.cx;
01639                 h = size.cy;
01640             }
01641             iBufSize = w * h;
01642             // Use DWORD multiple for compatibility
01643             iBufSize += 3;
01644             iBufSize /= 4;
01645             iBufSize *= 4;
01646         }
01647 
01648         // If we need to allocate Larger Buffers, then do so - but allocate
01649         // An extra 50 % so that we don't do too many mallocs !
01650         if (iBufSize > iCurBufSize) {
01651             if (bitmapBuffer) {
01652                 __wglFree(bitmapBuffer);
01653             }
01654             if (invertedBitmapBuffer) {
01655                 __wglFree(invertedBitmapBuffer);
01656             }
01657 
01658             iCurBufSize = iBufSize * 2;
01659             bitmapBuffer = (DWORD *) __wglMalloc(iCurBufSize);
01660             invertedBitmapBuffer = (DWORD *) __wglMalloc(iCurBufSize);
01661 
01662             if (bitmapBuffer == NULL || invertedBitmapBuffer == NULL) {
01663                 bSuccessOrFail = FALSE;
01664                 break;
01665             }
01666         }
01667 
01668         // If we fail to get the Glyph data, delete the display lists
01669         // Created so far and return FALSE.
01670         if (bTrueType) {
01671             // Use TrueType support to get bitmap of glyph
01672             if (GetGlyphOutline(hDC, i, GGO_BITMAP, &gm,
01673                     iBufSize, bitmapBuffer, &mat) == GDI_ERROR) {
01674                 bSuccessOrFail = FALSE;
01675                 break;
01676             }
01677 
01678             // Setup glBitmap parameters for current font glyph
01679             w  = gm.gmBlackBoxX;
01680             h  = gm.gmBlackBoxY;
01681             ox = gm.gmptGlyphOrigin.x;
01682             oy = gm.gmptGlyphOrigin.y;
01683             ix = gm.gmCellIncX;
01684             iy = gm.gmCellIncY;
01685         }
01686         else {
01687             // Use generic GDI support to create bitmap of glyph
01688             ZeroMemory(bitmapBuffer, iBufSize);
01689 
01690             if (i >= tm.tmFirstChar && i <= tm.tmLastChar) {
01691                 // Only create bitmaps for actual font glyphs
01692                 hBitmap = CreateBitmap(w, h, 1, 1, NULL);
01693                 SelectObject(hDCMem, hBitmap);
01694                 // Make bitmap of current font glyph
01695                 SetRect(&rect, 0, 0, w, h);
01696                 DrawText(hDCMem, (LPCTSTR)&i, 1, &rect,
01697                     DT_LEFT | DT_BOTTOM | DT_SINGLELINE | DT_NOCLIP);
01698                 // Make copy of bitmap in our local buffer
01699                 ZeroMemory(&bmi, sizeof(bmi));
01700                 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
01701                 bmi.bmiHeader.biWidth = w;
01702                 bmi.bmiHeader.biHeight = -h;
01703                 bmi.bmiHeader.biPlanes = 1;
01704                 bmi.bmiHeader.biBitCount = 1;
01705                 bmi.bmiHeader.biCompression = BI_RGB;
01706                 GetDIBits(hDCMem, hBitmap, 0, h, bitmapBuffer, &bmi, 0);
01707                 DeleteObject(hBitmap);
01708             }
01709             else {
01710                 // Otherwise use empty display list for non-existing glyph
01711                 iBufSize = 0;
01712             }
01713 
01714             // Setup glBitmap parameters for current font glyph
01715             ox = 0;
01716             oy = tm.tmDescent;
01717             ix = w;
01718             iy = 0;
01719         }
01720 
01721         // Create an OpenGL display list.
01722         _GLD_glNewList((listBase + i), GL_COMPILE);
01723 
01724         // Some fonts have no data for the space character, yet advertise
01725         // a non-zero size.
01726         if (0 == iBufSize) {
01727             _GLD_glBitmap(0, 0, 0.0f, 0.0f, (GLfloat) ix, (GLfloat) iy, NULL);
01728         } else {
01729             // Invert the Glyph data.
01730             InvertGlyphBitmap(w, h, bitmapBuffer, invertedBitmapBuffer);
01731 
01732             // Render an OpenGL bitmap and invert the origin.
01733             _GLD_glBitmap(w, h,
01734                 (GLfloat) ox, (GLfloat) (h-oy),
01735                 (GLfloat) ix, (GLfloat) iy,
01736                 (GLubyte *) invertedBitmapBuffer);
01737         }
01738 
01739         // Close this display list.
01740         _GLD_glEndList();
01741     }
01742 
01743     if (bSuccessOrFail == FALSE) {
01744         ddlogMessage(DDLOG_ERROR, "DGL_UseFontBitmaps: Get glyph failed\n");
01745         _GLD_glDeleteLists((i+listBase), (i-first));
01746     }
01747 
01748     // Release resources used
01749     DeleteObject(hFont);
01750     DeleteDC(hDCMem);
01751 
01752     if (bitmapBuffer)
01753         __wglFree(bitmapBuffer);
01754     if (invertedBitmapBuffer)
01755         __wglFree(invertedBitmapBuffer);
01756 
01757     return(bSuccessOrFail);
01758 }
01759 
01760 // ***********************************************************************
01761 
01762 BOOL APIENTRY _GLD_WGL_EXPORT(UseFontBitmapsW)(
01763     HDC a,
01764     DWORD b,
01765     DWORD c,
01766     DWORD d)
01767 {
01768     // Validate license
01769     if (!dglValidate())
01770         return FALSE;
01771 
01772     return _GLD_WGL_EXPORT(UseFontBitmapsA)(a, b, c, d);
01773 }
01774 
01775 // ***********************************************************************
01776 // ***********************************************************************
01777 // Support for outline TrueType fonts.
01778 // ***********************************************************************
01779 // ***********************************************************************
01780 
01781 void * __wglRealloc(
01782     void *oldPtr,
01783     size_t newSize)
01784 {
01785     void *newPtr = NULL;
01786     
01787     if (newSize != 0) {
01788         newPtr = (void *) GlobalAlloc(GPTR, newSize);
01789         if (oldPtr && newPtr) {
01790             DWORD oldSize = GlobalSize(oldPtr);
01791             
01792             memcpy(newPtr, oldPtr, (oldSize <= newSize ? oldSize : newSize));
01793             GlobalFree(oldPtr);
01794         }
01795     } else if (oldPtr) {
01796         GlobalFree(oldPtr);
01797     }
01798     if (newPtr == NULL) {
01799         return NULL;    /* XXX out of memory error */
01800     }
01801     return newPtr;
01802 }
01803 
01804 // ***********************************************************************
01805 
01806 
01807 /*****************************************************************************
01808  * wglUseFontOutlinesW
01809  *
01810  * Converts a subrange of the glyphs in a TrueType font to OpenGL display
01811  * lists.
01812  *****************************************************************************/
01813 
01814 BOOL APIENTRY _GLD_WGL_EXPORT(UseFontOutlinesW)(
01815     IN  HDC         hDC,
01816     IN  DWORD           first,
01817     IN  DWORD           count,
01818     IN  DWORD           listBase,
01819     IN  FLOAT           chordalDeviation,
01820     IN  FLOAT           extrusion,
01821     IN  INT         format,
01822     OUT LPGLYPHMETRICSFLOAT lpgmf)
01823 {
01824     return _GLD_WGL_EXPORT(UseFontOutlinesA)(hDC, first, count, listBase,
01825         chordalDeviation, extrusion, format, lpgmf);
01826 }
01827 
01828 /*****************************************************************************
01829  * wglUseFontOutlinesA
01830  *
01831  * Converts a subrange of the glyphs in a TrueType font to OpenGL display
01832  * lists.
01833  *****************************************************************************/
01834 
01835 BOOL APIENTRY _GLD_WGL_EXPORT(UseFontOutlinesA)(
01836     IN  HDC         hDC,
01837             IN  DWORD           first,
01838             IN  DWORD           count,
01839             IN  DWORD           listBase,
01840             IN  FLOAT           chordalDeviation,
01841             IN  FLOAT           extrusion,
01842             IN  INT         format,
01843             OUT LPGLYPHMETRICSFLOAT glyphMetricsFloatArray)
01844     {
01845     DWORD   glyphIndex;
01846     UCHAR*  glyphBuf;
01847     DWORD   glyphBufSize;
01848 
01849 
01850     /*
01851      * Flush any previous OpenGL errors.  This allows us to check for
01852      * new errors so they can be reported via the function return value.
01853      */
01854     while (_GLD_glGetError() != GL_NO_ERROR)
01855         ;
01856 
01857     /*
01858      * Make sure that the current font can be sampled accurately.
01859      */
01860     hNewFont = CreateHighResolutionFont(hDC);
01861     if (!hNewFont)
01862         return FALSE;
01863 
01864     hOldFont = SelectObject(hDC, hNewFont);
01865     if (!hOldFont)
01866         return FALSE;
01867 
01868     /*
01869      * Preallocate a buffer for the outline data, and track its size:
01870      */
01871     glyphBuf = (UCHAR*) __wglMalloc(glyphBufSize = 10240);
01872     if (!glyphBuf)
01873         return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
01874 
01875     /*
01876      * Process each glyph in the given range:
01877      */
01878     for (glyphIndex = first; glyphIndex - first < count; ++glyphIndex)
01879         {
01880         GLYPHMETRICS    glyphMetrics;
01881         DWORD       glyphSize;
01882         static MAT2 matrix =
01883             {
01884             {0, 1},     {0, 0},
01885             {0, 0},     {0, 1}
01886             };
01887         LPGLYPHMETRICSFLOAT glyphMetricsFloat =
01888             &glyphMetricsFloatArray[glyphIndex - first];
01889 
01890 
01891         /*
01892          * Determine how much space is needed to store the glyph's
01893          * outlines.  If our glyph buffer isn't large enough,
01894          * resize it.
01895          */
01896         glyphSize = GetGlyphOutline(    hDC,
01897                         glyphIndex,
01898                         GGO_NATIVE,
01899                         &glyphMetrics,
01900                         0,
01901                         NULL,
01902                         &matrix
01903                         );
01904         if (glyphSize < 0)
01905             return FALSE; /*WGL_STATUS_FAILURE*/
01906         if (glyphSize > glyphBufSize)
01907             {
01908             __wglFree(glyphBuf);
01909             glyphBuf = (UCHAR*) __wglMalloc(glyphBufSize = glyphSize);
01910             if (!glyphBuf)
01911                 return FALSE; /*WGL_STATUS_NOT_ENOUGH_MEMORY*/
01912             }
01913 
01914 
01915         /*
01916          * Get the glyph's outlines.
01917          */
01918         if (GetGlyphOutline(    hDC,
01919                     glyphIndex,
01920                     GGO_NATIVE,
01921                     &glyphMetrics,
01922                     glyphBufSize,
01923                     glyphBuf,
01924                     &matrix
01925                     ) < 0)
01926             {
01927             __wglFree(glyphBuf);
01928             return FALSE; /*WGL_STATUS_FAILURE*/
01929             }
01930         
01931         glyphMetricsFloat->gmfBlackBoxX =
01932             (FLOAT) glyphMetrics.gmBlackBoxX * ScaleFactor;
01933         glyphMetricsFloat->gmfBlackBoxY =
01934             (FLOAT) glyphMetrics.gmBlackBoxY * ScaleFactor;
01935         glyphMetricsFloat->gmfptGlyphOrigin.x =
01936             (FLOAT) glyphMetrics.gmptGlyphOrigin.x * ScaleFactor;
01937         glyphMetricsFloat->gmfptGlyphOrigin.y =
01938             (FLOAT) glyphMetrics.gmptGlyphOrigin.y * ScaleFactor;
01939         glyphMetricsFloat->gmfCellIncX =
01940             (FLOAT) glyphMetrics.gmCellIncX * ScaleFactor;
01941         glyphMetricsFloat->gmfCellIncY =
01942             (FLOAT) glyphMetrics.gmCellIncY * ScaleFactor;
01943         
01944         /*
01945          * Turn the glyph into a display list:
01946          */
01947         if (!MakeDisplayListFromGlyph(  (glyphIndex - first) + listBase,
01948                         glyphBuf,
01949                         glyphSize,
01950                         glyphMetricsFloat,
01951                         chordalDeviation + ScaleFactor,
01952                         extrusion,
01953                         format))
01954             {
01955             __wglFree(glyphBuf);
01956             return FALSE; /*WGL_STATUS_FAILURE*/
01957             }
01958         }
01959 
01960 
01961     /*
01962      * Clean up temporary storage and return.  If an error occurred,
01963      * clear all OpenGL error flags and return FAILURE status;
01964      * otherwise just return SUCCESS.
01965      */
01966     __wglFree(glyphBuf);
01967 
01968     SelectObject(hDC, hOldFont);
01969 
01970     if (_GLD_glGetError() == GL_NO_ERROR)
01971         return TRUE; /*WGL_STATUS_SUCCESS*/
01972     else
01973         {
01974         while (_GLD_glGetError() != GL_NO_ERROR)
01975             ;
01976         return FALSE; /*WGL_STATUS_FAILURE*/
01977         }
01978     }
01979 
01980 
01981 
01982 /*****************************************************************************
01983  * CreateHighResolutionFont
01984  *
01985  * Gets metrics for the current font and creates an equivalent font
01986  * scaled to the design units of the font.
01987  * 
01988  *****************************************************************************/
01989 
01990 static HFONT
01991 CreateHighResolutionFont(HDC hDC)
01992     {
01993     UINT otmSize;
01994     OUTLINETEXTMETRIC *otm;
01995     LONG fontHeight, fontWidth, fontUnits;
01996     LOGFONT logFont;
01997 
01998     otmSize = GetOutlineTextMetrics(hDC, 0, NULL);
01999     if (otmSize == 0) 
02000         return NULL;
02001 
02002     otm = (OUTLINETEXTMETRIC *) __wglMalloc(otmSize);
02003     if (otm == NULL)
02004         return NULL;
02005 
02006     otm->otmSize = otmSize;
02007     if (GetOutlineTextMetrics(hDC, otmSize, otm) == 0) 
02008         return NULL;
02009     
02010     fontHeight = otm->otmTextMetrics.tmHeight -
02011             otm->otmTextMetrics.tmInternalLeading;
02012     fontWidth = otm->otmTextMetrics.tmAveCharWidth;
02013     fontUnits = (LONG) otm->otmEMSquare;
02014     
02015     ScaleFactor = 1.0F / (FLOAT) fontUnits;
02016 
02017     logFont.lfHeight = - ((LONG) fontUnits);
02018     logFont.lfWidth = (LONG)
02019         ((FLOAT) (fontWidth * fontUnits) / (FLOAT) fontHeight);
02020     logFont.lfEscapement = 0;
02021     logFont.lfOrientation = 0;
02022     logFont.lfWeight = otm->otmTextMetrics.tmWeight;
02023     logFont.lfItalic = otm->otmTextMetrics.tmItalic;
02024     logFont.lfUnderline = otm->otmTextMetrics.tmUnderlined;
02025     logFont.lfStrikeOut = otm->otmTextMetrics.tmStruckOut;
02026     logFont.lfCharSet = otm->otmTextMetrics.tmCharSet;
02027     logFont.lfOutPrecision = OUT_OUTLINE_PRECIS;
02028     logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
02029     logFont.lfQuality = DEFAULT_QUALITY;
02030     logFont.lfPitchAndFamily =
02031         otm->otmTextMetrics.tmPitchAndFamily & 0xf0;
02032     strcpy(logFont.lfFaceName,
02033            (char *)otm + (int)otm->otmpFaceName);
02034 
02035     hNewFont = CreateFontIndirect(&logFont);
02036     if (hNewFont == NULL)
02037         return NULL;
02038 
02039     __wglFree(otm);
02040 
02041     return hNewFont;
02042     }
02043 
02044 
02045 
02046 /*****************************************************************************
02047  * MakeDisplayListFromGlyph
02048  * 
02049  * Converts the outline of a glyph to an OpenGL display list.
02050  *
02051  * Return value is nonzero for success, zero for failure.
02052  *
02053  * Does not check for OpenGL errors, so if the caller needs to know about them,
02054  * it should call glGetError().
02055  *****************************************************************************/
02056 
02057 static int
02058 MakeDisplayListFromGlyph(   IN  DWORD       listName,
02059                 IN  UCHAR*      glyphBuf,
02060                 IN  DWORD       glyphSize,
02061                 IN  LPGLYPHMETRICSFLOAT glyphMetricsFloat,
02062                 IN  FLOAT       chordalDeviation,
02063                 IN  FLOAT       extrusion,
02064                 IN  INT         format)
02065     {
02066     int status;
02067 
02068     _GLD_glNewList(listName, GL_COMPILE);
02069         status = DrawGlyph( glyphBuf,
02070                     glyphSize,
02071                     chordalDeviation,
02072                     extrusion,
02073                     format);
02074         
02075     _GLD_glTranslatef(glyphMetricsFloat->gmfCellIncX,
02076              glyphMetricsFloat->gmfCellIncY,
02077              0.0F);
02078     _GLD_glEndList();
02079 
02080     return status;
02081     }
02082 
02083 
02084 
02085 /*****************************************************************************
02086  * DrawGlyph
02087  * 
02088  * Converts the outline of a glyph to OpenGL drawing primitives, tessellating
02089  * as needed, and then draws the glyph.  Tessellation of the quadratic splines
02090  * in the outline is controlled by "chordalDeviation", and the drawing
02091  * primitives (lines or polygons) are selected by "format".
02092  *
02093  * Return value is nonzero for success, zero for failure.
02094  *
02095  * Does not check for OpenGL errors, so if the caller needs to know about them,
02096  * it should call glGetError().
02097  *****************************************************************************/
02098 
02099 static int
02100 DrawGlyph(  IN  UCHAR*  glyphBuf,
02101         IN  DWORD   glyphSize,
02102         IN  FLOAT   chordalDeviation,
02103         IN  FLOAT   extrusion,
02104         IN  INT     format)
02105     {
02106     INT         status = 0;
02107     FLOAT*          p;
02108     DWORD           loop;
02109     DWORD           point;
02110     GLUtesselator*      tess = NULL;
02111 
02112 
02113     /*
02114      * Initialize the global buffer into which we place the outlines:
02115      */
02116     if (!InitLineBuf())
02117         goto exit;
02118 
02119 
02120     /*
02121      * Convert the glyph outlines to a set of polyline loops.
02122      * (See MakeLinesFromGlyph() for the format of the loop data
02123      * structure.)
02124      */
02125     if (!MakeLinesFromGlyph(glyphBuf, glyphSize, chordalDeviation))
02126         goto exit;
02127     p = LineBuf;
02128 
02129 
02130     /*
02131      * Now draw the loops in the appropriate format:
02132      */
02133     if (format == WGL_FONT_LINES)
02134         {
02135         /*
02136          * This is the easy case.  Just draw the outlines.
02137          */
02138         for (loop = (DWORD) *p++; loop; --loop)
02139             {
02140             _GLD_glBegin(GL_LINE_LOOP);
02141                 for (point = (DWORD) *p++; point; --point)
02142                     {
02143                     _GLD_glVertex2fv(p);
02144                     p += 2;
02145                     }
02146             _GLD_glEnd();
02147             }
02148         status = 1;
02149         }
02150 
02151     else if (format == WGL_FONT_POLYGONS)
02152         {
02153         double v[3];
02154         FLOAT *save_p = p;
02155         GLfloat z_value;
02156         
02157         /*
02158          * This is the hard case.  We have to set up a tessellator
02159          * to convert the outlines into a set of polygonal
02160          * primitives, which the tessellator passes to some
02161          * auxiliary routines for drawing.
02162          */
02163         if (!LoadGLUTesselator())
02164             goto exit;
02165         if (!InitVertBuf())
02166             goto exit;
02167         if (!(tess = gluNewTessProc()))
02168             goto exit;
02169         gluTessCallbackProc(tess,   GLU_BEGIN,  (void(CALLBACK *)()) _GLD_glBegin);
02170         gluTessCallbackProc(tess,   GLU_TESS_VERTEX_DATA,
02171                     (void(CALLBACK *)()) TessVertexOutData);
02172         gluTessCallbackProc(tess,   GLU_END,    (void(CALLBACK *)()) _GLD_glEnd);
02173         gluTessCallbackProc(tess,   GLU_ERROR,  (void(CALLBACK *)()) TessError);
02174         gluTessCallbackProc(tess,   GLU_TESS_COMBINE, (void(CALLBACK *)()) TessCombine);
02175         gluTessNormalProc(tess, 0.0F, 0.0F, 1.0F);
02176 
02177         TessErrorOccurred = 0;
02178         _GLD_glNormal3f(0.0f, 0.0f, 1.0f);
02179         v[2] = 0.0;
02180         z_value = 0.0f;
02181 
02182         gluTessBeginPolygonProc(tess, (void *)*(int *)&z_value);
02183             for (loop = (DWORD) *p++; loop; --loop)
02184                 {
02185                 gluTessBeginContourProc(tess);
02186                 
02187                 for (point = (DWORD) *p++; point; --point)
02188                     {
02189                     v[0] = p[0];
02190                     v[1] = p[1];
02191                     gluTessVertexProc(tess, v, p);
02192                     p += 2;
02193                     }
02194 
02195                 gluTessEndContourProc(tess);
02196                 }
02197         gluTessEndPolygonProc(tess);
02198 
02199         status = !TessErrorOccurred;
02200 
02201         /* Extrusion code */
02202         if (extrusion) {
02203             DWORD loops;
02204             GLfloat thickness = (GLfloat) -extrusion;
02205             FLOAT *vert, *vert2;
02206             DWORD count;
02207 
02208             p = save_p;
02209             loops = (DWORD) *p++;
02210 
02211             for (loop = 0; loop < loops; loop++) {
02212                 GLfloat dx, dy, len;
02213                 DWORD last;
02214 
02215                 count = (DWORD) *p++;
02216                 _GLD_glBegin(GL_QUAD_STRIP);
02217 
02218                 /* Check if the first and last vertex are identical
02219                  * so we don't draw the same quad twice.
02220                  */
02221                 vert = p + (count-1)*2;
02222                 last = (p[0] == vert[0] && p[1] == vert[1]) ? count-1 : count;
02223 
02224                 for (point = 0; point <= last; point++) {
02225                     vert  = p + 2 * (point % last);
02226                     vert2 = p + 2 * ((point+1) % last);
02227 
02228                     dx = vert[0] - vert2[0];
02229                     dy = vert[1] - vert2[1];
02230                     len = (GLfloat)sqrt(dx * dx + dy * dy);
02231 
02232                     _GLD_glNormal3f(dy / len, -dx / len, 0.0f);
02233                     _GLD_glVertex3f((GLfloat) vert[0],
02234                                (GLfloat) vert[1], thickness);
02235                     _GLD_glVertex3f((GLfloat) vert[0],
02236                                (GLfloat) vert[1], 0.0f);
02237                 }
02238 
02239                 _GLD_glEnd();
02240                 p += count*2;
02241             }
02242 
02243             /* Draw the back face */
02244             p = save_p;
02245             v[2] = thickness;
02246             _GLD_glNormal3f(0.0f, 0.0f, -1.0f);
02247             gluTessNormalProc(tess, 0.0F, 0.0F, -1.0F);
02248 
02249             gluTessBeginPolygonProc(tess, (void *)*(int *)&thickness);
02250 
02251             for (loop = (DWORD) *p++; loop; --loop)
02252             {
02253                 count = (DWORD) *p++;
02254 
02255                 gluTessBeginContourProc(tess);
02256                 
02257                 for (point = 0; point < count; point++)
02258                 {
02259                     vert = p + ((count-point-1)<<1);
02260                     v[0] = vert[0];
02261                     v[1] = vert[1];
02262                     gluTessVertexProc(tess, v, vert);
02263                 }
02264                 p += count*2;
02265 
02266                 gluTessEndContourProc(tess);
02267             }
02268             gluTessEndPolygonProc(tess);
02269         }
02270 
02271 #if DEBUG
02272     if (TessErrorOccurred)
02273         printf("Tessellation error %s\n",
02274             gluErrorString(TessErrorOccurred));
02275 #endif
02276         }
02277 
02278 
02279 exit:
02280     FreeLineBuf();
02281     if (tess)
02282         gluDeleteTessProc(tess);
02283     // UnloadGLUTesselator();
02284     FreeVertBuf();
02285     return status;
02286     }
02287 
02288 
02289 
02290 /*****************************************************************************
02291  * LoadGLUTesselator
02292  *
02293  * Maps the glu32.dll module and gets function pointers for the 
02294  * tesselator functions.
02295  *****************************************************************************/
02296 
02297 static BOOL
02298 LoadGLUTesselator(void)
02299     {
02300     if (gluModuleHandle != NULL)
02301         return TRUE;
02302 
02303     {
02304         extern HINSTANCE hInstanceOpenGL;
02305         char *gluName = "GLU32.DLL";
02306 //      char name[256];
02307 //      char *ptr;
02308 //      int len;
02309 
02310 /*
02311         len = GetModuleFileName(hInstanceOpenGL, name, 255);
02312         if (len != 0)
02313             {
02314             ptr = name+len-1;
02315             while (ptr > name && *ptr != '\\')
02316                 ptr--;
02317             if (*ptr == '\\')
02318                 ptr++;
02319             if (!stricmp(ptr, "cosmogl.dll"))
02320                 {
02321                 gluName = "COSMOGLU.DLL";
02322                 }
02323             else if (!stricmp(ptr, "opengl32.dll"))
02324                 {
02325                 gluName = "GLU32.DLL";
02326                 }
02327             }
02328 */
02329         if ((gluModuleHandle = LoadLibrary(gluName)) == NULL)
02330             return FALSE;
02331     }
02332 
02333     if ((gluNewTessProc = (gluNewTessProto)
02334         GetProcAddress(gluModuleHandle, "gluNewTess")) == NULL)
02335         return FALSE;
02336     
02337     if ((gluDeleteTessProc = (gluDeleteTessProto)
02338         GetProcAddress(gluModuleHandle, "gluDeleteTess")) == NULL)
02339         return FALSE;
02340     
02341     if ((gluTessBeginPolygonProc = (gluTessBeginPolygonProto)
02342         GetProcAddress(gluModuleHandle, "gluTessBeginPolygon")) == NULL)
02343         return FALSE;
02344     
02345     if ((gluTessBeginContourProc = (gluTessBeginContourProto)
02346         GetProcAddress(gluModuleHandle, "gluTessBeginContour")) == NULL)
02347         return FALSE;
02348     
02349     if ((gluTessVertexProc = (gluTessVertexProto)
02350         GetProcAddress(gluModuleHandle, "gluTessVertex")) == NULL)
02351         return FALSE;
02352     
02353     if ((gluTessEndContourProc = (gluTessEndContourProto)
02354         GetProcAddress(gluModuleHandle, "gluTessEndContour")) == NULL)
02355         return FALSE;
02356     
02357     if ((gluTessEndPolygonProc = (gluTessEndPolygonProto)
02358         GetProcAddress(gluModuleHandle, "gluTessEndPolygon")) == NULL)
02359         return FALSE;
02360     
02361     if ((gluTessPropertyProc = (gluTessPropertyProto)
02362         GetProcAddress(gluModuleHandle, "gluTessProperty")) == NULL)
02363         return FALSE;
02364 
02365     if ((gluTessNormalProc = (gluTessNormalProto)
02366         GetProcAddress(gluModuleHandle, "gluTessNormal")) == NULL)
02367         return FALSE;
02368     
02369     if ((gluTessCallbackProc = (gluTessCallbackProto)
02370         GetProcAddress(gluModuleHandle, "gluTessCallback")) == NULL)
02371         return FALSE;
02372 
02373     return TRUE;
02374     }
02375 
02376 
02377 
02378 /*****************************************************************************
02379  * UnloadGLUTesselator
02380  *
02381  * Unmaps the glu32.dll module.
02382  *****************************************************************************/
02383 
02384 static BOOL
02385 UnloadGLUTesselator(void)
02386     {
02387     if (gluModuleHandle != NULL)
02388         if (FreeLibrary(gluModuleHandle) == FALSE)
02389         return FALSE;
02390     gluModuleHandle = NULL;
02391     }
02392 
02393 
02394 
02395 /*****************************************************************************
02396  * TessVertexOut
02397  *
02398  * Used by tessellator to handle output vertexes.
02399  *****************************************************************************/
02400  
02401 static void CALLBACK
02402 TessVertexOut(FLOAT p[3])
02403     {
02404         GLfloat v[2];
02405 
02406         v[0] = p[0] * ScaleFactor;
02407         v[1] = p[1] * ScaleFactor;
02408         _GLD_glVertex2fv(v);
02409     }
02410 
02411 static void CALLBACK
02412 TessVertexOutData(FLOAT p[3], GLfloat z)
02413 {
02414     GLfloat v[3];
02415 
02416     v[0] = (GLfloat) p[0];
02417     v[1] = (GLfloat) p[1];
02418     v[2] = z;
02419     _GLD_glVertex3fv(v);
02420 }
02421 
02422 
02423 /*****************************************************************************
02424  * TessCombine
02425  *
02426  * Used by tessellator to handle self-intersecting contours and degenerate
02427  * geometry.
02428  *****************************************************************************/
02429  
02430 static void CALLBACK
02431 TessCombine(double  coords[3],
02432         void*   vertex_data[4],
02433         FLOAT   weight[4],
02434         void**  outData)
02435     {
02436     if (!AppendToVertBuf((FLOAT) coords[0])
02437      || !AppendToVertBuf((FLOAT) coords[1])
02438      || !AppendToVertBuf((FLOAT) coords[2]))
02439         TessErrorOccurred = GL_OUT_OF_MEMORY;
02440     *outData = VertBuf + (VertBufIndex - 3);
02441     }
02442 
02443 
02444 
02445 /*****************************************************************************
02446  * TessError
02447  *
02448  * Saves the last tessellator error code in the global TessErrorOccurred.
02449  *****************************************************************************/
02450  
02451 static void CALLBACK
02452 TessError(GLenum error)
02453     {
02454     TessErrorOccurred = error;
02455     }
02456 
02457 
02458 
02459 /*****************************************************************************
02460  * MakeLinesFromGlyph
02461  * 
02462  * Converts the outline of a glyph from the TTPOLYGON format to a simple
02463  * array of floating-point values containing one or more loops.
02464  *
02465  * The first element of the output array is a count of the number of loops.
02466  * The loop data follows this count.  Each loop consists of a count of the
02467  * number of vertices it contains, followed by the vertices.  Each vertex
02468  * is an X and Y coordinate.  For example, a single triangle might be
02469  * described by this array:
02470  *
02471  *  1., 3., 0., 0.,     1., 0.,     0., 1.
02472  *       ^   ^   ^    ^      ^    ^      ^    ^
02473  *     #loops   #verts   x1   y1     x2   y2     x3   y3
02474  *
02475  * A two-loop glyph would look like this:
02476  *
02477  *  2., 3.,  0.,0.,  1.,0.,  0.,1., 3.,  .2,.2,  .4,.2,  .2,.4
02478  *
02479  * Line segments from the TTPOLYGON are transferred to the output array in
02480  * the obvious way.  Quadratic splines in the TTPOLYGON are converted to
02481  * collections of line segments
02482  *****************************************************************************/
02483 
02484 static int
02485 MakeLinesFromGlyph(IN  UCHAR*   glyphBuf,
02486            IN  DWORD    glyphSize,
02487            IN  FLOAT    chordalDeviation)
02488     {
02489     UCHAR*  p;
02490     int status = 0;
02491 
02492 
02493     /*
02494      * Pick up all the polygons (aka loops) that make up the glyph:
02495      */
02496     if (!AppendToLineBuf(0.0F)) /* loop count at LineBuf[0] */
02497         goto exit;
02498 
02499     p = glyphBuf;
02500     while (p < glyphBuf + glyphSize)
02501         {
02502         if (!MakeLinesFromTTPolygon(&p, chordalDeviation))
02503             goto exit;
02504         LineBuf[0] += 1.0F; /* increment loop count */
02505         }
02506 
02507     status = 1;
02508 
02509 exit:
02510     return status;
02511     }
02512 
02513 
02514 
02515 /*****************************************************************************
02516  * MakeLinesFromTTPolygon
02517  *
02518  * Converts a TTPOLYGONHEADER and its associated curve structures into a
02519  * single polyline loop in the global LineBuf.
02520  *****************************************************************************/
02521 
02522 static int
02523 MakeLinesFromTTPolygon( IN OUT  UCHAR** pp,
02524             IN  FLOAT   chordalDeviation)
02525     {
02526     DWORD   polySize;
02527     UCHAR*  polyStart;
02528     DWORD   vertexCountIndex;
02529 
02530     /*
02531      * Record where the polygon data begins, and where the loop's
02532      * vertex count resides:
02533      */
02534     polyStart = *pp;
02535     vertexCountIndex = LineBufIndex;
02536     if (!AppendToLineBuf(0.0F))
02537         return 0;
02538 
02539     /*
02540      * Extract relevant data from the TTPOLYGONHEADER:
02541      */
02542     polySize = GetDWord(pp);
02543     if (GetDWord(pp) != TT_POLYGON_TYPE)    /* polygon type */
02544         return 0;
02545     if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first X coord */
02546         return 0;
02547     if (!AppendToLineBuf((FLOAT) GetFixed(pp))) /* first Y coord */
02548         return 0;
02549     LineBuf[vertexCountIndex] += 1.0F;
02550 
02551     /*
02552      * Process each of the TTPOLYCURVE structures in the polygon:
02553      */
02554     while (*pp < polyStart + polySize)
02555         if (!MakeLinesFromTTPolycurve(  pp,
02556                         vertexCountIndex,
02557                         chordalDeviation))
02558         return 0;
02559 
02560     return 1;
02561     }
02562 
02563 
02564 
02565 /*****************************************************************************
02566  * MakeLinesFromTTPolyCurve
02567  *
02568  * Converts the lines and splines in a single TTPOLYCURVE structure to points
02569  * in the global LineBuf.
02570  *****************************************************************************/
02571 
02572 static int
02573 MakeLinesFromTTPolycurve(   IN OUT  UCHAR** pp,
02574                 IN  DWORD   vertexCountIndex,
02575                 IN  FLOAT   chordalDeviation)
02576     {
02577     WORD type;
02578     WORD pointCount;
02579 
02580 
02581     /*
02582      * Pick up the relevant fields of the TTPOLYCURVE structure:
02583      */
02584     type = (WORD) GetWord(pp);
02585     pointCount = (WORD) GetWord(pp);
02586 
02587     /*
02588      * Convert the "curve" to line segments:
02589      */
02590     if (type == TT_PRIM_LINE)
02591         return MakeLinesFromTTLine( pp,
02592                         vertexCountIndex,
02593                         pointCount);
02594     else if (type == TT_PRIM_QSPLINE)
02595         return MakeLinesFromTTQSpline(  pp,
02596                         vertexCountIndex,
02597                         pointCount,
02598                         chordalDeviation);
02599     else
02600         return 0;
02601     }
02602 
02603 
02604 
02605 /*****************************************************************************
02606  * MakeLinesFromTTLine
02607  *
02608  * Converts points from the polyline in a TT_PRIM_LINE structure to
02609  * equivalent points in the global LineBuf.
02610  *****************************************************************************/
02611 static int
02612 MakeLinesFromTTLine(    IN OUT  UCHAR** pp,
02613             IN  DWORD   vertexCountIndex,
02614             IN  WORD    pointCount)
02615     {
02616     /*
02617      * Just copy the line segments into the line buffer (converting
02618      * type as we go):
02619      */
02620     LineBuf[vertexCountIndex] += pointCount;
02621     while (pointCount--)
02622         {
02623         if (!AppendToLineBuf((FLOAT) GetFixed(pp))  /* X coord */
02624          || !AppendToLineBuf((FLOAT) GetFixed(pp))) /* Y coord */
02625             return 0;
02626         }
02627 
02628     return 1;
02629     }
02630 
02631 
02632 
02633 /*****************************************************************************
02634  * MakeLinesFromTTQSpline
02635  *
02636  * Converts points from the poly quadratic spline in a TT_PRIM_QSPLINE
02637  * structure to polyline points in the global LineBuf.
02638  *****************************************************************************/
02639 
02640 static int
02641 MakeLinesFromTTQSpline( IN OUT  UCHAR** pp,
02642             IN  DWORD   vertexCountIndex,
02643             IN  WORD    pointCount,
02644             IN  FLOAT   chordalDeviation)
02645     {
02646     FLOAT x0, y0, x1, y1, x2, y2;
02647     WORD point;
02648 
02649     /*
02650      * Process each of the non-interpolated points in the outline.
02651      * To do this, we need to generate two interpolated points (the
02652      * start and end of the arc) for each non-interpolated point.
02653      * The first interpolated point is always the one most recently
02654      * stored in LineBuf, so we just extract it from there.  The
02655      * second interpolated point is either the average of the next
02656      * two points in the QSpline, or the last point in the QSpline
02657      * if only one remains.
02658      */
02659     for (point = 0; point < pointCount - 1; ++point)
02660         {
02661         x0 = LineBuf[LineBufIndex - 2];
02662         y0 = LineBuf[LineBufIndex - 1];
02663 
02664         x1 = (FLOAT) GetFixed(pp);
02665         y1 = (FLOAT) GetFixed(pp);
02666 
02667         if (point == pointCount - 2)
02668             {
02669             /*
02670              * This is the last arc in the QSpline.  The final
02671              * point is the end of the arc.
02672              */
02673             x2 = (FLOAT) GetFixed(pp);
02674             y2 = (FLOAT) GetFixed(pp);
02675             }
02676         else
02677             {
02678             /*
02679              * Peek at the next point in the input to compute
02680              * the end of the arc:
02681              */
02682             x2 = 0.5F * (x1 + (FLOAT) GetFixed(pp));
02683             y2 = 0.5F * (y1 + (FLOAT) GetFixed(pp));
02684             /*
02685              * Push the point back onto the input so it will
02686              * be reused as the next off-curve point:
02687              */
02688             *pp -= 8;
02689             }
02690 
02691         if (!MakeLinesFromArc(  x0, y0,
02692                     x1, y1,
02693                     x2, y2,
02694                     vertexCountIndex,
02695                     chordalDeviation * chordalDeviation))
02696             return 0;
02697         }
02698 
02699     return 1;
02700     }
02701 
02702 
02703 
02704 /*****************************************************************************
02705  * MakeLinesFromArc
02706  *
02707  * Subdivides one arc of a quadratic spline until the chordal deviation
02708  * tolerance requirement is met, then places the resulting set of line
02709  * segments in the global LineBuf.
02710  *****************************************************************************/
02711 
02712 static int
02713 MakeLinesFromArc(   IN  FLOAT   x0,
02714             IN  FLOAT   y0,
02715             IN  FLOAT   x1,
02716             IN  FLOAT   y1,
02717             IN  FLOAT   x2,
02718             IN  FLOAT   y2,
02719             IN  DWORD   vertexCountIndex,
02720             IN  FLOAT   chordalDeviationSquared)
02721     {
02722     FLOAT   x01;
02723     FLOAT   y01;
02724     FLOAT   x12;
02725     FLOAT   y12;
02726     FLOAT   midPointX;
02727     FLOAT   midPointY;
02728     FLOAT   deltaX;
02729     FLOAT   deltaY;
02730 
02731     /*
02732      * Calculate midpoint of the curve by de Casteljau:
02733      */
02734     x01 = 0.5F * (x0 + x1);
02735     y01 = 0.5F * (y0 + y1);
02736     x12 = 0.5F * (x1 + x2);
02737     y12 = 0.5F * (y1 + y2);
02738     midPointX = 0.5F * (x01 + x12);
02739     midPointY = 0.5F * (y01 + y12);
02740 
02741 
02742     /*
02743      * Estimate chordal deviation by the distance from the midpoint
02744      * of the curve to its non-interpolated control point.  If this
02745      * distance is greater than the specified chordal deviation
02746      * constraint, then subdivide.  Otherwise, generate polylines
02747      * from the three control points.
02748      */
02749     deltaX = midPointX - x1;
02750     deltaY = midPointY - y1;
02751     if (deltaX * deltaX + deltaY * deltaY > chordalDeviationSquared)
02752         {
02753         MakeLinesFromArc(   x0, y0,
02754                     x01, y01,
02755                     midPointX, midPointY,
02756                     vertexCountIndex,
02757                     chordalDeviationSquared);
02758         
02759         MakeLinesFromArc(   midPointX, midPointY,
02760                     x12, y12,
02761                     x2, y2,
02762                     vertexCountIndex,
02763                     chordalDeviationSquared);
02764         }
02765     else
02766         {
02767         /*
02768          * The "pen" is already at (x0, y0), so we don't need to
02769          * add that point to the LineBuf.
02770          */
02771         if (!AppendToLineBuf(x1)
02772          || !AppendToLineBuf(y1)
02773          || !AppendToLineBuf(x2)
02774          || !AppendToLineBuf(y2))
02775             return 0;
02776         LineBuf[vertexCountIndex] += 2.0F;
02777         }
02778 
02779     return 1;
02780     }
02781 
02782 
02783 
02784 /*****************************************************************************
02785  * InitLineBuf
02786  *
02787  * Initializes the global LineBuf and its associated size and current-element
02788  * counters.
02789  *****************************************************************************/
02790 
02791 static int
02792 InitLineBuf(void)
02793     {
02794     if (!(LineBuf = (FLOAT*)
02795         __wglMalloc((LineBufSize = LINE_BUF_QUANT) * sizeof(FLOAT))))
02796             return 0;
02797     LineBufIndex = 0;
02798     return 1;
02799     }
02800 
02801 
02802 
02803 /*****************************************************************************
02804  * InitVertBuf
02805  *
02806  * Initializes the global VertBuf and its associated size and current-element
02807  * counters.
02808  *****************************************************************************/
02809 
02810 static int
02811 InitVertBuf(void)
02812     {
02813     if (!(VertBuf = (FLOAT*)
02814         __wglMalloc((VertBufSize = VERT_BUF_QUANT) * sizeof(FLOAT))))
02815             return 0;
02816     VertBufIndex = 0;
02817     return 1;
02818     }
02819 
02820 
02821 
02822 /*****************************************************************************
02823  * AppendToLineBuf
02824  *
02825  * Appends one floating-point value to the global LineBuf array.  Return value
02826  * is non-zero for success, zero for failure.
02827  *****************************************************************************/
02828 
02829 static int
02830 AppendToLineBuf(FLOAT value)
02831     {
02832     if (LineBufIndex >= LineBufSize)
02833         {
02834         FLOAT* f;
02835         
02836         f = (FLOAT*) __wglRealloc(LineBuf,
02837             (LineBufSize += LINE_BUF_QUANT) * sizeof(FLOAT));
02838         if (!f)
02839             return 0;
02840         LineBuf = f;
02841         }
02842     LineBuf[LineBufIndex++] = value;
02843     return 1;
02844     }
02845 
02846 
02847 
02848 /*****************************************************************************
02849  * AppendToVertBuf
02850  *
02851  * Appends one floating-point value to the global VertBuf array.  Return value
02852  * is non-zero for success, zero for failure.
02853  *
02854  * Note that we can't realloc this one, because the tessellator is using
02855  * pointers into it.
02856  *****************************************************************************/
02857 
02858 static int
02859 AppendToVertBuf(FLOAT value)
02860     {
02861     if (VertBufIndex >= VertBufSize)
02862         return 0;
02863     VertBuf[VertBufIndex++] = value;
02864     return 1;
02865     }
02866 
02867 
02868 
02869 /*****************************************************************************
02870  * FreeLineBuf
02871  *
02872  * Cleans up vertex buffer structure.
02873  *****************************************************************************/
02874 
02875 static void
02876 FreeLineBuf(void)
02877     {
02878     if (LineBuf)
02879         {
02880         __wglFree(LineBuf);
02881         LineBuf = NULL;
02882         }
02883     }
02884 
02885 
02886 
02887 /*****************************************************************************
02888  * FreeVertBuf
02889  *
02890  * Cleans up vertex buffer structure.
02891  *****************************************************************************/
02892 
02893 static void
02894 FreeVertBuf(void)
02895     {
02896     if (VertBuf)
02897         {
02898         __wglFree(VertBuf);
02899         VertBuf = NULL;
02900         }
02901     }
02902 
02903 
02904 
02905 /*****************************************************************************
02906  * GetWord
02907  *
02908  * Fetch the next 16-bit word from a little-endian byte stream, and increment
02909  * the stream pointer to the next unscanned byte.
02910  *****************************************************************************/
02911 
02912 static long GetWord(UCHAR** p)
02913     {
02914     long value;
02915 
02916     value = ((*p)[1] << 8) + (*p)[0];
02917     *p += 2;
02918     return value;
02919     }
02920 
02921 
02922 
02923 /*****************************************************************************
02924  * GetDWord
02925  *
02926  * Fetch the next 32-bit word from a little-endian byte stream, and increment
02927  * the stream pointer to the next unscanned byte.
02928  *****************************************************************************/
02929 
02930 static long GetDWord(UCHAR** p)
02931     {
02932     long value;
02933 
02934     value = ((*p)[3] << 24) + ((*p)[2] << 16) + ((*p)[1] << 8) + (*p)[0];
02935     *p += 4;
02936     return value;
02937     }
02938 
02939 
02940 
02941 
02942 /*****************************************************************************
02943  * GetFixed
02944  *
02945  * Fetch the next 32-bit fixed-point value from a little-endian byte stream,
02946  * convert it to floating-point, and increment the stream pointer to the next
02947  * unscanned byte.
02948  *****************************************************************************/
02949 
02950 static double GetFixed(
02951     UCHAR** p)
02952 {
02953     long hiBits, loBits;
02954     double value;
02955 
02956     loBits = GetWord(p);
02957     hiBits = GetWord(p);
02958     value = (double) ((hiBits << 16) | loBits) / 65536.0;
02959 
02960     return value * ScaleFactor;
02961 }
02962 
02963 // ***********************************************************************
02964 

Generated on Sat May 26 2012 04:18:44 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.