gdi32: Revert 1440eb5a35dc95dea1836d9035b51e2b15d83703 and add the test showing that...
[wine] / dlls / gdi32 / opengl.c
1 /*
2  * OpenGL function forwarding to the display driver
3  *
4  * Copyright (c) 1999 Lionel Ulmer
5  * Copyright (c) 2005 Raphael Junqueira
6  * Copyright (c) 2006 Roderick Colenbrander
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdarg.h>
27 #include <string.h>
28 #include <stdlib.h>
29
30 #include "windef.h"
31 #include "winbase.h"
32 #include "wingdi.h"
33 #include "winerror.h"
34 #include "winternl.h"
35 #include "winnt.h"
36 #include "gdi_private.h"
37 #include "wine/debug.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(wgl);
40
41 static HDC default_hdc = 0;
42
43 typedef struct opengl_context
44 {
45     HDC hdc;
46 } *OPENGL_Context;
47
48 /* We route all wgl functions from opengl32.dll through gdi32.dll to
49  * the display driver. Various wgl calls have a hDC as one of their parameters.
50  * Using DC_GetDCPtr we get access to the functions exported by the driver.
51  * Some functions don't receive a hDC. This function creates a global hdc and
52  * if there's already a global hdc, it returns it.
53  */
54 static DC* OPENGL_GetDefaultDC()
55 {
56     if(!default_hdc)
57         default_hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
58         
59     return DC_GetDCPtr(default_hdc);
60 }
61
62 /***********************************************************************
63  *              wglCreateContext (OPENGL32.@)
64  */
65 HGLRC WINAPI wglCreateContext(HDC hdc)
66 {
67     HGLRC ret = 0;
68     DC * dc = DC_GetDCPtr( hdc );
69
70     TRACE("(%p)\n",hdc);
71
72     if (!dc) return 0;
73
74     if (!dc->funcs->pwglCreateContext) FIXME(" :stub\n");
75     else ret = dc->funcs->pwglCreateContext(dc->physDev);
76
77     GDI_ReleaseObj( hdc );
78     return ret;
79 }
80
81
82 /***********************************************************************
83  *              wglDeleteContext (OPENGL32.@)
84  */
85 BOOL WINAPI wglDeleteContext(HGLRC hglrc)
86 {
87     DC *dc;
88     BOOL ret = FALSE;
89     OPENGL_Context ctx = (OPENGL_Context)hglrc;
90
91     TRACE("hglrc: (%p)\n", hglrc);
92     if(ctx == NULL)
93         return FALSE;
94
95     /* Retrieve the HDC associated with the context to access the display driver */
96     dc = DC_GetDCPtr(ctx->hdc);
97     if (!dc) return FALSE;
98
99     if (!dc->funcs->pwglDeleteContext) FIXME(" :stub\n");
100     else ret = dc->funcs->pwglDeleteContext(hglrc);
101
102     GDI_ReleaseObj(ctx->hdc);
103     return ret;
104 }
105
106 /***********************************************************************
107  *              wglGetCurrentContext (OPENGL32.@)
108  */
109 HGLRC WINAPI wglGetCurrentContext(void)
110 {
111     HGLRC ret = NtCurrentTeb()->glContext;
112     TRACE(" returning %p\n", ret);
113     return ret;
114 }
115
116 /***********************************************************************
117  *              wglGetCurrentDC (OPENGL32.@)
118  */
119 HDC WINAPI wglGetCurrentDC(void)
120 {
121     OPENGL_Context ctx = (OPENGL_Context)wglGetCurrentContext();
122
123     TRACE(" found context: %p\n", ctx);
124     if(ctx == NULL)
125         return NULL;
126
127     /* Retrieve the current DC from the active context */
128     TRACE(" returning hdc: %p\n", ctx->hdc);
129     return ctx->hdc;
130 }
131
132 /***********************************************************************
133  *              wglGetPbufferDCARB
134  */
135 static HDC WINAPI wglGetPbufferDCARB(void *pbuffer)
136 {
137     HDC ret = 0;
138
139     /* Create a device context to associate with the pbuffer */
140     HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
141     DC *dc = DC_GetDCPtr(hdc);
142
143     TRACE("(%p)\n", pbuffer);
144
145     if (!dc) return FALSE;
146
147     /* The display driver has to do the rest of the work because
148      * we need access to lowlevel datatypes which we can't access here
149      */
150     if (!dc->funcs->pwglGetPbufferDCARB) FIXME(" :stub\n");
151     else ret = dc->funcs->pwglGetPbufferDCARB(dc->physDev, pbuffer);
152
153     TRACE("(%p), hdc=%p\n", pbuffer, ret);
154     
155     GDI_ReleaseObj(hdc);
156     return ret;
157 }
158
159 /***********************************************************************
160  *              wglMakeCurrent (OPENGL32.@)
161  */
162 BOOL WINAPI wglMakeCurrent(HDC hdc, HGLRC hglrc)
163 {
164     BOOL ret = FALSE;
165     DC * dc = NULL;
166
167     /* When the context hglrc is NULL, the HDC is ignored and can be NULL.
168      * In that case use the global hDC to get access to the driver.  */
169     if(hglrc == NULL)
170         dc = OPENGL_GetDefaultDC();
171     else
172         dc = DC_GetDCUpdate( hdc );
173
174     TRACE("hdc: (%p), hglrc: (%p)\n", hdc, hglrc);
175
176     if (!dc) return FALSE;
177
178     if (!dc->funcs->pwglMakeCurrent) FIXME(" :stub\n");
179     else ret = dc->funcs->pwglMakeCurrent(dc->physDev,hglrc);
180
181     if(hglrc == NULL)
182         GDI_ReleaseObj(default_hdc);
183     else
184         GDI_ReleaseObj(hdc);
185
186     return ret;
187 }
188
189 /***********************************************************************
190  *              wglMakeContextCurrentARB
191  */
192 static BOOL WINAPI wglMakeContextCurrentARB(HDC hDrawDC, HDC hReadDC, HGLRC hglrc)
193 {
194     BOOL ret = FALSE;
195     DC *DrawDC;
196     DC *ReadDC;
197
198     TRACE("hDrawDC: (%p), hReadDC: (%p) hglrc: (%p)\n", hDrawDC, hReadDC, hglrc);
199
200     /* Both hDrawDC and hReadDC need to be valid */
201     DrawDC = DC_GetDCPtr( hDrawDC);
202     if (!DrawDC) return FALSE;
203
204     ReadDC = DC_GetDCPtr( hReadDC);
205     if (!ReadDC) {
206         GDI_ReleaseObj(hDrawDC);
207         return FALSE;
208     }
209
210     if (!DrawDC->funcs->pwglMakeContextCurrentARB) FIXME(" :stub\n");
211     else ret = DrawDC->funcs->pwglMakeContextCurrentARB(DrawDC->physDev, ReadDC->physDev, hglrc);
212
213     GDI_ReleaseObj(hDrawDC);
214     GDI_ReleaseObj(hReadDC);
215
216     return ret;
217 }
218
219 /***********************************************************************
220  *              wglShareLists (OPENGL32.@)
221  */
222 BOOL WINAPI wglShareLists(HGLRC hglrc1, HGLRC hglrc2)
223 {
224     DC *dc;
225     BOOL ret = FALSE;
226     OPENGL_Context ctx = (OPENGL_Context)hglrc1;
227
228     TRACE("hglrc1: (%p); hglrc: (%p)\n", hglrc1, hglrc2);
229     if(ctx == NULL)
230         return FALSE;
231     
232     /* Retrieve the HDC associated with the context to access the display driver */
233     dc = DC_GetDCPtr(ctx->hdc);
234     if (!dc) return FALSE;
235
236     if (!dc->funcs->pwglShareLists) FIXME(" :stub\n");
237     else ret = dc->funcs->pwglShareLists(hglrc1, hglrc2);
238
239     GDI_ReleaseObj(ctx->hdc);
240     return ret;
241 }
242
243 /***********************************************************************
244  *              wglUseFontBitmapsA (OPENGL32.@)
245  */
246 BOOL WINAPI wglUseFontBitmapsA(HDC hdc, DWORD first, DWORD count, DWORD listBase)
247 {
248     BOOL ret = FALSE;
249     DC * dc = DC_GetDCPtr( hdc );
250
251     TRACE("(%p, %d, %d, %d)\n", hdc, first, count, listBase);
252
253     if (!dc) return FALSE;
254
255     if (!dc->funcs->pwglUseFontBitmapsA) FIXME(" :stub\n");
256     else ret = dc->funcs->pwglUseFontBitmapsA(dc->physDev, first, count, listBase);
257
258     GDI_ReleaseObj( hdc);
259     return ret;
260 }
261
262 /***********************************************************************
263  *              wglUseFontBitmapsW (OPENGL32.@)
264  */
265 BOOL WINAPI wglUseFontBitmapsW(HDC hdc, DWORD first, DWORD count, DWORD listBase)
266 {
267     BOOL ret = FALSE;
268     DC * dc = DC_GetDCPtr( hdc );
269
270     TRACE("(%p, %d, %d, %d)\n", hdc, first, count, listBase);
271
272     if (!dc) return FALSE;
273
274     if (!dc->funcs->pwglUseFontBitmapsW) FIXME(" :stub\n");
275     else ret = dc->funcs->pwglUseFontBitmapsW(dc->physDev, first, count, listBase);
276
277     GDI_ReleaseObj( hdc);
278     return ret;
279 }
280
281 /***********************************************************************
282  *              Internal wglGetProcAddress for retrieving WGL extensions
283  */
284 PROC WINAPI wglGetProcAddress(LPCSTR func)
285 {
286     PROC ret = NULL;
287     DC *dc;
288
289     if(!func)
290         return NULL;
291
292     TRACE("func: '%p'\n", func);
293
294     /* Retrieve the global hDC to get access to the driver.  */
295     dc = OPENGL_GetDefaultDC();
296     if (!dc) return FALSE;
297
298     if (!dc->funcs->pwglGetProcAddress) FIXME(" :stub\n");
299     else ret = dc->funcs->pwglGetProcAddress(func);
300
301     GDI_ReleaseObj(default_hdc);
302
303     /* At the moment we implement one WGL extension which requires a HDC. When we
304      * are looking up this call and when the Extension is available (that is the case
305      * when a non-NULL value is returned by wglGetProcAddress), we return the address
306      * of a wrapper function which will handle the HDC->PhysDev conversion.
307      */
308     if(ret && strcmp(func, "wglMakeContextCurrentARB") == 0)
309         return wglMakeContextCurrentARB;
310     else if(ret && strcmp(func, "wglGetPbufferDCARB") == 0)
311         return (PROC)wglGetPbufferDCARB;
312
313     return ret;
314 }