Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendglwgl.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
1.7.6.1
|