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