1 2 /* 3 * This library is free software; you can redistribute it and/or 4 * modify it under the terms of the GNU Library General Public 5 * License as published by the Free Software Foundation; either 6 * version 2 of the License, or (at your option) any later version. 7 * 8 * This library is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * Library General Public License for more details. 12 * 13 * You should have received a copy of the GNU Library General Public 14 * License along with this library; if not, write to the Free 15 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 16 * 17 */ 18 19 /* 20 * File name : wgl.c 21 * WGL stuff. Added by Oleg Letsinsky, ajl (at) ultersys.ru 22 * Some things originated from the 3Dfx WGL functions 23 */ 24 25 /* 26 * This file contains the implementation of the wgl* functions for 27 * Mesa on Windows. Since these functions are provided by Windows in 28 * GDI/OpenGL, we must supply our versions that work with Mesa here. 29 */ 30 31 32 #include <windows.h> 33 34 #include "main/config.h" 35 #include "glapi/glapi.h" 36 #include "swrast/swrast.h" 37 #include "GL/wmesa.h" /* protos for wmesa* functions */ 38 39 /* 40 * Pixel Format Descriptors 41 */ 42 43 /* Extend the PFD to include DB flag */ 44 struct __pixelformat__ 45 { 46 PIXELFORMATDESCRIPTOR pfd; 47 GLboolean doubleBuffered; 48 }; 49 50 51 52 /* These are the PFD's supported by this driver. */ 53 struct __pixelformat__ pfd[] = 54 { 55 #if 0 56 /* Double Buffer, alpha */ 57 { 58 { 59 sizeof(PIXELFORMATDESCRIPTOR), 1, 60 PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL| 61 PFD_GENERIC_FORMAT|PFD_DOUBLEBUFFER|PFD_SWAP_COPY, 62 PFD_TYPE_RGBA, 63 24, 64 8, 0, 65 8, 8, 66 8, 16, 67 8, 24, 68 0, 0, 0, 0, 0, 69 DEFAULT_SOFTWARE_DEPTH_BITS, 8, 70 0, 0, 0, 71 0, 0, 0 72 }, 73 GL_TRUE 74 }, 75 /* Single Buffer, alpha */ 76 { 77 { 78 sizeof(PIXELFORMATDESCRIPTOR), 1, 79 PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL| 80 PFD_GENERIC_FORMAT, 81 PFD_TYPE_RGBA, 82 24, 83 8, 0, 84 8, 8, 85 8, 16, 86 8, 24, 87 0, 0, 0, 0, 0, 88 DEFAULT_SOFTWARE_DEPTH_BITS, 8, 89 0, 0, 0, 90 0, 0, 0 91 }, 92 GL_FALSE 93 }, 94 #endif 95 /* Double Buffer, no alpha */ 96 { 97 { 98 sizeof(PIXELFORMATDESCRIPTOR), 1, 99 PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL| 100 PFD_GENERIC_FORMAT|PFD_DOUBLEBUFFER|PFD_SWAP_COPY, 101 PFD_TYPE_RGBA, 102 24, 103 8, 0, 104 8, 8, 105 8, 16, 106 0, 0, 107 0, 0, 0, 0, 0, 108 DEFAULT_SOFTWARE_DEPTH_BITS, 8, 109 0, 0, 0, 110 0, 0, 0 111 }, 112 GL_TRUE 113 }, 114 /* Single Buffer, no alpha */ 115 { 116 { 117 sizeof(PIXELFORMATDESCRIPTOR), 1, 118 PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL| 119 PFD_GENERIC_FORMAT, 120 PFD_TYPE_RGBA, 121 24, 122 8, 0, 123 8, 8, 124 8, 16, 125 0, 0, 126 0, 0, 0, 0, 0, 127 DEFAULT_SOFTWARE_DEPTH_BITS, 8, 128 0, 0, 0, 129 0, 0, 0 130 }, 131 GL_FALSE 132 }, 133 }; 134 135 int npfd = sizeof(pfd) / sizeof(pfd[0]); 136 137 138 /* 139 * Contexts 140 */ 141 142 typedef struct { 143 WMesaContext ctx; 144 } MesaWglCtx; 145 146 #define MESAWGL_CTX_MAX_COUNT 20 147 148 static MesaWglCtx wgl_ctx[MESAWGL_CTX_MAX_COUNT]; 149 150 static unsigned ctx_count = 0; 151 static int ctx_current = -1; 152 static unsigned curPFD = 0; 153 154 static HDC CurrentHDC = 0; 155 156 157 WINGDIAPI HGLRC GLAPIENTRY wglCreateContext(HDC hdc) 158 { 159 int i = 0; 160 if (!ctx_count) { 161 for(i=0;i<MESAWGL_CTX_MAX_COUNT;i++) { 162 wgl_ctx[i].ctx = NULL; 163 } 164 } 165 for( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ ) { 166 if ( wgl_ctx[i].ctx == NULL ) { 167 wgl_ctx[i].ctx = 168 WMesaCreateContext(hdc, NULL, (GLboolean)GL_TRUE, 169 (GLboolean) (pfd[curPFD-1].doubleBuffered ? 170 GL_TRUE : GL_FALSE), 171 (GLboolean)(pfd[curPFD-1].pfd.cAlphaBits ? 172 GL_TRUE : GL_FALSE) ); 173 if (wgl_ctx[i].ctx == NULL) 174 break; 175 ctx_count++; 176 return ((HGLRC)wgl_ctx[i].ctx); 177 } 178 } 179 SetLastError(0); 180 return(NULL); 181 } 182 183 WINGDIAPI BOOL GLAPIENTRY wglDeleteContext(HGLRC hglrc) 184 { 185 int i; 186 for ( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ ) { 187 if ( wgl_ctx[i].ctx == (WMesaContext) hglrc ){ 188 WMesaMakeCurrent((WMesaContext) hglrc, NULL); 189 WMesaDestroyContext(wgl_ctx[i].ctx); 190 wgl_ctx[i].ctx = NULL; 191 ctx_count--; 192 return(TRUE); 193 } 194 } 195 SetLastError(0); 196 return(FALSE); 197 } 198 199 WINGDIAPI HGLRC GLAPIENTRY wglGetCurrentContext(VOID) 200 { 201 if (ctx_current < 0) 202 return 0; 203 else 204 return (HGLRC) wgl_ctx[ctx_current].ctx; 205 } 206 207 WINGDIAPI HDC GLAPIENTRY wglGetCurrentDC(VOID) 208 { 209 return CurrentHDC; 210 } 211 212 WINGDIAPI BOOL GLAPIENTRY wglMakeCurrent(HDC hdc, HGLRC hglrc) 213 { 214 int i; 215 216 CurrentHDC = hdc; 217 218 if (!hdc || !hglrc) { 219 WMesaMakeCurrent(NULL, NULL); 220 ctx_current = -1; 221 return TRUE; 222 } 223 224 for ( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ ) { 225 if ( wgl_ctx[i].ctx == (WMesaContext) hglrc ) { 226 WMesaMakeCurrent( (WMesaContext) hglrc, hdc ); 227 ctx_current = i; 228 return TRUE; 229 } 230 } 231 return FALSE; 232 } 233 234 235 WINGDIAPI int GLAPIENTRY wglChoosePixelFormat(HDC hdc, 236 CONST 237 PIXELFORMATDESCRIPTOR *ppfd) 238 { 239 int i,best = -1,bestdelta = 0x7FFFFFFF,delta; 240 (void) hdc; 241 242 if(ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR) || ppfd->nVersion != 1) 243 { 244 SetLastError(0); 245 return(0); 246 } 247 for(i = 0; i < npfd;i++) 248 { 249 delta = 0; 250 if( 251 (ppfd->dwFlags & PFD_DRAW_TO_WINDOW) && 252 !(pfd[i].pfd.dwFlags & PFD_DRAW_TO_WINDOW)) 253 continue; 254 if( 255 (ppfd->dwFlags & PFD_DRAW_TO_BITMAP) && 256 !(pfd[i].pfd.dwFlags & PFD_DRAW_TO_BITMAP)) 257 continue; 258 if( 259 (ppfd->dwFlags & PFD_SUPPORT_GDI) && 260 !(pfd[i].pfd.dwFlags & PFD_SUPPORT_GDI)) 261 continue; 262 if( 263 (ppfd->dwFlags & PFD_SUPPORT_OPENGL) && 264 !(pfd[i].pfd.dwFlags & PFD_SUPPORT_OPENGL)) 265 continue; 266 if( 267 !(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) && 268 ((ppfd->dwFlags & PFD_DOUBLEBUFFER) != 269 (pfd[i].pfd.dwFlags & PFD_DOUBLEBUFFER))) 270 continue; 271 if( 272 !(ppfd->dwFlags & PFD_STEREO_DONTCARE) && 273 ((ppfd->dwFlags & PFD_STEREO) != 274 (pfd[i].pfd.dwFlags & PFD_STEREO))) 275 continue; 276 if(ppfd->iPixelType != pfd[i].pfd.iPixelType) 277 delta++; 278 if(ppfd->cAlphaBits != pfd[i].pfd.cAlphaBits) 279 delta++; 280 if(delta < bestdelta) 281 { 282 best = i + 1; 283 bestdelta = delta; 284 if(bestdelta == 0) 285 break; 286 } 287 } 288 if(best == -1) 289 { 290 SetLastError(0); 291 return(0); 292 } 293 return(best); 294 } 295 296 WINGDIAPI int GLAPIENTRY wglDescribePixelFormat(HDC hdc, 297 int iPixelFormat, 298 UINT nBytes, 299 LPPIXELFORMATDESCRIPTOR ppfd) 300 { 301 (void) hdc; 302 303 if(ppfd == NULL) 304 return(npfd); 305 if(iPixelFormat < 1 || iPixelFormat > npfd || 306 nBytes != sizeof(PIXELFORMATDESCRIPTOR)) 307 { 308 SetLastError(0); 309 return(0); 310 } 311 *ppfd = pfd[iPixelFormat - 1].pfd; 312 return(npfd); 313 } 314 315 WINGDIAPI PROC GLAPIENTRY wglGetProcAddress(LPCSTR lpszProc) 316 { 317 PROC p = (PROC) _glapi_get_proc_address((const char *) lpszProc); 318 if (p) 319 return p; 320 321 SetLastError(0); 322 return(NULL); 323 } 324 325 WINGDIAPI int GLAPIENTRY wglGetPixelFormat(HDC hdc) 326 { 327 (void) hdc; 328 if(curPFD == 0) { 329 SetLastError(0); 330 return(0); 331 } 332 return(curPFD); 333 } 334 335 WINGDIAPI BOOL GLAPIENTRY wglSetPixelFormat(HDC hdc,int iPixelFormat, 336 const PIXELFORMATDESCRIPTOR *ppfd) 337 { 338 (void) hdc; 339 340 /* SetPixelFormat (hence wglSetPixelFormat) must not touch ppfd, per 341 * http://msdn.microsoft.com/en-us/library/dd369049(v=vs.85).aspx 342 */ 343 (void) ppfd; 344 345 if(iPixelFormat < 1 || iPixelFormat > npfd) { 346 SetLastError(0); 347 return(FALSE); 348 } 349 curPFD = iPixelFormat; 350 return(TRUE); 351 } 352 353 WINGDIAPI BOOL GLAPIENTRY wglSwapBuffers(HDC hdc) 354 { 355 WMesaSwapBuffers(hdc); 356 return TRUE; 357 } 358 359 static FIXED FixedFromDouble(double d) 360 { 361 long l = (long) (d * 65536L); 362 return *(FIXED *) (void *) &l; 363 } 364 365 366 /* 367 ** This is cribbed from FX/fxwgl.c, and seems to implement support 368 ** for bitmap fonts where the wglUseFontBitmapsA() code implements 369 ** support for outline fonts. In combination they hopefully give 370 ** fairly generic support for fonts. 371 */ 372 static BOOL wglUseFontBitmaps_FX(HDC fontDevice, DWORD firstChar, 373 DWORD numChars, DWORD listBase) 374 { 375 #define VERIFY(a) (void)(a) 376 377 TEXTMETRIC metric; 378 BITMAPINFO *dibInfo; 379 HDC bitDevice; 380 COLORREF tempColor; 381 int i; 382 383 VERIFY(GetTextMetrics(fontDevice, &metric)); 384 385 dibInfo = (BITMAPINFO *) calloc(sizeof(BITMAPINFO) + sizeof(RGBQUAD), 1); 386 dibInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 387 dibInfo->bmiHeader.biPlanes = 1; 388 dibInfo->bmiHeader.biBitCount = 1; 389 dibInfo->bmiHeader.biCompression = BI_RGB; 390 391 bitDevice = CreateCompatibleDC(fontDevice); 392 393 /* Swap fore and back colors so the bitmap has the right polarity */ 394 tempColor = GetBkColor(bitDevice); 395 SetBkColor(bitDevice, GetTextColor(bitDevice)); 396 SetTextColor(bitDevice, tempColor); 397 398 /* Place chars based on base line */ 399 VERIFY(SetTextAlign(bitDevice, TA_BASELINE) != GDI_ERROR ? 1 : 0); 400 401 for(i = 0; i < (int)numChars; i++) { 402 SIZE size; 403 char curChar; 404 int charWidth,charHeight,bmapWidth,bmapHeight,numBytes,res; 405 HBITMAP bitObject; 406 HGDIOBJ origBmap; 407 unsigned char *bmap; 408 409 curChar = (char)(i + firstChar); 410 411 /* Find how high/wide this character is */ 412 VERIFY(GetTextExtentPoint32(bitDevice, &curChar, 1, &size)); 413 414 /* Create the output bitmap */ 415 charWidth = size.cx; 416 charHeight = size.cy; 417 /* Round up to the next multiple of 32 bits */ 418 bmapWidth = ((charWidth + 31) / 32) * 32; 419 bmapHeight = charHeight; 420 bitObject = CreateCompatibleBitmap(bitDevice, 421 bmapWidth, 422 bmapHeight); 423 /* VERIFY(bitObject); */ 424 425 /* Assign the output bitmap to the device */ 426 origBmap = SelectObject(bitDevice, bitObject); 427 (void) VERIFY(origBmap); 428 429 VERIFY( PatBlt( bitDevice, 0, 0, bmapWidth, bmapHeight,BLACKNESS ) ); 430 431 /* Use our source font on the device */ 432 VERIFY(SelectObject(bitDevice, GetCurrentObject(fontDevice,OBJ_FONT))); 433 434 /* Draw the character */ 435 VERIFY(TextOut(bitDevice, 0, metric.tmAscent, &curChar, 1)); 436 437 /* Unselect our bmap object */ 438 VERIFY(SelectObject(bitDevice, origBmap)); 439 440 /* Convert the display dependant representation to a 1 bit deep DIB */ 441 numBytes = (bmapWidth * bmapHeight) / 8; 442 bmap = malloc(numBytes); 443 dibInfo->bmiHeader.biWidth = bmapWidth; 444 dibInfo->bmiHeader.biHeight = bmapHeight; 445 res = GetDIBits(bitDevice, bitObject, 0, bmapHeight, bmap, 446 dibInfo, 447 DIB_RGB_COLORS); 448 /* VERIFY(res); */ 449 450 /* Create the GL object */ 451 glNewList(i + listBase, GL_COMPILE); 452 glBitmap(bmapWidth, bmapHeight, 0.0, (GLfloat)metric.tmDescent, 453 (GLfloat)charWidth, 0.0, 454 bmap); 455 glEndList(); 456 /* CheckGL(); */ 457 458 /* Destroy the bmap object */ 459 DeleteObject(bitObject); 460 461 /* Deallocate the bitmap data */ 462 free(bmap); 463 } 464 465 /* Destroy the DC */ 466 VERIFY(DeleteDC(bitDevice)); 467 468 free(dibInfo); 469 470 return TRUE; 471 #undef VERIFY 472 } 473 474 WINGDIAPI BOOL GLAPIENTRY wglUseFontBitmapsA(HDC hdc, DWORD first, 475 DWORD count, DWORD listBase) 476 { 477 int i; 478 GLuint font_list; 479 DWORD size; 480 GLYPHMETRICS gm; 481 HANDLE hBits; 482 LPSTR lpBits; 483 MAT2 mat; 484 int success = TRUE; 485 486 if (count == 0) 487 return FALSE; 488 489 font_list = listBase; 490 491 mat.eM11 = FixedFromDouble(1); 492 mat.eM12 = FixedFromDouble(0); 493 mat.eM21 = FixedFromDouble(0); 494 mat.eM22 = FixedFromDouble(-1); 495 496 memset(&gm,0,sizeof(gm)); 497 498 /* 499 ** If we can't get the glyph outline, it may be because this is a fixed 500 ** font. Try processing it that way. 501 */ 502 if( GetGlyphOutline(hdc, first, GGO_BITMAP, &gm, 0, NULL, &mat) 503 == GDI_ERROR ) { 504 return wglUseFontBitmaps_FX( hdc, first, count, listBase ); 505 } 506 507 /* 508 ** Otherwise process all desired characters. 509 */ 510 for (i = 0; i < (int)count; i++) { 511 DWORD err; 512 513 glNewList( font_list+i, GL_COMPILE ); 514 515 /* allocate space for the bitmap/outline */ 516 size = GetGlyphOutline(hdc, first + i, GGO_BITMAP, 517 &gm, 0, NULL, &mat); 518 if (size == GDI_ERROR) { 519 glEndList( ); 520 err = GetLastError(); 521 success = FALSE; 522 continue; 523 } 524 525 hBits = GlobalAlloc(GHND, size+1); 526 lpBits = GlobalLock(hBits); 527 528 err = 529 GetGlyphOutline(hdc, /* handle to device context */ 530 first + i, /* character to query */ 531 GGO_BITMAP, /* format of data to return */ 532 &gm, /* ptr to structure for metrics*/ 533 size, /* size of buffer for data */ 534 lpBits, /* pointer to buffer for data */ 535 &mat /* pointer to transformation */ 536 /* matrix structure */ 537 ); 538 539 if (err == GDI_ERROR) { 540 GlobalUnlock(hBits); 541 GlobalFree(hBits); 542 543 glEndList( ); 544 err = GetLastError(); 545 success = FALSE; 546 continue; 547 } 548 549 glBitmap(gm.gmBlackBoxX,gm.gmBlackBoxY, 550 (GLfloat)-gm.gmptGlyphOrigin.x, 551 (GLfloat)gm.gmptGlyphOrigin.y, 552 (GLfloat)gm.gmCellIncX, 553 (GLfloat)gm.gmCellIncY, 554 (const GLubyte * )lpBits); 555 556 GlobalUnlock(hBits); 557 GlobalFree(hBits); 558 559 glEndList( ); 560 } 561 562 return success; 563 } 564 565 WINGDIAPI BOOL GLAPIENTRY wglShareLists(HGLRC hglrc1, 566 HGLRC hglrc2) 567 { 568 WMesaShareLists((WMesaContext)hglrc1, (WMesaContext)hglrc2); 569 return(TRUE); 570 } 571 572 573 574 /* NOT IMPLEMENTED YET */ 575 WINGDIAPI BOOL GLAPIENTRY wglCopyContext(HGLRC hglrcSrc, 576 HGLRC hglrcDst, 577 UINT mask) 578 { 579 (void) hglrcSrc; (void) hglrcDst; (void) mask; 580 return(FALSE); 581 } 582 583 WINGDIAPI HGLRC GLAPIENTRY wglCreateLayerContext(HDC hdc, 584 int iLayerPlane) 585 { 586 SetLastError(0); 587 if (iLayerPlane == 0) 588 return wglCreateContext( hdc ); 589 return(NULL); 590 } 591 592 593 WINGDIAPI BOOL GLAPIENTRY wglUseFontBitmapsW(HDC hdc, 594 DWORD first, 595 DWORD count, 596 DWORD listBase) 597 { 598 (void) hdc; (void) first; (void) count; (void) listBase; 599 return FALSE; 600 } 601 602 WINGDIAPI BOOL GLAPIENTRY wglUseFontOutlinesA(HDC hdc, 603 DWORD first, 604 DWORD count, 605 DWORD listBase, 606 FLOAT deviation, 607 FLOAT extrusion, 608 int format, 609 LPGLYPHMETRICSFLOAT lpgmf) 610 { 611 (void) hdc; (void) first; (void) count; 612 (void) listBase; (void) deviation; (void) extrusion; (void) format; 613 (void) lpgmf; 614 SetLastError(0); 615 return(FALSE); 616 } 617 618 WINGDIAPI BOOL GLAPIENTRY wglUseFontOutlinesW(HDC hdc, 619 DWORD first, 620 DWORD count, 621 DWORD listBase, 622 FLOAT deviation, 623 FLOAT extrusion, 624 int format, 625 LPGLYPHMETRICSFLOAT lpgmf) 626 { 627 (void) hdc; (void) first; (void) count; 628 (void) listBase; (void) deviation; (void) extrusion; (void) format; 629 (void) lpgmf; 630 SetLastError(0); 631 return(FALSE); 632 } 633 634 WINGDIAPI BOOL GLAPIENTRY wglDescribeLayerPlane(HDC hdc, 635 int iPixelFormat, 636 int iLayerPlane, 637 UINT nBytes, 638 LPLAYERPLANEDESCRIPTOR plpd) 639 { 640 (void) hdc; (void) iPixelFormat; (void) iLayerPlane; 641 (void) nBytes; (void) plpd; 642 SetLastError(0); 643 return(FALSE); 644 } 645 646 WINGDIAPI int GLAPIENTRY wglSetLayerPaletteEntries(HDC hdc, 647 int iLayerPlane, 648 int iStart, 649 int cEntries, 650 CONST COLORREF *pcr) 651 { 652 (void) hdc; (void) iLayerPlane; (void) iStart; 653 (void) cEntries; (void) pcr; 654 SetLastError(0); 655 return(0); 656 } 657 658 WINGDIAPI int GLAPIENTRY wglGetLayerPaletteEntries(HDC hdc, 659 int iLayerPlane, 660 int iStart, 661 int cEntries, 662 COLORREF *pcr) 663 { 664 (void) hdc; (void) iLayerPlane; (void) iStart; (void) cEntries; (void) pcr; 665 SetLastError(0); 666 return(0); 667 } 668 669 WINGDIAPI BOOL GLAPIENTRY wglRealizeLayerPalette(HDC hdc, 670 int iLayerPlane, 671 BOOL bRealize) 672 { 673 (void) hdc; (void) iLayerPlane; (void) bRealize; 674 SetLastError(0); 675 return(FALSE); 676 } 677 678 WINGDIAPI BOOL GLAPIENTRY wglSwapLayerBuffers(HDC hdc, 679 UINT fuPlanes) 680 { 681 (void) hdc; (void) fuPlanes; 682 SetLastError(0); 683 return(FALSE); 684 } 685 686 WINGDIAPI const char * GLAPIENTRY wglGetExtensionsStringARB(HDC hdc) 687 { 688 return "WGL_ARB_extensions_string"; 689 } 690