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#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 */
44struct __pixelformat__
45{
46    PIXELFORMATDESCRIPTOR pfd;
47    GLboolean doubleBuffered;
48};
49
50
51
52/* These are the PFD's supported by this driver. */
53struct __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
135int npfd = sizeof(pfd) / sizeof(pfd[0]);
136
137
138/*
139 * Contexts
140 */
141
142typedef struct {
143    WMesaContext ctx;
144} MesaWglCtx;
145
146#define MESAWGL_CTX_MAX_COUNT 20
147
148static MesaWglCtx wgl_ctx[MESAWGL_CTX_MAX_COUNT];
149
150static unsigned ctx_count = 0;
151static int ctx_current = -1;
152static unsigned curPFD = 0;
153
154static HDC CurrentHDC = 0;
155
156
157WINGDIAPI 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
183WINGDIAPI 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
199WINGDIAPI 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
207WINGDIAPI HDC GLAPIENTRY wglGetCurrentDC(VOID)
208{
209    return CurrentHDC;
210}
211
212WINGDIAPI 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
235WINGDIAPI 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
296WINGDIAPI 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
315WINGDIAPI 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
325WINGDIAPI 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
335WINGDIAPI 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
353WINGDIAPI BOOL GLAPIENTRY wglSwapBuffers(HDC hdc)
354{
355    WMesaSwapBuffers(hdc);
356    return TRUE;
357}
358
359static 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*/
372static 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
474WINGDIAPI 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
565WINGDIAPI 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 */
575WINGDIAPI BOOL GLAPIENTRY wglCopyContext(HGLRC hglrcSrc,
576					 HGLRC hglrcDst,
577					 UINT mask)
578{
579    (void) hglrcSrc; (void) hglrcDst; (void) mask;
580    return(FALSE);
581}
582
583WINGDIAPI 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
593WINGDIAPI 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
602WINGDIAPI 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
618WINGDIAPI 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
634WINGDIAPI 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
646WINGDIAPI 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
658WINGDIAPI 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
669WINGDIAPI 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
678WINGDIAPI BOOL GLAPIENTRY wglSwapLayerBuffers(HDC hdc,
679					      UINT fuPlanes)
680{
681    (void) hdc; (void) fuPlanes;
682    SetLastError(0);
683    return(FALSE);
684}
685
686WINGDIAPI const char * GLAPIENTRY wglGetExtensionsStringARB(HDC hdc)
687{
688    return "WGL_ARB_extensions_string";
689}
690